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