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 (shouldShowWifiPicker()) { 292 // Have the user pick a wifi network if necessary. 293 // It is not possible to ask the user to pick a wifi network if 294 // the screen is locked. 295 // TODO: remove this check once we know the screen will not be locked. 296 if (mKeyguardManager.inKeyguardRestrictedInputMode()) { 297 // TODO: decide on what to do in that case; fail? retry on screen unlock? 298 ProvisionLogger.logi("Cannot pick wifi because the screen is locked."); 299 } else if (canRequestWifiPick()) { 300 // we resume this method after a successful WiFi pick 301 // TODO: refactor as evil - logic should be less spread out 302 mUi.requestWifiPick(); 303 return; 304 } else { 305 mUi.showErrorAndClose(R.string.cant_set_up_device, 306 R.string.contact_your_admin_for_help, 307 "Cannot pick WiFi because there is no handler to the intent"); 308 } 309 } 310 } 311 312 mTimeLogger.start(); 313 mProvisioningAnalyticsTracker.logPreProvisioningStarted(mContext, intent); 314 315 if (mParams.isOrganizationOwnedProvisioning) { 316 mUi.prepareAdminIntegratedFlow(mParams); 317 } else { 318 // skipUserConsent can only be set from a device owner provisioning to a work profile. 319 if (mParams.skipUserConsent || Utils.isSilentProvisioning(mContext, mParams)) { 320 continueProvisioningAfterUserConsent(); 321 } else { 322 showUserConsentScreen(); 323 } 324 } 325 } 326 shouldShowWifiPicker()327 private boolean shouldShowWifiPicker() { 328 if (mParams.wifiInfo != null) { 329 return false; 330 } 331 if (mParams.deviceAdminDownloadInfo == null) { 332 return false; 333 } 334 if (mUtils.isConnectedToWifi(mContext)) { 335 return false; 336 } 337 if (mParams.useMobileData) { 338 return !mUtils.isMobileNetworkConnectedToInternet(mContext); 339 } 340 return true; 341 } 342 showUserConsentScreen()343 void showUserConsentScreen() { 344 // Check whether provisioning is allowed for the current action 345 if (!checkDevicePolicyPreconditions()) { 346 if (mParams.isOrganizationOwnedProvisioning) { 347 mUi.showFactoryResetDialog(R.string.cant_set_up_device, 348 R.string.contact_your_admin_for_help); 349 } else { 350 return; 351 } 352 } 353 354 ProvisionLogger.logd("Sending user consent:" + mParams.provisioningAction); 355 356 CustomizationParams customization = 357 CustomizationParams.createInstance(mParams, mContext, mUtils); 358 359 ProvisionLogger.logd("Provisioning action for user consent:" + mParams.provisioningAction); 360 361 // show UI so we can get user's consent to continue 362 final String packageName = mParams.inferDeviceAdminPackageName(); 363 final MdmPackageInfo packageInfo = 364 MdmPackageInfo.createFromPackageName(mContext, packageName); 365 final UiParams uiParams = new UiParams(); 366 uiParams.customization = customization; 367 uiParams.deviceAdminIconFilePath = mParams.deviceAdminIconFilePath; 368 uiParams.deviceAdminLabel = mParams.deviceAdminLabel; 369 uiParams.disclaimerHeadings = getDisclaimerHeadings(); 370 uiParams.provisioningMode = mParams.provisioningMode; 371 uiParams.provisioningAction = mParams.provisioningAction; 372 uiParams.packageName = packageName; 373 uiParams.isDeviceManaged = mDevicePolicyManager.isDeviceManaged(); 374 uiParams.packageInfo = packageInfo; 375 uiParams.viewTermsIntent = createViewTermsIntent(); 376 uiParams.isSilentProvisioning = Utils.isSilentProvisioning(mContext, mParams); 377 uiParams.isOrganizationOwnedProvisioning = mParams.isOrganizationOwnedProvisioning; 378 379 mUi.initiateUi(uiParams); 380 } 381 updateProvisioningParamsFromIntent(Intent resultIntent)382 boolean updateProvisioningParamsFromIntent(Intent resultIntent) { 383 final int provisioningMode = resultIntent.getIntExtra( 384 DevicePolicyManager.EXTRA_PROVISIONING_MODE, 0); 385 final ProvisioningParams.Builder builder = mParams.toBuilder(); 386 switch (provisioningMode) { 387 case DevicePolicyManager.PROVISIONING_MODE_FULLY_MANAGED_DEVICE: 388 builder.setProvisioningMode(PROVISIONING_MODE_FULLY_MANAGED_DEVICE); 389 builder.setProvisioningAction(ACTION_PROVISION_MANAGED_DEVICE); 390 maybeUpdateAdminExtrasBundle(builder, resultIntent); 391 maybeUpdateSkipEducationScreens(builder, resultIntent); 392 mParams = builder.build(); 393 return true; 394 case DevicePolicyManager.PROVISIONING_MODE_MANAGED_PROFILE: 395 builder.setProvisioningMode(PROVISIONING_MODE_MANAGED_PROFILE); 396 builder.setProvisioningAction(ACTION_PROVISION_MANAGED_PROFILE); 397 maybeUpdateAccountToMigrate(builder, resultIntent); 398 maybeUpdateAdminExtrasBundle(builder, resultIntent); 399 maybeUpdateSkipEducationScreens(builder, resultIntent); 400 mParams = builder.build(); 401 return true; 402 default: 403 ProvisionLogger.logw("Unknown returned provisioning mode:" 404 + provisioningMode); 405 return false; 406 } 407 } 408 maybeUpdateSkipEducationScreens(ProvisioningParams.Builder builder, Intent resultIntent)409 private void maybeUpdateSkipEducationScreens(ProvisioningParams.Builder builder, 410 Intent resultIntent) { 411 if (resultIntent.hasExtra(EXTRA_PROVISIONING_SKIP_EDUCATION_SCREENS)) { 412 builder.setSkipEducationScreens(resultIntent.getBooleanExtra( 413 EXTRA_PROVISIONING_SKIP_EDUCATION_SCREENS, /* defaultValue */ false)); 414 } 415 } 416 maybeUpdateAccountToMigrate(ProvisioningParams.Builder builder, Intent resultIntent)417 private void maybeUpdateAccountToMigrate(ProvisioningParams.Builder builder, 418 Intent resultIntent) { 419 if (resultIntent.hasExtra(EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE)) { 420 final Account account = resultIntent.getParcelableExtra( 421 EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE); 422 builder.setAccountToMigrate(account); 423 } 424 } 425 maybeUpdateAdminExtrasBundle(ProvisioningParams.Builder builder, Intent resultIntent)426 private void maybeUpdateAdminExtrasBundle(ProvisioningParams.Builder builder, 427 Intent resultIntent) { 428 if (resultIntent.hasExtra(EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE)) { 429 final PersistableBundle bundle = resultIntent.getParcelableExtra( 430 EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE); 431 builder.setAdminExtrasBundle(bundle); 432 } 433 } 434 setProvisioningMode(int provisioningMode)435 void setProvisioningMode(int provisioningMode) { 436 mParams = mParams.toBuilder().setProvisioningMode(provisioningMode).build(); 437 } 438 putExtrasIntoGetModeIntent(Intent intentGetMode)439 void putExtrasIntoGetModeIntent(Intent intentGetMode) { 440 final TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class); 441 intentGetMode.putExtra(EXTRA_PROVISIONING_IMEI, telephonyManager.getImei()); 442 intentGetMode.putExtra(EXTRA_PROVISIONING_SERIAL_NUMBER, Build.getSerial()); 443 intentGetMode.putExtra(EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE, mParams.adminExtrasBundle); 444 } 445 getDisclaimerHeadings()446 private @NonNull List<String> getDisclaimerHeadings() { 447 // TODO: only fetch headings, no need to fetch content; now not fast, but at least correct 448 return new TermsProvider(mContext, StoreUtils::readString, mUtils) 449 .getTerms(mParams, TermsProvider.Flags.SKIP_GENERAL_DISCLAIMER) 450 .stream() 451 .map(TermsDocument::getHeading) 452 .collect(Collectors.toList()); 453 } 454 createViewTermsIntent()455 private Intent createViewTermsIntent() { 456 return new Intent(mContext, TermsActivity.class).putExtra( 457 ProvisioningParams.EXTRA_PROVISIONING_PARAMS, mParams); 458 } 459 460 /** 461 * Start provisioning for real. In profile owner case, double check that the launcher 462 * supports managed profiles if necessary. In device owner case, possibly create a new user 463 * before starting provisioning. 464 */ continueProvisioningAfterUserConsent()465 public void continueProvisioningAfterUserConsent() { 466 mProvisioningAnalyticsTracker.logProvisioningAction(mContext, mParams.provisioningAction); 467 468 // check if encryption is required 469 if (isEncryptionRequired()) { 470 if (mDevicePolicyManager.getStorageEncryptionStatus() 471 == DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED) { 472 mUi.showErrorAndClose(R.string.cant_set_up_device, 473 R.string.device_doesnt_allow_encryption_contact_admin, 474 "This device does not support encryption, and " 475 + DevicePolicyManager.EXTRA_PROVISIONING_SKIP_ENCRYPTION 476 + " was not passed."); 477 } else { 478 mUi.requestEncryption(mParams); 479 // we come back to this method after returning from encryption dialog 480 // TODO: refactor as evil - logic should be less spread out 481 } 482 return; 483 } 484 485 if (isProfileOwnerProvisioning()) { // PO case 486 // Check whether the current launcher supports managed profiles. 487 if (!mUtils.currentLauncherSupportsManagedProfiles(mContext)) { 488 mUi.showCurrentLauncherInvalid(); 489 // we come back to this method after returning from launcher dialog 490 // TODO: refactor as evil - logic should be less spread out 491 return; 492 } else { 493 // Cancel the boot reminder as provisioning has now started. 494 mEncryptionController.cancelEncryptionReminder(); 495 stopTimeLogger(); 496 mUi.startProvisioning(mUserManager.getUserHandle(), mParams); 497 } 498 } else { // DO case 499 // Cancel the boot reminder as provisioning has now started. 500 mEncryptionController.cancelEncryptionReminder(); 501 if (isMeatUserCreationRequired(mParams.provisioningAction)) { 502 // Create the primary user, and continue the provisioning in this user. 503 // successful end of this task triggers provisioning 504 // TODO: refactor as evil - logic should be less spread out 505 new CreatePrimaryUserTask().execute(); 506 } else { 507 stopTimeLogger(); 508 mUi.startProvisioning(mUserManager.getUserHandle(), mParams); 509 } 510 } 511 } 512 513 /** @return False if condition preventing further provisioning */ 514 @VisibleForTesting checkFactoryResetProtection(ProvisioningParams params, String callingPackage)515 boolean checkFactoryResetProtection(ProvisioningParams params, String callingPackage) { 516 if (skipFactoryResetProtectionCheck(params, callingPackage)) { 517 return true; 518 } 519 if (factoryResetProtected()) { 520 mUi.showErrorAndClose(R.string.cant_set_up_device, 521 R.string.device_has_reset_protection_contact_admin, 522 "Factory reset protection blocks provisioning."); 523 return false; 524 } 525 return true; 526 } 527 skipFactoryResetProtectionCheck( ProvisioningParams params, String callingPackage)528 private boolean skipFactoryResetProtectionCheck( 529 ProvisioningParams params, String callingPackage) { 530 if (TextUtils.isEmpty(callingPackage)) { 531 return false; 532 } 533 String persistentDataPackageName = mContext.getResources() 534 .getString(com.android.internal.R.string.config_persistentDataPackageName); 535 try { 536 // Only skip the FRP check if the caller is the package responsible for maintaining FRP 537 // - i.e. if this is a flow for restoring device owner after factory reset. 538 PackageInfo callingPackageInfo = mPackageManager.getPackageInfo(callingPackage, 0); 539 return callingPackageInfo != null 540 && callingPackageInfo.applicationInfo != null 541 && callingPackageInfo.applicationInfo.isSystemApp() 542 && !TextUtils.isEmpty(persistentDataPackageName) 543 && callingPackage.equals(persistentDataPackageName) 544 && params != null 545 && params.startedByTrustedSource; 546 } catch (PackageManager.NameNotFoundException e) { 547 ProvisionLogger.loge("Calling package not found.", e); 548 return false; 549 } 550 } 551 552 /** @return False if condition preventing further provisioning */ checkDevicePolicyPreconditions()553 @VisibleForTesting protected boolean checkDevicePolicyPreconditions() { 554 // If isSilentProvisioningForTestingDeviceOwner returns true, the component must be 555 // current device owner, and we can safely ignore isProvisioningAllowed as we don't call 556 // setDeviceOwner. 557 if (Utils.isSilentProvisioningForTestingDeviceOwner(mContext, mParams)) { 558 return true; 559 } 560 561 int provisioningPreCondition = mDevicePolicyManager.checkProvisioningPreCondition( 562 mParams.provisioningAction, mParams.inferDeviceAdminPackageName()); 563 // Check whether provisioning is allowed for the current action. 564 if (provisioningPreCondition != CODE_OK) { 565 mProvisioningAnalyticsTracker.logProvisioningNotAllowed(mContext, 566 provisioningPreCondition); 567 showProvisioningErrorAndClose(mParams.provisioningAction, provisioningPreCondition); 568 return false; 569 } 570 return true; 571 } 572 573 /** @return False if condition preventing further provisioning */ tryParseParameters(Intent intent, ProvisioningParams params)574 private boolean tryParseParameters(Intent intent, ProvisioningParams params) { 575 try { 576 // Read the provisioning params from the provisioning intent 577 mParams = params == null ? mMessageParser.parse(intent) : params; 578 } catch (IllegalProvisioningArgumentException e) { 579 mUi.showErrorAndClose(R.string.cant_set_up_device, R.string.contact_your_admin_for_help, 580 e.getMessage()); 581 return false; 582 } 583 return true; 584 } 585 586 /** @return False if condition preventing further provisioning */ verifyActionAndCaller(Intent intent, String callingPackage)587 @VisibleForTesting protected boolean verifyActionAndCaller(Intent intent, 588 String callingPackage) { 589 if (verifyActionAndCallerInner(intent, callingPackage)) { 590 return true; 591 } else { 592 mUi.showErrorAndClose(R.string.cant_set_up_device, R.string.contact_your_admin_for_help, 593 "invalid intent or calling package"); 594 return false; 595 } 596 } 597 verifyActionAndCallerInner(Intent intent, String callingPackage)598 private boolean verifyActionAndCallerInner(Intent intent, String callingPackage) { 599 // If this is a resume after encryption or trusted intent, we verify the activity alias. 600 // Otherwise, verify that the calling app is trying to set itself as Device/ProfileOwner 601 if (ACTION_RESUME_PROVISIONING.equals(intent.getAction())) { 602 return verifyActivityAlias(intent, "PreProvisioningActivityAfterEncryption"); 603 } else if (ACTION_NDEF_DISCOVERED.equals(intent.getAction())) { 604 return verifyActivityAlias(intent, "PreProvisioningActivityViaNfc"); 605 } else if (ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE.equals(intent.getAction())) { 606 return verifyActivityAlias(intent, "PreProvisioningActivityViaTrustedApp"); 607 } else { 608 return verifyCaller(callingPackage); 609 } 610 } 611 verifyActivityAlias(Intent intent, String activityAlias)612 private boolean verifyActivityAlias(Intent intent, String activityAlias) { 613 ComponentName componentName = intent.getComponent(); 614 if (componentName == null || componentName.getClassName() == null) { 615 ProvisionLogger.loge("null class in component when verifying activity alias " 616 + activityAlias); 617 return false; 618 } 619 620 if (!componentName.getClassName().endsWith(activityAlias)) { 621 ProvisionLogger.loge("Looking for activity alias " + activityAlias + ", but got " 622 + componentName.getClassName()); 623 return false; 624 } 625 626 return true; 627 } 628 629 /** 630 * Verify that the caller is trying to set itself as owner. 631 * @return false if the caller is trying to set a different package as owner. 632 */ verifyCaller(@onNull String callingPackage)633 private boolean verifyCaller(@NonNull String callingPackage) { 634 if (callingPackage == null) { 635 ProvisionLogger.loge("Calling package is null. Was startActivityForResult used to " 636 + "start this activity?"); 637 return false; 638 } 639 640 if (!callingPackage.equals(mParams.inferDeviceAdminPackageName())) { 641 ProvisionLogger.loge("Permission denied, " 642 + "calling package tried to set a different package as owner. "); 643 return false; 644 } 645 646 return true; 647 } 648 649 /** 650 * Returns whether the device needs encryption. 651 */ isEncryptionRequired()652 private boolean isEncryptionRequired() { 653 return !mParams.skipEncryption && mUtils.isEncryptionRequired(); 654 } 655 656 /** 657 * Returns whether the device is frp protected during setup wizard. 658 */ factoryResetProtected()659 private boolean factoryResetProtected() { 660 // If we are started during setup wizard, check for factory reset protection. 661 // If the device is already setup successfully, do not check factory reset protection. 662 if (mSettingsFacade.isDeviceProvisioned(mContext)) { 663 ProvisionLogger.logd("Device is provisioned, FRP not required."); 664 return false; 665 } 666 667 if (mPdbManager == null) { 668 ProvisionLogger.logd("Reset protection not supported."); 669 return false; 670 } 671 int size = mPdbManager.getDataBlockSize(); 672 ProvisionLogger.logd("Data block size: " + size); 673 return size > 0; 674 } 675 676 /** 677 * Returns whether meat user creation is required or not. 678 * @param action Intent action that started provisioning 679 */ isMeatUserCreationRequired(String action)680 public boolean isMeatUserCreationRequired(String action) { 681 if (mUtils.isSplitSystemUser() 682 && ACTION_PROVISION_MANAGED_DEVICE.equals(action)) { 683 List<UserInfo> users = mUserManager.getUsers(); 684 if (users.size() > 1) { 685 mUi.showErrorAndClose(R.string.cant_set_up_device, 686 R.string.contact_your_admin_for_help, 687 "Cannot start Device Owner Provisioning because there are already " 688 + users.size() + " users"); 689 return false; 690 } 691 return true; 692 } else { 693 return false; 694 } 695 } 696 697 /** 698 * Returns whether activity to pick wifi can be requested or not. 699 */ canRequestWifiPick()700 private boolean canRequestWifiPick() { 701 return mPackageManager.resolveActivity(mUtils.getWifiPickIntent(), 0) != null; 702 } 703 704 /** 705 * Returns whether the provisioning process is a profile owner provisioning process. 706 */ isProfileOwnerProvisioning()707 public boolean isProfileOwnerProvisioning() { 708 return mUtils.isProfileOwnerAction(mParams.provisioningAction); 709 } 710 711 /** 712 * Returns whether the provisioning process is a device owner provisioning process. 713 */ isDeviceOwnerProvisioning()714 public boolean isDeviceOwnerProvisioning() { 715 return mUtils.isDeviceOwnerAction(mParams.provisioningAction); 716 } 717 718 719 @Nullable getParams()720 public ProvisioningParams getParams() { 721 return mParams; 722 } 723 724 /** 725 * Notifies the time logger to stop. 726 */ stopTimeLogger()727 public void stopTimeLogger() { 728 mTimeLogger.stop(); 729 } 730 731 /** 732 * Log if PreProvisioning was cancelled. 733 */ logPreProvisioningCancelled()734 public void logPreProvisioningCancelled() { 735 mProvisioningAnalyticsTracker.logProvisioningCancelled(mContext, 736 CANCELLED_BEFORE_PROVISIONING); 737 } 738 739 /** 740 * Removes a user profile. If we are in COMP case, and were blocked by having to delete a user, 741 * resumes COMP provisioning. 742 */ removeUser(int userProfileId)743 public void removeUser(int userProfileId) { 744 // There is a possibility that the DO has set the disallow remove managed profile user 745 // restriction, but is initiating the provisioning. In this case, we still want to remove 746 // the managed profile. 747 // We know that we can remove the managed profile because we checked 748 // DevicePolicyManager.checkProvisioningPreCondition 749 mUserManager.removeUserEvenWhenDisallowed(userProfileId); 750 } 751 getSettingsFacade()752 SettingsFacade getSettingsFacade() { 753 return mSettingsFacade; 754 } 755 756 // TODO: review the use of async task for the case where the activity might have got killed 757 private class CreatePrimaryUserTask extends AsyncTask<Void, Void, UserInfo> { 758 @Override doInBackground(Void... args)759 protected UserInfo doInBackground(Void... args) { 760 // Create the user where we're going to install the device owner. 761 UserInfo userInfo = mUserManager.createUser( 762 mContext.getString(R.string.default_first_meat_user_name), 763 UserInfo.FLAG_PRIMARY | UserInfo.FLAG_ADMIN); 764 765 if (userInfo != null) { 766 ProvisionLogger.logi("Created user " + userInfo.id + " to hold the device owner"); 767 } 768 return userInfo; 769 } 770 771 @Override onPostExecute(UserInfo userInfo)772 protected void onPostExecute(UserInfo userInfo) { 773 if (userInfo == null) { 774 mUi.showErrorAndClose(R.string.cant_set_up_device, 775 R.string.contact_your_admin_for_help, 776 "Could not create user to hold the device owner"); 777 } else { 778 mActivityManager.switchUser(userInfo.id); 779 stopTimeLogger(); 780 // TODO: refactor as evil - logic should be less spread out 781 mUi.startProvisioning(userInfo.id, mParams); 782 } 783 } 784 } 785 showProvisioningErrorAndClose(String action, int provisioningPreCondition)786 private void showProvisioningErrorAndClose(String action, int provisioningPreCondition) { 787 // Try to show an error message explaining why provisioning is not allowed. 788 switch (action) { 789 case ACTION_PROVISION_MANAGED_USER: 790 mUi.showErrorAndClose(R.string.cant_set_up_device, 791 R.string.contact_your_admin_for_help, 792 "Exiting managed user provisioning, setup incomplete"); 793 return; 794 case ACTION_PROVISION_MANAGED_PROFILE: 795 showManagedProfileErrorAndClose(provisioningPreCondition); 796 return; 797 case ACTION_PROVISION_MANAGED_DEVICE: 798 case ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE: 799 showDeviceOwnerErrorAndClose(provisioningPreCondition); 800 return; 801 } 802 // This should never be the case, as showProvisioningError is always called after 803 // verifying the supported provisioning actions. 804 } 805 showManagedProfileErrorAndClose(int provisioningPreCondition)806 private void showManagedProfileErrorAndClose(int provisioningPreCondition) { 807 UserInfo userInfo = mUserManager.getUserInfo(mUserManager.getUserHandle()); 808 ProvisionLogger.logw("DevicePolicyManager.checkProvisioningPreCondition returns code: " 809 + provisioningPreCondition); 810 switch (provisioningPreCondition) { 811 case CODE_ADD_MANAGED_PROFILE_DISALLOWED: 812 case CODE_MANAGED_USERS_NOT_SUPPORTED: 813 mUi.showErrorAndClose(R.string.cant_add_work_profile, 814 R.string.work_profile_cant_be_added_contact_admin, 815 "Exiting managed profile provisioning, managed profiles feature is not available"); 816 break; 817 case CODE_CANNOT_ADD_MANAGED_PROFILE: 818 if (!userInfo.canHaveProfile()) { 819 mUi.showErrorAndClose(R.string.cant_add_work_profile, 820 R.string.work_profile_cant_be_added_contact_admin, 821 "Exiting managed profile provisioning, calling user cannot have managed profiles"); 822 } else if (isRemovingManagedProfileDisallowed()){ 823 mUi.showErrorAndClose(R.string.cant_replace_or_remove_work_profile, 824 R.string.for_help_contact_admin, 825 "Exiting managed profile provisioning, removing managed profile is disallowed"); 826 } else { 827 mUi.showErrorAndClose(R.string.cant_add_work_profile, 828 R.string.work_profile_cant_be_added_contact_admin, 829 "Exiting managed profile provisioning, cannot add more managed profiles"); 830 } 831 break; 832 case CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER: 833 mUi.showErrorAndClose(R.string.cant_add_work_profile, 834 R.string.contact_your_admin_for_help, 835 "Exiting managed profile provisioning, a device owner exists"); 836 break; 837 default: 838 mUi.showErrorAndClose(R.string.cant_add_work_profile, 839 R.string.contact_your_admin_for_help, 840 "Managed profile provisioning not allowed for an unknown " + 841 "reason, code: " + provisioningPreCondition); 842 } 843 } 844 isRemovingManagedProfileDisallowed()845 private boolean isRemovingManagedProfileDisallowed() { 846 return mUtils.alreadyHasManagedProfile(mContext) != -1 847 && mUserManager.hasUserRestriction(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE); 848 } 849 showDeviceOwnerErrorAndClose(int provisioningPreCondition)850 private void showDeviceOwnerErrorAndClose(int provisioningPreCondition) { 851 switch (provisioningPreCondition) { 852 case CODE_HAS_DEVICE_OWNER: 853 case CODE_USER_SETUP_COMPLETED: 854 mUi.showErrorAndClose(R.string.device_already_set_up, 855 R.string.if_questions_contact_admin, "Device already provisioned."); 856 return; 857 case CODE_NOT_SYSTEM_USER: 858 mUi.showErrorAndClose(R.string.cant_set_up_device, 859 R.string.contact_your_admin_for_help, 860 "Device owner can only be set up for USER_SYSTEM."); 861 return; 862 case CODE_NOT_SYSTEM_USER_SPLIT: 863 mUi.showErrorAndClose(R.string.cant_set_up_device, 864 R.string.contact_your_admin_for_help, 865 "System User Device owner can only be set on a split-user system."); 866 return; 867 } 868 mUi.showErrorAndClose(R.string.cant_set_up_device, R.string.contact_your_admin_for_help, 869 "Device Owner provisioning not allowed for an unknown reason."); 870 } 871 } 872