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.EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE; 24 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE; 25 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ALLOWED_PROVISIONING_MODES; 26 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DISCLAIMERS; 27 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_IMEI; 28 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION; 29 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED; 30 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LOCALE; 31 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LOCAL_TIME; 32 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_SENSORS_PERMISSION_GRANT_OPT_OUT; 33 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_SERIAL_NUMBER; 34 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_SKIP_EDUCATION_SCREENS; 35 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_SKIP_ENCRYPTION; 36 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_TIME_ZONE; 37 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_TRIGGER; 38 import static android.app.admin.DevicePolicyManager.FLAG_SUPPORTED_MODES_DEVICE_OWNER; 39 import static android.app.admin.DevicePolicyManager.FLAG_SUPPORTED_MODES_ORGANIZATION_OWNED; 40 import static android.app.admin.DevicePolicyManager.PROVISIONING_MODE_MANAGED_PROFILE_ON_PERSONAL_DEVICE; 41 import static android.app.admin.DevicePolicyManager.PROVISIONING_TRIGGER_NFC; 42 import static android.app.admin.DevicePolicyManager.PROVISIONING_TRIGGER_QR_CODE; 43 import static android.app.admin.DevicePolicyManager.PROVISIONING_TRIGGER_UNSPECIFIED; 44 import static android.app.admin.DevicePolicyManager.STATUS_CANNOT_ADD_MANAGED_PROFILE; 45 import static android.app.admin.DevicePolicyManager.STATUS_HAS_DEVICE_OWNER; 46 import static android.app.admin.DevicePolicyManager.STATUS_MANAGED_USERS_NOT_SUPPORTED; 47 import static android.app.admin.DevicePolicyManager.STATUS_NOT_SYSTEM_USER; 48 import static android.app.admin.DevicePolicyManager.STATUS_OK; 49 import static android.app.admin.DevicePolicyManager.STATUS_PROVISIONING_NOT_ALLOWED_FOR_NON_DEVELOPER_USERS; 50 import static android.app.admin.DevicePolicyManager.STATUS_USER_SETUP_COMPLETED; 51 52 import static com.android.managedprovisioning.analytics.ProvisioningAnalyticsTracker.CANCELLED_BEFORE_PROVISIONING; 53 import static com.android.managedprovisioning.common.Globals.ACTION_RESUME_PROVISIONING; 54 import static com.android.managedprovisioning.model.ProvisioningParams.DEFAULT_EXTRA_PROVISIONING_KEEP_ACCOUNT_MIGRATED; 55 import static com.android.managedprovisioning.model.ProvisioningParams.DEFAULT_EXTRA_PROVISIONING_PERMISSION_GRANT_OPT_OUT; 56 import static com.android.managedprovisioning.model.ProvisioningParams.DEFAULT_EXTRA_PROVISIONING_SKIP_ENCRYPTION; 57 import static com.android.managedprovisioning.model.ProvisioningParams.DEFAULT_LEAVE_ALL_SYSTEM_APPS_ENABLED; 58 import static com.android.managedprovisioning.model.ProvisioningParams.FLOW_TYPE_ADMIN_INTEGRATED; 59 60 import static java.util.Objects.requireNonNull; 61 62 import android.accounts.Account; 63 import android.annotation.NonNull; 64 import android.annotation.Nullable; 65 import android.app.Activity; 66 import android.app.KeyguardManager; 67 import android.app.admin.DevicePolicyManager; 68 import android.content.ComponentName; 69 import android.content.Context; 70 import android.content.Intent; 71 import android.content.pm.PackageInfo; 72 import android.content.pm.PackageManager; 73 import android.os.Build; 74 import android.os.Bundle; 75 import android.os.PersistableBundle; 76 import android.os.SystemClock; 77 import android.os.UserManager; 78 import android.service.persistentdata.PersistentDataBlockManager; 79 import android.telephony.TelephonyManager; 80 import android.text.TextUtils; 81 82 import androidx.activity.ComponentActivity; 83 import androidx.lifecycle.LiveData; 84 import androidx.lifecycle.ViewModelProvider; 85 86 import com.android.internal.annotations.VisibleForTesting; 87 import com.android.managedprovisioning.ManagedProvisioningBaseApplication; 88 import com.android.managedprovisioning.ManagedProvisioningScreens; 89 import com.android.managedprovisioning.R; 90 import com.android.managedprovisioning.analytics.MetricsWriterFactory; 91 import com.android.managedprovisioning.analytics.ProvisioningAnalyticsTracker; 92 import com.android.managedprovisioning.common.DefaultFeatureFlagChecker; 93 import com.android.managedprovisioning.common.DefaultIntentResolverChecker; 94 import com.android.managedprovisioning.common.DefaultPackageInstallChecker; 95 import com.android.managedprovisioning.common.DeviceManagementRoleHolderHelper; 96 import com.android.managedprovisioning.common.DeviceManagementRoleHolderHelper.DefaultResolveIntentChecker; 97 import com.android.managedprovisioning.common.DeviceManagementRoleHolderHelper.DefaultRoleHolderStubChecker; 98 import com.android.managedprovisioning.common.DeviceManagementRoleHolderUpdaterHelper; 99 import com.android.managedprovisioning.common.GetProvisioningModeUtils; 100 import com.android.managedprovisioning.common.IllegalProvisioningArgumentException; 101 import com.android.managedprovisioning.common.ManagedProvisioningSharedPreferences; 102 import com.android.managedprovisioning.common.PolicyComplianceUtils; 103 import com.android.managedprovisioning.common.ProvisionLogger; 104 import com.android.managedprovisioning.common.RoleHolderProvider; 105 import com.android.managedprovisioning.common.RoleHolderUpdaterProvider; 106 import com.android.managedprovisioning.common.SettingsFacade; 107 import com.android.managedprovisioning.common.StoreUtils; 108 import com.android.managedprovisioning.common.Utils; 109 import com.android.managedprovisioning.model.DisclaimersParam; 110 import com.android.managedprovisioning.model.ProvisioningParams; 111 import com.android.managedprovisioning.model.ProvisioningParams.FlowType; 112 import com.android.managedprovisioning.parser.DisclaimerParser; 113 import com.android.managedprovisioning.parser.DisclaimersParserImpl; 114 import com.android.managedprovisioning.preprovisioning.PreProvisioningViewModel.DefaultConfig; 115 import com.android.managedprovisioning.preprovisioning.PreProvisioningViewModel.PreProvisioningViewModelFactory; 116 import com.android.managedprovisioning.provisioning.Constants; 117 import com.android.managedprovisioning.util.LazyStringResource; 118 119 import com.google.android.setupdesign.util.DeviceHelper; 120 121 import java.util.IllformedLocaleException; 122 import java.util.List; 123 import java.util.function.BiFunction; 124 125 /** 126 * Controller which contains business logic related to provisioning preparation. 127 * 128 * @see PreProvisioningActivity 129 */ 130 public class PreProvisioningActivityController { 131 private final Context mContext; 132 private final Ui mUi; 133 private final Utils mUtils; 134 private final PolicyComplianceUtils mPolicyComplianceUtils; 135 private final GetProvisioningModeUtils mGetProvisioningModeUtils; 136 private final SettingsFacade mSettingsFacade; 137 138 // used system services 139 private final DevicePolicyManager mDevicePolicyManager; 140 private final UserManager mUserManager; 141 private final PackageManager mPackageManager; 142 private final KeyguardManager mKeyguardManager; 143 private final PersistentDataBlockManager mPdbManager; 144 private final ProvisioningAnalyticsTracker mProvisioningAnalyticsTracker; 145 private final ManagedProvisioningSharedPreferences mSharedPreferences; 146 147 private final PreProvisioningViewModel mViewModel; 148 private final BiFunction<Context, Long, DisclaimerParser> mDisclaimerParserProvider; 149 private final DeviceManagementRoleHolderHelper mRoleHolderHelper; 150 private final DeviceManagementRoleHolderUpdaterHelper mRoleHolderUpdaterHelper; 151 PreProvisioningActivityController( @onNull ComponentActivity activity, @NonNull Ui ui)152 public PreProvisioningActivityController( 153 @NonNull ComponentActivity activity, 154 @NonNull Ui ui) { 155 this(activity, ui, 156 new Utils(), new SettingsFacade(), 157 new ManagedProvisioningSharedPreferences(activity), 158 new PolicyComplianceUtils(), 159 new GetProvisioningModeUtils(), 160 new ViewModelProvider( 161 activity, 162 new PreProvisioningViewModelFactory( 163 (ManagedProvisioningBaseApplication) activity.getApplication(), 164 new DefaultConfig(), 165 new Utils())) 166 .get(PreProvisioningViewModel.class), 167 DisclaimersParserImpl::new, 168 new DeviceManagementRoleHolderHelper( 169 RoleHolderProvider.DEFAULT.getPackageName(activity), 170 new DefaultPackageInstallChecker(activity.getPackageManager(), new Utils()), 171 new DefaultResolveIntentChecker(), 172 new DefaultRoleHolderStubChecker(), 173 new DefaultFeatureFlagChecker(activity.getContentResolver()) 174 ), 175 new DeviceManagementRoleHolderUpdaterHelper( 176 RoleHolderUpdaterProvider.DEFAULT.getPackageName(activity), 177 RoleHolderProvider.DEFAULT.getPackageName(activity), 178 new DefaultPackageInstallChecker(activity.getPackageManager(), new Utils()), 179 new DefaultIntentResolverChecker(activity.getPackageManager()), 180 new DefaultFeatureFlagChecker(activity.getContentResolver()))); 181 } 182 183 @VisibleForTesting PreProvisioningActivityController( @onNull Context context, @NonNull Ui ui, @NonNull Utils utils, @NonNull SettingsFacade settingsFacade, @NonNull ManagedProvisioningSharedPreferences sharedPreferences, @NonNull PolicyComplianceUtils policyComplianceUtils, @NonNull GetProvisioningModeUtils getProvisioningModeUtils, @NonNull PreProvisioningViewModel viewModel, @NonNull BiFunction<Context, Long, DisclaimerParser> disclaimerParserProvider, @NonNull DeviceManagementRoleHolderHelper roleHolderHelper, @NonNull DeviceManagementRoleHolderUpdaterHelper roleHolderUpdaterHelper)184 PreProvisioningActivityController( 185 @NonNull Context context, 186 @NonNull Ui ui, 187 @NonNull Utils utils, 188 @NonNull SettingsFacade settingsFacade, 189 @NonNull ManagedProvisioningSharedPreferences sharedPreferences, 190 @NonNull PolicyComplianceUtils policyComplianceUtils, 191 @NonNull GetProvisioningModeUtils getProvisioningModeUtils, 192 @NonNull PreProvisioningViewModel viewModel, 193 @NonNull BiFunction<Context, Long, DisclaimerParser> disclaimerParserProvider, 194 @NonNull DeviceManagementRoleHolderHelper roleHolderHelper, 195 @NonNull DeviceManagementRoleHolderUpdaterHelper roleHolderUpdaterHelper) { 196 mContext = requireNonNull(context, "Context must not be null"); 197 mUi = requireNonNull(ui, "Ui must not be null"); 198 mSettingsFacade = requireNonNull(settingsFacade); 199 mUtils = requireNonNull(utils, "Utils must not be null"); 200 mPolicyComplianceUtils = requireNonNull(policyComplianceUtils, 201 "PolicyComplianceUtils cannot be null"); 202 mGetProvisioningModeUtils = requireNonNull(getProvisioningModeUtils, 203 "GetProvisioningModeUtils cannot be null"); 204 mSharedPreferences = requireNonNull(sharedPreferences); 205 mViewModel = requireNonNull(viewModel); 206 207 mDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class); 208 mUserManager = mContext.getSystemService(UserManager.class); 209 mPackageManager = mContext.getPackageManager(); 210 mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); 211 mPdbManager = (PersistentDataBlockManager) 212 mContext.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE); 213 mProvisioningAnalyticsTracker = new ProvisioningAnalyticsTracker( 214 MetricsWriterFactory.getMetricsWriter(mContext, mSettingsFacade), 215 mSharedPreferences); 216 mDisclaimerParserProvider = requireNonNull(disclaimerParserProvider); 217 mRoleHolderHelper = requireNonNull(roleHolderHelper); 218 mRoleHolderUpdaterHelper = requireNonNull(roleHolderUpdaterHelper); 219 } 220 221 /** 222 * Starts provisioning via the role holder if possible, or if offline provisioning is allowed, 223 * falls back to AOSP ManagedProvisioning provisioning. 224 * 225 * @return {@code true} if any form of provisioning was started (either role holder or 226 * platform). 227 */ startAppropriateProvisioning( Intent managedProvisioningIntent, Bundle roleHolderAdditionalExtras, String callingPackage)228 boolean startAppropriateProvisioning( 229 Intent managedProvisioningIntent, 230 Bundle roleHolderAdditionalExtras, 231 String callingPackage) { 232 boolean isRoleHolderReadyForProvisioning = mRoleHolderHelper 233 .isRoleHolderReadyForProvisioning(mContext, managedProvisioningIntent); 234 boolean isRoleHolderProvisioningAllowed = 235 Constants.isRoleHolderProvisioningAllowedForAction( 236 managedProvisioningIntent.getAction()); 237 238 // In T allowOffline is used here to force platform provisioning. 239 if (getParams().allowOffline) { 240 ProvisionLogger.logw("allowOffline set, provisioning via platform."); 241 performPlatformProvidedProvisioning(); 242 return true; 243 } 244 245 if (isRoleHolderReadyForProvisioning && isRoleHolderProvisioningAllowed) { 246 ProvisionLogger.logw("Provisioning via role holder."); 247 mRoleHolderHelper.ensureRoleGranted(mContext, success -> { 248 if (success) { 249 Intent roleHolderProvisioningIntent = 250 mRoleHolderHelper.createRoleHolderProvisioningIntent( 251 managedProvisioningIntent, 252 roleHolderAdditionalExtras, callingPackage, 253 mViewModel.getRoleHolderState() 254 ); 255 mSharedPreferences.setIsProvisioningFlowDelegatedToRoleHolder(true); 256 mViewModel.onRoleHolderProvisioningInitiated(); 257 mUi.startRoleHolderProvisioning(roleHolderProvisioningIntent); 258 } else { 259 ProvisionLogger.logw("Falling back to provisioning via platform."); 260 performPlatformProvidedProvisioning(); 261 } 262 }); 263 return true; 264 } else if (!mRoleHolderHelper.isRoleHolderProvisioningEnabled() 265 || !mRoleHolderUpdaterHelper.isRoleHolderUpdaterDefined() 266 || !isRoleHolderProvisioningAllowed) { 267 ProvisionLogger.logw("Provisioning via platform."); 268 performPlatformProvidedProvisioning(); 269 return true; 270 } 271 ProvisionLogger.logw("Role holder is configured, can't provision via role holder and " 272 + "PROVISIONING_ALLOW_OFFLINE is false."); 273 return false; 274 } 275 276 /** 277 * Starts the role holder updater, saving {@code roleHolderState} to be used to restart 278 * the role holder. 279 * 280 * @see DevicePolicyManager#EXTRA_ROLE_HOLDER_STATE 281 */ startRoleHolderUpdater( boolean isRoleHolderRequestedUpdate, @Nullable PersistableBundle roleHolderState)282 public void startRoleHolderUpdater( 283 boolean isRoleHolderRequestedUpdate, @Nullable PersistableBundle roleHolderState) { 284 mViewModel.onRoleHolderUpdateInitiated(); 285 mViewModel.setRoleHolderState(roleHolderState); 286 mUi.startRoleHolderUpdater(isRoleHolderRequestedUpdate); 287 } 288 289 /** 290 * Starts the role holder updater with the last provided role holder state. 291 * 292 * <p>This can be useful in update retry cases. 293 */ startRoleHolderUpdaterWithLastState(boolean isRoleHolderRequestedUpdate)294 public void startRoleHolderUpdaterWithLastState(boolean isRoleHolderRequestedUpdate) { 295 startRoleHolderUpdater(isRoleHolderRequestedUpdate, mViewModel.getRoleHolderState()); 296 } 297 298 interface Ui { 299 /** 300 * Show an error message and cancel provisioning. 301 * 302 * @param title resource id used to form the user facing error title 303 * @param message resource id used to form the user facing error message 304 * @param errorMessage an error message that gets logged for debugging 305 */ showErrorAndClose( LazyStringResource title, LazyStringResource message, String errorMessage)306 void showErrorAndClose( 307 LazyStringResource title, LazyStringResource message, String errorMessage); 308 309 /** 310 * Show an error message and cancel provisioning. 311 * 312 * @see #showErrorAndClose(LazyStringResource, LazyStringResource, String) 313 */ showErrorAndClose(Integer titleId, int messageId, String errorMessage)314 void showErrorAndClose(Integer titleId, int messageId, String errorMessage); 315 316 /** 317 * Request the user to encrypt the device. 318 * 319 * @param params the {@link ProvisioningParams} object related to the ongoing provisioning 320 */ requestEncryption(ProvisioningParams params)321 void requestEncryption(ProvisioningParams params); 322 323 /** 324 * Request the user to choose a wifi network. 325 */ requestWifiPick()326 void requestWifiPick(); 327 328 /** 329 * Start provisioning. 330 * 331 * @param params the {@link ProvisioningParams} object related to the ongoing provisioning 332 */ startProvisioning(ProvisioningParams params)333 void startProvisioning(ProvisioningParams params); 334 335 /** 336 * Show an error dialog indicating that the current launcher does not support managed 337 * profiles and ask the user to choose a different one. 338 */ showCurrentLauncherInvalid()339 void showCurrentLauncherInvalid(); 340 showOwnershipDisclaimerScreen(ProvisioningParams params)341 void showOwnershipDisclaimerScreen(ProvisioningParams params); 342 prepareFinancedDeviceFlow(ProvisioningParams params)343 void prepareFinancedDeviceFlow(ProvisioningParams params); 344 showFactoryResetDialog(Integer titleId, int messageId)345 void showFactoryResetDialog(Integer titleId, int messageId); 346 showFactoryResetDialog(LazyStringResource titleId, LazyStringResource messageId)347 void showFactoryResetDialog(LazyStringResource titleId, LazyStringResource messageId); 348 initiateUi(UiParams uiParams)349 void initiateUi(UiParams uiParams); 350 351 /** 352 * Abort provisioning and close app 353 */ abortProvisioning()354 void abortProvisioning(); 355 prepareAdminIntegratedFlow(ProvisioningParams params)356 void prepareAdminIntegratedFlow(ProvisioningParams params); 357 startRoleHolderUpdater(boolean isRoleHolderRequestedUpdate)358 void startRoleHolderUpdater(boolean isRoleHolderRequestedUpdate); 359 startRoleHolderProvisioning(Intent intent)360 void startRoleHolderProvisioning(Intent intent); 361 onParamsValidated(ProvisioningParams params)362 void onParamsValidated(ProvisioningParams params); 363 startPlatformDrivenRoleHolderDownload()364 void startPlatformDrivenRoleHolderDownload(); 365 } 366 367 /** 368 * Wrapper which holds information related to the consent screen. 369 * <p>Does not implement {@link Object#equals(Object)}, {@link Object#hashCode()} 370 * or {@link Object#toString()}. 371 */ 372 public static class UiParams { 373 /** 374 * Admin application package name. 375 */ 376 public String packageName; 377 /** 378 * List of headings for the organization-provided terms and conditions. 379 */ 380 public List<String> disclaimerHeadings; 381 public boolean isDeviceManaged; 382 /** 383 * The original provisioning action, kept for backwards compatibility. 384 */ 385 public String provisioningAction; 386 public boolean isOrganizationOwnedProvisioning; 387 } 388 389 /** 390 * Initiates Profile owner and device owner provisioning. 391 * 392 * @param intent Intent that started provisioning. 393 * @param callingPackage Package that started provisioning. 394 */ initiateProvisioning(Intent intent, String callingPackage)395 public void initiateProvisioning(Intent intent, String callingPackage) { 396 mSharedPreferences.writeProvisioningStartedTimestamp(SystemClock.elapsedRealtime()); 397 mSharedPreferences.setIsProvisioningFlowDelegatedToRoleHolder(false); 398 mProvisioningAnalyticsTracker.logProvisioningSessionStarted(mContext); 399 400 logProvisioningExtras(intent); 401 402 if (!tryParseParameters(intent)) { 403 return; 404 } 405 406 ProvisioningParams params = mViewModel.getParams(); 407 if (!checkFactoryResetProtection(params, callingPackage)) { 408 return; 409 } 410 411 if (!verifyActionAndCaller(intent, callingPackage)) { 412 return; 413 } 414 415 mProvisioningAnalyticsTracker.logProvisioningExtras(mContext, intent); 416 mProvisioningAnalyticsTracker.logEntryPoint(mContext, intent, mSettingsFacade); 417 418 // Check whether provisioning is allowed for the current action. This check needs to happen 419 // before any actions that might affect the state of the device. 420 // Note that checkDevicePolicyPreconditions takes care of calling 421 // showProvisioningErrorAndClose. So we only need to show the factory reset dialog (if 422 // applicable) and return. 423 if (!checkDevicePolicyPreconditions()) { 424 return; 425 } 426 427 if (!isIntentActionValid(intent.getAction())) { 428 ProvisionLogger.loge( 429 ACTION_PROVISION_MANAGED_DEVICE + " is no longer a supported intent action."); 430 mUi.abortProvisioning(); 431 return; 432 } 433 434 if (isDeviceOwnerProvisioning()) { 435 // TODO: make a general test based on deviceAdminDownloadInfo field 436 // PO doesn't ever initialize that field, so OK as a general case 437 if (shouldShowWifiPicker(intent)) { 438 // Have the user pick a wifi network if necessary. 439 // It is not possible to ask the user to pick a wifi network if 440 // the screen is locked. 441 // TODO: remove this check once we know the screen will not be locked. 442 if (mKeyguardManager.inKeyguardRestrictedInputMode()) { 443 // TODO: decide on what to do in that case; fail? retry on screen unlock? 444 ProvisionLogger.logi("Cannot pick wifi because the screen is locked."); 445 } else if (canRequestWifiPick()) { 446 // we resume this method after a successful WiFi pick 447 // TODO: refactor as evil - logic should be less spread out 448 mUi.requestWifiPick(); 449 return; 450 } else { 451 mUi.showErrorAndClose(R.string.cant_set_up_device, 452 R.string.contact_your_admin_for_help, 453 "Cannot pick WiFi because there is no handler to the intent"); 454 } 455 } 456 } 457 458 mUi.onParamsValidated(params); 459 460 // TODO(b/207376815): Have a PreProvisioningForwarderActivity to forward to either 461 // platform-provided provisioning or DMRH 462 if (mRoleHolderUpdaterHelper.shouldPlatformDownloadRoleHolder(intent, params) 463 && !params.allowOffline) { 464 mUi.startPlatformDrivenRoleHolderDownload(); 465 } else if (mRoleHolderUpdaterHelper 466 .shouldStartRoleHolderUpdater(mContext, intent, params) && !params.allowOffline) { 467 resetRoleHolderUpdateRetryCount(); 468 startRoleHolderUpdater( 469 /* isRoleHolderRequestedUpdate= */ false, /* roleHolderState= */ null); 470 } else { 471 boolean isProvisioningStarted = 472 startAppropriateProvisioning(intent, new Bundle(), callingPackage); 473 if (!isProvisioningStarted) { 474 mUi.showErrorAndClose( 475 R.string.cant_set_up_device, 476 R.string.contact_your_admin_for_help, 477 "Could not start provisioning."); 478 } 479 } 480 } 481 logProvisioningExtras(Intent intent)482 private void logProvisioningExtras(Intent intent) { 483 Bundle extras = intent.getExtras(); 484 if (extras == null) { 485 ProvisionLogger.logi("No extras have been passed."); 486 return; 487 } 488 ProvisionLogger.logi("Start logging provisioning extras"); 489 for (String key : extras.keySet()) { 490 ProvisionLogger.logi("Extra key: " + key + ", extra value: " + extras.get(key)); 491 } 492 ProvisionLogger.logi("Finish logging provisioning extras"); 493 } 494 performPlatformProvidedProvisioning()495 void performPlatformProvidedProvisioning() { 496 ProvisionLogger.logw("Provisioning via platform-provided provisioning"); 497 ProvisioningParams params = mViewModel.getParams(); 498 if (mSharedPreferences.isProvisioningFlowDelegatedToRoleHolder()) { 499 mSharedPreferences.setIsProvisioningFlowDelegatedToRoleHolder(false); 500 } 501 502 mViewModel.getTimeLogger().start(); 503 mViewModel.onPlatformProvisioningInitiated(); 504 505 if (mUtils.checkAdminIntegratedFlowPreconditions(params)) { 506 if (mUtils.shouldShowOwnershipDisclaimerScreen(params)) { 507 mUi.showOwnershipDisclaimerScreen(params); 508 } else { 509 mUi.prepareAdminIntegratedFlow(params); 510 } 511 mViewModel.onAdminIntegratedFlowInitiated(); 512 } else if (mUtils.isFinancedDeviceAction(params.provisioningAction)) { 513 mUi.prepareFinancedDeviceFlow(params); 514 } else if (isProfileOwnerProvisioning()) { 515 startManagedProfileFlow(); 516 } 517 } 518 isIntentActionValid(String action)519 private boolean isIntentActionValid(String action) { 520 return !ACTION_PROVISION_MANAGED_DEVICE.equals(action); 521 } 522 startManagedProfileFlow()523 private void startManagedProfileFlow() { 524 ProvisionLogger.logi("Starting the managed profile flow."); 525 showUserConsentScreen(); 526 } 527 isNfcProvisioning(Intent intent)528 private boolean isNfcProvisioning(Intent intent) { 529 return intent.getIntExtra(EXTRA_PROVISIONING_TRIGGER, PROVISIONING_TRIGGER_UNSPECIFIED) 530 == PROVISIONING_TRIGGER_NFC; 531 } 532 isQrCodeProvisioning(Intent intent)533 private boolean isQrCodeProvisioning(Intent intent) { 534 if (!ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE.equals(intent.getAction())) { 535 return false; 536 } 537 final int provisioningTrigger = intent.getIntExtra(EXTRA_PROVISIONING_TRIGGER, 538 PROVISIONING_TRIGGER_UNSPECIFIED); 539 return provisioningTrigger == PROVISIONING_TRIGGER_QR_CODE; 540 } 541 shouldShowWifiPicker(Intent intent)542 private boolean shouldShowWifiPicker(Intent intent) { 543 if (mSharedPreferences.isEstablishNetworkConnectionRun()) { 544 return false; 545 } 546 ProvisioningParams params = mViewModel.getParams(); 547 if (params.wifiInfo != null) { 548 return false; 549 } 550 if (params.deviceAdminDownloadInfo == null) { 551 return false; 552 } 553 var networkCapabilities = mUtils.getActiveNetworkCapabilities(mContext); 554 if (networkCapabilities != null 555 && (mUtils.isNetworkConnectedToInternetViaWiFi(networkCapabilities) 556 || mUtils.isNetworkConnectedToInternetViaEthernet(networkCapabilities))) { 557 return false; 558 } 559 // we intentionally disregard whether mobile is connected for QR and NFC 560 // provisioning. b/153442588 for context 561 if (params.useMobileData 562 && (isQrCodeProvisioning(intent) || isNfcProvisioning(intent))) { 563 return false; 564 } 565 if (params.useMobileData) { 566 return !mUtils.isMobileNetworkConnectedToInternet(mContext); 567 } 568 return true; 569 } 570 showUserConsentScreen()571 void showUserConsentScreen() { 572 // Check whether provisioning is allowed for the current action 573 if (!checkDevicePolicyPreconditions()) { 574 return; 575 } 576 577 if (mViewModel.getParams().provisioningAction.equals(ACTION_PROVISION_MANAGED_PROFILE) 578 && mViewModel.getParams().isOrganizationOwnedProvisioning) { 579 mProvisioningAnalyticsTracker.logOrganizationOwnedManagedProfileProvisioning(); 580 } 581 582 // show UI so we can get user's consent to continue 583 final String packageName = mViewModel.getParams().inferDeviceAdminPackageName(); 584 final UiParams uiParams = new UiParams(); 585 uiParams.provisioningAction = mViewModel.getParams().provisioningAction; 586 uiParams.packageName = packageName; 587 uiParams.isDeviceManaged = mDevicePolicyManager.isDeviceManaged(); 588 uiParams.isOrganizationOwnedProvisioning = 589 mViewModel.getParams().isOrganizationOwnedProvisioning; 590 591 mUi.initiateUi(uiParams); 592 mViewModel.onShowUserConsent(); 593 } 594 updateProvisioningParamsFromIntent(Intent resultIntent)595 boolean updateProvisioningParamsFromIntent(Intent resultIntent) { 596 final int provisioningMode = resultIntent.getIntExtra( 597 DevicePolicyManager.EXTRA_PROVISIONING_MODE, 0); 598 if (!mViewModel.getParams().allowedProvisioningModes.contains(provisioningMode)) { 599 ProvisionLogger.loge("Invalid provisioning mode chosen by the DPC: " + provisioningMode 600 + ", but expected one of " 601 + mViewModel.getParams().allowedProvisioningModes.toString()); 602 return false; 603 } 604 switch (provisioningMode) { 605 case DevicePolicyManager.PROVISIONING_MODE_FULLY_MANAGED_DEVICE: 606 updateParamsPostProvisioningModeDecision( 607 resultIntent, 608 ACTION_PROVISION_MANAGED_DEVICE, 609 /* isOrganizationOwnedProvisioning */ true, 610 /* updateAccountToMigrate */ false); 611 return true; 612 case DevicePolicyManager.PROVISIONING_MODE_MANAGED_PROFILE: 613 updateParamsPostProvisioningModeDecision( 614 resultIntent, 615 ACTION_PROVISION_MANAGED_PROFILE, 616 mUtils.isOrganizationOwnedAllowed(mViewModel.getParams()), 617 /* updateAccountToMigrate */ true); 618 return true; 619 case PROVISIONING_MODE_MANAGED_PROFILE_ON_PERSONAL_DEVICE: 620 updateParamsPostProvisioningModeDecision( 621 resultIntent, 622 ACTION_PROVISION_MANAGED_PROFILE, 623 /* isOrganizationOwnedProvisioning */ false, 624 /* updateAccountToMigrate */ true); 625 return true; 626 default: 627 ProvisionLogger.logw("Unknown returned provisioning mode:" 628 + provisioningMode); 629 return false; 630 } 631 } 632 updateParamsPostProvisioningModeDecision(Intent resultIntent, String provisioningAction, boolean isOrganizationOwnedProvisioning, boolean updateAccountToMigrate)633 private void updateParamsPostProvisioningModeDecision(Intent resultIntent, 634 String provisioningAction, boolean isOrganizationOwnedProvisioning, 635 boolean updateAccountToMigrate) { 636 ProvisioningParams.Builder builder = mViewModel.getParams().toBuilder(); 637 builder.setFlowType(FLOW_TYPE_ADMIN_INTEGRATED); 638 builder.setProvisioningAction(provisioningAction); 639 builder.setIsOrganizationOwnedProvisioning(isOrganizationOwnedProvisioning); 640 maybeUpdateAdminExtrasBundle(builder, resultIntent); 641 maybeUpdateSkipEducationScreens(builder, resultIntent); 642 maybeUpdateDisclaimers(builder, resultIntent); 643 maybeUpdateSkipEncryption(builder, resultIntent); 644 if (updateAccountToMigrate) { 645 maybeUpdateAccountToMigrate(builder, resultIntent); 646 } 647 if (provisioningAction.equals(ACTION_PROVISION_MANAGED_PROFILE)) { 648 maybeUpdateKeepAccountMigrated(builder, resultIntent); 649 maybeUpdateLeaveAllSystemAppsEnabled(builder, resultIntent); 650 } else if (provisioningAction.equals(ACTION_PROVISION_MANAGED_DEVICE)) { 651 maybeUpdateDeviceOwnerPermissionGrantOptOut(builder, resultIntent); 652 maybeUpdateLocale(builder, resultIntent); 653 maybeUpdateLocalTime(builder, resultIntent); 654 maybeUpdateTimeZone(builder, resultIntent); 655 } 656 mViewModel.updateParams(builder.build()); 657 } 658 maybeUpdateDeviceOwnerPermissionGrantOptOut( ProvisioningParams.Builder builder, Intent resultIntent)659 private void maybeUpdateDeviceOwnerPermissionGrantOptOut( 660 ProvisioningParams.Builder builder, Intent resultIntent) { 661 if (resultIntent.hasExtra(EXTRA_PROVISIONING_SENSORS_PERMISSION_GRANT_OPT_OUT)) { 662 builder.setDeviceOwnerPermissionGrantOptOut(resultIntent.getBooleanExtra( 663 EXTRA_PROVISIONING_SENSORS_PERMISSION_GRANT_OPT_OUT, 664 DEFAULT_EXTRA_PROVISIONING_PERMISSION_GRANT_OPT_OUT)); 665 } 666 } 667 maybeUpdateSkipEncryption( ProvisioningParams.Builder builder, Intent resultIntent)668 private void maybeUpdateSkipEncryption( 669 ProvisioningParams.Builder builder, Intent resultIntent) { 670 if (resultIntent.hasExtra(EXTRA_PROVISIONING_SKIP_ENCRYPTION)) { 671 builder.setSkipEncryption(resultIntent.getBooleanExtra( 672 EXTRA_PROVISIONING_SKIP_ENCRYPTION, 673 DEFAULT_EXTRA_PROVISIONING_SKIP_ENCRYPTION)); 674 } 675 } 676 maybeUpdateTimeZone(ProvisioningParams.Builder builder, Intent resultIntent)677 private void maybeUpdateTimeZone(ProvisioningParams.Builder builder, Intent resultIntent) { 678 if (resultIntent.hasExtra(EXTRA_PROVISIONING_TIME_ZONE)) { 679 builder.setTimeZone(resultIntent.getStringExtra(EXTRA_PROVISIONING_TIME_ZONE)); 680 } 681 } 682 maybeUpdateLocalTime(ProvisioningParams.Builder builder, Intent resultIntent)683 private void maybeUpdateLocalTime(ProvisioningParams.Builder builder, Intent resultIntent) { 684 if (resultIntent.hasExtra(EXTRA_PROVISIONING_LOCAL_TIME)) { 685 builder.setLocalTime(resultIntent.getLongExtra( 686 EXTRA_PROVISIONING_LOCAL_TIME, ProvisioningParams.DEFAULT_LOCAL_TIME)); 687 } 688 } 689 maybeUpdateLocale(ProvisioningParams.Builder builder, Intent resultIntent)690 private void maybeUpdateLocale(ProvisioningParams.Builder builder, Intent resultIntent) { 691 if (resultIntent.hasExtra(EXTRA_PROVISIONING_LOCALE)) { 692 try { 693 builder.setLocale(StoreUtils.stringToLocale( 694 resultIntent.getStringExtra(EXTRA_PROVISIONING_LOCALE))); 695 } catch (IllformedLocaleException e) { 696 ProvisionLogger.loge("Could not parse locale.", e); 697 } 698 } 699 } 700 maybeUpdateDisclaimers(ProvisioningParams.Builder builder, Intent resultIntent)701 private void maybeUpdateDisclaimers(ProvisioningParams.Builder builder, Intent resultIntent) { 702 if (resultIntent.hasExtra(EXTRA_PROVISIONING_DISCLAIMERS)) { 703 try { 704 DisclaimersParam disclaimersParam = mDisclaimerParserProvider.apply( 705 mContext, 706 mSharedPreferences.getProvisioningId()) 707 .parse(resultIntent.getParcelableArrayExtra( 708 EXTRA_PROVISIONING_DISCLAIMERS)); 709 builder.setDisclaimersParam(disclaimersParam); 710 } catch (ClassCastException e) { 711 ProvisionLogger.loge("Could not parse disclaimer params.", e); 712 } 713 } 714 } 715 maybeUpdateSkipEducationScreens(ProvisioningParams.Builder builder, Intent resultIntent)716 private void maybeUpdateSkipEducationScreens(ProvisioningParams.Builder builder, 717 Intent resultIntent) { 718 if (resultIntent.hasExtra(EXTRA_PROVISIONING_SKIP_EDUCATION_SCREENS)) { 719 builder.setSkipEducationScreens(resultIntent.getBooleanExtra( 720 EXTRA_PROVISIONING_SKIP_EDUCATION_SCREENS, /* defaultValue */ false)); 721 } 722 } 723 maybeUpdateAccountToMigrate(ProvisioningParams.Builder builder, Intent resultIntent)724 private void maybeUpdateAccountToMigrate(ProvisioningParams.Builder builder, 725 Intent resultIntent) { 726 if (resultIntent.hasExtra(EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE)) { 727 final Account account = resultIntent.getParcelableExtra( 728 EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE); 729 builder.setAccountToMigrate(account); 730 } 731 } 732 733 /** 734 * Appends the admin bundle in {@code resultIntent}, if provided, to the existing admin bundle, 735 * if it exists, and stores the result in {@code builder}. 736 */ maybeUpdateAdminExtrasBundle(ProvisioningParams.Builder builder, Intent resultIntent)737 private void maybeUpdateAdminExtrasBundle(ProvisioningParams.Builder builder, 738 Intent resultIntent) { 739 if (resultIntent.hasExtra(EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE)) { 740 PersistableBundle resultBundle = 741 resultIntent.getParcelableExtra(EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE); 742 if (mViewModel.getParams().adminExtrasBundle != null) { 743 PersistableBundle existingBundle = 744 new PersistableBundle(mViewModel.getParams().adminExtrasBundle); 745 existingBundle.putAll(resultBundle); 746 resultBundle = existingBundle; 747 } 748 builder.setAdminExtrasBundle(resultBundle); 749 } 750 } 751 maybeUpdateKeepAccountMigrated( ProvisioningParams.Builder builder, Intent resultIntent)752 private void maybeUpdateKeepAccountMigrated( 753 ProvisioningParams.Builder builder, 754 Intent resultIntent) { 755 if (resultIntent.hasExtra(EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION)) { 756 final boolean keepAccountMigrated = resultIntent.getBooleanExtra( 757 EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION, 758 DEFAULT_EXTRA_PROVISIONING_KEEP_ACCOUNT_MIGRATED); 759 builder.setKeepAccountMigrated(keepAccountMigrated); 760 } 761 } 762 maybeUpdateLeaveAllSystemAppsEnabled( ProvisioningParams.Builder builder, Intent resultIntent)763 private void maybeUpdateLeaveAllSystemAppsEnabled( 764 ProvisioningParams.Builder builder, 765 Intent resultIntent) { 766 if (resultIntent.hasExtra(EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED)) { 767 final boolean leaveAllSystemAppsEnabled = resultIntent.getBooleanExtra( 768 EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED, 769 DEFAULT_LEAVE_ALL_SYSTEM_APPS_ENABLED); 770 builder.setLeaveAllSystemAppsEnabled(leaveAllSystemAppsEnabled); 771 } 772 } 773 updateProvisioningFlowState(@lowType int flowType)774 void updateProvisioningFlowState(@FlowType int flowType) { 775 mViewModel.updateParams(mViewModel.getParams().toBuilder().setFlowType(flowType).build()); 776 } 777 getAdditionalExtrasForGetProvisioningModeIntent()778 Bundle getAdditionalExtrasForGetProvisioningModeIntent() { 779 Bundle bundle = new Bundle(); 780 if (shouldPassPersonalDataToAdminApp()) { 781 final TelephonyManager telephonyManager = mContext.getSystemService( 782 TelephonyManager.class); 783 bundle.putString(EXTRA_PROVISIONING_IMEI, telephonyManager.getImei()); 784 bundle.putString(EXTRA_PROVISIONING_SERIAL_NUMBER, Build.getSerial()); 785 } 786 ProvisioningParams params = mViewModel.getParams(); 787 bundle.putParcelable(EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE, 788 params.adminExtrasBundle); 789 bundle.putIntegerArrayList(EXTRA_PROVISIONING_ALLOWED_PROVISIONING_MODES, 790 params.allowedProvisioningModes); 791 792 if (params.allowedProvisioningModes.contains( 793 DevicePolicyManager.PROVISIONING_MODE_FULLY_MANAGED_DEVICE)) { 794 bundle.putBoolean(EXTRA_PROVISIONING_SENSORS_PERMISSION_GRANT_OPT_OUT, 795 params.deviceOwnerPermissionGrantOptOut); 796 } 797 return bundle; 798 } 799 shouldPassPersonalDataToAdminApp()800 private boolean shouldPassPersonalDataToAdminApp() { 801 ProvisioningParams params = mViewModel.getParams(); 802 return params.initiatorRequestedProvisioningModes == FLAG_SUPPORTED_MODES_ORGANIZATION_OWNED 803 || params.initiatorRequestedProvisioningModes == FLAG_SUPPORTED_MODES_DEVICE_OWNER; 804 } 805 createViewTermsIntent()806 protected Intent createViewTermsIntent() { 807 return new Intent(mContext, getTermsActivityClass()) 808 .putExtra(ProvisioningParams.EXTRA_PROVISIONING_PARAMS, mViewModel.getParams()); 809 } 810 getTermsActivityClass()811 private Class<? extends Activity> getTermsActivityClass() { 812 return getBaseApplication().getActivityClassForScreen(ManagedProvisioningScreens.TERMS); 813 } 814 getBaseApplication()815 private ManagedProvisioningBaseApplication getBaseApplication() { 816 return (ManagedProvisioningBaseApplication) mContext.getApplicationContext(); 817 } 818 819 /** 820 * Start provisioning for real. In profile owner case, double check that the launcher 821 * supports managed profiles if necessary. In device owner case, possibly create a new user 822 * before starting provisioning. 823 */ continueProvisioningAfterUserConsent()824 public void continueProvisioningAfterUserConsent() { 825 mProvisioningAnalyticsTracker.logProvisioningAction( 826 mContext, mViewModel.getParams().provisioningAction); 827 // check if encryption is required 828 if (isEncryptionRequired()) { 829 if (mDevicePolicyManager.getStorageEncryptionStatus() 830 == DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED) { 831 CharSequence deviceName = DeviceHelper.getDeviceName(mContext); 832 mUi.showErrorAndClose( 833 LazyStringResource.of(R.string.cant_set_up_device), 834 LazyStringResource.of( 835 R.string.device_doesnt_allow_encryption_contact_admin, deviceName), 836 "This device does not support encryption, and " 837 + DevicePolicyManager.EXTRA_PROVISIONING_SKIP_ENCRYPTION 838 + " was not passed."); 839 } else { 840 mUi.requestEncryption(mViewModel.getParams()); 841 // we come back to this method after returning from encryption dialog 842 // TODO: refactor as evil - logic should be less spread out 843 } 844 return; 845 } 846 847 if (isProfileOwnerProvisioning()) { // PO case 848 // Check whether the current launcher supports managed profiles. 849 if (!mUtils.currentLauncherSupportsManagedProfiles(mContext)) { 850 mUi.showCurrentLauncherInvalid(); 851 // we come back to this method after returning from launcher dialog 852 // TODO: refactor as evil - logic should be less spread out 853 return; 854 } 855 } 856 // Cancel the boot reminder as provisioning has now started. 857 mViewModel.getEncryptionController().cancelEncryptionReminder(); 858 stopTimeLogger(); 859 mUi.startProvisioning(mViewModel.getParams()); 860 861 mViewModel.onProvisioningStartedAfterUserConsent(); 862 } 863 864 /** 865 * @return False if condition preventing further provisioning 866 */ 867 @VisibleForTesting checkFactoryResetProtection(ProvisioningParams params, String callingPackage)868 boolean checkFactoryResetProtection(ProvisioningParams params, String callingPackage) { 869 if (skipFactoryResetProtectionCheck(params, callingPackage)) { 870 return true; 871 } 872 if (factoryResetProtected()) { 873 CharSequence deviceName = DeviceHelper.getDeviceName(mContext); 874 mUi.showErrorAndClose( 875 LazyStringResource.of(R.string.cant_set_up_device), 876 LazyStringResource.of( 877 R.string.device_has_reset_protection_contact_admin, deviceName), 878 "Factory reset protection blocks provisioning."); 879 return false; 880 } 881 return true; 882 } 883 skipFactoryResetProtectionCheck( ProvisioningParams params, String callingPackage)884 private boolean skipFactoryResetProtectionCheck( 885 ProvisioningParams params, String callingPackage) { 886 if (TextUtils.isEmpty(callingPackage)) { 887 return false; 888 } 889 String persistentDataPackageName = mContext.getResources() 890 .getString(com.android.internal.R.string.config_persistentDataPackageName); 891 try { 892 // Only skip the FRP check if the caller is the package responsible for maintaining FRP 893 // - i.e. if this is a flow for restoring device owner after factory reset. 894 PackageInfo callingPackageInfo = mPackageManager.getPackageInfo(callingPackage, 0); 895 return callingPackageInfo != null 896 && callingPackageInfo.applicationInfo != null 897 && callingPackageInfo.applicationInfo.isSystemApp() 898 && !TextUtils.isEmpty(persistentDataPackageName) 899 && callingPackage.equals(persistentDataPackageName) 900 && params != null 901 && params.startedByTrustedSource; 902 } catch (PackageManager.NameNotFoundException e) { 903 ProvisionLogger.loge("Calling package not found.", e); 904 return false; 905 } 906 } 907 908 /** @return False if condition preventing further provisioning */ 909 @VisibleForTesting checkDevicePolicyPreconditions()910 protected boolean checkDevicePolicyPreconditions() { 911 ProvisioningParams params = mViewModel.getParams(); 912 int provisioningPreCondition = mDevicePolicyManager.checkProvisioningPrecondition( 913 params.provisioningAction, 914 params.inferDeviceAdminPackageName()); 915 // Check whether provisioning is allowed for the current action. 916 if (provisioningPreCondition != STATUS_OK) { 917 mProvisioningAnalyticsTracker.logProvisioningNotAllowed(mContext, 918 provisioningPreCondition); 919 showProvisioningErrorAndClose( 920 params.provisioningAction, provisioningPreCondition); 921 return false; 922 } 923 return true; 924 } 925 926 /** @return False if condition preventing further provisioning */ tryParseParameters(Intent intent)927 private boolean tryParseParameters(Intent intent) { 928 try { 929 // Read the provisioning params from the provisioning intent 930 mViewModel.loadParamsIfNecessary(intent); 931 } catch (IllegalProvisioningArgumentException e) { 932 mUi.showErrorAndClose(R.string.cant_set_up_device, R.string.contact_your_admin_for_help, 933 e.getMessage()); 934 return false; 935 } 936 return true; 937 } 938 939 /** @return False if condition preventing further provisioning */ 940 @VisibleForTesting verifyActionAndCaller(Intent intent, String callingPackage)941 protected boolean verifyActionAndCaller(Intent intent, 942 String callingPackage) { 943 if (verifyActionAndCallerInner(intent, callingPackage)) { 944 return true; 945 } else { 946 mUi.showErrorAndClose(R.string.cant_set_up_device, R.string.contact_your_admin_for_help, 947 "invalid intent or calling package"); 948 return false; 949 } 950 } 951 verifyActionAndCallerInner(Intent intent, String callingPackage)952 private boolean verifyActionAndCallerInner(Intent intent, String callingPackage) { 953 // If this is a resume after encryption or trusted intent, we verify the activity alias. 954 // Otherwise, verify that the calling app is trying to set itself as Device/ProfileOwner 955 if (ACTION_RESUME_PROVISIONING.equals(intent.getAction())) { 956 return verifyActivityAlias(intent, "PreProvisioningActivityAfterEncryption"); 957 } else if (ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE.equals(intent.getAction()) 958 || ACTION_PROVISION_FINANCED_DEVICE.equals(intent.getAction())) { 959 return verifyActivityAlias(intent, "PreProvisioningActivityViaTrustedApp"); 960 } else { 961 return verifyCaller(callingPackage); 962 } 963 } 964 verifyActivityAlias(Intent intent, String activityAlias)965 private boolean verifyActivityAlias(Intent intent, String activityAlias) { 966 ComponentName componentName = intent.getComponent(); 967 if (componentName == null || componentName.getClassName() == null) { 968 ProvisionLogger.loge("null class in component when verifying activity alias " 969 + activityAlias); 970 return false; 971 } 972 973 if (!componentName.getClassName().endsWith(activityAlias)) { 974 ProvisionLogger.loge("Looking for activity alias " + activityAlias + ", but got " 975 + componentName.getClassName()); 976 return false; 977 } 978 979 return true; 980 } 981 982 /** 983 * Verify that the caller is trying to set itself as owner. 984 * 985 * @return false if the caller is trying to set a different package as owner. 986 */ verifyCaller(@onNull String callingPackage)987 private boolean verifyCaller(@NonNull String callingPackage) { 988 if (callingPackage == null) { 989 ProvisionLogger.loge("Calling package is null. Was startActivityForResult used to " 990 + "start this activity?"); 991 return false; 992 } 993 994 if (!callingPackage.equals(mViewModel.getParams().inferDeviceAdminPackageName())) { 995 ProvisionLogger.loge("Permission denied, " 996 + "calling package tried to set a different package as owner. "); 997 return false; 998 } 999 1000 return true; 1001 } 1002 1003 /** 1004 * Returns whether the device needs encryption. 1005 */ isEncryptionRequired()1006 private boolean isEncryptionRequired() { 1007 return !mViewModel.getParams().skipEncryption && mUtils.isEncryptionRequired(); 1008 } 1009 1010 /** 1011 * Returns whether the device is frp protected during setup wizard. 1012 */ factoryResetProtected()1013 private boolean factoryResetProtected() { 1014 // If we are started during setup wizard, check for factory reset protection. 1015 // If the device is already setup successfully, do not check factory reset protection. 1016 if (mSettingsFacade.isDeviceProvisioned(mContext)) { 1017 ProvisionLogger.logd("Device is provisioned, FRP not required."); 1018 return false; 1019 } 1020 1021 if (mPdbManager == null) { 1022 ProvisionLogger.logd("Reset protection not supported."); 1023 return false; 1024 } 1025 int size = mPdbManager.getDataBlockSize(); 1026 ProvisionLogger.logd("Data block size: " + size); 1027 return size > 0; 1028 } 1029 1030 /** 1031 * Returns whether activity to pick wifi can be requested or not. 1032 */ canRequestWifiPick()1033 private boolean canRequestWifiPick() { 1034 return mPackageManager.resolveActivity(mUtils.getWifiPickIntent(), 0) != null; 1035 } 1036 1037 /** 1038 * Returns whether the provisioning process is a profile owner provisioning process. 1039 */ isProfileOwnerProvisioning()1040 public boolean isProfileOwnerProvisioning() { 1041 return mUtils.isProfileOwnerAction(mViewModel.getParams().provisioningAction); 1042 } 1043 1044 /** 1045 * Returns whether the provisioning process is a device owner provisioning process. 1046 */ isDeviceOwnerProvisioning()1047 public boolean isDeviceOwnerProvisioning() { 1048 return mUtils.isDeviceOwnerAction(mViewModel.getParams().provisioningAction); 1049 } 1050 1051 1052 @Nullable getParams()1053 public ProvisioningParams getParams() { 1054 return mViewModel.getParams(); 1055 } 1056 1057 /** 1058 * Notifies the time logger to stop. 1059 */ stopTimeLogger()1060 public void stopTimeLogger() { 1061 mViewModel.getTimeLogger().stop(); 1062 } 1063 1064 /** 1065 * Log if PreProvisioning was cancelled. 1066 */ logPreProvisioningCancelled()1067 public void logPreProvisioningCancelled() { 1068 mProvisioningAnalyticsTracker.logProvisioningCancelled(mContext, 1069 CANCELLED_BEFORE_PROVISIONING); 1070 } 1071 1072 /** 1073 * Logs the provisioning flow type. 1074 */ logProvisioningFlowType()1075 public void logProvisioningFlowType() { 1076 mProvisioningAnalyticsTracker.logProvisioningFlowType(mViewModel.getParams()); 1077 } 1078 1079 /** 1080 * Removes a user profile. If we are in COMP case, and were blocked by having to delete a user, 1081 * resumes COMP provisioning. 1082 */ removeUser(int userProfileId)1083 public void removeUser(int userProfileId) { 1084 // There is a possibility that the DO has set the disallow remove managed profile user 1085 // restriction, but is initiating the provisioning. In this case, we still want to remove 1086 // the managed profile. 1087 // We know that we can remove the managed profile because we checked 1088 // DevicePolicyManager.checkProvisioningPreCondition 1089 mUserManager.removeUserEvenWhenDisallowed(userProfileId); 1090 } 1091 getSettingsFacade()1092 SettingsFacade getSettingsFacade() { 1093 return mSettingsFacade; 1094 } 1095 getPolicyComplianceUtils()1096 public PolicyComplianceUtils getPolicyComplianceUtils() { 1097 return mPolicyComplianceUtils; 1098 } 1099 getGetProvisioningModeUtils()1100 public GetProvisioningModeUtils getGetProvisioningModeUtils() { 1101 return mGetProvisioningModeUtils; 1102 } 1103 onReturnFromProvisioning()1104 void onReturnFromProvisioning() { 1105 mViewModel.onReturnFromProvisioning(); 1106 } 1107 getState()1108 LiveData<Integer> getState() { 1109 return mViewModel.getState(); 1110 } 1111 incrementRoleHolderUpdateRetryCount()1112 void incrementRoleHolderUpdateRetryCount() { 1113 mViewModel.incrementRoleHolderUpdateRetryCount(); 1114 } 1115 resetRoleHolderUpdateRetryCount()1116 void resetRoleHolderUpdateRetryCount() { 1117 mViewModel.resetRoleHolderUpdateRetryCount(); 1118 } 1119 canRetryRoleHolderUpdate()1120 boolean canRetryRoleHolderUpdate() { 1121 return mViewModel.canRetryRoleHolderUpdate(); 1122 } 1123 showProvisioningErrorAndClose(String action, int provisioningPreCondition)1124 private void showProvisioningErrorAndClose(String action, int provisioningPreCondition) { 1125 // Try to show an error message explaining why provisioning is not allowed. 1126 switch (action) { 1127 case ACTION_PROVISION_MANAGED_PROFILE: 1128 showManagedProfileErrorAndClose(provisioningPreCondition); 1129 return; 1130 case ACTION_PROVISION_MANAGED_DEVICE: 1131 showDeviceOwnerErrorAndClose(provisioningPreCondition); 1132 } 1133 // This should never be the case, as showProvisioningError is always called after 1134 // verifying the supported provisioning actions. 1135 } 1136 showManagedProfileErrorAndClose(int provisioningPreCondition)1137 private void showManagedProfileErrorAndClose(int provisioningPreCondition) { 1138 var userInfo = mUserManager.getUserInfo(mUserManager.getProcessUserId()); 1139 ProvisionLogger.logw( 1140 "DevicePolicyManager.checkProvisioningPrecondition returns code: " 1141 + provisioningPreCondition); 1142 // If this is organization-owned provisioning, do not show any other error dialog, just 1143 // show the factory reset dialog and return. 1144 // This cannot be abused by regular apps to force a factory reset because 1145 // isOrganizationOwnedProvisioning is only set to true if the provisioning action was 1146 // from a trusted source. See Utils.isOrganizationOwnedProvisioning where we check for 1147 // ACTION_ROLE_HOLDER_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE which is guarded by the 1148 // DISPATCH_PROVISIONING_MESSAGE system|privileged permission. 1149 if (mUtils.isOrganizationOwnedAllowed(mViewModel.getParams())) { 1150 ProvisionLogger.loge( 1151 "Provisioning preconditions failed for organization-owned provisioning."); 1152 mUi.showFactoryResetDialog(R.string.cant_set_up_device, 1153 R.string.contact_your_admin_for_help); 1154 return; 1155 } 1156 CharSequence deviceName = DeviceHelper.getDeviceName(mContext); 1157 switch (provisioningPreCondition) { 1158 case STATUS_MANAGED_USERS_NOT_SUPPORTED: 1159 mUi.showErrorAndClose( 1160 LazyStringResource.of(R.string.cant_add_work_profile), 1161 LazyStringResource.of( 1162 R.string.work_profile_cant_be_added_contact_admin, deviceName), 1163 "Exiting managed profile provisioning, managed profiles " 1164 + "feature is not available"); 1165 break; 1166 case STATUS_CANNOT_ADD_MANAGED_PROFILE: 1167 String errorMessage; 1168 if (!userInfo.canHaveProfile()) { 1169 errorMessage = "Exiting managed profile provisioning, calling user cannot " 1170 + "have managed profiles"; 1171 } else if (!canAddManagedProfile()) { 1172 errorMessage = "Exiting managed profile provisioning, a managed profile " 1173 + "already exists"; 1174 } else { 1175 errorMessage = "Exiting managed profile provisioning, cannot add more managed " 1176 + "profiles"; 1177 } 1178 mUi.showErrorAndClose( 1179 LazyStringResource.of(R.string.cant_add_work_profile), 1180 LazyStringResource.of( 1181 R.string.work_profile_cant_be_added_contact_admin, deviceName), 1182 errorMessage); 1183 break; 1184 case STATUS_PROVISIONING_NOT_ALLOWED_FOR_NON_DEVELOPER_USERS: 1185 mUi.showErrorAndClose( 1186 LazyStringResource.of(R.string.cant_add_work_profile), 1187 LazyStringResource.of( 1188 R.string.work_profile_cant_be_added_contact_admin, deviceName), 1189 "Exiting managed profile provisioning, " 1190 + "provisioning not allowed by OEM"); 1191 break; 1192 default: 1193 mUi.showErrorAndClose( 1194 R.string.cant_add_work_profile, 1195 R.string.contact_your_admin_for_help, 1196 "Managed profile provisioning not allowed for an unknown " 1197 + "reason, code: " 1198 + provisioningPreCondition); 1199 } 1200 } 1201 canAddManagedProfile()1202 private boolean canAddManagedProfile() { 1203 return mUserManager.canAddMoreManagedProfiles( 1204 mContext.getUserId(), /* allowedToRemoveOne= */ false); 1205 } 1206 showDeviceOwnerErrorAndClose(int provisioningPreCondition)1207 private void showDeviceOwnerErrorAndClose(int provisioningPreCondition) { 1208 CharSequence deviceName = DeviceHelper.getDeviceName(mContext); 1209 switch (provisioningPreCondition) { 1210 case STATUS_HAS_DEVICE_OWNER: 1211 case STATUS_USER_SETUP_COMPLETED: 1212 mUi.showErrorAndClose( 1213 LazyStringResource.of(R.string.device_already_set_up, deviceName), 1214 LazyStringResource.of(R.string.if_questions_contact_admin), 1215 "Device already provisioned."); 1216 return; 1217 case STATUS_NOT_SYSTEM_USER: 1218 mUi.showErrorAndClose( 1219 R.string.cant_set_up_device, 1220 R.string.contact_your_admin_for_help, 1221 "Device owner can only be set up for USER_SYSTEM."); 1222 return; 1223 case STATUS_PROVISIONING_NOT_ALLOWED_FOR_NON_DEVELOPER_USERS: 1224 mUi.showErrorAndClose( 1225 R.string.cant_set_up_device, 1226 R.string.contact_your_admin_for_help, 1227 "Provisioning not allowed by OEM"); 1228 return; 1229 } 1230 mUi.showErrorAndClose( 1231 R.string.cant_set_up_device, 1232 R.string.contact_your_admin_for_help, 1233 "Device Owner provisioning not allowed for an unknown reason."); 1234 } 1235 } 1236