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