1 /* 2 * Copyright 2016, 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.managedprovisioning.preprovisioning; 18 19 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE; 20 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE; 21 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE; 22 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE; 23 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER; 24 import static android.app.admin.DevicePolicyManager.CODE_ADD_MANAGED_PROFILE_DISALLOWED; 25 import static android.app.admin.DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE; 26 import static android.app.admin.DevicePolicyManager.CODE_HAS_DEVICE_OWNER; 27 import static android.app.admin.DevicePolicyManager.CODE_MANAGED_USERS_NOT_SUPPORTED; 28 import static android.app.admin.DevicePolicyManager.CODE_NOT_SYSTEM_USER; 29 import static android.app.admin.DevicePolicyManager.CODE_NOT_SYSTEM_USER_SPLIT; 30 import static android.app.admin.DevicePolicyManager.CODE_OK; 31 import static android.app.admin.DevicePolicyManager.CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER; 32 import static android.nfc.NfcAdapter.ACTION_NDEF_DISCOVERED; 33 34 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_PREPROVISIONING_ACTIVITY_TIME_MS; 35 import static com.android.internal.util.Preconditions.checkNotNull; 36 import static com.android.managedprovisioning.analytics.ProvisioningAnalyticsTracker.CANCELLED_BEFORE_PROVISIONING; 37 import static com.android.managedprovisioning.common.Globals.ACTION_RESUME_PROVISIONING; 38 39 import android.annotation.NonNull; 40 import android.annotation.Nullable; 41 import android.app.ActivityManager; 42 import android.app.KeyguardManager; 43 import android.app.admin.DevicePolicyManager; 44 import android.content.ComponentName; 45 import android.content.Context; 46 import android.content.Intent; 47 import android.content.pm.PackageInfo; 48 import android.content.pm.PackageManager; 49 import android.content.pm.UserInfo; 50 import android.graphics.Bitmap; 51 import android.graphics.BitmapFactory; 52 import android.graphics.drawable.BitmapDrawable; 53 import android.graphics.drawable.Drawable; 54 import android.os.AsyncTask; 55 import android.os.UserManager; 56 import android.service.persistentdata.PersistentDataBlockManager; 57 import android.text.TextUtils; 58 59 import com.android.internal.annotations.VisibleForTesting; 60 import com.android.managedprovisioning.R; 61 import com.android.managedprovisioning.analytics.ProvisioningAnalyticsTracker; 62 import com.android.managedprovisioning.analytics.TimeLogger; 63 import com.android.managedprovisioning.common.IllegalProvisioningArgumentException; 64 import com.android.managedprovisioning.common.MdmPackageInfo; 65 import com.android.managedprovisioning.common.ProvisionLogger; 66 import com.android.managedprovisioning.common.SettingsFacade; 67 import com.android.managedprovisioning.common.StoreUtils; 68 import com.android.managedprovisioning.common.Utils; 69 import com.android.managedprovisioning.model.CustomizationParams; 70 import com.android.managedprovisioning.model.ProvisioningParams; 71 import com.android.managedprovisioning.parser.MessageParser; 72 import com.android.managedprovisioning.preprovisioning.terms.TermsDocument; 73 import com.android.managedprovisioning.preprovisioning.terms.TermsProvider; 74 75 import java.util.List; 76 import java.util.stream.Collectors; 77 78 public class PreProvisioningController { 79 private final Context mContext; 80 private final Ui mUi; 81 private final MessageParser mMessageParser; 82 private final Utils mUtils; 83 private final SettingsFacade mSettingsFacade; 84 private final EncryptionController mEncryptionController; 85 86 // used system services 87 private final DevicePolicyManager mDevicePolicyManager; 88 private final UserManager mUserManager; 89 private final PackageManager mPackageManager; 90 private final ActivityManager mActivityManager; 91 private final KeyguardManager mKeyguardManager; 92 private final PersistentDataBlockManager mPdbManager; 93 private final TimeLogger mTimeLogger; 94 private final ProvisioningAnalyticsTracker mProvisioningAnalyticsTracker; 95 96 private ProvisioningParams mParams; 97 98 public PreProvisioningController( 99 @NonNull Context context, 100 @NonNull Ui ui) { 101 this(context, ui, 102 new TimeLogger(context, PROVISIONING_PREPROVISIONING_ACTIVITY_TIME_MS), 103 new MessageParser(context), new Utils(), new SettingsFacade(), 104 EncryptionController.getInstance(context)); 105 } 106 107 @VisibleForTesting 108 PreProvisioningController( 109 @NonNull Context context, 110 @NonNull Ui ui, 111 @NonNull TimeLogger timeLogger, 112 @NonNull MessageParser parser, 113 @NonNull Utils utils, 114 @NonNull SettingsFacade settingsFacade, 115 @NonNull EncryptionController encryptionController) { 116 mContext = checkNotNull(context, "Context must not be null"); 117 mUi = checkNotNull(ui, "Ui must not be null"); 118 mTimeLogger = checkNotNull(timeLogger, "Time logger must not be null"); 119 mMessageParser = checkNotNull(parser, "MessageParser must not be null"); 120 mSettingsFacade = checkNotNull(settingsFacade); 121 mUtils = checkNotNull(utils, "Utils must not be null"); 122 mEncryptionController = checkNotNull(encryptionController, 123 "EncryptionController must not be null"); 124 125 mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService( 126 Context.DEVICE_POLICY_SERVICE); 127 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 128 mPackageManager = mContext.getPackageManager(); 129 mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); 130 mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); 131 mPdbManager = (PersistentDataBlockManager) mContext.getSystemService( 132 Context.PERSISTENT_DATA_BLOCK_SERVICE); 133 mProvisioningAnalyticsTracker = ProvisioningAnalyticsTracker.getInstance(); 134 } 135 136 interface Ui { 137 /** 138 * Show an error message and cancel provisioning. 139 * @param titleId resource id used to form the user facing error title 140 * @param messageId resource id used to form the user facing error message 141 * @param errorMessage an error message that gets logged for debugging 142 */ 143 void showErrorAndClose(Integer titleId, int messageId, String errorMessage); 144 145 /** 146 * Request the user to encrypt the device. 147 * @param params the {@link ProvisioningParams} object related to the ongoing provisioning 148 */ 149 void requestEncryption(ProvisioningParams params); 150 151 /** 152 * Request the user to choose a wifi network. 153 */ 154 void requestWifiPick(); 155 156 /** 157 * Initialize the pre provisioning UI 158 * @param layoutRes resource id for the layout 159 * @param titleRes resource id for the title text 160 * @param packageLabel package label 161 * @param packageIcon package icon 162 * @param isProfileOwnerProvisioning false for Device Owner provisioning 163 * @param isComp true if in COMP provisioning mode 164 * @param termsHeaders list of terms headers 165 * @param customization customization parameters 166 */ 167 void initiateUi(int layoutRes, int titleRes, @Nullable String packageLabel, 168 @Nullable Drawable packageIcon, boolean isProfileOwnerProvisioning, boolean isComp, 169 @NonNull List<String> termsHeaders, @NonNull CustomizationParams customization); 170 171 /** 172 * Start provisioning. 173 * @param userId the id of the user we want to start provisioning on 174 * @param params the {@link ProvisioningParams} object related to the ongoing provisioning 175 */ 176 void startProvisioning(int userId, ProvisioningParams params); 177 178 /** 179 * Show a dialog to delete an existing managed profile. 180 * @param mdmPackageName the {@link ComponentName} of the existing profile's profile owner 181 * @param domainName domain name of the organization which owns the managed profile 182 * @param userId the user id of the existing profile 183 */ 184 void showDeleteManagedProfileDialog(ComponentName mdmPackageName, String domainName, 185 int userId); 186 187 /** 188 * Show an error dialog indicating that the current launcher does not support managed 189 * profiles and ask the user to choose a different one. 190 */ 191 void showCurrentLauncherInvalid(); 192 } 193 194 /** 195 * Initiates Profile owner and device owner provisioning. 196 * @param intent Intent that started provisioning. 197 * @param params cached ProvisioningParams if it has been parsed from Intent 198 * @param callingPackage Package that started provisioning. 199 */ 200 public void initiateProvisioning(Intent intent, ProvisioningParams params, 201 String callingPackage) { 202 mProvisioningAnalyticsTracker.logProvisioningSessionStarted(mContext); 203 204 if (!tryParseParameters(intent, params)) { 205 return; 206 } 207 208 if (!checkFactoryResetProtection(mParams, callingPackage)) { 209 return; 210 } 211 212 if (!verifyActionAndCaller(intent, callingPackage)) { 213 return; 214 } 215 216 // Check whether provisioning is allowed for the current action 217 if (!checkDevicePolicyPreconditions()) { 218 return; 219 } 220 221 // PO preconditions 222 boolean waitForUserDelete = false; 223 if (isProfileOwnerProvisioning()) { 224 // If there is already a managed profile, setup the profile deletion dialog. 225 int existingManagedProfileUserId = mUtils.alreadyHasManagedProfile(mContext); 226 if (existingManagedProfileUserId != -1) { 227 ComponentName mdmPackageName = mDevicePolicyManager 228 .getProfileOwnerAsUser(existingManagedProfileUserId); 229 String domainName = mDevicePolicyManager 230 .getProfileOwnerNameAsUser(existingManagedProfileUserId); 231 mUi.showDeleteManagedProfileDialog(mdmPackageName, domainName, 232 existingManagedProfileUserId); 233 waitForUserDelete = true; 234 } 235 } 236 237 // DO preconditions 238 if (!isProfileOwnerProvisioning()) { 239 // TODO: make a general test based on deviceAdminDownloadInfo field 240 // PO doesn't ever initialize that field, so OK as a general case 241 if (!mUtils.isConnectedToNetwork(mContext) && mParams.wifiInfo == null 242 && mParams.deviceAdminDownloadInfo != null) { 243 // Have the user pick a wifi network if necessary. 244 // It is not possible to ask the user to pick a wifi network if 245 // the screen is locked. 246 // TODO: remove this check once we know the screen will not be locked. 247 if (mKeyguardManager.inKeyguardRestrictedInputMode()) { 248 // TODO: decide on what to do in that case; fail? retry on screen unlock? 249 ProvisionLogger.logi("Cannot pick wifi because the screen is locked."); 250 } else if (canRequestWifiPick()) { 251 // we resume this method after a successful WiFi pick 252 // TODO: refactor as evil - logic should be less spread out 253 mUi.requestWifiPick(); 254 return; 255 } else { 256 mUi.showErrorAndClose(R.string.cant_set_up_device, 257 R.string.contact_your_admin_for_help, 258 "Cannot pick WiFi because there is no handler to the intent"); 259 } 260 } 261 } 262 263 mTimeLogger.start(); 264 mProvisioningAnalyticsTracker.logPreProvisioningStarted(mContext, intent); 265 266 // as of now this is only true for COMP provisioning, where we already have a user consent 267 // since the DPC is DO already 268 if (mParams.skipUserConsent || isSilentProvisioningForTestingDeviceOwner() 269 || isSilentProvisioningForTestingManagedProfile()) { 270 if (!waitForUserDelete) { 271 continueProvisioningAfterUserConsent(); 272 } 273 return; 274 } 275 276 CustomizationParams customization = CustomizationParams.createInstance(mParams, mContext, 277 mUtils); 278 279 // show UI so we can get user's consent to continue 280 if (isProfileOwnerProvisioning()) { 281 boolean isComp = mDevicePolicyManager.isDeviceManaged(); 282 mUi.initiateUi(R.layout.intro_profile_owner, R.string.setup_profile, null, null, true, 283 isComp, getDisclaimerHeadings(), customization); 284 } else { 285 String packageName = mParams.inferDeviceAdminPackageName(); 286 MdmPackageInfo packageInfo = MdmPackageInfo.createFromPackageName(mContext, 287 packageName); 288 // Always take packageInfo first for installed app since PackageManager is more reliable 289 String packageLabel = packageInfo != null ? packageInfo.appLabel 290 : mParams.deviceAdminLabel != null ? mParams.deviceAdminLabel : packageName; 291 Drawable packageIcon = packageInfo != null ? packageInfo.packageIcon 292 : getDeviceAdminIconDrawable(mParams.deviceAdminIconFilePath); 293 mUi.initiateUi(R.layout.intro_device_owner, 294 R.string.setup_device, 295 packageLabel, 296 packageIcon, 297 false /* isProfileOwnerProvisioning */, 298 false, /* isComp */ 299 getDisclaimerHeadings(), 300 customization); 301 } 302 } 303 304 private @NonNull List<String> getDisclaimerHeadings() { 305 // TODO: only fetch headings, no need to fetch content; now not fast, but at least correct 306 return new TermsProvider(mContext, StoreUtils::readString, mUtils) 307 .getTerms(mParams, TermsProvider.Flags.SKIP_GENERAL_DISCLAIMER) 308 .stream() 309 .map(TermsDocument::getHeading) 310 .collect(Collectors.toList()); 311 } 312 313 private Drawable getDeviceAdminIconDrawable(String deviceAdminIconFilePath) { 314 if (deviceAdminIconFilePath == null) { 315 return null; 316 } 317 318 Bitmap bitmap = BitmapFactory.decodeFile(mParams.deviceAdminIconFilePath); 319 if (bitmap == null) { 320 return null; 321 } 322 return new BitmapDrawable(mContext.getResources(), bitmap); 323 } 324 325 /** 326 * Start provisioning for real. In profile owner case, double check that the launcher 327 * supports managed profiles if necessary. In device owner case, possibly create a new user 328 * before starting provisioning. 329 */ 330 public void continueProvisioningAfterUserConsent() { 331 // check if encryption is required 332 if (isEncryptionRequired()) { 333 if (mDevicePolicyManager.getStorageEncryptionStatus() 334 == DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED) { 335 mUi.showErrorAndClose(R.string.cant_set_up_device, 336 R.string.device_doesnt_allow_encryption_contact_admin, 337 "This device does not support encryption, and " 338 + DevicePolicyManager.EXTRA_PROVISIONING_SKIP_ENCRYPTION 339 + " was not passed."); 340 } else { 341 mUi.requestEncryption(mParams); 342 // we come back to this method after returning from encryption dialog 343 // TODO: refactor as evil - logic should be less spread out 344 } 345 return; 346 } 347 348 if (isProfileOwnerProvisioning()) { // PO case 349 // Check whether the current launcher supports managed profiles. 350 if (!mUtils.currentLauncherSupportsManagedProfiles(mContext)) { 351 mUi.showCurrentLauncherInvalid(); 352 // we come back to this method after returning from launcher dialog 353 // TODO: refactor as evil - logic should be less spread out 354 return; 355 } else { 356 // Cancel the boot reminder as provisioning has now started. 357 mEncryptionController.cancelEncryptionReminder(); 358 stopTimeLogger(); 359 mUi.startProvisioning(mUserManager.getUserHandle(), mParams); 360 } 361 } else { // DO case 362 // Cancel the boot reminder as provisioning has now started. 363 mEncryptionController.cancelEncryptionReminder(); 364 if (isMeatUserCreationRequired(mParams.provisioningAction)) { 365 // Create the primary user, and continue the provisioning in this user. 366 // successful end of this task triggers provisioning 367 // TODO: refactor as evil - logic should be less spread out 368 new CreatePrimaryUserTask().execute(); 369 } else { 370 stopTimeLogger(); 371 mUi.startProvisioning(mUserManager.getUserHandle(), mParams); 372 } 373 } 374 } 375 376 /** @return False if condition preventing further provisioning */ 377 @VisibleForTesting 378 boolean checkFactoryResetProtection(ProvisioningParams params, String callingPackage) { 379 if (skipFactoryResetProtectionCheck(params, callingPackage)) { 380 return true; 381 } 382 if (factoryResetProtected()) { 383 mUi.showErrorAndClose(R.string.cant_set_up_device, 384 R.string.device_has_reset_protection_contact_admin, 385 "Factory reset protection blocks provisioning."); 386 return false; 387 } 388 return true; 389 } 390 391 private boolean skipFactoryResetProtectionCheck( 392 ProvisioningParams params, String callingPackage) { 393 if (TextUtils.isEmpty(callingPackage)) { 394 return false; 395 } 396 String persistentDataPackageName = mContext.getResources() 397 .getString(com.android.internal.R.string.config_persistentDataPackageName); 398 try { 399 // Only skip the FRP check if the caller is the package responsible for maintaining FRP 400 // - i.e. if this is a flow for restoring device owner after factory reset. 401 PackageInfo callingPackageInfo = mPackageManager.getPackageInfo(callingPackage, 0); 402 return callingPackageInfo != null 403 && callingPackageInfo.applicationInfo != null 404 && callingPackageInfo.applicationInfo.isSystemApp() 405 && !TextUtils.isEmpty(persistentDataPackageName) 406 && callingPackage.equals(persistentDataPackageName) 407 && params != null 408 && params.startedByTrustedSource; 409 } catch (PackageManager.NameNotFoundException e) { 410 ProvisionLogger.loge("Calling package not found.", e); 411 return false; 412 } 413 } 414 415 /** @return False if condition preventing further provisioning */ 416 @VisibleForTesting protected boolean checkDevicePolicyPreconditions() { 417 // If isSilentProvisioningForTestingDeviceOwner returns true, the component must be 418 // current device owner, and we can safely ignore isProvisioningAllowed as we don't call 419 // setDeviceOwner. 420 if (isSilentProvisioningForTestingDeviceOwner()) { 421 return true; 422 } 423 424 int provisioningPreCondition = mDevicePolicyManager.checkProvisioningPreCondition( 425 mParams.provisioningAction, mParams.inferDeviceAdminPackageName()); 426 // Check whether provisioning is allowed for the current action. 427 if (provisioningPreCondition != CODE_OK) { 428 mProvisioningAnalyticsTracker.logProvisioningNotAllowed(mContext, 429 provisioningPreCondition); 430 showProvisioningErrorAndClose(mParams.provisioningAction, provisioningPreCondition); 431 return false; 432 } 433 return true; 434 } 435 436 /** @return False if condition preventing further provisioning */ 437 private boolean tryParseParameters(Intent intent, ProvisioningParams params) { 438 try { 439 // Read the provisioning params from the provisioning intent 440 mParams = params == null ? mMessageParser.parse(intent) : params; 441 } catch (IllegalProvisioningArgumentException e) { 442 mUi.showErrorAndClose(R.string.cant_set_up_device, R.string.contact_your_admin_for_help, 443 e.getMessage()); 444 return false; 445 } 446 return true; 447 } 448 449 /** @return False if condition preventing further provisioning */ 450 @VisibleForTesting protected boolean verifyActionAndCaller(Intent intent, 451 String callingPackage) { 452 if (verifyActionAndCallerInner(intent, callingPackage)) { 453 return true; 454 } else { 455 mUi.showErrorAndClose(R.string.cant_set_up_device, R.string.contact_your_admin_for_help, 456 "invalid intent or calling package"); 457 return false; 458 } 459 } 460 461 private boolean verifyActionAndCallerInner(Intent intent, String callingPackage) { 462 // If this is a resume after encryption or trusted intent, we verify the activity alias. 463 // Otherwise, verify that the calling app is trying to set itself as Device/ProfileOwner 464 if (ACTION_RESUME_PROVISIONING.equals(intent.getAction())) { 465 return verifyActivityAlias(intent, "PreProvisioningActivityAfterEncryption"); 466 } else if (ACTION_NDEF_DISCOVERED.equals(intent.getAction())) { 467 return verifyActivityAlias(intent, "PreProvisioningActivityViaNfc"); 468 } else if (ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE.equals(intent.getAction())) { 469 return verifyActivityAlias(intent, "PreProvisioningActivityViaTrustedApp"); 470 } else { 471 return verifyCaller(callingPackage); 472 } 473 } 474 475 private boolean verifyActivityAlias(Intent intent, String activityAlias) { 476 ComponentName componentName = intent.getComponent(); 477 if (componentName == null || componentName.getClassName() == null) { 478 ProvisionLogger.loge("null class in component when verifying activity alias " 479 + activityAlias); 480 return false; 481 } 482 483 if (!componentName.getClassName().endsWith(activityAlias)) { 484 ProvisionLogger.loge("Looking for activity alias " + activityAlias + ", but got " 485 + componentName.getClassName()); 486 return false; 487 } 488 489 return true; 490 } 491 492 /** 493 * Verify that the caller is trying to set itself as owner. 494 * @return false if the caller is trying to set a different package as owner. 495 */ 496 private boolean verifyCaller(@NonNull String callingPackage) { 497 if (callingPackage == null) { 498 ProvisionLogger.loge("Calling package is null. Was startActivityForResult used to " 499 + "start this activity?"); 500 return false; 501 } 502 503 if (!callingPackage.equals(mParams.inferDeviceAdminPackageName())) { 504 ProvisionLogger.loge("Permission denied, " 505 + "calling package tried to set a different package as owner. "); 506 return false; 507 } 508 509 return true; 510 } 511 512 /** 513 * Returns whether the device needs encryption. 514 */ 515 private boolean isEncryptionRequired() { 516 return !mParams.skipEncryption && mUtils.isEncryptionRequired(); 517 } 518 519 private boolean isSilentProvisioningForTestingDeviceOwner() { 520 final ComponentName currentDeviceOwner = 521 mDevicePolicyManager.getDeviceOwnerComponentOnCallingUser(); 522 final ComponentName targetDeviceAdmin = mParams.deviceAdminComponentName; 523 524 switch (mParams.provisioningAction) { 525 case DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE: 526 return isPackageTestOnly() 527 && currentDeviceOwner != null 528 && targetDeviceAdmin != null 529 && currentDeviceOwner.equals(targetDeviceAdmin); 530 default: 531 return false; 532 } 533 } 534 535 private boolean isSilentProvisioningForTestingManagedProfile() { 536 return DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE.equals( 537 mParams.provisioningAction) && isPackageTestOnly(); 538 } 539 540 private boolean isPackageTestOnly() { 541 return mUtils.isPackageTestOnly(mContext.getPackageManager(), 542 mParams.inferDeviceAdminPackageName(), mUserManager.getUserHandle()); 543 } 544 545 /** 546 * Returns whether the device is frp protected during setup wizard. 547 */ 548 private boolean factoryResetProtected() { 549 // If we are started during setup wizard, check for factory reset protection. 550 // If the device is already setup successfully, do not check factory reset protection. 551 if (mSettingsFacade.isDeviceProvisioned(mContext)) { 552 ProvisionLogger.logd("Device is provisioned, FRP not required."); 553 return false; 554 } 555 556 if (mPdbManager == null) { 557 ProvisionLogger.logd("Reset protection not supported."); 558 return false; 559 } 560 int size = mPdbManager.getDataBlockSize(); 561 ProvisionLogger.logd("Data block size: " + size); 562 return size > 0; 563 } 564 565 /** 566 * Returns whether meat user creation is required or not. 567 * @param action Intent action that started provisioning 568 */ 569 public boolean isMeatUserCreationRequired(String action) { 570 if (mUtils.isSplitSystemUser() 571 && ACTION_PROVISION_MANAGED_DEVICE.equals(action)) { 572 List<UserInfo> users = mUserManager.getUsers(); 573 if (users.size() > 1) { 574 mUi.showErrorAndClose(R.string.cant_set_up_device, 575 R.string.contact_your_admin_for_help, 576 "Cannot start Device Owner Provisioning because there are already " 577 + users.size() + " users"); 578 return false; 579 } 580 return true; 581 } else { 582 return false; 583 } 584 } 585 586 /** 587 * Returns whether activity to pick wifi can be requested or not. 588 */ 589 private boolean canRequestWifiPick() { 590 return mPackageManager.resolveActivity(mUtils.getWifiPickIntent(), 0) != null; 591 } 592 593 /** 594 * Returns whether the provisioning process is a profile owner provisioning process. 595 */ 596 public boolean isProfileOwnerProvisioning() { 597 return mUtils.isProfileOwnerAction(mParams.provisioningAction); 598 } 599 600 @Nullable 601 public ProvisioningParams getParams() { 602 return mParams; 603 } 604 605 /** 606 * Notifies the time logger to stop. 607 */ 608 public void stopTimeLogger() { 609 mTimeLogger.stop(); 610 } 611 612 /** 613 * Log if PreProvisioning was cancelled. 614 */ 615 public void logPreProvisioningCancelled() { 616 mProvisioningAnalyticsTracker.logProvisioningCancelled(mContext, 617 CANCELLED_BEFORE_PROVISIONING); 618 } 619 620 /** 621 * Removes a user profile. If we are in COMP case, and were blocked by having to delete a user, 622 * resumes COMP provisioning. 623 */ 624 public void removeUser(int userProfileId) { 625 // There is a possibility that the DO has set the disallow remove managed profile user 626 // restriction, but is initiating the provisioning. In this case, we still want to remove 627 // the managed profile. 628 // We know that we can remove the managed profile because we checked 629 // DevicePolicyManager.checkProvisioningPreCondition 630 mUserManager.removeUserEvenWhenDisallowed(userProfileId); 631 } 632 633 /** 634 * See comment in place of usage. Check if we were in silent provisioning, got blocked, and now 635 * can resume. 636 */ 637 public void checkResumeSilentProvisioning() { 638 if (mParams.skipUserConsent || isSilentProvisioningForTestingDeviceOwner() 639 || isSilentProvisioningForTestingManagedProfile()) { 640 continueProvisioningAfterUserConsent(); 641 } 642 } 643 644 // TODO: review the use of async task for the case where the activity might have got killed 645 private class CreatePrimaryUserTask extends AsyncTask<Void, Void, UserInfo> { 646 @Override 647 protected UserInfo doInBackground(Void... args) { 648 // Create the user where we're going to install the device owner. 649 UserInfo userInfo = mUserManager.createUser( 650 mContext.getString(R.string.default_first_meat_user_name), 651 UserInfo.FLAG_PRIMARY | UserInfo.FLAG_ADMIN); 652 653 if (userInfo != null) { 654 ProvisionLogger.logi("Created user " + userInfo.id + " to hold the device owner"); 655 } 656 return userInfo; 657 } 658 659 @Override 660 protected void onPostExecute(UserInfo userInfo) { 661 if (userInfo == null) { 662 mUi.showErrorAndClose(R.string.cant_set_up_device, 663 R.string.contact_your_admin_for_help, 664 "Could not create user to hold the device owner"); 665 } else { 666 mActivityManager.switchUser(userInfo.id); 667 stopTimeLogger(); 668 // TODO: refactor as evil - logic should be less spread out 669 mUi.startProvisioning(userInfo.id, mParams); 670 } 671 } 672 } 673 674 private void showProvisioningErrorAndClose(String action, int provisioningPreCondition) { 675 // Try to show an error message explaining why provisioning is not allowed. 676 switch (action) { 677 case ACTION_PROVISION_MANAGED_USER: 678 mUi.showErrorAndClose(R.string.cant_set_up_device, 679 R.string.contact_your_admin_for_help, 680 "Exiting managed user provisioning, setup incomplete"); 681 return; 682 case ACTION_PROVISION_MANAGED_PROFILE: 683 showManagedProfileErrorAndClose(provisioningPreCondition); 684 return; 685 case ACTION_PROVISION_MANAGED_DEVICE: 686 case ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE: 687 showDeviceOwnerErrorAndClose(provisioningPreCondition); 688 return; 689 } 690 // This should never be the case, as showProvisioningError is always called after 691 // verifying the supported provisioning actions. 692 } 693 694 private void showManagedProfileErrorAndClose(int provisioningPreCondition) { 695 UserInfo userInfo = mUserManager.getUserInfo(mUserManager.getUserHandle()); 696 ProvisionLogger.logw("DevicePolicyManager.checkProvisioningPreCondition returns code: " 697 + provisioningPreCondition); 698 switch (provisioningPreCondition) { 699 case CODE_ADD_MANAGED_PROFILE_DISALLOWED: 700 case CODE_MANAGED_USERS_NOT_SUPPORTED: 701 mUi.showErrorAndClose(R.string.cant_add_work_profile, 702 R.string.work_profile_cant_be_added_contact_admin, 703 "Exiting managed profile provisioning, managed profiles feature is not available"); 704 break; 705 case CODE_CANNOT_ADD_MANAGED_PROFILE: 706 if (!userInfo.canHaveProfile()) { 707 mUi.showErrorAndClose(R.string.cant_add_work_profile, 708 R.string.work_profile_cant_be_added_contact_admin, 709 "Exiting managed profile provisioning, calling user cannot have managed profiles"); 710 } else if (isRemovingManagedProfileDisallowed()){ 711 mUi.showErrorAndClose(R.string.cant_replace_or_remove_work_profile, 712 R.string.for_help_contact_admin, 713 "Exiting managed profile provisioning, removing managed profile is disallowed"); 714 } else { 715 mUi.showErrorAndClose(R.string.cant_add_work_profile, 716 R.string.work_profile_cant_be_added_contact_admin, 717 "Exiting managed profile provisioning, cannot add more managed profiles"); 718 } 719 break; 720 case CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER: 721 mUi.showErrorAndClose(R.string.cant_add_work_profile, 722 R.string.contact_your_admin_for_help, 723 "Exiting managed profile provisioning, a device owner exists"); 724 break; 725 default: 726 mUi.showErrorAndClose(R.string.cant_add_work_profile, 727 R.string.contact_your_admin_for_help, 728 "Managed profile provisioning not allowed for an unknown " + 729 "reason, code: " + provisioningPreCondition); 730 } 731 } 732 733 private boolean isRemovingManagedProfileDisallowed() { 734 return mUtils.alreadyHasManagedProfile(mContext) != -1 735 && mUserManager.hasUserRestriction(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE); 736 } 737 738 private void showDeviceOwnerErrorAndClose(int provisioningPreCondition) { 739 switch (provisioningPreCondition) { 740 case CODE_HAS_DEVICE_OWNER: 741 mUi.showErrorAndClose(R.string.device_already_set_up, 742 R.string.if_questions_contact_admin, "Device already provisioned."); 743 return; 744 case CODE_NOT_SYSTEM_USER: 745 mUi.showErrorAndClose(R.string.cant_set_up_device, 746 R.string.contact_your_admin_for_help, 747 "Device owner can only be set up for USER_SYSTEM."); 748 return; 749 case CODE_NOT_SYSTEM_USER_SPLIT: 750 mUi.showErrorAndClose(R.string.cant_set_up_device, 751 R.string.contact_your_admin_for_help, 752 "System User Device owner can only be set on a split-user system."); 753 return; 754 } 755 mUi.showErrorAndClose(R.string.cant_set_up_device, R.string.contact_your_admin_for_help, 756 "Device Owner provisioning not allowed for an unknown reason."); 757 } 758 } 759