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