|
34 | 34 | import android.content.pm.ApplicationInfo;
|
35 | 35 | import android.content.pm.PackageManager;
|
36 | 36 | import android.content.pm.ResolveInfo;
|
| 37 | +import android.content.pm.ServiceInfo; |
37 | 38 | import android.net.ProxyInfo;
|
38 | 39 | import android.net.Uri;
|
39 | 40 | import android.os.AsyncTask;
|
|
46 | 47 | import android.provider.Settings;
|
47 | 48 | import android.security.KeyChain;
|
48 | 49 | import android.security.KeyChainAliasCallback;
|
| 50 | +import android.service.notification.NotificationListenerService; |
49 | 51 | import android.support.annotation.StringRes;
|
50 | 52 | import android.support.v14.preference.SwitchPreference;
|
51 | 53 | import android.support.v4.content.FileProvider;
|
|
80 | 82 | import com.afwsamples.testdpc.common.CertificateUtil;
|
81 | 83 | import com.afwsamples.testdpc.common.MediaDisplayFragment;
|
82 | 84 | import com.afwsamples.testdpc.common.Util;
|
| 85 | +import com.afwsamples.testdpc.common.CertificateUtil; |
| 86 | +import com.afwsamples.testdpc.common.ReflectionUtil; |
83 | 87 | import com.afwsamples.testdpc.common.preference.DpcPreference;
|
84 | 88 | import com.afwsamples.testdpc.common.preference.DpcPreferenceBase;
|
85 | 89 | import com.afwsamples.testdpc.common.preference.DpcPreferenceHelper;
|
|
111 | 115 | import java.io.FileNotFoundException;
|
112 | 116 | import java.io.IOException;
|
113 | 117 | import java.io.InputStream;
|
| 118 | +import java.lang.reflect.InvocationTargetException; |
| 119 | +import java.lang.reflect.Method; |
| 120 | +import java.security.KeyStore; |
114 | 121 | import java.security.KeyStoreException;
|
115 | 122 | import java.security.NoSuchAlgorithmException;
|
116 | 123 | import java.security.PrivateKey;
|
@@ -274,6 +281,8 @@ public class PolicyManagementFragment extends BaseSearchablePolicyPreferenceFrag
|
274 | 281 | private static final String SET_DISABLE_ACCOUNT_MANAGEMENT_KEY
|
275 | 282 | = "set_disable_account_management";
|
276 | 283 | private static final String SET_INPUT_METHODS_KEY = "set_input_methods";
|
| 284 | + private static final String SET_NOTIFICATION_LISTENERS_KEY = "set_notification_listeners"; |
| 285 | + private static final String SET_NOTIFICATION_LISTENERS_TEXT_KEY = "set_notification_listeners_text"; |
277 | 286 | private static final String SET_LONG_SUPPORT_MESSAGE_KEY = "set_long_support_message";
|
278 | 287 | private static final String SET_PERMISSION_POLICY_KEY = "set_permission_policy";
|
279 | 288 | private static final String SET_SHORT_SUPPORT_MESSAGE_KEY = "set_short_support_message";
|
@@ -333,6 +342,7 @@ public class PolicyManagementFragment extends BaseSearchablePolicyPreferenceFrag
|
333 | 342 |
|
334 | 343 | private GetAccessibilityServicesTask mGetAccessibilityServicesTask = null;
|
335 | 344 | private GetInputMethodsTask mGetInputMethodsTask = null;
|
| 345 | + private GetNotificationListenersTask mGetNotificationListenersTask = null; |
336 | 346 | private ShowCaCertificateListTask mShowCaCertificateListTask = null;
|
337 | 347 |
|
338 | 348 | private Uri mImageUri;
|
@@ -416,6 +426,8 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
416 | 426 | mEnableNetworkLoggingPreference.setOnPreferenceChangeListener(this);
|
417 | 427 | findPreference(SET_ACCESSIBILITY_SERVICES_KEY).setOnPreferenceClickListener(this);
|
418 | 428 | findPreference(SET_INPUT_METHODS_KEY).setOnPreferenceClickListener(this);
|
| 429 | + findPreference(SET_NOTIFICATION_LISTENERS_KEY).setOnPreferenceClickListener(this); |
| 430 | + findPreference(SET_NOTIFICATION_LISTENERS_TEXT_KEY).setOnPreferenceClickListener(this); |
419 | 431 | findPreference(SET_DISABLE_ACCOUNT_MANAGEMENT_KEY).setOnPreferenceClickListener(this);
|
420 | 432 | findPreference(GET_DISABLE_ACCOUNT_MANAGEMENT_KEY).setOnPreferenceClickListener(this);
|
421 | 433 | findPreference(ADD_ACCOUNT_KEY).setOnPreferenceClickListener(this);
|
@@ -600,6 +612,18 @@ public void onPositiveButtonClicked(String[] lockTaskArray) {
|
600 | 612 | mGetInputMethodsTask = new GetInputMethodsTask();
|
601 | 613 | mGetInputMethodsTask.execute();
|
602 | 614 | return true;
|
| 615 | + case SET_NOTIFICATION_LISTENERS_KEY: |
| 616 | + // Avoid starting the same task twice. |
| 617 | + if (mGetNotificationListenersTask != null |
| 618 | + && !mGetNotificationListenersTask.isCancelled()) { |
| 619 | + mGetNotificationListenersTask.cancel(true); |
| 620 | + } |
| 621 | + mGetNotificationListenersTask = new GetNotificationListenersTask(); |
| 622 | + mGetNotificationListenersTask.execute(); |
| 623 | + return true; |
| 624 | + case SET_NOTIFICATION_LISTENERS_TEXT_KEY: |
| 625 | + setNotificationWhitelistEditBox(); |
| 626 | + return true; |
603 | 627 | case SET_DISABLE_ACCOUNT_MANAGEMENT_KEY:
|
604 | 628 | showSetDisableAccountManagementPrompt();
|
605 | 629 | return true;
|
@@ -2288,6 +2312,101 @@ protected void setPermittedComponentsList(List<String> permittedInputMethods) {
|
2288 | 2312 | }
|
2289 | 2313 | }
|
2290 | 2314 |
|
| 2315 | + private void setNotificationWhitelistEditBox() { |
| 2316 | + if (getActivity() == null || getActivity().isFinishing()) { |
| 2317 | + return; |
| 2318 | + } |
| 2319 | + View view = getActivity().getLayoutInflater().inflate(R.layout.simple_edittext, null); |
| 2320 | + final EditText input = (EditText) view.findViewById(R.id.input); |
| 2321 | + input.setHint(getString(R.string.set_notification_listener_text_hint)); |
| 2322 | + List<String> enabledComponents = getPermittedNotificationListeners(); |
| 2323 | + if (enabledComponents == null) { |
| 2324 | + input.setText("null"); |
| 2325 | + } else { |
| 2326 | + input.setText(TextUtils.join(", ", enabledComponents)); |
| 2327 | + } |
| 2328 | + |
| 2329 | + new AlertDialog.Builder(getActivity()) |
| 2330 | + .setTitle(getString(R.string.set_notification_listener_text_hint)) |
| 2331 | + .setView(view) |
| 2332 | + .setPositiveButton(android.R.string.ok, |
| 2333 | + (DialogInterface dialog, int which) -> { |
| 2334 | + String packageNames = input.getText().toString(); |
| 2335 | + if (packageNames.trim().equals("null")) { |
| 2336 | + setPermittedNotificationListeners(null); |
| 2337 | + } else { |
| 2338 | + List<String> items = Arrays.asList( |
| 2339 | + packageNames.trim().split("\\s*,\\s*")); |
| 2340 | + setPermittedNotificationListeners(items); |
| 2341 | + } |
| 2342 | + dialog.dismiss(); |
| 2343 | + }) |
| 2344 | + .setNegativeButton(android.R.string.cancel, |
| 2345 | + (DialogInterface dialog, int which) -> dialog.dismiss()) |
| 2346 | + .show(); |
| 2347 | + } |
| 2348 | + |
| 2349 | + /** |
| 2350 | + * Gets all the NotificationListenerServices and displays them in a prompt. |
| 2351 | + */ |
| 2352 | + private class GetNotificationListenersTask extends GetAvailableComponentsTask<ResolveInfo> { |
| 2353 | + public GetNotificationListenersTask() { |
| 2354 | + super(getActivity(), R.string.set_notification_listeners); |
| 2355 | + } |
| 2356 | + |
| 2357 | + @Override |
| 2358 | + protected List<ResolveInfo> doInBackground(Void... voids) { |
| 2359 | + return mPackageManager.queryIntentServices( |
| 2360 | + new Intent(NotificationListenerService.SERVICE_INTERFACE), |
| 2361 | + PackageManager.GET_META_DATA | PackageManager.MATCH_UNINSTALLED_PACKAGES); |
| 2362 | + } |
| 2363 | + |
| 2364 | + @Override |
| 2365 | + protected List<ResolveInfo> getResolveInfoListFromAvailableComponents( |
| 2366 | + List<ResolveInfo> notificationListenerServices) { |
| 2367 | + return notificationListenerServices; |
| 2368 | + } |
| 2369 | + |
| 2370 | + @Override |
| 2371 | + protected List<String> getPermittedComponentsList() { |
| 2372 | + return getPermittedNotificationListeners(); |
| 2373 | + } |
| 2374 | + |
| 2375 | + @Override |
| 2376 | + protected void setPermittedComponentsList(List<String> permittedNotificationListeners) { |
| 2377 | + setPermittedNotificationListeners(permittedNotificationListeners); |
| 2378 | + } |
| 2379 | + } |
| 2380 | + |
| 2381 | + private void setPermittedNotificationListeners(List<String> permittedNotificationListeners) { |
| 2382 | + // STOPSHIP: Call actual method once in the SDK |
| 2383 | + boolean result; |
| 2384 | + try { |
| 2385 | + result = (boolean) ReflectionUtil.invoke(mDevicePolicyManager, |
| 2386 | + "setPermittedCrossProfileNotificationListeners", |
| 2387 | + new Class<?>[] {ComponentName.class, List.class}, |
| 2388 | + mAdminComponentName, permittedNotificationListeners); |
| 2389 | + } catch (ReflectionUtil.ReflectionIsTemporaryException e) { |
| 2390 | + Log.e(TAG, "Setting permitted notification listeners failed", e); |
| 2391 | + result = false; |
| 2392 | + } |
| 2393 | + int successMsgId = (permittedNotificationListeners == null) |
| 2394 | + ? R.string.all_notification_listeners_enabled |
| 2395 | + : R.string.set_notification_listeners_successful; |
| 2396 | + showToast(result ? successMsgId : R.string.set_notification_listeners_fail); |
| 2397 | + } |
| 2398 | + |
| 2399 | + private List<String> getPermittedNotificationListeners() { |
| 2400 | + // STOPSHIP: Call actual method once in the SDK |
| 2401 | + try { |
| 2402 | + return (List<String>) ReflectionUtil.invoke(mDevicePolicyManager, |
| 2403 | + "getPermittedCrossProfileNotificationListeners", mAdminComponentName); |
| 2404 | + } catch (ReflectionUtil.ReflectionIsTemporaryException e) { |
| 2405 | + Log.e(TAG, "Setting permitted notification listeners failed", e); |
| 2406 | + } |
| 2407 | + return null; |
| 2408 | + } |
| 2409 | + |
2291 | 2410 | /**
|
2292 | 2411 | * Gets all CA certificates and displays them in a prompt.
|
2293 | 2412 | */
|
|
0 commit comments