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.EXTRA_PROVISIONING_TRIGGER; 20 import static android.app.admin.DevicePolicyManager.EXTRA_RESULT_LAUNCH_INTENT; 21 import static android.app.admin.DevicePolicyManager.EXTRA_ROLE_HOLDER_UPDATE_FAILURE_STRATEGY; 22 import static android.app.admin.DevicePolicyManager.EXTRA_ROLE_HOLDER_UPDATE_RESULT_CODE; 23 import static android.app.admin.DevicePolicyManager.PROVISIONING_TRIGGER_UNSPECIFIED; 24 import static android.app.admin.DevicePolicyManager.RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_PROVISIONING_DISABLED; 25 import static android.app.admin.DevicePolicyManager.RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_RECOVERABLE_ERROR; 26 import static android.app.admin.DevicePolicyManager.RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR; 27 import static android.app.admin.DevicePolicyManager.RESULT_UPDATE_ROLE_HOLDER; 28 import static android.app.admin.DevicePolicyManager.ROLE_HOLDER_UPDATE_FAILURE_STRATEGY_FAIL_PROVISIONING; 29 import static android.app.admin.DevicePolicyManager.ROLE_HOLDER_UPDATE_FAILURE_STRATEGY_FALLBACK_TO_PLATFORM_PROVISIONING; 30 import static android.content.res.Configuration.UI_MODE_NIGHT_MASK; 31 import static android.content.res.Configuration.UI_MODE_NIGHT_YES; 32 33 import static com.android.managedprovisioning.ManagedProvisioningScreens.RETRY_LAUNCH; 34 import static com.android.managedprovisioning.common.ErrorDialogUtils.EXTRA_DIALOG_TITLE_ID; 35 import static com.android.managedprovisioning.common.ErrorDialogUtils.EXTRA_ERROR_MESSAGE_RES; 36 import static com.android.managedprovisioning.common.ErrorDialogUtils.EXTRA_FACTORY_RESET_REQUIRED; 37 import static com.android.managedprovisioning.common.RetryLaunchActivity.EXTRA_INTENT_TO_LAUNCH; 38 import static com.android.managedprovisioning.model.ProvisioningParams.FLOW_TYPE_LEGACY; 39 import static com.android.managedprovisioning.preprovisioning.PreProvisioningViewModel.STATE_PREPROVISIONING_INITIALIZING; 40 import static com.android.managedprovisioning.preprovisioning.PreProvisioningViewModel.STATE_SHOWING_USER_CONSENT; 41 import static com.android.managedprovisioning.provisioning.Constants.PROVISIONING_SERVICE_INTENT; 42 43 import static com.google.android.setupcompat.util.WizardManagerHelper.EXTRA_IS_SETUP_FLOW; 44 45 import static java.util.Objects.requireNonNull; 46 47 import android.annotation.NonNull; 48 import android.annotation.Nullable; 49 import android.app.Activity; 50 import android.app.BackgroundServiceStartNotAllowedException; 51 import android.app.DialogFragment; 52 import android.app.admin.DevicePolicyManager; 53 import android.content.Intent; 54 import android.os.Bundle; 55 import android.os.PersistableBundle; 56 import android.provider.Settings; 57 import android.text.TextUtils; 58 import android.view.ContextMenu; 59 import android.view.ContextMenu.ContextMenuInfo; 60 import android.view.View; 61 import android.widget.TextView; 62 63 import androidx.annotation.VisibleForTesting; 64 65 import com.android.managedprovisioning.ManagedProvisioningBaseApplication; 66 import com.android.managedprovisioning.ManagedProvisioningScreens; 67 import com.android.managedprovisioning.R; 68 import com.android.managedprovisioning.analytics.MetricsWriterFactory; 69 import com.android.managedprovisioning.analytics.ProvisioningAnalyticsTracker; 70 import com.android.managedprovisioning.common.AccessibilityContextMenuMaker; 71 import com.android.managedprovisioning.common.DefaultFeatureFlagChecker; 72 import com.android.managedprovisioning.common.DefaultIntentResolverChecker; 73 import com.android.managedprovisioning.common.DefaultPackageInstallChecker; 74 import com.android.managedprovisioning.common.DeviceManagementRoleHolderUpdaterHelper; 75 import com.android.managedprovisioning.common.Flags; 76 import com.android.managedprovisioning.common.GetProvisioningModeUtils; 77 import com.android.managedprovisioning.common.ManagedProvisioningSharedPreferences; 78 import com.android.managedprovisioning.common.ProvisionLogger; 79 import com.android.managedprovisioning.common.RetryLaunchActivity; 80 import com.android.managedprovisioning.common.RoleHolderProvider; 81 import com.android.managedprovisioning.common.RoleHolderUpdaterProvider; 82 import com.android.managedprovisioning.common.SettingsFacade; 83 import com.android.managedprovisioning.common.SetupGlifLayoutActivity; 84 import com.android.managedprovisioning.common.SimpleDialog; 85 import com.android.managedprovisioning.common.ThemeHelper; 86 import com.android.managedprovisioning.common.ThemeHelper.DefaultNightModeChecker; 87 import com.android.managedprovisioning.common.ThemeHelper.DefaultSetupWizardBridge; 88 import com.android.managedprovisioning.common.Utils; 89 import com.android.managedprovisioning.contracts.DownloadRoleHolderArguments; 90 import com.android.managedprovisioning.contracts.DownloadRoleHolderContract; 91 import com.android.managedprovisioning.model.ProvisioningParams; 92 import com.android.managedprovisioning.preprovisioning.PreProvisioningActivityController.UiParams; 93 import com.android.managedprovisioning.provisioning.AdminIntegratedFlowPrepareActivity; 94 import com.android.managedprovisioning.provisioning.ProvisioningActivity; 95 import com.android.managedprovisioning.util.LazyStringResource; 96 97 import com.google.android.setupcompat.logging.ScreenKey; 98 import com.google.android.setupcompat.logging.SetupMetric; 99 import com.google.android.setupcompat.logging.SetupMetricsLogger; 100 import com.google.android.setupcompat.util.WizardManagerHelper; 101 import com.google.android.setupdesign.transition.TransitionHelper; 102 103 import dagger.hilt.android.AndroidEntryPoint; 104 105 import javax.inject.Inject; 106 107 @AndroidEntryPoint(SetupGlifLayoutActivity.class) 108 public class PreProvisioningActivity extends Hilt_PreProvisioningActivity implements 109 SimpleDialog.SimpleDialogListener, PreProvisioningActivityController.Ui { 110 111 private static final int ENCRYPT_DEVICE_REQUEST_CODE = 1; 112 @VisibleForTesting 113 protected static final int PROVISIONING_REQUEST_CODE = 2; 114 private static final int WIFI_REQUEST_CODE = 3; 115 private static final int CHANGE_LAUNCHER_REQUEST_CODE = 4; 116 private static final int ORGANIZATION_OWNED_LANDING_PAGE_REQUEST_CODE = 5; 117 private static final int GET_PROVISIONING_MODE_REQUEST_CODE = 6; 118 private static final int FINANCED_DEVICE_PREPARE_REQUEST_CODE = 7; 119 private static final int ADMIN_INTEGRATED_FLOW_PREPARE_REQUEST_CODE = 8; 120 private static final int START_PLATFORM_REQUESTED_ROLE_HOLDER_UPDATE_REQUEST_CODE = 9; 121 private static final int START_DEVICE_MANAGEMENT_ROLE_HOLDER_PROVISIONING_REQUEST_CODE = 10; 122 private static final int DOWNLOAD_DEVICE_MANAGEMENT_ROLE_HOLDER_FROM_PLATFORM_REQUEST_CODE = 11; 123 private static final int START_ROLE_HOLDER_REQUESTED_UPDATE_REQUEST_CODE = 12; 124 125 // Note: must match the constant defined in HomeSettings 126 private static final String EXTRA_SUPPORT_MANAGED_PROFILES = "support_managed_profiles"; 127 128 private static final String ERROR_AND_CLOSE_DIALOG = "PreProvErrorAndCloseDialog"; 129 private static final String BACK_PRESSED_DIALOG_RESET = "PreProvBackPressedDialogReset"; 130 private static final String BACK_PRESSED_DIALOG_CLOSE_ACTIVITY = 131 "PreProvBackPressedDialogCloseActivity"; 132 private static final String LAUNCHER_INVALID_DIALOG = "PreProvCurrentLauncherInvalidDialog"; 133 private static final String SETUP_METRIC_PREPROVISIONING_SCREEN_NAME = 134 "ShowPreProvisioningScreen"; 135 136 private PreProvisioningActivityController mController; 137 private final ControllerProvider mControllerProvider; 138 private final AccessibilityContextMenuMaker mContextMenuMaker; 139 private PreProvisioningActivityBridge mBridge; 140 private boolean mShouldForwardTransition; 141 private final RoleHolderUpdaterProvider mRoleHolderUpdaterProvider; 142 private final RoleHolderProvider mRoleHolderProvider; 143 144 private static final String ERROR_DIALOG_RESET = "ErrorDialogReset"; 145 private static final int SETUP_METRIC_DEFAULT_ERROR_CODE = -1; 146 private ProvisioningAnalyticsTracker mAnalyticsTracker; 147 private boolean mAlreadyInitialized; 148 protected ScreenKey mScreenKey; 149 protected String setupMetricScreenName; 150 151 @Inject 152 protected Flags mFlags; 153 @Inject 154 protected DownloadRoleHolderContract mDownloadRoleHolderContract; 155 PreProvisioningActivity()156 public PreProvisioningActivity() { 157 this(activity -> 158 new PreProvisioningActivityController(activity, activity), 159 null, 160 new Utils(), 161 new SettingsFacade(), 162 new ThemeHelper( 163 new DefaultNightModeChecker(), 164 new DefaultSetupWizardBridge()), 165 RoleHolderProvider.DEFAULT, 166 RoleHolderUpdaterProvider.DEFAULT); 167 } 168 169 @VisibleForTesting PreProvisioningActivity( ControllerProvider controllerProvider, AccessibilityContextMenuMaker contextMenuMaker, Utils utils, SettingsFacade settingsFacade, ThemeHelper themeHelper, RoleHolderProvider roleHolderProvider, RoleHolderUpdaterProvider roleHolderUpdaterProvider)170 public PreProvisioningActivity( 171 ControllerProvider controllerProvider, 172 AccessibilityContextMenuMaker contextMenuMaker, Utils utils, 173 SettingsFacade settingsFacade, ThemeHelper themeHelper, 174 RoleHolderProvider roleHolderProvider, 175 RoleHolderUpdaterProvider roleHolderUpdaterProvider) { 176 super(utils, settingsFacade, themeHelper); 177 mControllerProvider = requireNonNull(controllerProvider); 178 mContextMenuMaker = 179 contextMenuMaker != null ? contextMenuMaker : new AccessibilityContextMenuMaker( 180 this); 181 mRoleHolderUpdaterProvider = requireNonNull(roleHolderUpdaterProvider); 182 mRoleHolderProvider = requireNonNull(roleHolderProvider); 183 } 184 185 @Override onCreate(Bundle savedInstanceState)186 protected void onCreate(Bundle savedInstanceState) { 187 // TODO(b/192074477): Remove deferred setup-specific logic after the managed account flow 188 // starts ManagedProvisioning with the isSetupFlow extra 189 // This temporary fix only works when called before super.onCreate 190 if (mSettingsFacade.isDeferredSetup(getApplicationContext())) { 191 getIntent().putExtra(EXTRA_IS_SETUP_FLOW, true); 192 } 193 194 super.onCreate(savedInstanceState); 195 setupMetricScreenName = SETUP_METRIC_PREPROVISIONING_SCREEN_NAME; 196 mScreenKey = ScreenKey.of(setupMetricScreenName, this); 197 198 if (savedInstanceState == null) { 199 mAlreadyInitialized = false; 200 } 201 mController = mControllerProvider.getInstance(this); 202 mBridge = createBridge(); 203 mController.getState().observe(this, this::onStateChanged); 204 205 mAnalyticsTracker = 206 new ProvisioningAnalyticsTracker( 207 MetricsWriterFactory.getMetricsWriter(this, new SettingsFacade()), 208 new ManagedProvisioningSharedPreferences(this)); 209 logMetrics(); 210 } 211 212 @Override onStart()213 protected void onStart() { 214 super.onStart(); 215 try { 216 getApplicationContext().startService(PROVISIONING_SERVICE_INTENT); 217 } catch (BackgroundServiceStartNotAllowedException e) { 218 ProvisionLogger.loge(e); 219 } 220 mController.getState().observe(this, this::onStateChanged); 221 } 222 223 @Override onResume()224 protected void onResume() { 225 super.onResume(); 226 SetupMetricsLogger.logMetrics(this, mScreenKey, 227 SetupMetric.ofImpression(setupMetricScreenName)); 228 if (mShouldForwardTransition) { 229 TransitionHelper.applyForwardTransition( 230 this, TransitionHelper.TRANSITION_FADE_THROUGH); 231 mShouldForwardTransition = false; 232 } 233 } 234 createBridge()235 protected PreProvisioningActivityBridge createBridge() { 236 return new PreProvisioningActivityBridgeImpl( 237 /* activity= */ this, 238 mUtils, 239 PreProvisioningActivity.this::initializeLayoutParams, 240 createBridgeCallbacks(), 241 getThemeHelper(), 242 setupMetricScreenName); 243 } 244 createBridgeCallbacks()245 protected final PreProvisioningActivityBridgeCallbacks createBridgeCallbacks() { 246 return new PreProvisioningActivityBridgeCallbacks() { 247 @Override 248 public void onTermsAccepted() { 249 mController.continueProvisioningAfterUserConsent(); 250 } 251 252 @Override 253 public void onTermsButtonClicked() { 254 getTransitionHelper() 255 .startActivityWithTransition(PreProvisioningActivity.this, 256 mController.createViewTermsIntent()); 257 } 258 }; 259 } 260 261 private void onStateChanged(Integer state) { 262 switch (state) { 263 case STATE_PREPROVISIONING_INITIALIZING: 264 if (!mAlreadyInitialized) { 265 mController.initiateProvisioning(getIntent(), getCallingPackage()); 266 mAlreadyInitialized = true; 267 } 268 break; 269 case STATE_SHOWING_USER_CONSENT: 270 mController.showUserConsentScreen(); 271 break; 272 } 273 } 274 275 @Override 276 public void finish() { 277 // The user has backed out of provisioning, so we perform the necessary clean up steps. 278 ProvisioningParams params = mController.getParams(); 279 if (params != null) { 280 params.cleanUp(); 281 } 282 getEncryptionController().cancelEncryptionReminder(); 283 getApplicationContext().stopService(PROVISIONING_SERVICE_INTENT); 284 super.finish(); 285 } 286 287 @SuppressWarnings("MissingSuperCall") // TODO: Fix me 288 @Override 289 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 290 switch (requestCode) { 291 case ENCRYPT_DEVICE_REQUEST_CODE: 292 if (resultCode == RESULT_CANCELED) { 293 ProvisionLogger.loge("User canceled device encryption."); 294 } 295 break; 296 case PROVISIONING_REQUEST_CODE: 297 mController.onReturnFromProvisioning(); 298 setResult(resultCode); 299 getTransitionHelper().finishActivity(this); 300 break; 301 case CHANGE_LAUNCHER_REQUEST_CODE: 302 mController.continueProvisioningAfterUserConsent(); 303 break; 304 case WIFI_REQUEST_CODE: 305 if (resultCode == RESULT_CANCELED) { 306 ProvisionLogger.loge("User canceled wifi picking."); 307 setResult(resultCode); 308 getTransitionHelper().finishActivity(this); 309 } else { 310 if (resultCode == RESULT_OK) { 311 ProvisionLogger.logd("Wifi request result is OK"); 312 } 313 mController.initiateProvisioning(getIntent(), getCallingPackage()); 314 } 315 break; 316 case ORGANIZATION_OWNED_LANDING_PAGE_REQUEST_CODE: 317 case ADMIN_INTEGRATED_FLOW_PREPARE_REQUEST_CODE: 318 if (resultCode == RESULT_OK) { 319 handleAdminIntegratedFlowPreparerResult(); 320 } else { 321 ProvisionLogger.loge( 322 "Provisioning was aborted in the preparation stage, " 323 + "requestCode = " + requestCode); 324 SetupMetricsLogger.logMetrics(this, mScreenKey, 325 SetupMetric.ofError(setupMetricScreenName, resultCode)); 326 if (isDpcInstalled() 327 && mUtils.isOrganizationOwnedAllowed(mController.getParams())) { 328 showFactoryResetDialog(R.string.cant_set_up_device, 329 R.string.contact_your_admin_for_help); 330 } else { 331 showErrorAndClose( 332 R.string.cant_set_up_device, 333 R.string.contact_your_admin_for_help, 334 "Failed provisioning device."); 335 } 336 } 337 break; 338 case GET_PROVISIONING_MODE_REQUEST_CODE: 339 mShouldForwardTransition = true; 340 if (resultCode == RESULT_OK) { 341 if (data != null && mController.updateProvisioningParamsFromIntent(data)) { 342 mController.showUserConsentScreen(); 343 } else { 344 ProvisionLogger.loge( 345 "Invalid data object returned from GET_PROVISIONING_MODE."); 346 SetupMetricsLogger.logMetrics(this, mScreenKey, 347 SetupMetric.ofError(setupMetricScreenName, resultCode)); 348 if (mUtils.isOrganizationOwnedAllowed(mController.getParams())) { 349 showFactoryResetDialog(R.string.cant_set_up_device, 350 R.string.contact_your_admin_for_help); 351 } else { 352 showErrorAndClose( 353 R.string.cant_set_up_device, 354 R.string.contact_your_admin_for_help, 355 "Failed provisioning personally-owned device."); 356 } 357 } 358 } else { 359 ProvisionLogger.loge("Invalid result code from GET_PROVISIONING_MODE. Expected " 360 + RESULT_OK + " but got " + resultCode + "."); 361 SetupMetricsLogger.logMetrics(this, mScreenKey, 362 SetupMetric.ofError(setupMetricScreenName, resultCode)); 363 if (mUtils.isOrganizationOwnedAllowed(mController.getParams())) { 364 showFactoryResetDialog(R.string.cant_set_up_device, 365 R.string.contact_your_admin_for_help); 366 } else { 367 showErrorAndClose( 368 R.string.cant_set_up_device, 369 R.string.contact_your_admin_for_help, 370 "Failed to provision personally-owned device."); 371 } 372 } 373 break; 374 case FINANCED_DEVICE_PREPARE_REQUEST_CODE: 375 if (resultCode == RESULT_OK) { 376 startFinancedDeviceFlow(); 377 } else { 378 setResult(resultCode); 379 getTransitionHelper().finishActivity(this); 380 } 381 break; 382 case START_PLATFORM_REQUESTED_ROLE_HOLDER_UPDATE_REQUEST_CODE: 383 handlePlatformRequestedUpdateResult(resultCode, data); 384 break; 385 case START_ROLE_HOLDER_REQUESTED_UPDATE_REQUEST_CODE: 386 handleRoleHolderRequestedUpdateResult(resultCode, data); 387 break; 388 case START_DEVICE_MANAGEMENT_ROLE_HOLDER_PROVISIONING_REQUEST_CODE: 389 ProvisionLogger.logw("Role holder returned result code " + resultCode); 390 mAnalyticsTracker.logRoleHolderProvisioningFinish(); 391 if (resultCode == RESULT_UPDATE_ROLE_HOLDER) { 392 if (handleUpdateRequestedWithNoRoleHolderUpdater(resultCode)) { 393 return; 394 } 395 if (handleUpdateRequestedWithWrongStateType(data)) { 396 return; 397 } 398 PersistableBundle roleHolderState = 399 data.getParcelableExtra(DevicePolicyManager.EXTRA_ROLE_HOLDER_STATE); 400 mController.resetRoleHolderUpdateRetryCount(); 401 mController.startRoleHolderUpdater( 402 /* isRoleHolderRequestedUpdate= */ true, roleHolderState); 403 } else { 404 maybeHandleLaunchIntent(resultCode, data); 405 getTransitionHelper().finishActivity(this); 406 } 407 break; 408 case DOWNLOAD_DEVICE_MANAGEMENT_ROLE_HOLDER_FROM_PLATFORM_REQUEST_CODE: 409 mAnalyticsTracker.logPlatformRoleHolderUpdateFinished(resultCode); 410 if (resultCode == RESULT_OK 411 || mController.getParams().allowOffline) { 412 boolean isProvisioningStarted = mController.startAppropriateProvisioning( 413 getIntent(), 414 new Bundle(), 415 getCallingPackage()); 416 if (!isProvisioningStarted) { 417 mAnalyticsTracker.logPlatformRoleHolderUpdateFailed(); 418 ProvisionLogger.loge("Provisioning could not be started following " 419 + "platform-side role holder download."); 420 SetupMetricsLogger.logMetrics(this, mScreenKey, 421 SetupMetric.ofError(setupMetricScreenName, resultCode)); 422 showRoleHolderDownloadFailedDialog(new Intent()); 423 } 424 } else if (data != null && data.hasExtra(EXTRA_ERROR_MESSAGE_RES)) { 425 mAnalyticsTracker.logPlatformRoleHolderUpdateFailed(); 426 ProvisionLogger.loge("Role holder download failed and offline provisioning is " 427 + "not allowed."); 428 SetupMetricsLogger.logMetrics(this, mScreenKey, 429 SetupMetric.ofError(setupMetricScreenName, resultCode)); 430 showRoleHolderDownloadFailedDialog(data); 431 } else { 432 mAnalyticsTracker.logPlatformRoleHolderUpdateFailed(); 433 ProvisionLogger.loge("Role holder download failed and offline provisioning is " 434 + "not allowed."); 435 SetupMetricsLogger.logMetrics(this, mScreenKey, 436 SetupMetric.ofError(setupMetricScreenName, resultCode)); 437 showRoleHolderDownloadFailedDialog(new Intent()); 438 } 439 break; 440 default: 441 ProvisionLogger.logw("Unknown result code :" + resultCode); 442 SetupMetricsLogger.logMetrics(this, mScreenKey, 443 SetupMetric.ofError(setupMetricScreenName, resultCode)); 444 break; 445 } 446 } 447 448 private boolean handleUpdateRequestedWithWrongStateType(Intent data) { 449 if (!(data.getParcelableExtra(DevicePolicyManager.EXTRA_ROLE_HOLDER_STATE) 450 instanceof PersistableBundle)) { 451 ProvisionLogger.loge("Failed to process role holder state result."); 452 SetupMetricsLogger.logMetrics(this, mScreenKey, 453 SetupMetric.ofError(setupMetricScreenName, SETUP_METRIC_DEFAULT_ERROR_CODE)); 454 if (mUtils.isOrganizationOwnedAllowed(mController.getParams())) { 455 showFactoryResetDialog(R.string.cant_set_up_device, 456 R.string.contact_your_admin_for_help); 457 } else { 458 showErrorAndClose( 459 R.string.cant_set_up_device, 460 R.string.contact_your_admin_for_help, 461 "Failed to process role holder state result."); 462 } 463 return true; 464 } 465 return false; 466 } 467 468 private boolean handleUpdateRequestedWithNoRoleHolderUpdater(int resultCode) { 469 if (TextUtils.isEmpty( 470 mRoleHolderUpdaterProvider.getPackageName(this))) { 471 ProvisionLogger.logw("Role holder requested update, but there is no role " 472 + "holder updater present. Restarting the role holder."); 473 boolean isProvisioningStarted = mController.startAppropriateProvisioning( 474 getIntent(), 475 createRoleHolderAdditionalExtras(resultCode), 476 getCallingPackage()); 477 if (!isProvisioningStarted) { 478 failRoleHolderUpdate(); 479 ProvisionLogger.loge("Failed to start provisioning after a " 480 + "role holder-requested role holder update and no updater " 481 + "present. Result is " + resultCode + " and allow offline " 482 + "provisioning is " + mController.getParams().allowOffline); 483 SetupMetricsLogger.logMetrics(this, mScreenKey, 484 SetupMetric.ofError(setupMetricScreenName, resultCode)); 485 } 486 return true; 487 } 488 return false; 489 } 490 491 private Bundle createRoleHolderAdditionalExtras(int resultCode) { 492 Bundle additionalExtras = new Bundle(); 493 additionalExtras.putInt(EXTRA_ROLE_HOLDER_UPDATE_RESULT_CODE, resultCode); 494 return additionalExtras; 495 } 496 497 private void handlePlatformRequestedUpdateResult(int resultCode, @Nullable Intent resultData) { 498 mAnalyticsTracker.logRoleHolderUpdaterUpdateFinish(resultCode); 499 if ((resultCode 500 == RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_RECOVERABLE_ERROR 501 || resultCode == RESULT_CANCELED) 502 && mController.canRetryRoleHolderUpdate()) { 503 mController.startRoleHolderUpdaterWithLastState( 504 /* isRoleHolderRequestedUpdate= */ false); 505 mController.incrementRoleHolderUpdateRetryCount(); 506 mAnalyticsTracker.logRoleHolderUpdaterUpdateRetry(); 507 } else if (resultCode 508 == RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_PROVISIONING_DISABLED 509 ) { 510 mController.performPlatformProvidedProvisioning(); 511 } else if (resultCode 512 != RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR) { 513 mController.resetRoleHolderUpdateRetryCount(); 514 boolean isProvisioningStarted = mController.startAppropriateProvisioning( 515 getIntent(), 516 createRoleHolderAdditionalExtras(resultCode), 517 getCallingPackage()); 518 if (!isProvisioningStarted) { 519 if (isRoleHolderUpdaterRequestingPlatformDrivenProvisioning(resultData)) { 520 ProvisionLogger.logi("Result is " + resultCode 521 + " and applied fallback strategy."); 522 mController.performPlatformProvidedProvisioning(); 523 } else { 524 mAnalyticsTracker.logRoleHolderUpdaterUpdateFailed(); 525 failRoleHolderUpdate(); 526 ProvisionLogger.loge("Failed to start provisioning after a " 527 + "platform-requested role holder update. Result is " + resultCode 528 + " and allow offline provisioning is " 529 + mController.getParams().allowOffline); 530 SetupMetricsLogger.logMetrics(this, mScreenKey, 531 SetupMetric.ofError(setupMetricScreenName, resultCode)); 532 } 533 } 534 } else if (mController.getParams().allowOffline) { 535 ProvisionLogger.logi("Result is " + resultCode + ". Allowed offline provisioning."); 536 mController.performPlatformProvidedProvisioning(); 537 } else if (isRoleHolderUpdaterRequestingPlatformDrivenProvisioning(resultData)) { 538 ProvisionLogger.logi("Result is " + resultCode + " and applied fallback strategy."); 539 mController.performPlatformProvidedProvisioning(); 540 } else { 541 mAnalyticsTracker.logRoleHolderUpdaterUpdateFailed(); 542 failRoleHolderUpdate(); 543 ProvisionLogger.loge("Failed to perform a platform-requested role holder " 544 + "update. Result is " + resultCode + " and allow offline provisioning" 545 + " is " + mController.getParams().allowOffline); 546 SetupMetricsLogger.logMetrics(this, mScreenKey, 547 SetupMetric.ofError(setupMetricScreenName, resultCode)); 548 } 549 } 550 551 private void handleRoleHolderRequestedUpdateResult(int resultCode, Intent resultData) { 552 if ((resultCode 553 == RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_RECOVERABLE_ERROR 554 || resultCode == RESULT_CANCELED) 555 && mController.canRetryRoleHolderUpdate()) { 556 mController.startRoleHolderUpdaterWithLastState( 557 /* isRoleHolderRequestedUpdate= */ true); 558 mController.incrementRoleHolderUpdateRetryCount(); 559 } else if (resultCode 560 == RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_PROVISIONING_DISABLED) { 561 mController.performPlatformProvidedProvisioning(); 562 } else if (resultCode 563 != RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR) { 564 boolean isProvisioningStarted = mController.startAppropriateProvisioning( 565 getIntent(), 566 createRoleHolderAdditionalExtras(resultCode), 567 getCallingPackage()); 568 if (!isProvisioningStarted) { 569 if (isRoleHolderUpdaterRequestingPlatformDrivenProvisioning(resultData)) { 570 ProvisionLogger.logi("Result is " + resultCode 571 + " and applied fallback strategy."); 572 mController.performPlatformProvidedProvisioning(); 573 } else { 574 failRoleHolderUpdate(); 575 ProvisionLogger.loge("Failed to start provisioning after a " 576 + "role holder-requested role holder update. Result is " 577 + resultCode + " and allow offline provisioning is " 578 + mController.getParams().allowOffline); 579 SetupMetricsLogger.logMetrics(this, mScreenKey, 580 SetupMetric.ofError(setupMetricScreenName, resultCode)); 581 } 582 } 583 } else if (mController.getParams().allowOffline) { 584 ProvisionLogger.logi("Result is " + resultCode + ". Allowed offline provisioning."); 585 mController.performPlatformProvidedProvisioning(); 586 } else if (isRoleHolderUpdaterRequestingPlatformDrivenProvisioning(resultData)) { 587 ProvisionLogger.logi("Result is " + resultCode + " and applied fallback strategy."); 588 mController.performPlatformProvidedProvisioning(); 589 } else { 590 failRoleHolderUpdate(); 591 ProvisionLogger.loge("Failed to perform a role holder-requested role holder " 592 + "update. Result is " + resultCode + " and allow offline provisioning" 593 + " is " + mController.getParams().allowOffline); 594 SetupMetricsLogger.logMetrics(this, mScreenKey, 595 SetupMetric.ofError(setupMetricScreenName, resultCode)); 596 } 597 } 598 599 private boolean isRoleHolderUpdaterRequestingPlatformDrivenProvisioning( 600 @Nullable Intent resultData) { 601 if (resultData == null) { 602 return false; 603 } 604 return resultData.getIntExtra( 605 EXTRA_ROLE_HOLDER_UPDATE_FAILURE_STRATEGY, 606 ROLE_HOLDER_UPDATE_FAILURE_STRATEGY_FAIL_PROVISIONING) 607 == ROLE_HOLDER_UPDATE_FAILURE_STRATEGY_FALLBACK_TO_PLATFORM_PROVISIONING; 608 } 609 610 private void maybeHandleLaunchIntent(int resultCode, Intent data) { 611 if (data == null || !data.hasExtra(EXTRA_RESULT_LAUNCH_INTENT)) { 612 setResult(resultCode); 613 return; 614 } 615 616 Intent launchIntent = data.getParcelableExtra(EXTRA_RESULT_LAUNCH_INTENT, Intent.class); 617 ProvisionLogger.logi("Role holder returned result intent: " + launchIntent); 618 619 if (!mController.getParams().provisioningShouldLaunchResultIntent) { 620 ProvisionLogger.logi("Role Holder result intent to be launched by " 621 + "provisioning initiator"); 622 setResult(resultCode, launchIntent); 623 return; 624 } 625 626 ProvisionLogger.logi("Role Holder result intent launched by platform"); 627 startActivity(launchIntent); 628 } 629 630 private void failRoleHolderUpdate() { 631 ProvisionLogger.loge("Update failed and offline provisioning is not allowed."); 632 SetupMetricsLogger.logMetrics(this, mScreenKey, 633 SetupMetric.ofError(setupMetricScreenName, SETUP_METRIC_DEFAULT_ERROR_CODE)); 634 if (mUtils.isOrganizationOwnedAllowed(mController.getParams())) { 635 showFactoryResetDialog(R.string.cant_set_up_device, 636 R.string.contact_your_admin_for_help); 637 } else { 638 showErrorAndClose( 639 R.string.cant_set_up_device, 640 R.string.contact_your_admin_for_help, 641 "Failed to provision personally-owned device."); 642 } 643 } 644 645 private void showRoleHolderDownloadFailedDialog(@NonNull Intent data) { 646 int dialogTitleResId = data.getIntExtra( 647 EXTRA_DIALOG_TITLE_ID, 648 R.string.cant_set_up_device); 649 650 651 String dialogMessageRes = data.getStringExtra(EXTRA_ERROR_MESSAGE_RES); 652 LazyStringResource dialogMessage = !dialogMessageRes.isEmpty() ? LazyStringResource.of( 653 dialogMessageRes) : LazyStringResource.of(R.string.contact_your_admin_for_help); 654 655 656 if (data.getBooleanExtra(EXTRA_FACTORY_RESET_REQUIRED, /* defaultValue= */ false)) { 657 showFactoryResetDialog( 658 LazyStringResource.of(dialogTitleResId), 659 dialogMessage); 660 } else { 661 showErrorAndClose( 662 LazyStringResource.of(dialogTitleResId), 663 dialogMessage, 664 "Failed to provision personally-owned device."); 665 } 666 } 667 668 private boolean isDpcInstalled() { 669 String adminPackageName = mController.getParams().inferDeviceAdminPackageName(); 670 return mUtils.isPackageInstalled(adminPackageName, getPackageManager()); 671 } 672 673 private void handleAdminIntegratedFlowPreparerResult() { 674 if (isDpcInstalled()) { 675 startAdminIntegratedFlowPostDpcInstall(); 676 } else { 677 String adminPackageName = mController.getParams().inferDeviceAdminPackageName(); 678 showErrorAndClose( 679 R.string.cant_set_up_device, 680 R.string.contact_your_admin_for_help, 681 "Package name " + adminPackageName + " is not installed."); 682 } 683 } 684 685 @Override 686 public void showErrorAndClose(Integer titleId, int messageId, String logMessage) { 687 showErrorAndClose(LazyStringResource.of(titleId), LazyStringResource.of(messageId), 688 logMessage); 689 } 690 691 @Override 692 public void showErrorAndClose( 693 LazyStringResource title, LazyStringResource message, String logMessage) { 694 SimpleDialog.Builder dialogBuilder = 695 new SimpleDialog.Builder().setTitle(title).setMessage(message); 696 setShowErrorAndCloseParams(dialogBuilder, logMessage); 697 } 698 699 private void setShowErrorAndCloseParams(SimpleDialog.Builder dialogBuilder, String logText) { 700 ProvisionLogger.loge(logText); 701 702 SimpleDialog.Builder builder = 703 dialogBuilder 704 .setCancelable(false) 705 .setPositiveButtonMessage(R.string.device_owner_error_ok); 706 showDialog(builder, ERROR_AND_CLOSE_DIALOG); 707 } 708 709 @Override 710 public void onNegativeButtonClick(DialogFragment dialog) { 711 switch (dialog.getTag()) { 712 case BACK_PRESSED_DIALOG_CLOSE_ACTIVITY: 713 case BACK_PRESSED_DIALOG_RESET: 714 // user chose to continue. Do nothing 715 break; 716 case LAUNCHER_INVALID_DIALOG: 717 dialog.dismiss(); 718 break; 719 default: 720 SimpleDialog.throwButtonClickHandlerNotImplemented(dialog); 721 } 722 } 723 724 @Override 725 public void onPositiveButtonClick(DialogFragment dialog) { 726 switch (dialog.getTag()) { 727 case ERROR_AND_CLOSE_DIALOG: 728 case BACK_PRESSED_DIALOG_CLOSE_ACTIVITY: 729 onProvisioningAborted(); 730 break; 731 case BACK_PRESSED_DIALOG_RESET: 732 mUtils.factoryReset(this, "Provisioning cancelled by user on consent screen"); 733 onProvisioningAborted(); 734 break; 735 case LAUNCHER_INVALID_DIALOG: 736 requestLauncherPick(); 737 break; 738 case ERROR_DIALOG_RESET: 739 getUtils().factoryReset(this, "Error during preprovisioning"); 740 setResult(Activity.RESULT_CANCELED); 741 getTransitionHelper().finishActivity(this); 742 break; 743 default: 744 SimpleDialog.throwButtonClickHandlerNotImplemented(dialog); 745 } 746 } 747 748 private void onProvisioningAborted() { 749 setResult(Activity.RESULT_CANCELED); 750 mController.logPreProvisioningCancelled(); 751 getTransitionHelper().finishActivity(this); 752 } 753 754 @Override 755 public void requestEncryption(ProvisioningParams params) { 756 Intent encryptIntent = new Intent(this, 757 getActivityForScreen(ManagedProvisioningScreens.ENCRYPT)); 758 WizardManagerHelper.copyWizardManagerExtras(getIntent(), encryptIntent); 759 encryptIntent.putExtra(ProvisioningParams.EXTRA_PROVISIONING_PARAMS, params); 760 getTransitionHelper().startActivityForResultWithTransition( 761 this, encryptIntent, ENCRYPT_DEVICE_REQUEST_CODE); 762 } 763 764 @Override 765 public void requestWifiPick() { 766 final Intent intent = mUtils.getWifiPickIntent(); 767 WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent); 768 getTransitionHelper() 769 .startActivityForResultWithTransition(this, intent, WIFI_REQUEST_CODE); 770 } 771 772 @Override 773 public void showCurrentLauncherInvalid() { 774 SimpleDialog.Builder dialogBuilder = new SimpleDialog.Builder() 775 .setCancelable(false) 776 .setTitle(R.string.change_device_launcher) 777 .setMessage(R.string.launcher_app_cant_be_used_by_work_profile) 778 .setNegativeButtonMessage(R.string.cancel_provisioning) 779 .setPositiveButtonMessage(R.string.pick_launcher); 780 showDialog(dialogBuilder, LAUNCHER_INVALID_DIALOG); 781 } 782 783 @Override 784 public void abortProvisioning() { 785 onProvisioningAborted(); 786 } 787 788 @Override 789 public void prepareAdminIntegratedFlow(ProvisioningParams params) { 790 if (AdminIntegratedFlowPrepareActivity.shouldRunPrepareActivity(mUtils, this, params)) { 791 Intent intent = new Intent(this, 792 getActivityForScreen(ManagedProvisioningScreens.ADMIN_INTEGRATED_PREPARE)); 793 WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent); 794 intent.putExtra(ProvisioningParams.EXTRA_PROVISIONING_PARAMS, params); 795 getTransitionHelper().startActivityForResultWithTransition( 796 this, intent, ADMIN_INTEGRATED_FLOW_PREPARE_REQUEST_CODE); 797 } else { 798 handleAdminIntegratedFlowPreparerResult(); 799 } 800 } 801 802 @Override 803 public void startRoleHolderUpdater(boolean isRoleHolderRequestedUpdate) { 804 DeviceManagementRoleHolderUpdaterHelper roleHolderUpdaterHelper = 805 new DeviceManagementRoleHolderUpdaterHelper( 806 mRoleHolderUpdaterProvider.getPackageName(this), 807 RoleHolderProvider.DEFAULT.getPackageName(this), 808 new DefaultPackageInstallChecker(getPackageManager(), mUtils), 809 new DefaultIntentResolverChecker(getPackageManager()), 810 new DefaultFeatureFlagChecker(getContentResolver())); 811 Intent intent = new Intent(this, getActivityForScreen(RETRY_LAUNCH)); 812 intent.putExtra( 813 EXTRA_INTENT_TO_LAUNCH, 814 roleHolderUpdaterHelper.createRoleHolderUpdaterIntent( 815 getIntent(), 816 getIntent().getIntExtra( 817 EXTRA_PROVISIONING_TRIGGER, PROVISIONING_TRIGGER_UNSPECIFIED), 818 isRoleHolderRequestedUpdate)); 819 mAnalyticsTracker.logRoleHolderUpdaterUpdateStart(); 820 getTransitionHelper().startActivityForResultWithTransition( 821 this, 822 intent, 823 isRoleHolderRequestedUpdate 824 ? START_ROLE_HOLDER_REQUESTED_UPDATE_REQUEST_CODE 825 : START_PLATFORM_REQUESTED_ROLE_HOLDER_UPDATE_REQUEST_CODE); 826 } 827 828 @Override 829 public void startRoleHolderProvisioning(Intent intent) { 830 mAnalyticsTracker.logRoleHolderProvisioningStart(); 831 Intent retryLaunchIntent = new Intent(this, getActivityForScreen(RETRY_LAUNCH)); 832 retryLaunchIntent.putExtra(RetryLaunchActivity.EXTRA_INTENT_TO_LAUNCH, intent); 833 getTransitionHelper().startActivityForResultWithTransition( 834 /* activity= */ this, 835 retryLaunchIntent, 836 START_DEVICE_MANAGEMENT_ROLE_HOLDER_PROVISIONING_REQUEST_CODE); 837 } 838 839 @Override 840 public void onParamsValidated(ProvisioningParams params) { 841 ManagedProvisioningBaseApplication application = 842 (ManagedProvisioningBaseApplication) getApplication(); 843 application.keepScreenOn(this); 844 } 845 846 @Override 847 public void startPlatformDrivenRoleHolderDownload() { 848 mAnalyticsTracker.logPlatformRoleHolderUpdateStart(); 849 850 Intent intent; 851 if (mFlags.isCosmicRayEnabled()) { 852 intent = mDownloadRoleHolderContract.createIntent( 853 this, 854 DownloadRoleHolderArguments.of( 855 mDownloadRoleHolderContract.getSuwArgumentsSerializer().read( 856 getIntent()), 857 requireNonNull(mController.getParams()))); 858 } else { 859 intent = new Intent(this, 860 getActivityForScreen(ManagedProvisioningScreens.DOWNLOAD_ROLE_HOLDER)); 861 WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent); 862 intent.putExtra(ProvisioningParams.EXTRA_PROVISIONING_PARAMS, 863 mController.getParams()); 864 } 865 getTransitionHelper().startActivityForResultWithTransition( 866 this, intent, DOWNLOAD_DEVICE_MANAGEMENT_ROLE_HOLDER_FROM_PLATFORM_REQUEST_CODE); 867 } 868 869 private void requestLauncherPick() { 870 Intent changeLauncherIntent = new Intent(Settings.ACTION_HOME_SETTINGS); 871 changeLauncherIntent.putExtra(EXTRA_SUPPORT_MANAGED_PROFILES, true); 872 getTransitionHelper().startActivityForResultWithTransition( 873 this, changeLauncherIntent, CHANGE_LAUNCHER_REQUEST_CODE); 874 } 875 876 /** 877 * Starts {@link ProvisioningActivity}. 878 */ 879 @Override 880 public void startProvisioning(ProvisioningParams params) { 881 Intent intent = new Intent(this, 882 getActivityForScreen(ManagedProvisioningScreens.PROVISIONING)); 883 WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent); 884 intent.putExtra(ProvisioningParams.EXTRA_PROVISIONING_PARAMS, params); 885 getTransitionHelper().startActivityForResultWithTransition( 886 this, intent, PROVISIONING_REQUEST_CODE); 887 } 888 889 // TODO: The below group of methods do not belong in the activity. 890 // Move them to the controller instead. 891 892 /** 893 * Starts either the admin-integrated or the legacy flow, depending on the device state and 894 * DPC capabilities. 895 */ 896 private void startAdminIntegratedFlowPostDpcInstall() { 897 boolean canPerformAdminIntegratedFlow = mUtils.canPerformAdminIntegratedFlow( 898 this, 899 mController.getParams(), 900 mController.getPolicyComplianceUtils(), 901 mController.getGetProvisioningModeUtils()); 902 if (canPerformAdminIntegratedFlow) { 903 startAdminIntegratedFlowWithoutPredeterminedMode(); 904 } else { 905 ProvisionLogger.loge("The admin app does not have handlers for both " 906 + "ACTION_GET_PROVISIONING_MODE and ACTION_ADMIN_POLICY_COMPLIANCE " 907 + "intent actions."); 908 SetupMetricsLogger.logMetrics(this, mScreenKey, 909 SetupMetric.ofError(setupMetricScreenName, SETUP_METRIC_DEFAULT_ERROR_CODE)); 910 if (mUtils.isOrganizationOwnedAllowed(mController.getParams())) { 911 showFactoryResetDialog(R.string.cant_set_up_device, 912 R.string.contact_your_admin_for_help); 913 } else { 914 showErrorAndClose( 915 R.string.cant_set_up_device, 916 R.string.contact_your_admin_for_help, 917 "Failed provisioning personally-owned device."); 918 } 919 } 920 mController.logProvisioningFlowType(); 921 } 922 923 private void startAdminIntegratedFlowWithoutPredeterminedMode() { 924 ProvisionLogger.logi("Starting the admin-integrated flow."); 925 GetProvisioningModeUtils provisioningModeUtils = mController.getGetProvisioningModeUtils(); 926 Bundle additionalExtras = mController.getAdditionalExtrasForGetProvisioningModeIntent(); 927 provisioningModeUtils.startGetProvisioningModeActivityIfResolved( 928 this, mController.getParams(), additionalExtras, 929 GET_PROVISIONING_MODE_REQUEST_CODE, getTransitionHelper()); 930 } 931 932 private void startFinancedDeviceFlow() { 933 ProvisionLogger.logi("Starting the financed device flow."); 934 mController.updateProvisioningFlowState(FLOW_TYPE_LEGACY); 935 mController.continueProvisioningAfterUserConsent(); 936 } 937 938 @Override 939 public void showFactoryResetDialog(Integer titleId, int messageId) { 940 SimpleDialog.Builder dialogBuilder = new SimpleDialog.Builder() 941 .setTitle(titleId) 942 .setMessage(messageId) 943 .setCancelable(false) 944 .setPositiveButtonMessage(R.string.reset); 945 946 showDialog(dialogBuilder, ERROR_DIALOG_RESET); 947 } 948 949 @Override 950 public void showFactoryResetDialog(LazyStringResource titleId, LazyStringResource messageId) { 951 SimpleDialog.Builder dialogBuilder = new SimpleDialog.Builder() 952 .setTitle(titleId) 953 .setMessage(messageId) 954 .setCancelable(false) 955 .setPositiveButtonMessage(R.string.reset); 956 957 showDialog(dialogBuilder, ERROR_DIALOG_RESET); 958 } 959 960 @Override 961 public void initiateUi(UiParams uiParams) { 962 mBridge.initiateUi(uiParams); 963 } 964 965 @Override 966 public void showOwnershipDisclaimerScreen(ProvisioningParams params) { 967 Intent intent = new Intent(this, 968 getActivityForScreen(ManagedProvisioningScreens.LANDING)); 969 WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent); 970 intent.putExtra(ProvisioningParams.EXTRA_PROVISIONING_PARAMS, params); 971 getTransitionHelper().startActivityForResultWithTransition( 972 this, intent, ORGANIZATION_OWNED_LANDING_PAGE_REQUEST_CODE); 973 } 974 975 @Override 976 public void prepareFinancedDeviceFlow(ProvisioningParams params) { 977 Intent intent = new Intent(this, 978 getActivityForScreen(ManagedProvisioningScreens.FINANCED_DEVICE_LANDING)); 979 WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent); 980 intent.putExtra(ProvisioningParams.EXTRA_PROVISIONING_PARAMS, params); 981 getTransitionHelper().startActivityForResultWithTransition( 982 this, intent, FINANCED_DEVICE_PREPARE_REQUEST_CODE); 983 } 984 985 @Override 986 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { 987 super.onCreateContextMenu(menu, v, menuInfo); 988 if (v instanceof TextView) { 989 mContextMenuMaker.populateMenuContent(menu, (TextView) v); 990 } 991 } 992 993 @Override 994 public void onBackPressed() { 995 if (mUtils.isOrganizationOwnedAllowed(mController.getParams())) { 996 showDialog(mUtils.createCancelProvisioningResetDialogBuilder(getApplicationContext()), 997 BACK_PRESSED_DIALOG_RESET); 998 } else { 999 showDialog(mUtils.createCancelProvisioningDialogBuilder(), 1000 BACK_PRESSED_DIALOG_CLOSE_ACTIVITY); 1001 } 1002 } 1003 1004 private void logMetrics() { 1005 int nightMode = getResources().getConfiguration().uiMode & UI_MODE_NIGHT_MASK; 1006 mAnalyticsTracker.logIsNightMode(nightMode == UI_MODE_NIGHT_YES); 1007 } 1008 1009 /** 1010 * Constructs {@link PreProvisioningActivityController} for a given {@link 1011 * PreProvisioningActivity} 1012 */ 1013 interface ControllerProvider { 1014 /** 1015 * Constructs {@link PreProvisioningActivityController} for a given {@link 1016 * PreProvisioningActivity} 1017 */ 1018 PreProvisioningActivityController getInstance(PreProvisioningActivity activity); 1019 } 1020 } 1021