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