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