Home | History | Annotate | Download | only in managedprovisioning
      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.os.UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES;
     20 import static android.os.UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY;
     21 
     22 import android.app.KeyguardManager;
     23 import android.app.Notification;
     24 import android.app.NotificationChannel;
     25 import android.app.NotificationManager;
     26 import android.app.admin.DevicePolicyManager;
     27 import android.content.ComponentName;
     28 import android.content.Context;
     29 import android.content.Intent;
     30 import android.graphics.Color;
     31 import android.net.Uri;
     32 import android.os.Bundle;
     33 import android.os.Handler;
     34 import android.os.UserManager;
     35 import android.provider.MediaStore;
     36 import androidx.core.content.FileProvider;
     37 import androidx.core.util.Pair;
     38 import android.util.Log;
     39 
     40 import com.android.cts.verifier.R;
     41 import com.android.cts.verifier.location.LocationListenerActivity;
     42 import com.android.cts.verifier.managedprovisioning.ByodPresentMediaDialog.DialogCallback;
     43 
     44 import java.io.File;
     45 import java.util.ArrayList;
     46 
     47 /**
     48  * A helper activity from the managed profile side that responds to requests from CTS verifier in
     49  * primary user. Profile owner APIs are accessible inside this activity (given this activity is
     50  * started within the work profile). Its current functionalities include making sure the profile
     51  * owner is setup correctly, removing the work profile upon request, and verifying the image and
     52  * video capture functionality.
     53  *
     54  * Note: We have to use a dummy activity because cross-profile intents only work for activities.
     55  */
     56 public class ByodHelperActivity extends LocationListenerActivity
     57         implements DialogCallback {
     58 
     59     static final String TAG = "ByodHelperActivity";
     60 
     61     // Primary -> managed intent: query if the profile owner has been set up.
     62     public static final String ACTION_QUERY_PROFILE_OWNER = "com.android.cts.verifier.managedprovisioning.BYOD_QUERY";
     63     // Managed -> primary intent: update profile owner test status in primary's CtsVerifer
     64     public static final String ACTION_PROFILE_OWNER_STATUS = "com.android.cts.verifier.managedprovisioning.BYOD_STATUS";
     65     // Primary -> managed intent: request to delete the current profile
     66     public static final String ACTION_REMOVE_MANAGED_PROFILE = "com.android.cts.verifier.managedprovisioning.BYOD_REMOVE";
     67     // Managed -> managed intent: provisioning completed successfully
     68     public static final String ACTION_PROFILE_PROVISIONED = "com.android.cts.verifier.managedprovisioning.BYOD_PROVISIONED";
     69     // Primary -> managed intent: request to capture and check an image
     70     public static final String ACTION_CAPTURE_AND_CHECK_IMAGE = "com.android.cts.verifier.managedprovisioning.BYOD_CAPTURE_AND_CHECK_IMAGE";
     71     // Primary -> managed intent: request to capture and check a video with custom output path
     72     public static final String ACTION_CAPTURE_AND_CHECK_VIDEO_WITH_EXTRA_OUTPUT = "com.android.cts.verifier.managedprovisioning.BYOD_CAPTURE_AND_CHECK_VIDEO_WITH_EXTRA_OUTPUT";
     73     // Primary -> managed intent: request to capture and check a video without custom output path
     74     public static final String ACTION_CAPTURE_AND_CHECK_VIDEO_WITHOUT_EXTRA_OUTPUT = "com.android.cts.verifier.managedprovisioning.BYOD_CAPTURE_AND_CHECK_VIDEO_WITHOUT_EXTRA_OUTPUT";
     75     // Primary -> managed intent: request to capture and check an audio recording
     76     public static final String ACTION_CAPTURE_AND_CHECK_AUDIO = "com.android.cts.verifier.managedprovisioning.BYOD_CAPTURE_AND_CHECK_AUDIO";
     77     public static final String ACTION_KEYGUARD_DISABLED_FEATURES =
     78             "com.android.cts.verifier.managedprovisioning.BYOD_KEYGUARD_DISABLED_FEATURES";
     79     public static final String ACTION_LOCKNOW =
     80             "com.android.cts.verifier.managedprovisioning.BYOD_LOCKNOW";
     81     public static final String ACTION_TEST_NFC_BEAM = "com.android.cts.verifier.managedprovisioning.TEST_NFC_BEAM";
     82 
     83     public static final String EXTRA_PROVISIONED = "extra_provisioned";
     84     public static final String EXTRA_PARAMETER_1 = "extra_parameter_1";
     85 
     86     // Primary -> managed intent: check if the disk of the device is encrypted
     87     public static final String ACTION_CHECK_DISK_ENCRYPTION =
     88             "com.android.cts.verifier.managedprovisioning.action.BYOD_CHECK_DISK_ENCRYPTION";
     89     // Managed -> primary intent: update disk encryption status in primary's CtsVerifier
     90     public static final String ACTION_DISK_ENCRYPTION_STATUS =
     91             "com.android.cts.verifier.managedprovisioning.action.BYOD_DISK_ENCRYPTION_STATUS";
     92     // Int extra field indicating the encryption status of the device storage
     93     public static final String EXTRA_ENCRYPTION_STATUS = "extra_encryption_status";
     94 
     95     // Primary -> managed intent: set unknown sources restriction and install package
     96     public static final String ACTION_INSTALL_APK = "com.android.cts.verifier.managedprovisioning.BYOD_INSTALL_APK";
     97     public static final String EXTRA_ALLOW_NON_MARKET_APPS = "allow_non_market_apps";
     98     public static final String ACTION_INSTALL_APK_WORK_PROFILE_GLOBAL_RESTRICTION = "com.android.cts.verifier.managedprovisioning.BYOD_INSTALL_APK_WORK_PROFILE_GLOBAL_RESTRICTION";
     99     public static final String EXTRA_ALLOW_NON_MARKET_APPS_DEVICE_WIDE = "allow_non_market_apps_device_wide";
    100 
    101     // Primary -> managed intent: set unknown sources globally restriction
    102     public static final String ACTION_INSTALL_APK_PRIMARY_PROFILE_GLOBAL_RESTRICTION = "com.android.cts.verifier.managedprovisioning.BYOD_INSTALL_APK_PRIMARY_PROFILE_GLOBAL_RESTRICTION";
    103     // Managed -> primary intent: install primary profile app with global unknown sources
    104     // restriction.
    105     public static final String ACTION_INSTALL_APK_IN_PRIMARY = "com.android.cts.verifier.managedprovisioning.BYOD_INSTALL_APK_IN_PRIMARY";
    106 
    107     // Primary -> managed intent: check if the required cross profile intent filters are set.
    108     public static final String ACTION_CHECK_INTENT_FILTERS =
    109             "com.android.cts.verifier.managedprovisioning.action.CHECK_INTENT_FILTERS";
    110 
    111     // Primary -> managed intent: will send a cross profile intent and check if the user sees an
    112     // intent picker dialog and can open the apps.
    113     public static final String ACTION_TEST_CROSS_PROFILE_INTENTS_DIALOG =
    114             "com.android.cts.verifier.managedprovisioning.action.TEST_CROSS_PROFILE_INTENTS_DIALOG";
    115 
    116     // Primary -> managed intent: will send an app link intent and check if the user sees a
    117     // dialog and can open the apps. This test is extremely similar to
    118     // ACTION_TEST_CROSS_PROFILE_INTENTS_DIALOG, but the intent used is a web intent, and there is
    119     // some behavior which is specific to web intents.
    120     public static final String ACTION_TEST_APP_LINKING_DIALOG =
    121             "com.android.cts.verifier.managedprovisioning.action.TEST_APP_LINKING_DIALOG";
    122 
    123     // Primary -> managed intent: request to goto the location settings page and listen to updates.
    124     public static final String ACTION_BYOD_SET_LOCATION_AND_CHECK_UPDATES =
    125             "com.android.cts.verifier.managedprovisioning.BYOD_SET_LOCATION_AND_CHECK";
    126     public static final String ACTION_NOTIFICATION =
    127             "com.android.cts.verifier.managedprovisioning.NOTIFICATION";
    128     public static final String ACTION_NOTIFICATION_ON_LOCKSCREEN =
    129             "com.android.cts.verifier.managedprovisioning.LOCKSCREEN_NOTIFICATION";
    130     public static final String ACTION_CLEAR_NOTIFICATION =
    131             "com.android.cts.verifier.managedprovisioning.CLEAR_NOTIFICATION";
    132 
    133     // Primary -> managed intent: set a user restriction
    134     public static final String ACTION_SET_USER_RESTRICTION =
    135             "com.android.cts.verifier.managedprovisioning.BYOD_SET_USER_RESTRICTION";
    136 
    137     // Primary -> managed intent: reset a user restriction
    138     public static final String ACTION_CLEAR_USER_RESTRICTION =
    139             "com.android.cts.verifier.managedprovisioning.BYOD_CLEAR_USER_RESTRICTION";
    140 
    141     // Primary -> managed intent: Start the selection of a work challenge
    142     public static final String ACTION_TEST_SELECT_WORK_CHALLENGE =
    143             "com.android.cts.verifier.managedprovisioning.TEST_SELECT_WORK_CHALLENGE";
    144 
    145     // Primary -> managed intent: Start the selection of a work challenge
    146     public static final String ACTION_TEST_PATTERN_WORK_CHALLENGE =
    147             "com.android.cts.verifier.managedprovisioning.TEST_PATTERN_WORK_CHALLENGE";
    148 
    149     // Primary -> managed intent: Start the selection of a parent profile password.
    150     public static final String ACTION_TEST_PARENT_PROFILE_PASSWORD =
    151             "com.android.cts.verifier.managedprovisioning.TEST_PARENT_PROFILE_PASSWORD";
    152 
    153     // Primary -> managed intent: Start the confirm credentials screen for the managed profile
    154     public static final String ACTION_LAUNCH_CONFIRM_WORK_CREDENTIALS =
    155             "com.android.cts.verifier.managedprovisioning.LAUNCH_CONFIRM_WORK_CREDENTIALS";
    156 
    157     public static final String ACTION_SET_ORGANIZATION_INFO =
    158             "com.android.cts.verifier.managedprovisioning.TEST_ORGANIZATION_INFO";
    159 
    160     public static final int RESULT_FAILED = RESULT_FIRST_USER;
    161 
    162     private static final int REQUEST_INSTALL_PACKAGE = 2;
    163     private static final int REQUEST_IMAGE_CAPTURE = 3;
    164     private static final int REQUEST_VIDEO_CAPTURE_WITH_EXTRA_OUTPUT = 4;
    165     private static final int REQUEST_VIDEO_CAPTURE_WITHOUT_EXTRA_OUTPUT = 5;
    166     private static final int REQUEST_AUDIO_CAPTURE = 6;
    167 
    168     private static final String ORIGINAL_RESTRICTIONS_NAME = "original restrictions";
    169 
    170     private static final int NOTIFICATION_ID = 7;
    171     private static final String NOTIFICATION_CHANNEL_ID = TAG;
    172 
    173     private NotificationManager mNotificationManager;
    174     private Bundle mOriginalRestrictions;
    175 
    176     private ComponentName mAdminReceiverComponent;
    177     private DevicePolicyManager mDevicePolicyManager;
    178 
    179     private Uri mImageUri;
    180     private Uri mVideoUri;
    181     private File mImageFile;
    182 
    183     private ArrayList<File> mTempFiles = new ArrayList<File>();
    184 
    185     private Handler mMainThreadHandler;
    186 
    187     private void showNotification(int visibility) {
    188         final Notification notification = new Notification.Builder(this, NOTIFICATION_CHANNEL_ID)
    189                 .setSmallIcon(R.drawable.icon)
    190                 .setContentTitle(getString(R.string.provisioning_byod_notification_title))
    191                 .setContentText(getString(R.string.provisioning_byod_notification_title))
    192                 .setVisibility(visibility)
    193                 .setAutoCancel(true)
    194                 .setPublicVersion(createPublicVersionNotification())
    195                 .build();
    196         mNotificationManager.notify(NOTIFICATION_ID, notification);
    197     }
    198 
    199     private Notification createPublicVersionNotification() {
    200         return new Notification.Builder(this)
    201                 .setSmallIcon(R.drawable.icon)
    202                 .setContentTitle(getString(R.string.provisioning_byod_notification_public_title))
    203                 .setAutoCancel(true)
    204                 .build();
    205     }
    206 
    207     @Override
    208     protected void onCreate(Bundle savedInstanceState) {
    209         super.onCreate(savedInstanceState);
    210         mMainThreadHandler = new Handler(getMainLooper());
    211         if (savedInstanceState != null) {
    212             Log.w(TAG, "Restored state");
    213             mOriginalRestrictions = savedInstanceState.getBundle(ORIGINAL_RESTRICTIONS_NAME);
    214         } else {
    215             mOriginalRestrictions = new Bundle();
    216         }
    217 
    218         mAdminReceiverComponent = new ComponentName(this, DeviceAdminTestReceiver.class.getName());
    219         mDevicePolicyManager = (DevicePolicyManager) getSystemService(
    220                 Context.DEVICE_POLICY_SERVICE);
    221         mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    222         Intent intent = getIntent();
    223         String action = intent.getAction();
    224         Log.d(TAG, "ByodHelperActivity.onCreate: " + action);
    225         mNotificationManager.createNotificationChannel(new NotificationChannel(
    226                 NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_ID,
    227                 NotificationManager.IMPORTANCE_DEFAULT));
    228 
    229         // we are explicitly started by {@link DeviceAdminTestReceiver} after a successful provisioning.
    230         if (action.equals(ACTION_PROFILE_PROVISIONED)) {
    231             // Jump back to CTS verifier with result.
    232             Intent response = new Intent(ACTION_PROFILE_OWNER_STATUS);
    233             response.putExtra(EXTRA_PROVISIONED, isProfileOwner());
    234             new ByodFlowTestHelper(this).startActivityInPrimary(response);
    235             // Queried by CtsVerifier in the primary side using startActivityForResult.
    236         } else if (action.equals(ACTION_QUERY_PROFILE_OWNER)) {
    237             Intent response = new Intent();
    238             response.putExtra(EXTRA_PROVISIONED, isProfileOwner());
    239             setResult(RESULT_OK, response);
    240             // Request to delete work profile.
    241         } else if (action.equals(ACTION_REMOVE_MANAGED_PROFILE)) {
    242             if (isProfileOwner()) {
    243                 Log.d(TAG, "Clearing cross profile intents");
    244                 mDevicePolicyManager.clearCrossProfileIntentFilters(mAdminReceiverComponent);
    245                 mDevicePolicyManager.wipeData(0);
    246                 showToast(R.string.provisioning_byod_profile_deleted);
    247             }
    248         } else if (action.equals(ACTION_CHECK_DISK_ENCRYPTION)) {
    249             final int status = mDevicePolicyManager.getStorageEncryptionStatus();
    250             final Intent response = new Intent(ACTION_DISK_ENCRYPTION_STATUS)
    251                     .putExtra(EXTRA_ENCRYPTION_STATUS, status);
    252             setResult(RESULT_OK, response);
    253         } else if (action.equals(ACTION_INSTALL_APK)) {
    254             boolean allowNonMarket = intent.getBooleanExtra(EXTRA_ALLOW_NON_MARKET_APPS, false);
    255             setRestrictionAndSaveOriginal(DISALLOW_INSTALL_UNKNOWN_SOURCES, !allowNonMarket);
    256             startInstallerActivity(intent.getStringExtra(EXTRA_PARAMETER_1));
    257             // Not yet ready to finish - wait until the result comes back
    258             return;
    259         } else if (action.equals(ACTION_INSTALL_APK_WORK_PROFILE_GLOBAL_RESTRICTION)) {
    260             // Save original unknown sources setting to be restored later and clear it for now.
    261             setRestrictionAndSaveOriginal(DISALLOW_INSTALL_UNKNOWN_SOURCES, false);
    262             boolean allowNonMarketGlobal = intent.getBooleanExtra(
    263                     EXTRA_ALLOW_NON_MARKET_APPS_DEVICE_WIDE, false);
    264             setRestrictionAndSaveOriginal(DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY,
    265                     !allowNonMarketGlobal);
    266             startInstallerActivity(intent.getStringExtra(EXTRA_PARAMETER_1));
    267             // Not yet ready to finish - wait until the result comes back
    268             return;
    269         } else if (action.equals(ACTION_INSTALL_APK_PRIMARY_PROFILE_GLOBAL_RESTRICTION)) {
    270             boolean allowNonMarketGlobal = intent.getExtras().getBoolean(
    271                     EXTRA_ALLOW_NON_MARKET_APPS_DEVICE_WIDE, false);
    272             setRestrictionAndSaveOriginal(DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY,
    273                     !allowNonMarketGlobal);
    274             setRestrictionAndSaveOriginal(DISALLOW_INSTALL_UNKNOWN_SOURCES, false);
    275             Intent installPersonalProfileIntent = new Intent(ACTION_INSTALL_APK_IN_PRIMARY);
    276             // Attempt to install an apk in the primary profile
    277             startActivityForResult(installPersonalProfileIntent, REQUEST_INSTALL_PACKAGE);
    278             return;
    279         } else if (action.equals(ACTION_CHECK_INTENT_FILTERS)) {
    280             // Queried by CtsVerifier in the primary side using startActivityForResult.
    281             final boolean intentFiltersSetForManagedIntents =
    282                     new IntentFiltersTestHelper(this).checkCrossProfileIntentFilters(
    283                             IntentFiltersTestHelper.FLAG_INTENTS_FROM_MANAGED);
    284             setResult(intentFiltersSetForManagedIntents? RESULT_OK : RESULT_FAILED, null);
    285         } else if (action.equals(ACTION_CAPTURE_AND_CHECK_IMAGE)) {
    286             // We need the camera permission to send the image capture intent.
    287             grantCameraPermissionToSelf();
    288             Intent captureImageIntent = getCaptureImageIntent();
    289             Pair<File, Uri> pair = getTempUri("image.jpg");
    290             mImageFile = pair.first;
    291             mImageUri = pair.second;
    292             captureImageIntent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
    293             if (captureImageIntent.resolveActivity(getPackageManager()) != null) {
    294                 startActivityForResult(captureImageIntent, REQUEST_IMAGE_CAPTURE);
    295             } else {
    296                 Log.e(TAG, "Capture image intent could not be resolved in managed profile.");
    297                 showToast(R.string.provisioning_byod_capture_media_error);
    298                 finish();
    299             }
    300             return;
    301         } else if (action.equals(ACTION_CAPTURE_AND_CHECK_VIDEO_WITH_EXTRA_OUTPUT) ||
    302                 action.equals(ACTION_CAPTURE_AND_CHECK_VIDEO_WITHOUT_EXTRA_OUTPUT)) {
    303             // We need the camera permission to send the video capture intent.
    304             grantCameraPermissionToSelf();
    305             Intent captureVideoIntent = getCaptureVideoIntent();
    306             int videoCaptureRequestId;
    307             if (action.equals(ACTION_CAPTURE_AND_CHECK_VIDEO_WITH_EXTRA_OUTPUT)) {
    308                 mVideoUri = getTempUri("video.mp4").second;
    309                 captureVideoIntent.putExtra(MediaStore.EXTRA_OUTPUT, mVideoUri);
    310                 videoCaptureRequestId = REQUEST_VIDEO_CAPTURE_WITH_EXTRA_OUTPUT;
    311             } else {
    312                 videoCaptureRequestId = REQUEST_VIDEO_CAPTURE_WITHOUT_EXTRA_OUTPUT;
    313             }
    314             if (captureVideoIntent.resolveActivity(getPackageManager()) != null) {
    315                 startActivityForResult(captureVideoIntent, videoCaptureRequestId);
    316             } else {
    317                 Log.e(TAG, "Capture video intent could not be resolved in managed profile.");
    318                 showToast(R.string.provisioning_byod_capture_media_error);
    319                 finish();
    320             }
    321             return;
    322         } else if (action.equals(ACTION_CAPTURE_AND_CHECK_AUDIO)) {
    323             Intent captureAudioIntent = getCaptureAudioIntent();
    324             if (captureAudioIntent.resolveActivity(getPackageManager()) != null) {
    325                 startActivityForResult(captureAudioIntent, REQUEST_AUDIO_CAPTURE);
    326             } else {
    327                 Log.e(TAG, "Capture audio intent could not be resolved in managed profile.");
    328                 showToast(R.string.provisioning_byod_capture_media_error);
    329                 finish();
    330             }
    331             return;
    332         } else if (ACTION_KEYGUARD_DISABLED_FEATURES.equals(action)) {
    333             final int value = intent.getIntExtra(EXTRA_PARAMETER_1,
    334                     DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE);
    335             mDevicePolicyManager.setKeyguardDisabledFeatures(mAdminReceiverComponent, value);
    336         } else if (ACTION_LOCKNOW.equals(action)) {
    337             mDevicePolicyManager.lockNow();
    338             setResult(RESULT_OK);
    339         } else if (action.equals(ACTION_TEST_NFC_BEAM)) {
    340             Intent testNfcBeamIntent = new Intent(this, NfcTestActivity.class);
    341             testNfcBeamIntent.putExtras(intent);
    342             startActivity(testNfcBeamIntent);
    343             finish();
    344             return;
    345         } else if (action.equals(ACTION_TEST_CROSS_PROFILE_INTENTS_DIALOG)) {
    346             sendIntentInsideChooser(new Intent(
    347                     CrossProfileTestActivity.ACTION_CROSS_PROFILE_TO_PERSONAL));
    348         } else if (action.equals(ACTION_TEST_APP_LINKING_DIALOG)) {
    349             mDevicePolicyManager.addUserRestriction(
    350                     DeviceAdminTestReceiver.getReceiverComponentName(),
    351                     UserManager.ALLOW_PARENT_PROFILE_APP_LINKING);
    352             Intent toSend = new Intent(Intent.ACTION_VIEW);
    353             toSend.setData(Uri.parse("http://com.android.cts.verifier"));
    354             sendIntentInsideChooser(toSend);
    355         } else if (action.equals(ACTION_SET_USER_RESTRICTION)) {
    356             final String restriction = intent.getStringExtra(EXTRA_PARAMETER_1);
    357             if (restriction != null) {
    358                 mDevicePolicyManager.addUserRestriction(
    359                         DeviceAdminTestReceiver.getReceiverComponentName(), restriction);
    360             }
    361         } else if (action.equals(ACTION_CLEAR_USER_RESTRICTION)) {
    362             final String restriction = intent.getStringExtra(EXTRA_PARAMETER_1);
    363             if (restriction != null) {
    364                 mDevicePolicyManager.clearUserRestriction(
    365                         DeviceAdminTestReceiver.getReceiverComponentName(), restriction);
    366             }
    367         } else if (action.equals(ACTION_BYOD_SET_LOCATION_AND_CHECK_UPDATES)) {
    368             handleLocationAction();
    369             return;
    370         } else if (action.equals(ACTION_NOTIFICATION)) {
    371             showNotification(Notification.VISIBILITY_PUBLIC);
    372         } else if (ACTION_NOTIFICATION_ON_LOCKSCREEN.equals(action)) {
    373             mDevicePolicyManager.lockNow();
    374             showNotification(Notification.VISIBILITY_PRIVATE);
    375         } else if (ACTION_CLEAR_NOTIFICATION.equals(action)) {
    376             mNotificationManager.cancel(NOTIFICATION_ID);
    377         } else if (ACTION_TEST_SELECT_WORK_CHALLENGE.equals(action)) {
    378             mDevicePolicyManager.setOrganizationColor(mAdminReceiverComponent, Color.BLUE);
    379             mDevicePolicyManager.setOrganizationName(mAdminReceiverComponent, getResources()
    380                     .getString(R.string.provisioning_byod_confirm_work_credentials_header));
    381             startActivity(new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD));
    382         } else if (ACTION_LAUNCH_CONFIRM_WORK_CREDENTIALS.equals(action)) {
    383             KeyguardManager keyguardManager =
    384                     (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
    385             Intent launchIntent = keyguardManager.createConfirmDeviceCredentialIntent(null, null);
    386             if (launchIntent != null) {
    387                 startActivity(launchIntent);
    388             } else {
    389                 showToast(R.string.provisioning_byod_no_secure_lockscreen);
    390             }
    391         } else if (ACTION_TEST_PATTERN_WORK_CHALLENGE.equals(action)) {
    392             startActivity(new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD));
    393             // The remaining steps are manual.
    394         } else if (ACTION_SET_ORGANIZATION_INFO.equals(action)) {
    395             if(intent.hasExtra(OrganizationInfoTestActivity.EXTRA_ORGANIZATION_NAME)) {
    396                 final String organizationName = intent
    397                         .getStringExtra(OrganizationInfoTestActivity.EXTRA_ORGANIZATION_NAME);
    398                 mDevicePolicyManager.setOrganizationName(mAdminReceiverComponent, organizationName);
    399             }
    400             final int organizationColor = intent.getIntExtra(
    401                     OrganizationInfoTestActivity.EXTRA_ORGANIZATION_COLOR,
    402                     mDevicePolicyManager.getOrganizationColor(mAdminReceiverComponent));
    403             mDevicePolicyManager.setOrganizationColor(mAdminReceiverComponent, organizationColor);
    404         } else if (ACTION_TEST_PARENT_PROFILE_PASSWORD.equals(action)) {
    405             startActivity(new Intent(DevicePolicyManager.ACTION_SET_NEW_PARENT_PROFILE_PASSWORD));
    406         }
    407         // This activity has no UI and is only used to respond to CtsVerifier in the primary side.
    408         finish();
    409     }
    410 
    411     private void startInstallerActivity(String pathToApk) {
    412         // Start the installer activity until this activity is rendered to workaround a glitch.
    413         mMainThreadHandler.post(() -> {
    414             final Uri uri;
    415             if (pathToApk == null) {
    416                 // By default we reinstall ourselves, e.g. request to install a non-market app
    417                 uri = Uri.parse("package:" + getPackageName());
    418             } else {
    419                 uri = FileProvider.getUriForFile(
    420                     this, Utils.FILE_PROVIDER_AUTHORITY, new File(pathToApk));
    421             }
    422             final Intent installIntent = new Intent(Intent.ACTION_INSTALL_PACKAGE)
    423                 .setData(uri)
    424                 .putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true)
    425                 .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
    426                 .putExtra(Intent.EXTRA_RETURN_RESULT, true);
    427             startActivityForResult(installIntent, REQUEST_INSTALL_PACKAGE);
    428         });
    429     }
    430 
    431     @Override
    432     protected void onSaveInstanceState(final Bundle savedState) {
    433         super.onSaveInstanceState(savedState);
    434 
    435         savedState.putBundle(ORIGINAL_RESTRICTIONS_NAME, mOriginalRestrictions);
    436     }
    437 
    438     @Override
    439     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    440         switch (requestCode) {
    441             case REQUEST_INSTALL_PACKAGE: {
    442                 Log.w(TAG, "Received REQUEST_INSTALL_PACKAGE, resultCode = " + resultCode);
    443                 // Restore original settings for restrictions being changed before installs.
    444                 restoreOriginalRestriction(DISALLOW_INSTALL_UNKNOWN_SOURCES);
    445                 restoreOriginalRestriction(DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY);
    446                 finish();
    447                 break;
    448             }
    449             case REQUEST_IMAGE_CAPTURE: {
    450                 if (resultCode == RESULT_OK) {
    451                     ByodPresentMediaDialog.newImageInstance(mImageFile)
    452                             .show(getFragmentManager(), "ViewImageDialogFragment");
    453                 } else {
    454                     // Failed capturing image.
    455                     finish();
    456                 }
    457                 break;
    458             }
    459             case REQUEST_VIDEO_CAPTURE_WITH_EXTRA_OUTPUT: {
    460                 if (resultCode == RESULT_OK) {
    461                     ByodPresentMediaDialog.newVideoInstance(mVideoUri)
    462                             .show(getFragmentManager(), "PlayVideoDialogFragment");
    463                 } else {
    464                     // Failed capturing video.
    465                     finish();
    466                 }
    467                 break;
    468             }
    469             case REQUEST_VIDEO_CAPTURE_WITHOUT_EXTRA_OUTPUT: {
    470                 if (resultCode == RESULT_OK) {
    471                     ByodPresentMediaDialog.newVideoInstance(data.getData())
    472                             .show(getFragmentManager(), "PlayVideoDialogFragment");
    473                 } else {
    474                     // Failed capturing video.
    475                     finish();
    476                 }
    477                 break;
    478             }
    479             case REQUEST_AUDIO_CAPTURE: {
    480                 if (resultCode == RESULT_OK) {
    481                     ByodPresentMediaDialog.newAudioInstance(data.getData())
    482                             .show(getFragmentManager(), "PlayAudioDialogFragment");
    483                 } else {
    484                     // Failed capturing audio.
    485                     finish();
    486                 }
    487                 break;
    488             }
    489             default: {
    490                 super.onActivityResult(requestCode, resultCode, data);
    491                 break;
    492             }
    493         }
    494     }
    495 
    496     @Override
    497     protected void onDestroy() {
    498         cleanUpTempUris();
    499         super.onDestroy();
    500     }
    501 
    502     public static Intent getCaptureImageIntent() {
    503         return new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    504     }
    505 
    506     public static Intent getCaptureVideoIntent() {
    507         return new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
    508     }
    509 
    510     public static Intent getCaptureAudioIntent() {
    511         return new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
    512     }
    513 
    514     public static Intent createLockIntent() {
    515         return new Intent(ACTION_LOCKNOW);
    516     }
    517 
    518     private Pair<File, Uri> getTempUri(String fileName) {
    519         final File file = new File(getFilesDir() + File.separator + "images"
    520                 + File.separator + fileName);
    521         file.getParentFile().mkdirs(); //if the folder doesn't exists it is created
    522         mTempFiles.add(file);
    523         return new Pair<>(file, FileProvider.getUriForFile(
    524                 this, Utils.FILE_PROVIDER_AUTHORITY, file));
    525     }
    526 
    527     private void cleanUpTempUris() {
    528         for (File file : mTempFiles) {
    529             file.delete();
    530         }
    531     }
    532 
    533     private boolean isProfileOwner() {
    534         return mDevicePolicyManager.isAdminActive(mAdminReceiverComponent) &&
    535                 mDevicePolicyManager.isProfileOwnerApp(mAdminReceiverComponent.getPackageName());
    536     }
    537 
    538     private boolean isRestrictionSet(String restriction) {
    539         Bundle restrictions = mDevicePolicyManager.getUserRestrictions(mAdminReceiverComponent);
    540         // This defaults to false if there is no value already there. If a restriction was true,
    541         // the restriction would already be set.
    542         return restrictions.getBoolean(restriction, false);
    543     }
    544 
    545     private void setRestriction(String restriction, boolean enabled) {
    546         if (enabled) {
    547             mDevicePolicyManager.addUserRestriction(mAdminReceiverComponent, restriction);
    548         } else {
    549             mDevicePolicyManager.clearUserRestriction(mAdminReceiverComponent, restriction);
    550         }
    551     }
    552 
    553     private void setRestrictionAndSaveOriginal(String restriction, boolean enabled) {
    554         // Saves original restriction values in mOriginalRestrictions before changing its value.
    555         boolean original = isRestrictionSet(restriction);
    556         if (enabled != original) {
    557             setRestriction(restriction, enabled);
    558             mOriginalRestrictions.putBoolean(restriction, original);
    559         }
    560     }
    561 
    562     public void restoreOriginalRestriction(String restriction) {
    563         if (mOriginalRestrictions.containsKey(restriction)) {
    564             setRestriction(restriction, mOriginalRestrictions.getBoolean(restriction));
    565             mOriginalRestrictions.remove(restriction);
    566         }
    567     }
    568 
    569     private void grantCameraPermissionToSelf() {
    570         mDevicePolicyManager.setPermissionGrantState(mAdminReceiverComponent, getPackageName(),
    571                 android.Manifest.permission.CAMERA,
    572                 DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED);
    573     }
    574 
    575     private void sendIntentInsideChooser(Intent toSend) {
    576         toSend.putExtra(CrossProfileTestActivity.EXTRA_STARTED_FROM_WORK, true);
    577         Intent chooser = Intent.createChooser(toSend,
    578                 getResources().getString(R.string.provisioning_cross_profile_chooser));
    579         startActivity(chooser);
    580     }
    581 
    582     @Override
    583     protected void handleLocationAction() {
    584         // Grant the locaiton permission to the provile owner on cts-verifier.
    585         // The permission state does not have to be reverted at the end since the profile onwer
    586         // is going to be deleted when BYOD tests ends.
    587         grantLocationPermissionToSelf();
    588         super.handleLocationAction();
    589     }
    590 
    591     private void grantLocationPermissionToSelf() {
    592         mDevicePolicyManager.setPermissionGrantState(mAdminReceiverComponent, getPackageName(),
    593                 android.Manifest.permission.ACCESS_FINE_LOCATION,
    594                 DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED);
    595     }
    596 
    597     @Override
    598     public void onDialogClose() {
    599         finish();
    600     }
    601 
    602     @Override
    603     protected String getLogTag() {
    604         return TAG;
    605     }
    606 }
    607