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