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