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