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