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