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