• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.cts.verifier.managedprovisioning;
18 
19 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_HOME;
20 import static android.app.admin.DevicePolicyManager.MAKE_USER_EPHEMERAL;
21 import static android.app.admin.DevicePolicyManager.SKIP_SETUP_WIZARD;
22 
23 import android.Manifest;
24 import android.app.Activity;
25 import android.app.ActivityManager;
26 import android.app.KeyguardManager;
27 import android.app.PendingIntent;
28 import android.app.admin.DevicePolicyManager;
29 import android.content.ComponentName;
30 import android.content.Context;
31 import android.content.Intent;
32 import android.content.IntentFilter;
33 import android.content.pm.ApplicationInfo;
34 import android.content.pm.PackageInstaller;
35 import android.content.pm.PackageManager;
36 import android.content.pm.ResolveInfo;
37 import android.graphics.BitmapFactory;
38 import android.net.ProxyInfo;
39 import android.os.Bundle;
40 import android.os.PersistableBundle;
41 import android.os.UserHandle;
42 import android.os.UserManager;
43 import android.provider.ContactsContract;
44 import android.provider.MediaStore;
45 import android.provider.Settings;
46 import android.util.Log;
47 import android.view.inputmethod.InputMethodInfo;
48 import android.view.inputmethod.InputMethodManager;
49 import android.widget.Toast;
50 
51 import com.android.bedstead.dpmwrapper.TestAppSystemServiceFactory;
52 import com.android.cts.verifier.R;
53 
54 import java.io.File;
55 import java.io.FileInputStream;
56 import java.io.InputStream;
57 import java.io.OutputStream;
58 import java.util.ArrayList;
59 import java.util.Collections;
60 import java.util.List;
61 import java.util.concurrent.TimeUnit;
62 import java.util.stream.Collectors;
63 
64 public class CommandReceiverActivity extends Activity {
65     private static final String TAG = "CommandReceiverActivity";
66 
67     public static final String ACTION_EXECUTE_COMMAND =
68             "com.android.cts.verifier.managedprovisioning.action.EXECUTE_COMMAND";
69     public static final String EXTRA_COMMAND =
70             "com.android.cts.verifier.managedprovisioning.extra.COMMAND";
71 
72     public static final String COMMAND_SET_USER_RESTRICTION = "set-user_restriction";
73     public static final String COMMAND_DISALLOW_KEYGUARD_UNREDACTED_NOTIFICATIONS =
74             "disallow-keyguard-unredacted-notifications";
75     public static final String COMMAND_SET_AUTO_TIME_REQUIRED = "set-auto-time-required";
76     public static final String COMMAND_SET_GLOBAL_SETTING =
77             "set-global-setting";
78     public static final String COMMAND_SET_MAXIMUM_TO_LOCK = "set-maximum-time-to-lock";
79     public static final String COMMAND_SET_KEYGUARD_DISABLED = "set-keyguard-disabled";
80     public static final String COMMAND_SET_LOCK_SCREEN_INFO = "set-lock-screen-info";
81     public static final String COMMAND_SET_STATUSBAR_DISABLED = "set-statusbar-disabled";
82     public static final String COMMAND_SET_LOCK_TASK_FEATURES = "set-lock-task-features";
83     public static final String COMMAND_ALLOW_ONLY_SYSTEM_INPUT_METHODS =
84             "allow-only-system-input-methods";
85     public static final String COMMAND_ALLOW_ONLY_SYSTEM_ACCESSIBILITY_SERVICES =
86             "allow-only-system-accessibility-services";
87     public static final String COMMAND_CLEAR_POLICIES = "clear-policies";
88     public static final String COMMAND_REMOVE_DEVICE_OWNER = "remove-device-owner";
89     public static final String COMMAND_REQUEST_BUGREPORT = "request-bugreport";
90     public static final String COMMAND_SET_USER_ICON = "set-user-icon";
91     public static final String COMMAND_RETRIEVE_NETWORK_LOGS = "retrieve-network-logs";
92     public static final String COMMAND_RETRIEVE_SECURITY_LOGS = "retrieve-security-logs";
93     public static final String COMMAND_SET_ORGANIZATION_NAME = "set-organization-name";
94     public static final String COMMAND_ENABLE_NETWORK_LOGGING = "enable-network-logging";
95     public static final String COMMAND_DISABLE_NETWORK_LOGGING = "disable-network-logging";
96     public static final String COMMAND_INSTALL_HELPER_PACKAGE = "install-helper-package";
97     public static final String COMMAND_UNINSTALL_HELPER_PACKAGE = "uninstall-helper-package";
98     public static final String COMMAND_SET_PERMISSION_GRANT_STATE = "set-permission-grant-state";
99     public static final String COMMAND_ADD_PERSISTENT_PREFERRED_ACTIVITIES =
100             "add-persistent-preferred-activities";
101     public static final String COMMAND_CLEAR_PERSISTENT_PREFERRED_ACTIVITIES =
102             "clear-persistent-preferred-activities";
103     public static final String COMMAND_CREATE_MANAGED_PROFILE = "create-managed-profile";
104     public static final String COMMAND_REMOVE_MANAGED_PROFILE = "remove-managed-profile";
105     public static final String COMMAND_SET_ALWAYS_ON_VPN = "set-always-on-vpn";
106     public static final String COMMAND_CLEAR_ALWAYS_ON_VPN = "clear-always-on-vpn";
107     public static final String COMMAND_SET_GLOBAL_HTTP_PROXY = "set-global-http-proxy";
108     public static final String COMMAND_CLEAR_GLOBAL_HTTP_PROXY = "clear-global-http-proxy";
109     public static final String COMMAND_INSTALL_CA_CERT = "install-ca-cert";
110     public static final String COMMAND_CLEAR_CA_CERT = "clear-ca-cert";
111     public static final String COMMAND_SET_MAXIMUM_PASSWORD_ATTEMPTS =
112             "set-maximum-password-attempts";
113     public static final String COMMAND_CLEAR_MAXIMUM_PASSWORD_ATTEMPTS =
114             "clear-maximum-password-attempts";
115     public static final String COMMAND_SET_DEFAULT_IME = "set-default-ime";
116     public static final String COMMAND_CLEAR_DEFAULT_IME = "clear-default-ime";
117     public static final String COMMAND_CREATE_MANAGED_USER = "create-managed-user";
118     public static final String COMMAND_CREATE_MANAGED_USER_WITHOUT_SETUP =
119             "create-managed-user-without-setup";
120     public static final String COMMAND_REMOVE_SECONDARY_USERS = "remove-secondary-users";
121     public static final String COMMAND_WITH_USER_SWITCHER_MESSAGE = "with-user-switcher-message";
122     public static final String COMMAND_WITHOUT_USER_SWITCHER_MESSAGE =
123             "without-user-switcher-message";
124     public static final String COMMAND_ENABLE_LOGOUT = "enable-logout";
125     public static final String COMMAND_DISABLE_USB_DATA_SIGNALING = "disable-usb-data-signaling";
126     public static final String COMMAND_ENABLE_USB_DATA_SIGNALING = "enable-usb-data-signaling";
127     public static final String COMMAND_SET_REQUIRED_PASSWORD_COMPLEXITY =
128             "set-required-password-complexity";
129 
130     public static final String EXTRA_USER_RESTRICTION =
131             "com.android.cts.verifier.managedprovisioning.extra.USER_RESTRICTION";
132     public static final String EXTRA_USE_CURRENT_USER_DPM =
133             "com.android.cts.verifier.managedprovisioning.extra.USE_CURRENT_USER_DPM";
134     public static final String EXTRA_SETTING =
135             "com.android.cts.verifier.managedprovisioning.extra.SETTING";
136     // This extra can be used along with a command extra to set policy to
137     // specify if that policy is enforced or not.
138     public static final String EXTRA_ENFORCED =
139             "com.android.cts.verifier.managedprovisioning.extra.ENFORCED";
140     public static final String EXTRA_VALUE =
141             "com.android.cts.verifier.managedprovisioning.extra.VALUE";
142     public static final String EXTRA_ORGANIZATION_NAME =
143             "com.android.cts.verifier.managedprovisioning.extra.ORGANIZATION_NAME";
144     public static final String EXTRA_PERMISSION =
145             "com.android.cts.verifier.managedprovisioning.extra.PERMISSION";
146     public static final String EXTRA_GRANT_STATE =
147             "com.android.cts.verifier.managedprovisioning.extra.GRANT_STATE";
148 
149     // We care about installing and uninstalling only. It does not matter what apk is used.
150     // NotificationBot.apk is a good choice because it comes bundled with the CTS verifier.
151     protected static final String HELPER_APP_LOCATION = "/sdcard/NotificationBot.apk";
152     protected static final String HELPER_APP_PKG = "com.android.cts.robot";
153 
154     public static final String ACTION_INSTALL_COMPLETE =
155             "com.android.cts.verifier.managedprovisioning.action.ACTION_INSTALL_COMPLETE";
156     public static final String ACTION_UNINSTALL_COMPLETE =
157             "com.android.cts.verifier.managedprovisioning.action.ACTION_UNINSTALL_COMPLETE";
158 
159     /*
160      * The CA cert below is the content of cacert.pem as generated by:
161      *
162      * openssl req -new -x509 -days 3650 -extensions v3_ca -keyout cakey.pem -out cacert.pem
163      */
164     private static final String TEST_CA =
165             "-----BEGIN CERTIFICATE-----\n" +
166             "MIIDXTCCAkWgAwIBAgIJAK9Tl/F9V8kSMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV\n" +
167             "BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX\n" +
168             "aWRnaXRzIFB0eSBMdGQwHhcNMTUwMzA2MTczMjExWhcNMjUwMzAzMTczMjExWjBF\n" +
169             "MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50\n" +
170             "ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\n" +
171             "CgKCAQEAvItOutsE75WBTgTyNAHt4JXQ3JoseaGqcC3WQij6vhrleWi5KJ0jh1/M\n" +
172             "Rpry7Fajtwwb4t8VZa0NuM2h2YALv52w1xivql88zce/HU1y7XzbXhxis9o6SCI+\n" +
173             "oVQSbPeXRgBPppFzBEh3ZqYTVhAqw451XhwdA4Aqs3wts7ddjwlUzyMdU44osCUg\n" +
174             "kVg7lfPf9sTm5IoHVcfLSCWH5n6Nr9sH3o2ksyTwxuOAvsN11F/a0mmUoPciYPp+\n" +
175             "q7DzQzdi7akRG601DZ4YVOwo6UITGvDyuAAdxl5isovUXqe6Jmz2/myTSpAKxGFs\n" +
176             "jk9oRoG6WXWB1kni490GIPjJ1OceyQIDAQABo1AwTjAdBgNVHQ4EFgQUH1QIlPKL\n" +
177             "p2OQ/AoLOjKvBW4zK3AwHwYDVR0jBBgwFoAUH1QIlPKLp2OQ/AoLOjKvBW4zK3Aw\n" +
178             "DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAcMi4voMMJHeQLjtq8Oky\n" +
179             "Azpyk8moDwgCd4llcGj7izOkIIFqq/lyqKdtykVKUWz2bSHO5cLrtaOCiBWVlaCV\n" +
180             "DYAnnVLM8aqaA6hJDIfaGs4zmwz0dY8hVMFCuCBiLWuPfiYtbEmjHGSmpQTG6Qxn\n" +
181             "ZJlaK5CZyt5pgh5EdNdvQmDEbKGmu0wpCq9qjZImwdyAul1t/B0DrsWApZMgZpeI\n" +
182             "d2od0VBrCICB1K4p+C51D93xyQiva7xQcCne+TAnGNy9+gjQ/MyR8MRpwRLv5ikD\n" +
183             "u0anJCN8pXo6IMglfMAsoton1J6o5/ae5uhC6caQU8bNUsCK570gpNfjkzo6rbP0\n" +
184             "wQ==\n" +
185             "-----END CERTIFICATE-----";
186 
187     private ComponentName mAdmin;
188     private DevicePolicyManager mDpm;
189     private UserManager mUm;
190     private ActivityManager mAm;
191 
192     @Override
onCreate(Bundle savedInstanceState)193     public void onCreate(Bundle savedInstanceState) {
194         super.onCreate(savedInstanceState);
195         final Intent intent = getIntent();
196         try {
197             // On phones, the test runs on user 0, which is the Device Owner, but on headless system
198             // user mode it runs in a different user.
199             // Most DPM operations must be set on device owner user, but a few - like adding user
200             // restrictions - must be set in the current user.
201             boolean forDeviceOwner = !intent.getBooleanExtra(EXTRA_USE_CURRENT_USER_DPM, false);
202             mDpm = TestAppSystemServiceFactory.getDevicePolicyManager(this,
203                             DeviceAdminTestReceiver.class, forDeviceOwner);
204 
205             mUm = getSystemService(UserManager.class);
206             mAm = getSystemService(ActivityManager.class);
207             mAdmin = DeviceAdminTestReceiver.getReceiverComponentName();
208             final String command = intent.getStringExtra(EXTRA_COMMAND);
209             Log.i(TAG, "Command: " + command + " forDeviceOwner: " + forDeviceOwner);
210             switch (command) {
211                 case COMMAND_SET_USER_RESTRICTION: {
212                     String restrictionKey = intent.getStringExtra(EXTRA_USER_RESTRICTION);
213                     boolean enforced = intent.getBooleanExtra(EXTRA_ENFORCED, false);
214                     Log.i(TAG, "Setting '" + restrictionKey + "'=" + enforced
215                             + " using " + mDpm + " for user "
216                             + (forDeviceOwner ? UserHandle.SYSTEM : UserHandle.myUserId()));
217                     if (enforced) {
218                         mDpm.addUserRestriction(mAdmin, restrictionKey);
219                     } else {
220                         mDpm.clearUserRestriction(mAdmin, restrictionKey);
221                     }
222                 } break;
223                 case COMMAND_DISALLOW_KEYGUARD_UNREDACTED_NOTIFICATIONS: {
224                     boolean enforced = intent.getBooleanExtra(EXTRA_ENFORCED, false);
225                     mDpm.setKeyguardDisabledFeatures(mAdmin, enforced
226                             ? DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS
227                             : 0);
228                 } break;
229                 case COMMAND_SET_AUTO_TIME_REQUIRED: {
230                     mDpm.setAutoTimeRequired(mAdmin,
231                             intent.getBooleanExtra(EXTRA_ENFORCED, false));
232                     break;
233                 }
234                 case COMMAND_SET_LOCK_SCREEN_INFO: {
235                     mDpm.setDeviceOwnerLockScreenInfo(mAdmin, intent.getStringExtra(EXTRA_VALUE));
236                     break;
237                 }
238                 case COMMAND_SET_MAXIMUM_TO_LOCK: {
239                     final long timeInSeconds = Long.parseLong(intent.getStringExtra(EXTRA_VALUE));
240                     mDpm.setMaximumTimeToLock(mAdmin,
241                             TimeUnit.SECONDS.toMillis(timeInSeconds) /* in milliseconds */);
242                 } break;
243                 case COMMAND_SET_KEYGUARD_DISABLED: {
244                     boolean enforced = intent.getBooleanExtra(EXTRA_ENFORCED, false);
245                     KeyguardManager km = this.getSystemService(KeyguardManager.class);
246                     if (km.isKeyguardSecure()) {
247                         Toast.makeText(this, getString(R.string.device_owner_lockscreen_secure),
248                                 Toast.LENGTH_SHORT).show();
249                     } else {
250                         mDpm.setKeyguardDisabled(mAdmin, enforced);
251                     }
252                 } break;
253                 case COMMAND_SET_STATUSBAR_DISABLED: {
254                     boolean enforced = intent.getBooleanExtra(EXTRA_ENFORCED, false);
255                     Log.d(TAG, "calling setStatusBarDisabled("
256                             + ComponentName.flattenToShortString(mAdmin) + ", " + enforced
257                             + ") using " + mDpm + " on user " + UserHandle.myUserId());
258                     mDpm.setStatusBarDisabled(mAdmin, enforced);
259                 } break;
260                 case COMMAND_SET_LOCK_TASK_FEATURES: {
261                     int flags = intent.getIntExtra(EXTRA_VALUE,
262                             DevicePolicyManager.LOCK_TASK_FEATURE_NONE);
263                     mDpm.setLockTaskFeatures(mAdmin, flags);
264                     // If feature HOME is used, we need to allow the current launcher
265                     if ((flags & LOCK_TASK_FEATURE_HOME) != 0) {
266                         mDpm.setLockTaskPackages(mAdmin,
267                                 new String[] {getPackageName(), getCurrentLauncherPackage()});
268                     } else {
269                         mDpm.setLockTaskPackages(mAdmin, new String[] {getPackageName()});
270                     }
271                 } break;
272                 case COMMAND_ALLOW_ONLY_SYSTEM_INPUT_METHODS: {
273                     boolean enforced = intent.getBooleanExtra(EXTRA_ENFORCED, false);
274                     mDpm.setPermittedInputMethods(mAdmin,
275                             enforced ? getEnabledNonSystemImes() : null);
276                 } break;
277                 case COMMAND_ALLOW_ONLY_SYSTEM_ACCESSIBILITY_SERVICES: {
278                     boolean enforced = intent.getBooleanExtra(EXTRA_ENFORCED, false);
279                     mDpm.setPermittedAccessibilityServices(mAdmin,
280                             enforced ? new ArrayList() : null);
281                 } break;
282                 case COMMAND_SET_GLOBAL_SETTING: {
283                     final String setting = intent.getStringExtra(EXTRA_SETTING);
284                     final String value = intent.getStringExtra(EXTRA_VALUE);
285                     Log.d(TAG, "Setting global property '" + setting + "' to '" + value
286                             + "' using " + mDpm);
287                     mDpm.setGlobalSetting(mAdmin, setting, value);
288                 } break;
289                 case COMMAND_REMOVE_DEVICE_OWNER: {
290                     if (!mDpm.isDeviceOwnerApp(getPackageName())) {
291                         Log.e(TAG, COMMAND_REMOVE_DEVICE_OWNER + ": " + getPackageName()
292                                 + " is not DO for user " + UserHandle.myUserId());
293                         return;
294                     }
295                     clearAllPoliciesAndRestrictions();
296                     Log.i(TAG, "Clearing device owner app " + getPackageName());
297                     mDpm.clearDeviceOwnerApp(getPackageName());
298 
299                     if (UserManager.isHeadlessSystemUserMode()) {
300                         Log.i(TAG, "Clearing profile owner app (" + mAdmin.flattenToString()
301                                 + " on user " + UserHandle.myUserId());
302                         DevicePolicyManager localDpm = getSystemService(DevicePolicyManager.class);
303                         localDpm.clearProfileOwner(mAdmin);
304                     }
305 
306                 } break;
307                 case COMMAND_REQUEST_BUGREPORT: {
308                     if (!mDpm.isDeviceOwnerApp(getPackageName())) {
309                         return;
310                     }
311                     final boolean bugreportStarted = mDpm.requestBugreport(mAdmin);
312                     if (!bugreportStarted) {
313                         Utils.showBugreportNotification(this, getString(
314                                 R.string.bugreport_already_in_progress),
315                                 Utils.BUGREPORT_NOTIFICATION_ID);
316                     }
317                 } break;
318                 case COMMAND_CLEAR_POLICIES: {
319                     int mode = intent.getIntExtra(PolicyTransparencyTestListActivity.EXTRA_MODE,
320                             PolicyTransparencyTestListActivity.MODE_DEVICE_OWNER);
321                     if (mode == PolicyTransparencyTestListActivity.MODE_DEVICE_OWNER) {
322                         if (!mDpm.isDeviceOwnerApp(getPackageName())) {
323                             return;
324                         }
325                         clearAllPoliciesAndRestrictions();
326                     } else if (mode == PolicyTransparencyTestListActivity.MODE_MANAGED_PROFILE
327                             || mode == PolicyTransparencyTestListActivity.MODE_MANAGED_USER) {
328                         if (!mDpm.isProfileOwnerApp(getPackageName())) {
329                             return;
330                         }
331                         clearProfileOwnerRelatedPoliciesAndRestrictions(mode);
332                     }
333                     // No policies need to be cleared for COMP at the moment.
334                 } break;
335                 case COMMAND_SET_USER_ICON: {
336                     if (!mDpm.isDeviceOwnerApp(getPackageName())) {
337                         return;
338                     }
339                     int iconRes = intent.getIntExtra(EXTRA_VALUE,
340                             com.android.cts.verifier.R.drawable.icon);
341                     mDpm.setUserIcon(mAdmin, BitmapFactory.decodeResource(getResources(), iconRes));
342                 } break;
343                 case COMMAND_RETRIEVE_NETWORK_LOGS: {
344                     if (!mDpm.isDeviceOwnerApp(getPackageName())) {
345                         return;
346                     }
347                     mDpm.setNetworkLoggingEnabled(mAdmin, true);
348                     mDpm.retrieveNetworkLogs(mAdmin, 0 /* batchToken */);
349                     mDpm.setNetworkLoggingEnabled(mAdmin, false);
350                 } break;
351                 case COMMAND_RETRIEVE_SECURITY_LOGS: {
352                     if (!mDpm.isDeviceOwnerApp(getPackageName())) {
353                         return;
354                     }
355                     mDpm.setSecurityLoggingEnabled(mAdmin, true);
356                     mDpm.retrieveSecurityLogs(mAdmin);
357                     mDpm.setSecurityLoggingEnabled(mAdmin, false);
358                 } break;
359                 case COMMAND_SET_ORGANIZATION_NAME: {
360                     if (!mDpm.isDeviceOwnerApp(getPackageName())) {
361                         return;
362                     }
363                     mDpm.setOrganizationName(mAdmin,
364                             intent.getStringExtra(EXTRA_ORGANIZATION_NAME));
365                 } break;
366                 case COMMAND_ENABLE_NETWORK_LOGGING: {
367                     if (!mDpm.isDeviceOwnerApp(getPackageName())) {
368                         return;
369                     }
370                     mDpm.setNetworkLoggingEnabled(mAdmin, true);
371                 } break;
372                 case COMMAND_DISABLE_NETWORK_LOGGING: {
373                     if (!mDpm.isDeviceOwnerApp(getPackageName())) {
374                         return;
375                     }
376                     mDpm.setNetworkLoggingEnabled(mAdmin, false);
377                 } break;
378                 case COMMAND_INSTALL_HELPER_PACKAGE: {
379                     installHelperPackage();
380                 } break;
381                 case COMMAND_UNINSTALL_HELPER_PACKAGE: {
382                     uninstallHelperPackage();
383                 } break;
384                 case COMMAND_SET_PERMISSION_GRANT_STATE: {
385                     Log.d(TAG, "Granting permission using " + mDpm);
386                     mDpm.setPermissionGrantState(mAdmin, getPackageName(),
387                             intent.getStringExtra(EXTRA_PERMISSION),
388                             intent.getIntExtra(EXTRA_GRANT_STATE,
389                                     DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT));
390                 } break;
391                 case COMMAND_ADD_PERSISTENT_PREFERRED_ACTIVITIES: {
392                     final ComponentName componentName =
393                             EnterprisePrivacyTestDefaultAppActivity.COMPONENT_NAME;
394                     IntentFilter filter;
395                     // Camera
396                     filter = new IntentFilter();
397                     filter.addAction(MediaStore.ACTION_IMAGE_CAPTURE);
398                     filter.addAction(MediaStore.ACTION_VIDEO_CAPTURE);
399                     mDpm.addPersistentPreferredActivity(mAdmin, filter, componentName);
400                     // Map
401                     filter = new IntentFilter();
402                     filter.addAction(Intent.ACTION_VIEW);
403                     filter.addDataScheme("geo");
404                     mDpm.addPersistentPreferredActivity(mAdmin, filter, componentName);
405                     // E-mail
406                     filter = new IntentFilter();
407                     filter.addAction(Intent.ACTION_SENDTO);
408                     filter.addAction(Intent.ACTION_SEND);
409                     filter.addAction(Intent.ACTION_SEND_MULTIPLE);
410                     mDpm.addPersistentPreferredActivity(mAdmin, filter, componentName);
411                     // Calendar
412                     filter = new IntentFilter();
413                     filter.addAction(Intent.ACTION_INSERT);
414                     filter.addDataType("vnd.android.cursor.dir/event");
415                     mDpm.addPersistentPreferredActivity(mAdmin, filter, componentName);
416                     // Contacts
417                     filter = new IntentFilter();
418                     filter.addAction(Intent.ACTION_PICK);
419                     filter.addDataType(ContactsContract.Contacts.CONTENT_TYPE);
420                     mDpm.addPersistentPreferredActivity(mAdmin, filter, componentName);
421                     // Dialer
422                     filter = new IntentFilter();
423                     filter.addAction(Intent.ACTION_DIAL);
424                     filter.addAction(Intent.ACTION_CALL);
425                     mDpm.addPersistentPreferredActivity(mAdmin, filter, componentName);
426                     getPackageManager().setComponentEnabledSetting(componentName,
427                             PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
428                             PackageManager.DONT_KILL_APP);
429                 } break;
430                 case COMMAND_CLEAR_PERSISTENT_PREFERRED_ACTIVITIES: {
431                     mDpm.clearPackagePersistentPreferredActivities(mAdmin, getPackageName());
432                     getPackageManager().setComponentEnabledSetting(
433                             EnterprisePrivacyTestDefaultAppActivity.COMPONENT_NAME,
434                             PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
435                             PackageManager.DONT_KILL_APP);
436                 } break;
437                 case COMMAND_SET_ALWAYS_ON_VPN: {
438                     if (!mDpm.isDeviceOwnerApp(getPackageName())) {
439                         return;
440                     }
441                     mDpm.setAlwaysOnVpnPackage(mAdmin, getPackageName(),
442                             false /* lockdownEnabled */);
443                 } break;
444                 case COMMAND_CLEAR_ALWAYS_ON_VPN: {
445                     if (!mDpm.isDeviceOwnerApp(getPackageName())) {
446                         return;
447                     }
448                     mDpm.setAlwaysOnVpnPackage(mAdmin, null /* vpnPackage */,
449                             false /* lockdownEnabled */);
450                 } break;
451                 case COMMAND_SET_GLOBAL_HTTP_PROXY: {
452                     if (!mDpm.isDeviceOwnerApp(getPackageName())) {
453                         return;
454                     }
455                     mDpm.setRecommendedGlobalProxy(mAdmin,
456                             ProxyInfo.buildDirectProxy("example.com", 123));
457                 } break;
458                 case COMMAND_CLEAR_GLOBAL_HTTP_PROXY: {
459                     if (!mDpm.isDeviceOwnerApp(getPackageName())) {
460                         return;
461                     }
462                     mDpm.setRecommendedGlobalProxy(mAdmin, null);
463                 } break;
464                 case COMMAND_INSTALL_CA_CERT: {
465                     if (!mDpm.isDeviceOwnerApp(getPackageName())) {
466                         return;
467                     }
468                     mDpm.installCaCert(mAdmin, TEST_CA.getBytes());
469                 } break;
470                 case COMMAND_CLEAR_CA_CERT: {
471                     if (!mDpm.isDeviceOwnerApp(getPackageName())) {
472                         return;
473                     }
474                     mDpm.uninstallCaCert(mAdmin, TEST_CA.getBytes());
475                 } break;
476                 case COMMAND_SET_MAXIMUM_PASSWORD_ATTEMPTS: {
477                     if (!isDeviceOwner()) return;
478                     int max = 100;
479                     Log.d(TAG, "Setting maximum password attempts to " + max + " using" + mDpm);
480                     mDpm.setMaximumFailedPasswordsForWipe(mAdmin, max);
481                 } break;
482                 case COMMAND_CLEAR_MAXIMUM_PASSWORD_ATTEMPTS: {
483                     if (!isDeviceOwner()) return;
484                     Log.d(TAG, "Clearing maximum password attempts using" + mDpm);
485                     mDpm.setMaximumFailedPasswordsForWipe(mAdmin, 0);
486                 } break;
487                 case COMMAND_SET_DEFAULT_IME: {
488                     if (!isDeviceOwner()) return;
489                     Log.d(TAG, "Setting " + Settings.Secure.DEFAULT_INPUT_METHOD + " using "
490                             + mDpm);
491                     mDpm.setSecureSetting(mAdmin, Settings.Secure.DEFAULT_INPUT_METHOD,
492                             getPackageName());
493                 } break;
494                 case COMMAND_CLEAR_DEFAULT_IME: {
495                     if (!isDeviceOwner()) return;
496                     Log.d(TAG, "Clearing " + Settings.Secure.DEFAULT_INPUT_METHOD + " using "
497                             + mDpm);
498                     mDpm.setSecureSetting(mAdmin, Settings.Secure.DEFAULT_INPUT_METHOD, null);
499                 } break;
500                 case COMMAND_CREATE_MANAGED_USER:{
501                     if (!mDpm.isDeviceOwnerApp(getPackageName())) {
502                         return;
503                     }
504                     PersistableBundle extras = new PersistableBundle();
505                     extras.putBoolean(DeviceAdminTestReceiver.EXTRA_MANAGED_USER_TEST, true);
506                     UserHandle userHandle = mDpm.createAndManageUser(mAdmin, "managed user", mAdmin,
507                             extras,
508                             SKIP_SETUP_WIZARD | MAKE_USER_EPHEMERAL);
509                     Log.i(TAG, "Created user " + userHandle + "; setting affiliation ids to "
510                             + DeviceAdminTestReceiver.AFFILIATION_ID);
511                     mDpm.setAffiliationIds(mAdmin,
512                             Collections.singleton(DeviceAdminTestReceiver.AFFILIATION_ID));
513                     // TODO(b/204483021): move to helper class / restore after user is logged out
514                     if (UserManager.isHeadlessSystemUserMode()) {
515                         mAm.setStopUserOnSwitch(ActivityManager.STOP_USER_ON_SWITCH_FALSE);
516                     }
517                     Log.d(TAG, "Starting user " + userHandle);
518                     mDpm.startUserInBackground(mAdmin, userHandle);
519                 } break;
520                 case COMMAND_CREATE_MANAGED_USER_WITHOUT_SETUP:{
521                     if (!mDpm.isDeviceOwnerApp(getPackageName())) {
522                         return;
523                     }
524                     PersistableBundle extras = new PersistableBundle();
525                     extras.putBoolean(DeviceAdminTestReceiver.EXTRA_MANAGED_USER_TEST, true);
526                     mDpm.createAndManageUser(mAdmin, "managed user", mAdmin, extras, /* flags */ 0);
527                 } break;
528                 case COMMAND_REMOVE_SECONDARY_USERS: {
529                     if (!mDpm.isDeviceOwnerApp(getPackageName())) {
530                         return;
531                     }
532                     for (UserHandle secondaryUser : mDpm.getSecondaryUsers(mAdmin)) {
533                         mDpm.removeUser(mAdmin, secondaryUser);
534                     }
535                 } break;
536                 case COMMAND_WITH_USER_SWITCHER_MESSAGE: {
537                     createAndSwitchUserWithMessage("Start user session", "End user session");
538                 } break;
539                 case COMMAND_WITHOUT_USER_SWITCHER_MESSAGE: {
540                     createAndSwitchUserWithMessage(null, null);
541                 } break;
542                 case COMMAND_ENABLE_LOGOUT: {
543                     if (!mDpm.isDeviceOwnerApp(getPackageName())) {
544                         return;
545                     }
546                     mDpm.addUserRestriction(mAdmin, UserManager.DISALLOW_USER_SWITCH);
547                     mDpm.setLogoutEnabled(mAdmin, true);
548                     UserHandle userHandle = mDpm.createAndManageUser(mAdmin, "managed user", mAdmin,
549                             null, SKIP_SETUP_WIZARD | MAKE_USER_EPHEMERAL);
550                     mDpm.switchUser(mAdmin, userHandle);
551                 } break;
552                 case COMMAND_DISABLE_USB_DATA_SIGNALING: {
553                     mDpm.setUsbDataSignalingEnabled(false);
554                     break;
555                 }
556                 case COMMAND_ENABLE_USB_DATA_SIGNALING: {
557                     mDpm.setUsbDataSignalingEnabled(true);
558                     break;
559                 }
560                 case COMMAND_SET_REQUIRED_PASSWORD_COMPLEXITY: {
561                     int complexity = intent.getIntExtra(EXTRA_VALUE,
562                             DevicePolicyManager.PASSWORD_COMPLEXITY_NONE);
563                     mDpm.setRequiredPasswordComplexity(complexity);
564                 }
565             }
566         } catch (Exception e) {
567             Log.e(TAG, "Failed to execute command: " + intent, e);
568         } finally {
569             finish();
570         }
571     }
572 
573     /**
574      * Checks if {@code CtsVerifier} is the device owner.
575      */
isDeviceOwner()576     private boolean isDeviceOwner() {
577         // Cannot use mDpm as it would be the DPM of the current user on headless system user mode,
578         // which would return false
579         DevicePolicyManager dpm = TestAppSystemServiceFactory.getDevicePolicyManager(this,
580                 DeviceAdminTestReceiver.class, /* forDeviceOwner= */ true);
581         boolean isIt = dpm.isDeviceOwnerApp(getPackageName());
582         Log.v(TAG, "is " + getPackageName() + " DO, using " + dpm + "? " + isIt);
583         return isIt;
584     }
585 
installHelperPackage()586     private void installHelperPackage() throws Exception {
587         if (UserManager.isHeadlessSystemUserMode()) {
588             // App was already installed on user 0 (as instructed), so we just install it for the
589             // current user - installing directly to current user would be harder as it would
590             // require a custom ContentProvider to push the APK into a secondary user using adb
591             Log.i(TAG, "installing existing helper app (" + HELPER_APP_PKG + ") using " + mDpm);
592             mDpm.installExistingPackage(mAdmin, HELPER_APP_PKG);
593             return;
594         }
595         LogAndSelfUnregisterBroadcastReceiver.register(this, ACTION_INSTALL_COMPLETE);
596         final PackageInstaller packageInstaller = getPackageManager().getPackageInstaller();
597         final PackageInstaller.Session session = packageInstaller.openSession(
598                 packageInstaller.createSession(new PackageInstaller.SessionParams(
599                         PackageInstaller.SessionParams.MODE_FULL_INSTALL)));
600         final File file = new File(HELPER_APP_LOCATION);
601         Log.i(TAG, "installing helper package from " + file);
602         final InputStream in = new FileInputStream(file);
603         final OutputStream out = session.openWrite("CommandReceiverActivity", 0, file.length());
604         final byte[] buffer = new byte[65536];
605         int count;
606         while ((count = in.read(buffer)) != -1) {
607             out.write(buffer, 0, count);
608         }
609         session.fsync(out);
610         in.close();
611         out.close();
612         session.commit(PendingIntent
613                 .getBroadcast(this, 0, new Intent(ACTION_INSTALL_COMPLETE),
614                         PendingIntent.FLAG_MUTABLE_UNAUDITED)
615                 .getIntentSender());
616     }
617 
uninstallHelperPackage()618     private void uninstallHelperPackage() {
619         LogAndSelfUnregisterBroadcastReceiver.register(this, ACTION_UNINSTALL_COMPLETE);
620         PackageInstaller packageInstaller = getPackageManager().getPackageInstaller();
621         Log.i(TAG, "Uninstalling package " + HELPER_APP_PKG + " using " + packageInstaller);
622         try {
623             packageInstaller.uninstall(HELPER_APP_PKG, PendingIntent.getBroadcast(this,
624                     /* requestCode= */ 0, new Intent(ACTION_UNINSTALL_COMPLETE),
625                     PendingIntent.FLAG_MUTABLE_UNAUDITED).getIntentSender());
626         } catch (IllegalArgumentException e) {
627             // The package is not installed: that's fine
628         }
629     }
630 
clearAllPoliciesAndRestrictions()631     private void clearAllPoliciesAndRestrictions() throws Exception {
632         Log.d(TAG, "clearAllPoliciesAndRestrictions() started");
633         clearProfileOwnerRelatedPolicies();
634         clearPolicyTransparencyUserRestriction(
635                 PolicyTransparencyTestListActivity.MODE_DEVICE_OWNER);
636 
637         // There are a few user restrictions that are used, but not for policy transparency
638         mDpm.clearUserRestriction(mAdmin, UserManager.DISALLOW_CONFIG_BLUETOOTH);
639         mDpm.clearUserRestriction(mAdmin, UserManager.DISALLOW_CONFIG_VPN);
640         mDpm.clearUserRestriction(mAdmin, UserManager.DISALLOW_DATA_ROAMING);
641         mDpm.clearUserRestriction(mAdmin, UserManager.DISALLOW_USER_SWITCH);
642 
643         mDpm.setDeviceOwnerLockScreenInfo(mAdmin, null);
644         mDpm.setKeyguardDisabled(mAdmin, false);
645         mDpm.setAutoTimeRequired(mAdmin, false);
646         mDpm.setStatusBarDisabled(mAdmin, false);
647         mDpm.setOrganizationName(mAdmin, null);
648         mDpm.setNetworkLoggingEnabled(mAdmin, false);
649         mDpm.setSecurityLoggingEnabled(mAdmin, false);
650         mDpm.setPermissionGrantState(mAdmin, getPackageName(),
651                 Manifest.permission.ACCESS_FINE_LOCATION,
652                 DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);
653         mDpm.setPermissionGrantState(mAdmin, getPackageName(), Manifest.permission.RECORD_AUDIO,
654                 DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);
655         mDpm.setPermissionGrantState(mAdmin, getPackageName(), Manifest.permission.CAMERA,
656                 DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);
657         mDpm.clearPackagePersistentPreferredActivities(mAdmin, getPackageName());
658         mDpm.setAlwaysOnVpnPackage(mAdmin, null, false);
659         mDpm.setRecommendedGlobalProxy(mAdmin, null);
660         mDpm.uninstallCaCert(mAdmin, TEST_CA.getBytes());
661         mDpm.setMaximumFailedPasswordsForWipe(mAdmin, 0);
662         mDpm.setSecureSetting(mAdmin, Settings.Secure.DEFAULT_INPUT_METHOD, null);
663         mDpm.setStartUserSessionMessage(mAdmin, null);
664         mDpm.setEndUserSessionMessage(mAdmin, null);
665         mDpm.setLogoutEnabled(mAdmin, false);
666 
667         uninstallHelperPackage();
668 
669         // Must wait until package is uninstalled to reset affiliation ids, otherwise the package
670         // cannot be removed on headless system user mode (as caller must be an affiliated PO)
671         Log.d(TAG, "resetting affiliation ids");
672         mDpm.setAffiliationIds(mAdmin, Collections.emptySet());
673 
674         removeManagedProfile();
675         getPackageManager().setComponentEnabledSetting(
676                 EnterprisePrivacyTestDefaultAppActivity.COMPONENT_NAME,
677                 PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
678                 PackageManager.DONT_KILL_APP);
679         Log.d(TAG, "clearAllPoliciesAndRestrictions() finished");
680     }
681 
clearProfileOwnerRelatedPoliciesAndRestrictions(int mode)682     private void clearProfileOwnerRelatedPoliciesAndRestrictions(int mode) {
683         clearPolicyTransparencyUserRestriction(mode);
684         clearProfileOwnerRelatedPolicies();
685     }
686 
clearProfileOwnerRelatedPolicies()687     private void clearProfileOwnerRelatedPolicies() {
688         Log.d(TAG, "clearProfileOwnerRelatedPolicies() started");
689         mDpm.setKeyguardDisabledFeatures(mAdmin, 0);
690         mDpm.setPasswordQuality(mAdmin, 0);
691         mDpm.setMaximumTimeToLock(mAdmin, 0);
692         mDpm.setPermittedAccessibilityServices(mAdmin, null);
693         mDpm.setPermittedInputMethods(mAdmin, null);
694         Log.d(TAG, "clearProfileOwnerRelatedPolicies() finished");
695     }
696 
clearPolicyTransparencyUserRestriction(int mode)697     private void clearPolicyTransparencyUserRestriction(int mode) {
698         for (String userRestriction : UserRestrictions.getUserRestrictionsForPolicyTransparency(
699                 mode)) {
700             mDpm.clearUserRestriction(mAdmin, userRestriction);
701         }
702     }
703 
removeManagedProfile()704     private void removeManagedProfile() {
705         for (UserHandle userHandle : mUm.getUserProfiles()) {
706             Log.d(TAG, "removing managed profile for " + userHandle);
707             mDpm.removeUser(mAdmin, userHandle);
708         }
709     }
710 
711     /**
712      * Creates an intent to set the given user restriction using the device owner's {@code dpm}.
713      */
createSetDeviceOwnerUserRestrictionIntent(String restriction, boolean enforced)714     public static Intent createSetDeviceOwnerUserRestrictionIntent(String restriction,
715             boolean enforced) {
716         return createSetUserRestrictionIntent(restriction, enforced, /* currentUserDpm= */ false);
717     }
718 
719     /**
720      * Creates an intent to set the given user restriction using the current user's {@code dpm}.
721      */
createSetCurrentUserRestrictionIntent(String restriction, boolean enforced)722     public static Intent createSetCurrentUserRestrictionIntent(String restriction,
723             boolean enforced) {
724         return createSetUserRestrictionIntent(restriction, enforced, /* currentUserDpm= */ true);
725     }
726 
createSetUserRestrictionIntent(String restriction, boolean enforced, boolean forceCurrentUserDpm)727     private static Intent createSetUserRestrictionIntent(String restriction, boolean enforced,
728             boolean forceCurrentUserDpm) {
729         Log.d(TAG, "createSetUserRestrictionIntent(): restriction=" + restriction
730                 + ", enforced=" + enforced + ", forceCurrentUserDpm=" + forceCurrentUserDpm);
731         Intent intent = new Intent(ACTION_EXECUTE_COMMAND);
732         if (forceCurrentUserDpm) {
733             intent.putExtra(EXTRA_USE_CURRENT_USER_DPM, true);
734         }
735         return intent
736                 .putExtra(EXTRA_COMMAND, COMMAND_SET_USER_RESTRICTION)
737                 .putExtra(EXTRA_USER_RESTRICTION, restriction)
738                 .putExtra(EXTRA_ENFORCED, enforced);
739     }
740 
getEnabledNonSystemImes()741     private List<String> getEnabledNonSystemImes() {
742         InputMethodManager inputMethodManager = getSystemService(InputMethodManager.class);
743         final List<InputMethodInfo> inputMethods = inputMethodManager.getEnabledInputMethodList();
744         return inputMethods.stream()
745                 .filter(inputMethodInfo -> !isSystemInputMethodInfo(inputMethodInfo))
746                 .map(inputMethodInfo -> inputMethodInfo.getPackageName())
747                 .filter(packageName -> !packageName.equals(getPackageName()))
748                 .distinct()
749                 .collect(Collectors.toList());
750     }
751 
isSystemInputMethodInfo(InputMethodInfo inputMethodInfo)752     private boolean isSystemInputMethodInfo(InputMethodInfo inputMethodInfo) {
753         final ApplicationInfo applicationInfo = inputMethodInfo.getServiceInfo().applicationInfo;
754         return (applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
755     }
756 
createAndSwitchUserWithMessage(String startUserSessionMessage, String endUserSessionMessage)757     private void createAndSwitchUserWithMessage(String startUserSessionMessage,
758             String endUserSessionMessage) {
759         if (!mDpm.isDeviceOwnerApp(getPackageName())) {
760             return;
761         }
762         mDpm.setStartUserSessionMessage(mAdmin, startUserSessionMessage);
763         mDpm.setEndUserSessionMessage(mAdmin, endUserSessionMessage);
764         mDpm.setAffiliationIds(mAdmin,
765                 Collections.singleton(DeviceAdminTestReceiver.AFFILIATION_ID));
766 
767         PersistableBundle extras = new PersistableBundle();
768         extras.putBoolean(DeviceAdminTestReceiver.EXTRA_LOGOUT_ON_START, true);
769         UserHandle userHandle = mDpm.createAndManageUser(mAdmin, "managed user", mAdmin,
770                 extras,
771                 SKIP_SETUP_WIZARD | MAKE_USER_EPHEMERAL);
772         // TODO(b/204483021): move to helper class / restore after user is logged out
773         if (UserManager.isHeadlessSystemUserMode()) {
774             mAm.setStopUserOnSwitch(ActivityManager.STOP_USER_ON_SWITCH_FALSE);
775         }
776         Log.d(TAG, "Switching to user " + userHandle);
777         mDpm.switchUser(mAdmin, userHandle);
778     }
779 
getCurrentLauncherPackage()780     private String getCurrentLauncherPackage() {
781         ResolveInfo resolveInfo = getPackageManager()
782             .resolveActivity(new Intent(Intent.ACTION_MAIN)
783                 .addCategory(Intent.CATEGORY_HOME), PackageManager.MATCH_DEFAULT_ONLY);
784         if (resolveInfo == null || resolveInfo.activityInfo == null) {
785             return null;
786         }
787 
788         return resolveInfo.activityInfo.packageName;
789     }
790 
createIntentForDisablingKeyguardOrStatusBar(Context context, String command, boolean disabled)791     static Intent createIntentForDisablingKeyguardOrStatusBar(Context context, String command,
792             boolean disabled) {
793         return new Intent(context, CommandReceiverActivity.class)
794                 .putExtra(CommandReceiverActivity.EXTRA_USE_CURRENT_USER_DPM, true)
795                 .putExtra(CommandReceiverActivity.EXTRA_COMMAND, command)
796                 .putExtra(CommandReceiverActivity.EXTRA_ENFORCED, disabled);
797     }
798 }
799