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