1 /* 2 * Copyright (C) 2012 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.content.Intent.FLAG_ACTIVITY_NEW_TASK; 20 21 import android.app.KeyguardManager; 22 import android.app.admin.DevicePolicyManager; 23 import android.content.ActivityNotFoundException; 24 import android.content.BroadcastReceiver; 25 import android.content.ComponentName; 26 import android.content.Context; 27 import android.content.Intent; 28 import android.content.SharedPreferences; 29 import android.content.pm.PackageManager; 30 import android.net.ConnectivityManager; 31 import android.os.Bundle; 32 import android.os.Handler; 33 import android.os.Looper; 34 import android.provider.Settings; 35 import android.util.Log; 36 import android.widget.Toast; 37 38 import com.android.cts.verifier.ArrayTestListAdapter; 39 import com.android.cts.verifier.DialogTestListActivity; 40 import com.android.cts.verifier.R; 41 import com.android.cts.verifier.TestListActivity; 42 import com.android.cts.verifier.TestListAdapter.TestListItem; 43 import com.android.cts.verifier.TestResult; 44 45 /** 46 * CTS verifier test for BYOD managed provisioning flow 47 * 48 * This activity is responsible for starting the managed provisioning flow and verify the outcome of 49 * provisioning. It performs the following verifications: 50 * Full disk encryption is enabled. 51 * Profile owner is correctly installed. 52 * Profile owner shows up in the Settings app. 53 * Badged work apps show up in launcher. 54 * The first two verifications are performed automatically, by interacting with profile owner using 55 * cross-profile intents, while the last two are carried out manually by the user. 56 */ 57 public class ByodFlowTestActivity extends DialogTestListActivity { 58 59 // Action for delivering sub-test result from the profile. 60 public static final String ACTION_TEST_RESULT = 61 "com.android.cts.verifier.managedprovisioning.BYOD_TEST_RESULT"; 62 // Extra for ACTION_TEST_RESULT containing test result. 63 public static final String EXTRA_RESULT = "extra-result"; 64 protected static final String HELPER_APP_PATH = "/data/local/tmp/NotificationBot.apk"; 65 66 private static final String TAG = "ByodFlowTestActivity"; 67 private static final int PROVISIONING_CHECK_PERIOD_MS = 3000; 68 private static ConnectivityManager mCm; 69 private static final int REQUEST_MANAGED_PROVISIONING = 0; 70 private static final int REQUEST_PROFILE_OWNER_STATUS = 1; 71 private static final int REQUEST_INTENT_FILTERS_STATUS = 2; 72 private static final int REQUEST_CHECK_DISK_ENCRYPTION = 3; 73 private static final int REQUEST_SET_LOCK_FOR_ENCRYPTION = 4; 74 private static final int REQUEST_DELETE_MANAGED_PROFILE = 5; 75 76 private static final String PROVISIONING_PREFERENCES = "provisioning_preferences"; 77 private static final String PREFERENCE_PROVISIONING_COMPLETE_STATUS = 78 "provisioning_complete_status"; 79 private static final int PREFERENCE_PROVISIONING_COMPLETE_STATUS_NOT_RECEIVED = 0; 80 private static final int PREFERENCE_PROVISIONING_COMPLETE_STATUS_RECEIVED = 1; 81 private static final int PREFERENCE_PROVISIONING_COMPLETE_STATUS_PROCESSED = 2; 82 83 private ComponentName mAdminReceiverComponent; 84 private KeyguardManager mKeyguardManager; 85 private ByodFlowTestHelper mByodFlowTestHelper; 86 87 private DialogTestListItem mProfileOwnerInstalled; 88 private DialogTestListItem mDiskEncryptionTest; 89 private DialogTestListItem mWorkAppVisibleTest; 90 private DialogTestListItem mCrossProfileIntentFiltersTestFromPersonal; 91 private DialogTestListItem mCrossProfileIntentFiltersTestFromWork; 92 private TestListItem mCrossProfilePermissionControl; 93 private TestListItem mNonMarketAppsTest; 94 private DialogTestListItem mUserSettingsVisibleTest; 95 private DialogTestListItem mAppSettingsVisibleTest; 96 private DialogTestListItem mLocationSettingsVisibleTest; 97 private DialogTestListItem mWiFiDataUsageSettingsVisibleTest; 98 private DialogTestListItem mCellularDataUsageSettingsVisibleTest; 99 private DialogTestListItem mCredSettingsVisibleTest; 100 private DialogTestListItem mAllowNonDismissibleNotificationTest; 101 private DialogTestListItem mPrintSettingsVisibleTest; 102 private DialogTestListItem mIntentFiltersTest; 103 private DialogTestListItem mPermissionLockdownTest; 104 private DialogTestListItem mCrossProfileImageCaptureSupportTest; 105 private DialogTestListItem mCrossProfileMotionPhotoCaptureSupportTest; 106 private DialogTestListItem mCrossProfileVideoCaptureWithExtraOutputSupportTest; 107 private DialogTestListItem mCrossProfileVideoCaptureWithoutExtraOutputSupportTest; 108 private DialogTestListItem mCrossProfileAudioCaptureSupportTest; 109 private TestListItem mKeyguardDisabledFeaturesTest; 110 private TestListItem mAuthenticationBoundKeyTest; 111 private TestListItem mEnableLocationModeTest; 112 private TestListItem mDisableLocationModeThroughMainSwitchTest; 113 private TestListItem mDisableLocationModeThroughWorkSwitchTest; 114 private TestListItem mPrimaryLocationWhenWorkDisabledTest; 115 private DialogTestListItem mSelectWorkChallenge; 116 private DialogTestListItem mConfirmWorkCredentials; 117 private DialogTestListItem mPatternWorkChallenge; 118 private DialogTestListItem mParentProfilePassword; 119 private DialogTestListItem mPersonalRingtonesTest; 120 private TestListItem mScreenshotTest; 121 private TestListItem mVpnTest; 122 private TestListItem mKeyChainTest; 123 private TestListItem mAlwaysOnVpnSettingsTest; 124 private TestListItem mRecentsTest; 125 private TestListItem mDisallowAppsControlTest; 126 private TestListItem mOrganizationInfoTest; 127 private TestListItem mPolicyTransparencyTest; 128 private TestListItem mTurnOffWorkFeaturesTest; 129 private TestListItem mWidgetTest; 130 private final Handler mHandler = new Handler(Looper.myLooper()); 131 132 private final Runnable mPeriodicProvisioningCheckRunnable = new Runnable() { 133 @Override 134 public void run() { 135 if (isProvisioningCompleteBroadcastReceived(getApplicationContext())) { 136 markProvisioningCompleteBroadcastProcessed(getApplicationContext()); 137 queryProfileOwner(true); 138 } else { 139 mHandler.postDelayed(this, PROVISIONING_CHECK_PERIOD_MS); 140 } 141 } 142 }; 143 144 public static class ProvisioningCompleteReceiver extends BroadcastReceiver { 145 @Override onReceive(Context context, Intent intent)146 public void onReceive(Context context, Intent intent) { 147 markProvisioningCompleteBroadcastReceived(context); 148 } 149 } 150 ByodFlowTestActivity()151 public ByodFlowTestActivity() { 152 super(R.layout.provisioning_byod, 153 R.string.provisioning_byod, R.string.provisioning_byod_info, 154 R.string.provisioning_byod_instructions); 155 } 156 157 @Override onCreate(Bundle savedInstanceState)158 protected void onCreate(Bundle savedInstanceState) { 159 super.onCreate(savedInstanceState); 160 mByodFlowTestHelper = new ByodFlowTestHelper(this); 161 mAdminReceiverComponent = new ComponentName(this, DeviceAdminTestReceiver.class.getName()); 162 mKeyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE); 163 164 mByodFlowTestHelper.setup(); 165 166 mPrepareTestButton.setText(R.string.provisioning_byod_start); 167 mPrepareTestButton.setOnClickListener(v -> Utils.provisionManagedProfile( 168 ByodFlowTestActivity.this, mAdminReceiverComponent, 169 REQUEST_MANAGED_PROVISIONING)); 170 171 // If we are started by managed provisioning (fresh managed provisioning after encryption 172 // reboot), redirect the user back to the main test list. This is because the test result 173 // is only saved by the parent TestListActivity, and if we did allow the user to proceed 174 // here, the test result would be lost when this activity finishes. 175 if (ByodHelperActivity.ACTION_PROFILE_OWNER_STATUS.equals(getIntent().getAction())) { 176 startActivity(new Intent(this, TestListActivity.class)); 177 // Calling super.finish() because we delete managed profile in our overridden of finish(), 178 // which is not what we want to do here. 179 super.finish(); 180 } else { 181 queryProfileOwner(false); 182 } 183 } 184 185 @Override onStart()186 protected void onStart() { 187 super.onStart(); 188 startPeriodicProvisioningCheckIfNecessary(); 189 } 190 startPeriodicProvisioningCheckIfNecessary()191 private void startPeriodicProvisioningCheckIfNecessary() { 192 if (mHandler.hasCallbacks(mPeriodicProvisioningCheckRunnable)) { 193 return; 194 } 195 if (!isProvisioningCompleteBroadcastProcessed(this)) { 196 mHandler.post(mPeriodicProvisioningCheckRunnable); 197 } 198 } 199 200 @Override onStop()201 protected void onStop() { 202 super.onStop(); 203 mHandler.removeCallbacks(mPeriodicProvisioningCheckRunnable); 204 } 205 206 @Override onNewIntent(Intent intent)207 protected void onNewIntent(Intent intent) { 208 super.onNewIntent(intent); 209 if (ByodHelperActivity.ACTION_PROFILE_OWNER_STATUS.equals(intent.getAction())) { 210 // This is called when managed provisioning completes successfully without reboot. 211 handleStatusUpdate(RESULT_OK, intent); 212 } else if (ACTION_TEST_RESULT.equals(intent.getAction())) { 213 // Called when subtest cannot communicate test result from the profile via setResult(). 214 handleLaunchTestResult(RESULT_OK, intent.getParcelableExtra(EXTRA_RESULT)); 215 } 216 } 217 218 @Override handleActivityResult(int requestCode, int resultCode, Intent data)219 protected void handleActivityResult(int requestCode, int resultCode, Intent data) { 220 switch (requestCode) { 221 case REQUEST_MANAGED_PROVISIONING: 222 return; 223 case REQUEST_PROFILE_OWNER_STATUS: 224 // Called after queryProfileOwner() 225 handleStatusUpdate(resultCode, data); 226 break; 227 case REQUEST_CHECK_DISK_ENCRYPTION: 228 // Called after checkDiskEncryption() 229 handleDiskEncryptionStatus(resultCode, data); 230 break; 231 case REQUEST_SET_LOCK_FOR_ENCRYPTION: 232 // Called after handleDiskEncryptionStatus() to set screen lock if necessary 233 handleSetLockForEncryption(); 234 break; 235 case REQUEST_INTENT_FILTERS_STATUS: 236 // Called after checkIntentFilters() 237 handleIntentFiltersStatus(resultCode); 238 break; 239 case REQUEST_DELETE_MANAGED_PROFILE: 240 // Called during finish() 241 finishAfterProfileDeleted(); 242 break; 243 default: 244 super.handleActivityResult(requestCode, resultCode, data); 245 } 246 } 247 handleStatusUpdate(int resultCode, Intent data)248 private void handleStatusUpdate(int resultCode, Intent data) { 249 boolean provisioned = data != null && 250 data.getBooleanExtra(ByodHelperActivity.EXTRA_PROVISIONED, false); 251 setProfileOwnerTestResult((provisioned && resultCode == RESULT_OK) ? 252 TestResult.TEST_RESULT_PASSED : TestResult.TEST_RESULT_FAILED); 253 } 254 255 @Override finish()256 public void finish() { 257 // Pass and fail buttons are known to call finish() when clicked, and this is when we want to 258 // clean up the provisioned profile. 259 Intent intent = new Intent(ByodHelperActivity.ACTION_REMOVE_MANAGED_PROFILE); 260 // Wait until the managed profile is deleted before returning to the previous 261 // activity, to ensure the deletion is not interrupted. 262 startActivityForResult(intent, REQUEST_DELETE_MANAGED_PROFILE); 263 } 264 finishAfterProfileDeleted()265 private void finishAfterProfileDeleted() { 266 mByodFlowTestHelper.tearDown(); 267 super.finish(); 268 } 269 270 @Override setupTests(ArrayTestListAdapter adapter)271 protected void setupTests(ArrayTestListAdapter adapter) { 272 mProfileOwnerInstalled = new DialogTestListItem(this, 273 R.string.provisioning_byod_profileowner, 274 "BYOD_ProfileOwnerInstalled") { 275 @Override 276 public void performTest(DialogTestListActivity activity) { 277 queryProfileOwner(true); 278 } 279 }; 280 281 mDiskEncryptionTest = new DialogTestListItem(this, 282 R.string.provisioning_byod_disk_encryption, 283 "BYOD_DiskEncryptionTest") { 284 @Override 285 public void performTest(DialogTestListActivity activity) { 286 checkDiskEncryption(); 287 } 288 }; 289 290 /* 291 * To keep the image in this test up to date, use the instructions in 292 * {@link ByodIconSamplerActivity}. 293 */ 294 295 if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) { 296 mWorkAppVisibleTest = new DialogTestListItemWithIcon(this, 297 R.string.provisioning_byod_workapps_visible, 298 "BYOD_WorkAppVisibleTest", 299 R.string.provisioning_byod_workapps_visible_instruction, 300 new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME), 301 R.drawable.badged_icon); 302 303 mConfirmWorkCredentials = new DialogTestListItem(this, 304 R.string.provisioning_byod_confirm_work_credentials, 305 "BYOD_ConfirmWorkCredentials", 306 R.string.provisioning_byod_confirm_work_credentials_description, 307 new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME)); 308 309 mPatternWorkChallenge = new DialogTestListItem(this, 310 R.string.provisioning_byod_pattern_work_challenge, 311 "BYOD_PatternWorkChallenge", 312 R.string.provisioning_byod_pattern_work_challenge_description, 313 new Intent(ByodHelperActivity.ACTION_TEST_PATTERN_WORK_CHALLENGE)); 314 315 mWiFiDataUsageSettingsVisibleTest = new DialogTestListItem(this, 316 R.string.provisioning_byod_wifi_data_usage_settings, 317 "BYOD_WiFiDataUsageSettingsVisibleTest", 318 R.string.provisioning_byod_wifi_data_usage_settings_instruction, 319 new Intent(Settings.ACTION_SETTINGS)); 320 } 321 322 /* Disable due to b/111734436. 323 Intent workStatusToast = new Intent(WorkStatusTestActivity.ACTION_WORK_STATUS_TOAST); 324 workStatusToast.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 325 mWorkStatusBarToastTest = new DialogTestListItem(this, 326 R.string.provisioning_byod_work_status_toast, 327 "BYOD_WorkStatusBarToastTest", 328 R.string.provisioning_byod_work_status_toast_instruction, 329 workStatusToast); 330 */ 331 332 mNonMarketAppsTest = TestListItem.newTest(this, 333 R.string.provisioning_byod_non_market_apps, 334 NonMarketAppsActivity.class.getName(), 335 new Intent(this, NonMarketAppsActivity.class), null); 336 337 mUserSettingsVisibleTest = new DialogTestListItem(this, 338 R.string.provisioning_byod_user_settings, 339 "BYOD_UserSettingsVisibleTest", 340 R.string.provisioning_byod_user_settings_instruction, 341 new Intent(Settings.ACTION_SETTINGS)); 342 343 mAppSettingsVisibleTest = new DialogTestListItem(this, 344 R.string.provisioning_byod_app_settings, 345 "BYOD_AppSettingsVisibleTest", 346 R.string.provisioning_byod_app_settings_instruction, 347 new Intent(Settings.ACTION_APPLICATION_SETTINGS)); 348 349 mCredSettingsVisibleTest = new DialogTestListItem(this, 350 R.string.provisioning_byod_cred_settings, 351 "BYOD_CredSettingsVisibleTest", 352 R.string.provisioning_byod_cred_settings_instruction, 353 new Intent(Settings.ACTION_SECURITY_SETTINGS)); 354 355 mAllowNonDismissibleNotificationTest = new DialogTestListItem(this, 356 R.string.provisioning_byod_allow_nondismissible_notification, 357 "BYOD_AllowNonDismissibleNotificationTest", 358 R.string.provisioning_byod_allow_nondismissible_notification_instructions, 359 new Intent(this, NotificationActivity.class)); 360 361 mLocationSettingsVisibleTest = new DialogTestListItem(this, 362 R.string.provisioning_byod_location_settings, 363 "BYOD_LocationSettingsVisibleTest", 364 R.string.provisioning_byod_location_settings_instruction, 365 new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)); 366 367 mCellularDataUsageSettingsVisibleTest = new DialogTestListItem(this, 368 R.string.provisioning_byod_cellular_data_usage_settings, 369 "BYOD_CellularDataUsageSettingsVisibleTest", 370 R.string.provisioning_byod_cellular_data_usage_settings_instruction, 371 new Intent(Settings.ACTION_SETTINGS)); 372 373 mPrintSettingsVisibleTest = new DialogTestListItem(this, 374 R.string.provisioning_byod_print_settings, 375 "BYOD_PrintSettingsVisibleTest", 376 R.string.provisioning_byod_print_settings_instruction, 377 new Intent(Settings.ACTION_PRINT_SETTINGS)); 378 379 Intent intent = new Intent(CrossProfileTestActivity.ACTION_CROSS_PROFILE_TO_WORK); 380 intent.putExtra(CrossProfileTestActivity.EXTRA_STARTED_FROM_WORK, false); 381 Intent chooser = Intent.createChooser(intent, 382 getResources().getString(R.string.provisioning_cross_profile_chooser)); 383 mCrossProfileIntentFiltersTestFromPersonal = new DialogTestListItem(this, 384 R.string.provisioning_byod_cross_profile_from_personal, 385 "BYOD_CrossProfileIntentFiltersTestFromPersonal", 386 R.string.provisioning_byod_cross_profile_from_personal_instruction, 387 chooser); 388 389 mCrossProfileIntentFiltersTestFromWork = new DialogTestListItem(this, 390 R.string.provisioning_byod_cross_profile_from_work, 391 "BYOD_CrossProfileIntentFiltersTestFromWork", 392 R.string.provisioning_byod_cross_profile_from_work_instruction, 393 new Intent(ByodHelperActivity.ACTION_TEST_CROSS_PROFILE_INTENTS_DIALOG)); 394 395 /* Disable due to b/33571176 396 mAppLinkingTest = new DialogTestListItem(this, 397 R.string.provisioning_app_linking, 398 "BYOD_AppLinking", 399 R.string.provisioning_byod_app_linking_instruction, 400 new Intent(ByodHelperActivity.ACTION_TEST_APP_LINKING_DIALOG)); 401 */ 402 403 mKeyguardDisabledFeaturesTest = TestListItem.newTest(this, 404 R.string.provisioning_byod_keyguard_disabled_features, 405 KeyguardDisabledFeaturesActivity.class.getName(), 406 new Intent(this, KeyguardDisabledFeaturesActivity.class), null); 407 408 mAuthenticationBoundKeyTest = TestListItem.newTest(this, 409 R.string.provisioning_byod_auth_bound_key, 410 AuthenticationBoundKeyTestActivity.class.getName(), 411 new Intent(AuthenticationBoundKeyTestActivity.ACTION_AUTH_BOUND_KEY_TEST), 412 null); 413 414 mVpnTest = TestListItem.newTest(this, 415 R.string.provisioning_byod_vpn, 416 VpnTestActivity.class.getName(), 417 new Intent(VpnTestActivity.ACTION_VPN), 418 null); 419 420 mAlwaysOnVpnSettingsTest = TestListItem.newTest(this, 421 R.string.provisioning_byod_always_on_vpn, 422 AlwaysOnVpnSettingsTestActivity.class.getName(), 423 new Intent(AlwaysOnVpnSettingsTestActivity.ACTION_ALWAYS_ON_VPN_SETTINGS_TEST), 424 null); 425 426 mDisallowAppsControlTest = TestListItem.newTest(this, 427 R.string.provisioning_byod_disallow_apps_control, 428 DisallowAppsControlActivity.class.getName(), 429 new Intent(this, DisallowAppsControlActivity.class), null); 430 431 // Test for checking if the required intent filters are set during managed provisioning. 432 mIntentFiltersTest = new DialogTestListItem(this, 433 R.string.provisioning_byod_cross_profile_intent_filters, 434 "BYOD_IntentFiltersTest") { 435 @Override 436 public void performTest(DialogTestListActivity activity) { 437 checkIntentFilters(); 438 } 439 }; 440 441 mCrossProfilePermissionControl = TestListItem.newTest(this, 442 R.string.provisioning_byod_cross_profile_permission_control, 443 CrossProfilePermissionControlActivity.class.getName(), 444 new Intent( 445 CrossProfilePermissionControlActivity.ACTION_CROSS_PROFILE_PERMISSION_CONTROL), 446 null); 447 448 mTurnOffWorkFeaturesTest = TestListItem.newTest(this, 449 R.string.provisioning_byod_turn_off_work, 450 TurnOffWorkActivity.class.getName(), 451 new Intent(this, TurnOffWorkActivity.class), null); 452 453 Intent permissionCheckIntent = new Intent( 454 PermissionLockdownTestActivity.ACTION_MANAGED_PROFILE_CHECK_PERMISSION_LOCKDOWN); 455 mPermissionLockdownTest = new DialogTestListItem(this, 456 R.string.device_profile_owner_permission_lockdown_test, 457 "BYOD_PermissionLockdownTest", 458 R.string.profile_owner_permission_lockdown_test_info, 459 permissionCheckIntent); 460 461 mSelectWorkChallenge = new DialogTestListItem(this, 462 R.string.provisioning_byod_select_work_challenge, 463 "BYOD_SelectWorkChallenge", 464 R.string.provisioning_byod_select_work_challenge_description, 465 new Intent(ByodHelperActivity.ACTION_TEST_SELECT_WORK_CHALLENGE)); 466 467 mRecentsTest = TestListItem.newTest(this, 468 R.string.provisioning_byod_recents, 469 RecentsRedactionActivity.class.getName(), 470 new Intent(RecentsRedactionActivity.ACTION_RECENTS).setFlags( 471 FLAG_ACTIVITY_NEW_TASK), 472 null); 473 474 mOrganizationInfoTest = TestListItem.newTest(this, 475 R.string.provisioning_byod_organization_info, 476 OrganizationInfoTestActivity.class.getName(), 477 new Intent(this, OrganizationInfoTestActivity.class), 478 null); 479 480 mKeyChainTest = TestListItem.newTest(this, 481 R.string.provisioning_byod_keychain, 482 KeyChainTestActivity.class.getName(), 483 new Intent(KeyChainTestActivity.ACTION_KEYCHAIN), 484 null); 485 486 mParentProfilePassword = new DialogTestListItem(this, 487 R.string.provisioning_byod_parent_profile_password, 488 "BYOD_ParentProfilePasswordTest", 489 R.string.provisioning_byod_parent_profile_password_description, 490 new Intent(ByodHelperActivity.ACTION_TEST_PARENT_PROFILE_PASSWORD)); 491 492 mPersonalRingtonesTest = new DialogTestListItem(this, 493 R.string.provisioning_byod_personal_ringtones, 494 "BYOD_PersonalRingtones", 495 R.string.provisioning_byod_personal_ringtones_instruction, 496 new Intent(Settings.ACTION_SOUND_SETTINGS)); 497 498 mScreenshotTest = TestListItem.newTest(/* context= */ this, 499 R.string.provisioning_byod_screenshot, 500 ScreenshotTestActivity.class.getName(), 501 new Intent(ScreenshotTestActivity.ACTION_SCREENSHOT_TEST), 502 /* requiredFeatures= */ null); 503 504 final Intent policyTransparencyTestIntent = new Intent(this, 505 PolicyTransparencyTestListActivity.class); 506 policyTransparencyTestIntent.putExtra( 507 PolicyTransparencyTestListActivity.EXTRA_MODE, 508 PolicyTransparencyTestListActivity.MODE_MANAGED_PROFILE); 509 policyTransparencyTestIntent.putExtra( 510 PolicyTransparencyTestActivity.EXTRA_TEST_ID, "BYOD_PolicyTransparency"); 511 mPolicyTransparencyTest = TestListItem.newTest(this, 512 R.string.device_profile_owner_policy_transparency_test, 513 "BYOD_PolicyTransparency", 514 policyTransparencyTestIntent, null); 515 516 adapter.add(mProfileOwnerInstalled); 517 adapter.add(mDiskEncryptionTest); 518 519 // Badge related tests 520 if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) { 521 adapter.add(mWorkAppVisibleTest); 522 } 523 524 /* Disable due to b/111734436. 525 adapter.add(mWorkStatusBarToastTest); 526 */ 527 528 // Settings related tests. 529 adapter.add(mCredSettingsVisibleTest); 530 adapter.add(mUserSettingsVisibleTest); 531 adapter.add(mAppSettingsVisibleTest); 532 adapter.add(mLocationSettingsVisibleTest); 533 adapter.add(mPrintSettingsVisibleTest); 534 adapter.add(mPersonalRingtonesTest); 535 536 adapter.add(mCrossProfileIntentFiltersTestFromPersonal); 537 adapter.add(mCrossProfileIntentFiltersTestFromWork); 538 /* Disable due to b/33571176 539 adapter.add(mAppLinkingTest); 540 */ 541 adapter.add(mIntentFiltersTest); 542 adapter.add(mCrossProfilePermissionControl); 543 adapter.add(mNonMarketAppsTest); 544 adapter.add(mPermissionLockdownTest); 545 adapter.add(mKeyguardDisabledFeaturesTest); 546 adapter.add(mAuthenticationBoundKeyTest); 547 adapter.add(mVpnTest); 548 adapter.add(mAlwaysOnVpnSettingsTest); 549 adapter.add(mTurnOffWorkFeaturesTest); 550 adapter.add(mSelectWorkChallenge); 551 if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) { 552 adapter.add(mConfirmWorkCredentials); 553 adapter.add(mPatternWorkChallenge); 554 } 555 adapter.add(mRecentsTest); 556 adapter.add(mOrganizationInfoTest); 557 adapter.add(mParentProfilePassword); 558 adapter.add(mPolicyTransparencyTest); 559 560 if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) { 561 if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI)) { 562 adapter.add(mWiFiDataUsageSettingsVisibleTest); 563 } 564 } 565 566 mCm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); 567 if(mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) != null) { 568 adapter.add(mCellularDataUsageSettingsVisibleTest); 569 } 570 571 if (canResolveIntent(new Intent(Settings.ACTION_APPLICATION_SETTINGS))) { 572 adapter.add(mDisallowAppsControlTest); 573 } 574 575 /* If there is an application that handles ACTION_IMAGE_CAPTURE, test that it handles it 576 * well. 577 */ 578 if (canResolveIntent(ByodHelperActivity.getCaptureImageIntent())) { 579 // Capture image intent can be resolved in primary profile, so test. 580 mCrossProfileImageCaptureSupportTest = new DialogTestListItem(this, 581 R.string.provisioning_byod_capture_image_support, 582 "BYOD_CrossProfileImageCaptureSupportTest", 583 R.string.provisioning_byod_capture_image_support_info, 584 new Intent(ByodHelperActivity.ACTION_CAPTURE_AND_CHECK_IMAGE)); 585 adapter.add(mCrossProfileImageCaptureSupportTest); 586 } else { 587 // Capture image intent cannot be resolved in primary profile, so skip test. 588 Toast.makeText(ByodFlowTestActivity.this, 589 R.string.provisioning_byod_no_image_capture_resolver, Toast.LENGTH_SHORT) 590 .show(); 591 } 592 593 /* If there is an application that handles ACTION_VIDEO_CAPTURE, test that it handles it 594 * well. 595 */ 596 if (canResolveIntent(ByodHelperActivity.getCaptureVideoIntent())) { 597 // Capture video intent can be resolved in primary profile, so test. 598 mCrossProfileVideoCaptureWithExtraOutputSupportTest = new DialogTestListItem(this, 599 R.string.provisioning_byod_capture_video_support_with_extra_output, 600 "BYOD_CrossProfileVideoCaptureWithExtraOutputSupportTest", 601 R.string.provisioning_byod_capture_video_support_info, 602 new Intent(ByodHelperActivity.ACTION_CAPTURE_AND_CHECK_VIDEO_WITH_EXTRA_OUTPUT)); 603 adapter.add(mCrossProfileVideoCaptureWithExtraOutputSupportTest); 604 mCrossProfileVideoCaptureWithoutExtraOutputSupportTest = new DialogTestListItem(this, 605 R.string.provisioning_byod_capture_video_support_without_extra_output, 606 "BYOD_CrossProfileVideoCaptureWithoutExtraOutputSupportTest", 607 R.string.provisioning_byod_capture_video_support_info, 608 new Intent(ByodHelperActivity.ACTION_CAPTURE_AND_CHECK_VIDEO_WITHOUT_EXTRA_OUTPUT)); 609 adapter.add(mCrossProfileVideoCaptureWithoutExtraOutputSupportTest); 610 } else { 611 // Capture video intent cannot be resolved in primary profile, so skip test. 612 Toast.makeText(ByodFlowTestActivity.this, 613 R.string.provisioning_byod_no_video_capture_resolver, Toast.LENGTH_SHORT) 614 .show(); 615 } 616 617 /* If there is an application that handles ACTION_MOTION_PHOTO_CAPTURE, test that it handles 618 * it well. 619 */ 620 if (com.android.providers.media.flags.Flags.motionPhotoIntent()) { 621 if (canResolveIntent(ByodHelperActivity.getCaptureMotionPhotoIntent())) { 622 // Capture motion photo intent can be resolved in primary profile, so test. 623 mCrossProfileMotionPhotoCaptureSupportTest = new DialogTestListItem(this, 624 R.string.provisioning_byod_capture_motion_photo_support, 625 "BYOD_CrossProfileMotionPhotoCaptureSupportTest", 626 R.string.provisioning_byod_capture_motion_photo_support_info, 627 new Intent(ByodHelperActivity.ACTION_CAPTURE_AND_CHECK_MOTION_PHOTO)); 628 adapter.add(mCrossProfileMotionPhotoCaptureSupportTest); 629 } else { 630 // Capture motion photo intent cannot be resolved in primary profile, so skip test. 631 Toast.makeText(ByodFlowTestActivity.this, 632 R.string.provisioning_byod_no_motion_photo_capture_resolver, 633 Toast.LENGTH_SHORT) 634 .show(); 635 } 636 } 637 638 adapter.add(mKeyChainTest); 639 640 /* If there is an application that handles RECORD_SOUND_ACTION, test that it handles it 641 * well. 642 */ 643 if (canResolveIntent(ByodHelperActivity.getCaptureAudioIntent())) { 644 // Capture audio intent can be resolved in primary profile, so test. 645 mCrossProfileAudioCaptureSupportTest = new DialogTestListItem(this, 646 R.string.provisioning_byod_capture_audio_support, 647 "BYOD_CrossProfileAudioCaptureSupportTest", 648 R.string.provisioning_byod_capture_audio_support_info, 649 new Intent(ByodHelperActivity.ACTION_CAPTURE_AND_CHECK_AUDIO)); 650 adapter.add(mCrossProfileAudioCaptureSupportTest); 651 } else { 652 // Capture audio intent cannot be resolved in primary profile, so skip test. 653 Toast.makeText(ByodFlowTestActivity.this, 654 R.string.provisioning_byod_no_audio_capture_resolver, Toast.LENGTH_SHORT) 655 .show(); 656 } 657 658 if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_LOCATION_GPS)) { 659 mEnableLocationModeTest = TestListItem.newTest(this, 660 R.string.provisioning_byod_location_mode_enable, 661 LocationTestActivity.TEST_ID_LOCATION_ENABLED, 662 new Intent(LocationTestActivity.ACTION_TEST_LOCATION_ENABLED), 663 null); 664 mDisableLocationModeThroughMainSwitchTest = TestListItem.newTest(this, 665 R.string.provisioning_byod_location_mode_disable, 666 LocationTestActivity.TEST_ID_LOCATION_DISABLED, 667 new Intent(LocationTestActivity.ACTION_TEST_LOCATION_DISABLED), 668 null); 669 mDisableLocationModeThroughWorkSwitchTest = TestListItem.newTest(this, 670 R.string.provisioning_byod_work_location_mode_disable, 671 LocationTestActivity.TEST_ID_WORK_LOCATION_DISABLED, 672 new Intent(LocationTestActivity.ACTION_TEST_WORK_LOCATION_DISABLED), 673 null); 674 mPrimaryLocationWhenWorkDisabledTest = TestListItem.newTest(this, 675 R.string.provisioning_byod_primary_location_when_work_disabled, 676 LocationTestActivity.TEST_ID_WORK_LOCATION_DISABLED_PRIMARY, 677 new Intent(LocationTestActivity.ACTION_TEST_WORK_LOCATION_DISABLED_PRIMARY), 678 null); 679 adapter.add(mEnableLocationModeTest); 680 adapter.add(mDisableLocationModeThroughMainSwitchTest); 681 adapter.add(mDisableLocationModeThroughWorkSwitchTest); 682 adapter.add(mPrimaryLocationWhenWorkDisabledTest); 683 } else { 684 // The system does not support GPS feature, so skip test. 685 Toast.makeText(ByodFlowTestActivity.this, 686 R.string.provisioning_byod_no_gps_location_feature, Toast.LENGTH_SHORT) 687 .show(); 688 } 689 690 if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS)) { 691 mWidgetTest = TestListItem.newTest(this, 692 R.string.provisioning_byod_work_profile_widget, 693 WorkProfileWidgetActivity.class.getName(), 694 new Intent(WorkProfileWidgetActivity.ACTION_TEST_WORK_PROFILE_WIDGET), 695 new String[]{PackageManager.FEATURE_APP_WIDGETS}); 696 adapter.add(mWidgetTest); 697 } 698 699 adapter.add(new DialogTestListItem(this, 700 R.string.provisioning_byod_uninstall_work_app, 701 "BYOD_UninstallWorkApp", 702 R.string.provisioning_byod_uninstall_work_app_instruction, 703 createInstallWorkProfileAppIntent())); 704 705 adapter.add(new DialogTestListItem(this, 706 R.string.provisioning_byod_launch_work_tab, 707 "BYOD_LaunchWorkTab", 708 R.string.provisioning_byod_launch_work_tab_instruction, 709 createLaunchWorkTabIntent())); 710 711 adapter.add(mScreenshotTest); 712 adapter.add(mAllowNonDismissibleNotificationTest); 713 } 714 createInstallWorkProfileAppIntent()715 private Intent createInstallWorkProfileAppIntent() { 716 // We place the APK file in /data/local/tmp to make it visible from the work profile. 717 return new Intent(ByodHelperActivity.ACTION_INSTALL_APK) 718 .putExtra(ByodHelperActivity.EXTRA_ALLOW_NON_MARKET_APPS, true) 719 .putExtra(ByodHelperActivity.EXTRA_PARAMETER_1, HELPER_APP_PATH); 720 } 721 createLaunchWorkTabIntent()722 private Intent createLaunchWorkTabIntent() { 723 return new Intent(Intent.ACTION_SHOW_WORK_APPS) 724 .addCategory(Intent.CATEGORY_HOME) 725 .addCategory(Intent.CATEGORY_LAUNCHER_APP) 726 .addFlags(FLAG_ACTIVITY_NEW_TASK); 727 } 728 729 // Return whether the intent can be resolved in the current profile canResolveIntent(Intent intent)730 private boolean canResolveIntent(Intent intent) { 731 return intent.resolveActivity(getPackageManager()) != null; 732 } 733 734 @Override clearRemainingState(final DialogTestListItem test)735 protected void clearRemainingState(final DialogTestListItem test) { 736 super.clearRemainingState(test); 737 if (ByodHelperActivity.ACTION_NOTIFICATION.equals( 738 test.getManualTestIntent().getAction())) { 739 try { 740 startActivity(new Intent( 741 ByodHelperActivity.ACTION_CLEAR_NOTIFICATION)); 742 } catch (ActivityNotFoundException e) { 743 // User shouldn't run this test before work profile is set up. 744 } 745 } 746 } 747 queryProfileOwner(boolean showToast)748 private void queryProfileOwner(boolean showToast) { 749 try { 750 // Set execution start time for counting test execution time. 751 mStartTime = System.currentTimeMillis(); 752 Intent intent = new Intent(ByodHelperActivity.ACTION_QUERY_PROFILE_OWNER); 753 startActivityForResult(intent, REQUEST_PROFILE_OWNER_STATUS); 754 } 755 catch (ActivityNotFoundException e) { 756 Log.d(TAG, "queryProfileOwner: ActivityNotFoundException", e); 757 setProfileOwnerTestResult(TestResult.TEST_RESULT_FAILED); 758 if (showToast) { 759 Utils.showToast(this, R.string.provisioning_byod_no_activity); 760 } 761 } 762 } 763 setProfileOwnerTestResult(int result)764 private void setProfileOwnerTestResult(int result) { 765 setTestResult(mProfileOwnerInstalled, result); 766 if (result == TestResult.TEST_RESULT_FAILED) { 767 clearProvisioningCompleteBroadcastStatus(this); 768 startPeriodicProvisioningCheckIfNecessary(); 769 } 770 } 771 checkDiskEncryption()772 private void checkDiskEncryption() { 773 try { 774 Intent intent = new Intent(ByodHelperActivity.ACTION_CHECK_DISK_ENCRYPTION); 775 startActivityForResult(intent, REQUEST_CHECK_DISK_ENCRYPTION); 776 } catch (ActivityNotFoundException e) { 777 Log.d(TAG, "checkDiskEncryption: ActivityNotFoundException", e); 778 setTestResult(mDiskEncryptionTest, TestResult.TEST_RESULT_FAILED); 779 Utils.showToast(this, R.string.provisioning_byod_no_activity); 780 } 781 } 782 handleDiskEncryptionStatus(int resultCode, Intent data)783 private void handleDiskEncryptionStatus(int resultCode, Intent data) { 784 if (resultCode != RESULT_OK || data == null) { 785 Log.e(TAG, "Failed to get result for disk encryption, result code: " + resultCode); 786 setTestResult(mDiskEncryptionTest, TestResult.TEST_RESULT_FAILED); 787 return; 788 } 789 790 final int status = data.getIntExtra(ByodHelperActivity.EXTRA_ENCRYPTION_STATUS, 791 DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED); 792 switch (status) { 793 case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE: 794 case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER: 795 setTestResult(mDiskEncryptionTest, TestResult.TEST_RESULT_PASSED); 796 break; 797 case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY: 798 if (!mKeyguardManager.isDeviceSecure()) { 799 Utils.setScreenLock(this, REQUEST_SET_LOCK_FOR_ENCRYPTION); 800 return; 801 } 802 Log.e(TAG, "Disk encryption key is not entangled with lock screen credentials"); 803 Toast.makeText(this, R.string.provisioning_byod_disk_encryption_default_key_toast, 804 Toast.LENGTH_LONG).show(); 805 // fall through 806 default: 807 setTestResult(mDiskEncryptionTest, TestResult.TEST_RESULT_FAILED); 808 } 809 810 if (mKeyguardManager.isDeviceSecure()) { 811 Utils.removeScreenLock(this); 812 } 813 } 814 handleSetLockForEncryption()815 private void handleSetLockForEncryption() { 816 if (mKeyguardManager.isDeviceSecure()) { 817 checkDiskEncryption(); 818 } else { 819 setTestResult(mDiskEncryptionTest, TestResult.TEST_RESULT_FAILED); 820 Toast.makeText(this, R.string.provisioning_byod_disk_encryption_no_pin_toast, 821 Toast.LENGTH_LONG).show(); 822 } 823 } 824 checkIntentFilters()825 private void checkIntentFilters() { 826 try { 827 // Enable component HandleIntentActivity before intent filters are checked. 828 setHandleIntentActivityEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED); 829 // We disable the ByodHelperActivity in the primary profile. So, this intent 830 // will be handled by the ByodHelperActivity in the managed profile. 831 Intent intent = new Intent(ByodHelperActivity.ACTION_CHECK_INTENT_FILTERS); 832 startActivityForResult(intent, REQUEST_INTENT_FILTERS_STATUS); 833 } catch (ActivityNotFoundException e) { 834 // Disable component HandleIntentActivity if intent filters check fails. 835 setHandleIntentActivityEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED); 836 Log.d(TAG, "checkIntentFilters: ActivityNotFoundException", e); 837 setTestResult(mIntentFiltersTest, TestResult.TEST_RESULT_FAILED); 838 Utils.showToast(this, R.string.provisioning_byod_no_activity); 839 } 840 } 841 handleIntentFiltersStatus(int resultCode)842 private void handleIntentFiltersStatus(int resultCode) { 843 // Disable component HandleIntentActivity after intent filters are checked. 844 setHandleIntentActivityEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED); 845 // we use the resultCode from ByodHelperActivity in the managed profile to know if certain 846 // intents fired from the managed profile are forwarded. 847 final boolean intentFiltersSetForManagedIntents = (resultCode == RESULT_OK); 848 // Since the ByodFlowTestActivity is running in the primary profile, we directly use 849 // the IntentFiltersTestHelper to know if certain intents fired from the primary profile 850 // are forwarded. 851 final boolean intentFiltersSetForPrimaryIntents = 852 new IntentFiltersTestHelper(this).checkCrossProfileIntentFilters( 853 IntentFiltersTestHelper.FLAG_INTENTS_FROM_PRIMARY); 854 final boolean intentFiltersSet = 855 intentFiltersSetForPrimaryIntents & intentFiltersSetForManagedIntents; 856 setTestResult(mIntentFiltersTest, 857 intentFiltersSet ? TestResult.TEST_RESULT_PASSED : TestResult.TEST_RESULT_FAILED); 858 } 859 setHandleIntentActivityEnabledSetting(final int enableState)860 private void setHandleIntentActivityEnabledSetting(final int enableState) { 861 getPackageManager().setComponentEnabledSetting( 862 new ComponentName(ByodFlowTestActivity.this, HandleIntentActivity.class.getName()), 863 enableState, PackageManager.DONT_KILL_APP); 864 } 865 markProvisioningCompleteBroadcastReceived(Context context)866 private static void markProvisioningCompleteBroadcastReceived(Context context) { 867 markProvisioningCompleteBroadcastWithStatus(context, 868 PREFERENCE_PROVISIONING_COMPLETE_STATUS_RECEIVED); 869 } 870 markProvisioningCompleteBroadcastProcessed(Context context)871 private static void markProvisioningCompleteBroadcastProcessed(Context context) { 872 markProvisioningCompleteBroadcastWithStatus(context, 873 PREFERENCE_PROVISIONING_COMPLETE_STATUS_PROCESSED); 874 } 875 clearProvisioningCompleteBroadcastStatus(Context context)876 private static void clearProvisioningCompleteBroadcastStatus(Context context) { 877 markProvisioningCompleteBroadcastWithStatus(context, 878 PREFERENCE_PROVISIONING_COMPLETE_STATUS_NOT_RECEIVED); 879 } 880 markProvisioningCompleteBroadcastWithStatus(Context context, int status)881 private static void markProvisioningCompleteBroadcastWithStatus(Context context, int status) { 882 final SharedPreferences prefs = getProvisioningPreferences(context); 883 final SharedPreferences.Editor editor = prefs.edit(); 884 editor.putInt(PREFERENCE_PROVISIONING_COMPLETE_STATUS, status); 885 editor.commit(); 886 } 887 isProvisioningCompleteBroadcastReceived(Context context)888 private static boolean isProvisioningCompleteBroadcastReceived(Context context) { 889 return getProvisioningPreferences(context) 890 .getInt(PREFERENCE_PROVISIONING_COMPLETE_STATUS, 0) == 891 PREFERENCE_PROVISIONING_COMPLETE_STATUS_RECEIVED; 892 } 893 isProvisioningCompleteBroadcastProcessed(Context context)894 private static boolean isProvisioningCompleteBroadcastProcessed(Context context) { 895 return getProvisioningPreferences(context) 896 .getInt(PREFERENCE_PROVISIONING_COMPLETE_STATUS, 0) == 897 PREFERENCE_PROVISIONING_COMPLETE_STATUS_PROCESSED; 898 } 899 getProvisioningPreferences(Context context)900 private static SharedPreferences getProvisioningPreferences(Context context) { 901 return context.getSharedPreferences(PROVISIONING_PREFERENCES, MODE_PRIVATE); 902 } 903 } 904