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