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 DialogTestListItem mDisableNfcBeamTest; 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 (getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC) 618 && getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC_BEAM)) { 619 mDisableNfcBeamTest = new DialogTestListItem(this, R.string.provisioning_byod_nfc_beam, 620 "BYOD_DisableNfcBeamTest", 621 R.string.provisioning_byod_nfc_beam_allowed_instruction, 622 new Intent(ByodHelperActivity.ACTION_TEST_NFC_BEAM)) { 623 @Override 624 public void performTest(final DialogTestListActivity activity) { 625 activity.showManualTestDialog(mDisableNfcBeamTest, 626 new DefaultTestCallback(mDisableNfcBeamTest) { 627 @Override 628 public void onPass() { 629 // Start a second test with beam disallowed by policy. 630 Intent testNfcBeamIntent = new Intent( 631 ByodHelperActivity.ACTION_TEST_NFC_BEAM); 632 testNfcBeamIntent.putExtra(NfcTestActivity.EXTRA_DISALLOW_BY_POLICY, 633 true); 634 DialogTestListItem disableNfcBeamTest2 = 635 new DialogTestListItem(activity, 636 R.string.provisioning_byod_nfc_beam, 637 "BYOD_DisableNfcBeamTest", 638 R.string.provisioning_byod_nfc_beam_disallowed_instruction, 639 testNfcBeamIntent); 640 // The result should be reflected on the original test. 641 activity.showManualTestDialog(disableNfcBeamTest2, 642 new DefaultTestCallback(mDisableNfcBeamTest)); 643 } 644 }); 645 } 646 }; 647 adapter.add(mDisableNfcBeamTest); 648 } 649 650 adapter.add(mKeyChainTest); 651 652 /* If there is an application that handles RECORD_SOUND_ACTION, test that it handles it 653 * well. 654 */ 655 if (canResolveIntent(ByodHelperActivity.getCaptureAudioIntent())) { 656 // Capture audio intent can be resolved in primary profile, so test. 657 mCrossProfileAudioCaptureSupportTest = new DialogTestListItem(this, 658 R.string.provisioning_byod_capture_audio_support, 659 "BYOD_CrossProfileAudioCaptureSupportTest", 660 R.string.provisioning_byod_capture_audio_support_info, 661 new Intent(ByodHelperActivity.ACTION_CAPTURE_AND_CHECK_AUDIO)); 662 adapter.add(mCrossProfileAudioCaptureSupportTest); 663 } else { 664 // Capture audio intent cannot be resolved in primary profile, so skip test. 665 Toast.makeText(ByodFlowTestActivity.this, 666 R.string.provisioning_byod_no_audio_capture_resolver, Toast.LENGTH_SHORT) 667 .show(); 668 } 669 670 if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_LOCATION_GPS)) { 671 mEnableLocationModeTest = TestListItem.newTest(this, 672 R.string.provisioning_byod_location_mode_enable, 673 LocationTestActivity.TEST_ID_LOCATION_ENABLED, 674 new Intent(LocationTestActivity.ACTION_TEST_LOCATION_ENABLED), 675 null); 676 mDisableLocationModeThroughMainSwitchTest = TestListItem.newTest(this, 677 R.string.provisioning_byod_location_mode_disable, 678 LocationTestActivity.TEST_ID_LOCATION_DISABLED, 679 new Intent(LocationTestActivity.ACTION_TEST_LOCATION_DISABLED), 680 null); 681 mDisableLocationModeThroughWorkSwitchTest = TestListItem.newTest(this, 682 R.string.provisioning_byod_work_location_mode_disable, 683 LocationTestActivity.TEST_ID_WORK_LOCATION_DISABLED, 684 new Intent(LocationTestActivity.ACTION_TEST_WORK_LOCATION_DISABLED), 685 null); 686 mPrimaryLocationWhenWorkDisabledTest = TestListItem.newTest(this, 687 R.string.provisioning_byod_primary_location_when_work_disabled, 688 LocationTestActivity.TEST_ID_WORK_LOCATION_DISABLED_PRIMARY, 689 new Intent(LocationTestActivity.ACTION_TEST_WORK_LOCATION_DISABLED_PRIMARY), 690 null); 691 adapter.add(mEnableLocationModeTest); 692 adapter.add(mDisableLocationModeThroughMainSwitchTest); 693 adapter.add(mDisableLocationModeThroughWorkSwitchTest); 694 adapter.add(mPrimaryLocationWhenWorkDisabledTest); 695 } else { 696 // The system does not support GPS feature, so skip test. 697 Toast.makeText(ByodFlowTestActivity.this, 698 R.string.provisioning_byod_no_gps_location_feature, Toast.LENGTH_SHORT) 699 .show(); 700 } 701 702 if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS)) { 703 mWidgetTest = TestListItem.newTest(this, 704 R.string.provisioning_byod_work_profile_widget, 705 WorkProfileWidgetActivity.class.getName(), 706 new Intent(WorkProfileWidgetActivity.ACTION_TEST_WORK_PROFILE_WIDGET), 707 new String[]{PackageManager.FEATURE_APP_WIDGETS}); 708 adapter.add(mWidgetTest); 709 } 710 711 adapter.add(new DialogTestListItem(this, 712 R.string.provisioning_byod_uninstall_work_app, 713 "BYOD_UninstallWorkApp", 714 R.string.provisioning_byod_uninstall_work_app_instruction, 715 createInstallWorkProfileAppIntent())); 716 717 adapter.add(new DialogTestListItem(this, 718 R.string.provisioning_byod_launch_work_tab, 719 "BYOD_LaunchWorkTab", 720 R.string.provisioning_byod_launch_work_tab_instruction, 721 createLaunchWorkTabIntent())); 722 723 adapter.add(mScreenshotTest); 724 adapter.add(mAllowNonDismissibleNotificationTest); 725 } 726 createInstallWorkProfileAppIntent()727 private Intent createInstallWorkProfileAppIntent() { 728 // We place the APK file in /data/local/tmp to make it visible from the work profile. 729 return new Intent(ByodHelperActivity.ACTION_INSTALL_APK) 730 .putExtra(ByodHelperActivity.EXTRA_ALLOW_NON_MARKET_APPS, true) 731 .putExtra(ByodHelperActivity.EXTRA_PARAMETER_1, HELPER_APP_PATH); 732 } 733 createLaunchWorkTabIntent()734 private Intent createLaunchWorkTabIntent() { 735 return new Intent(Intent.ACTION_SHOW_WORK_APPS) 736 .addCategory(Intent.CATEGORY_HOME) 737 .addCategory(Intent.CATEGORY_LAUNCHER_APP) 738 .addFlags(FLAG_ACTIVITY_NEW_TASK); 739 } 740 741 // Return whether the intent can be resolved in the current profile canResolveIntent(Intent intent)742 private boolean canResolveIntent(Intent intent) { 743 return intent.resolveActivity(getPackageManager()) != null; 744 } 745 746 @Override clearRemainingState(final DialogTestListItem test)747 protected void clearRemainingState(final DialogTestListItem test) { 748 super.clearRemainingState(test); 749 if (ByodHelperActivity.ACTION_NOTIFICATION.equals( 750 test.getManualTestIntent().getAction())) { 751 try { 752 startActivity(new Intent( 753 ByodHelperActivity.ACTION_CLEAR_NOTIFICATION)); 754 } catch (ActivityNotFoundException e) { 755 // User shouldn't run this test before work profile is set up. 756 } 757 } 758 } 759 queryProfileOwner(boolean showToast)760 private void queryProfileOwner(boolean showToast) { 761 try { 762 // Set execution start time for counting test execution time. 763 mStartTime = System.currentTimeMillis(); 764 Intent intent = new Intent(ByodHelperActivity.ACTION_QUERY_PROFILE_OWNER); 765 startActivityForResult(intent, REQUEST_PROFILE_OWNER_STATUS); 766 } 767 catch (ActivityNotFoundException e) { 768 Log.d(TAG, "queryProfileOwner: ActivityNotFoundException", e); 769 setProfileOwnerTestResult(TestResult.TEST_RESULT_FAILED); 770 if (showToast) { 771 Utils.showToast(this, R.string.provisioning_byod_no_activity); 772 } 773 } 774 } 775 setProfileOwnerTestResult(int result)776 private void setProfileOwnerTestResult(int result) { 777 setTestResult(mProfileOwnerInstalled, result); 778 if (result == TestResult.TEST_RESULT_FAILED) { 779 clearProvisioningCompleteBroadcastStatus(this); 780 startPeriodicProvisioningCheckIfNecessary(); 781 } 782 } 783 checkDiskEncryption()784 private void checkDiskEncryption() { 785 try { 786 Intent intent = new Intent(ByodHelperActivity.ACTION_CHECK_DISK_ENCRYPTION); 787 startActivityForResult(intent, REQUEST_CHECK_DISK_ENCRYPTION); 788 } catch (ActivityNotFoundException e) { 789 Log.d(TAG, "checkDiskEncryption: ActivityNotFoundException", e); 790 setTestResult(mDiskEncryptionTest, TestResult.TEST_RESULT_FAILED); 791 Utils.showToast(this, R.string.provisioning_byod_no_activity); 792 } 793 } 794 handleDiskEncryptionStatus(int resultCode, Intent data)795 private void handleDiskEncryptionStatus(int resultCode, Intent data) { 796 if (resultCode != RESULT_OK || data == null) { 797 Log.e(TAG, "Failed to get result for disk encryption, result code: " + resultCode); 798 setTestResult(mDiskEncryptionTest, TestResult.TEST_RESULT_FAILED); 799 return; 800 } 801 802 final int status = data.getIntExtra(ByodHelperActivity.EXTRA_ENCRYPTION_STATUS, 803 DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED); 804 switch (status) { 805 case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE: 806 case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER: 807 setTestResult(mDiskEncryptionTest, TestResult.TEST_RESULT_PASSED); 808 break; 809 case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY: 810 if (!mKeyguardManager.isDeviceSecure()) { 811 Utils.setScreenLock(this, REQUEST_SET_LOCK_FOR_ENCRYPTION); 812 return; 813 } 814 Log.e(TAG, "Disk encryption key is not entangled with lock screen credentials"); 815 Toast.makeText(this, R.string.provisioning_byod_disk_encryption_default_key_toast, 816 Toast.LENGTH_LONG).show(); 817 // fall through 818 default: 819 setTestResult(mDiskEncryptionTest, TestResult.TEST_RESULT_FAILED); 820 } 821 822 if (mKeyguardManager.isDeviceSecure()) { 823 Utils.removeScreenLock(this); 824 } 825 } 826 handleSetLockForEncryption()827 private void handleSetLockForEncryption() { 828 if (mKeyguardManager.isDeviceSecure()) { 829 checkDiskEncryption(); 830 } else { 831 setTestResult(mDiskEncryptionTest, TestResult.TEST_RESULT_FAILED); 832 Toast.makeText(this, R.string.provisioning_byod_disk_encryption_no_pin_toast, 833 Toast.LENGTH_LONG).show(); 834 } 835 } 836 checkIntentFilters()837 private void checkIntentFilters() { 838 try { 839 // Enable component HandleIntentActivity before intent filters are checked. 840 setHandleIntentActivityEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED); 841 // We disable the ByodHelperActivity in the primary profile. So, this intent 842 // will be handled by the ByodHelperActivity in the managed profile. 843 Intent intent = new Intent(ByodHelperActivity.ACTION_CHECK_INTENT_FILTERS); 844 startActivityForResult(intent, REQUEST_INTENT_FILTERS_STATUS); 845 } catch (ActivityNotFoundException e) { 846 // Disable component HandleIntentActivity if intent filters check fails. 847 setHandleIntentActivityEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED); 848 Log.d(TAG, "checkIntentFilters: ActivityNotFoundException", e); 849 setTestResult(mIntentFiltersTest, TestResult.TEST_RESULT_FAILED); 850 Utils.showToast(this, R.string.provisioning_byod_no_activity); 851 } 852 } 853 handleIntentFiltersStatus(int resultCode)854 private void handleIntentFiltersStatus(int resultCode) { 855 // Disable component HandleIntentActivity after intent filters are checked. 856 setHandleIntentActivityEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED); 857 // we use the resultCode from ByodHelperActivity in the managed profile to know if certain 858 // intents fired from the managed profile are forwarded. 859 final boolean intentFiltersSetForManagedIntents = (resultCode == RESULT_OK); 860 // Since the ByodFlowTestActivity is running in the primary profile, we directly use 861 // the IntentFiltersTestHelper to know if certain intents fired from the primary profile 862 // are forwarded. 863 final boolean intentFiltersSetForPrimaryIntents = 864 new IntentFiltersTestHelper(this).checkCrossProfileIntentFilters( 865 IntentFiltersTestHelper.FLAG_INTENTS_FROM_PRIMARY); 866 final boolean intentFiltersSet = 867 intentFiltersSetForPrimaryIntents & intentFiltersSetForManagedIntents; 868 setTestResult(mIntentFiltersTest, 869 intentFiltersSet ? TestResult.TEST_RESULT_PASSED : TestResult.TEST_RESULT_FAILED); 870 } 871 setHandleIntentActivityEnabledSetting(final int enableState)872 private void setHandleIntentActivityEnabledSetting(final int enableState) { 873 getPackageManager().setComponentEnabledSetting( 874 new ComponentName(ByodFlowTestActivity.this, HandleIntentActivity.class.getName()), 875 enableState, PackageManager.DONT_KILL_APP); 876 } 877 markProvisioningCompleteBroadcastReceived(Context context)878 private static void markProvisioningCompleteBroadcastReceived(Context context) { 879 markProvisioningCompleteBroadcastWithStatus(context, 880 PREFERENCE_PROVISIONING_COMPLETE_STATUS_RECEIVED); 881 } 882 markProvisioningCompleteBroadcastProcessed(Context context)883 private static void markProvisioningCompleteBroadcastProcessed(Context context) { 884 markProvisioningCompleteBroadcastWithStatus(context, 885 PREFERENCE_PROVISIONING_COMPLETE_STATUS_PROCESSED); 886 } 887 clearProvisioningCompleteBroadcastStatus(Context context)888 private static void clearProvisioningCompleteBroadcastStatus(Context context) { 889 markProvisioningCompleteBroadcastWithStatus(context, 890 PREFERENCE_PROVISIONING_COMPLETE_STATUS_NOT_RECEIVED); 891 } 892 markProvisioningCompleteBroadcastWithStatus(Context context, int status)893 private static void markProvisioningCompleteBroadcastWithStatus(Context context, int status) { 894 final SharedPreferences prefs = getProvisioningPreferences(context); 895 final SharedPreferences.Editor editor = prefs.edit(); 896 editor.putInt(PREFERENCE_PROVISIONING_COMPLETE_STATUS, status); 897 editor.commit(); 898 } 899 isProvisioningCompleteBroadcastReceived(Context context)900 private static boolean isProvisioningCompleteBroadcastReceived(Context context) { 901 return getProvisioningPreferences(context) 902 .getInt(PREFERENCE_PROVISIONING_COMPLETE_STATUS, 0) == 903 PREFERENCE_PROVISIONING_COMPLETE_STATUS_RECEIVED; 904 } 905 isProvisioningCompleteBroadcastProcessed(Context context)906 private static boolean isProvisioningCompleteBroadcastProcessed(Context context) { 907 return getProvisioningPreferences(context) 908 .getInt(PREFERENCE_PROVISIONING_COMPLETE_STATUS, 0) == 909 PREFERENCE_PROVISIONING_COMPLETE_STATUS_PROCESSED; 910 } 911 getProvisioningPreferences(Context context)912 private static SharedPreferences getProvisioningPreferences(Context context) { 913 return context.getSharedPreferences(PROVISIONING_PREFERENCES, MODE_PRIVATE); 914 } 915 }