1 /* 2 * Copyright (C) 2008 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.settings; 18 19 import static android.app.admin.DevicePolicyResources.Strings.Settings.PERSONAL_CATEGORY_HEADER; 20 import static android.app.admin.DevicePolicyResources.Strings.Settings.PRIVATE_CATEGORY_HEADER; 21 import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_CATEGORY_HEADER; 22 23 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; 24 25 import android.accounts.Account; 26 import android.accounts.AccountManager; 27 import android.accounts.AuthenticatorDescription; 28 import android.app.ActionBar; 29 import android.app.Activity; 30 import android.app.AlertDialog; 31 import android.app.admin.DevicePolicyManager; 32 import android.app.settings.SettingsEnums; 33 import android.content.ComponentName; 34 import android.content.ContentResolver; 35 import android.content.Context; 36 import android.content.DialogInterface; 37 import android.content.Intent; 38 import android.content.pm.PackageManager; 39 import android.content.pm.ResolveInfo; 40 import android.content.pm.UserInfo; 41 import android.content.res.Resources; 42 import android.graphics.Color; 43 import android.graphics.drawable.Drawable; 44 import android.os.Bundle; 45 import android.os.Environment; 46 import android.os.SystemProperties; 47 import android.os.UserHandle; 48 import android.os.UserManager; 49 import android.os.image.DynamicSystemManager; 50 import android.provider.Settings; 51 import android.telephony.euicc.EuiccManager; 52 import android.text.TextUtils; 53 import android.util.Log; 54 import android.view.LayoutInflater; 55 import android.view.View; 56 import android.view.View.OnScrollChangeListener; 57 import android.view.ViewGroup; 58 import android.view.ViewTreeObserver.OnGlobalLayoutListener; 59 import android.widget.Button; 60 import android.widget.CheckBox; 61 import android.widget.ImageView; 62 import android.widget.LinearLayout; 63 import android.widget.ScrollView; 64 import android.widget.TextView; 65 66 import androidx.annotation.VisibleForTesting; 67 68 import com.android.settings.core.InstrumentedFragment; 69 import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper; 70 import com.android.settings.flags.Flags; 71 import com.android.settings.network.SubscriptionUtil; 72 import com.android.settings.password.ChooseLockSettingsHelper; 73 import com.android.settings.password.ConfirmLockPattern; 74 import com.android.settingslib.RestrictedLockUtilsInternal; 75 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; 76 import com.android.settingslib.development.DevelopmentSettingsEnabler; 77 78 import com.google.android.setupcompat.template.FooterBarMixin; 79 import com.google.android.setupcompat.template.FooterButton; 80 import com.google.android.setupcompat.template.FooterButton.ButtonType; 81 import com.google.android.setupdesign.GlifLayout; 82 83 import java.util.List; 84 85 /** 86 * Confirm and execute a reset of the device to a clean "just out of the box" 87 * state. Multiple confirmations are required: first, a general "are you sure 88 * you want to do this?" prompt, followed by a keyguard pattern trace if the user 89 * has defined one, followed by a final strongly-worded "THIS WILL ERASE EVERYTHING 90 * ON THE PHONE" prompt. If at any time the phone is allowed to go to sleep, is 91 * locked, et cetera, then the confirmation sequence is abandoned. 92 * 93 * This is the initial screen. 94 */ 95 public class MainClear extends InstrumentedFragment implements OnGlobalLayoutListener { 96 private static final String TAG = "MainClear"; 97 98 @VisibleForTesting 99 static final int KEYGUARD_REQUEST = 55; 100 @VisibleForTesting 101 static final int CREDENTIAL_CONFIRM_REQUEST = 56; 102 private static final String KEY_SHOW_ESIM_RESET_CHECKBOX = 103 "masterclear.allow_retain_esim_profiles_after_fdr"; 104 105 static final String ERASE_EXTERNAL_EXTRA = "erase_sd"; 106 static final String ERASE_ESIMS_EXTRA = "erase_esim"; 107 108 private View mContentView; 109 @VisibleForTesting 110 FooterButton mInitiateButton; 111 private View mExternalStorageContainer; 112 @VisibleForTesting 113 CheckBox mExternalStorage; 114 @VisibleForTesting 115 View mEsimStorageContainer; 116 @VisibleForTesting 117 CheckBox mEsimStorage; 118 @VisibleForTesting 119 ScrollView mScrollView; 120 121 @Override onGlobalLayout()122 public void onGlobalLayout() { 123 mInitiateButton.setEnabled(hasReachedBottom(mScrollView)); 124 } 125 setUpActionBarAndTitle()126 private void setUpActionBarAndTitle() { 127 final Activity activity = getActivity(); 128 if (activity == null) { 129 Log.e(TAG, "No activity attached, skipping setUpActionBarAndTitle"); 130 return; 131 } 132 final ActionBar actionBar = activity.getActionBar(); 133 if (actionBar == null) { 134 Log.e(TAG, "No actionbar, skipping setUpActionBarAndTitle"); 135 return; 136 } 137 actionBar.hide(); 138 activity.getWindow().setStatusBarColor(Color.TRANSPARENT); 139 } 140 141 /** 142 * Keyguard validation is run using the standard {@link ConfirmLockPattern} 143 * component as a subactivity 144 * 145 * @param request the request code to be returned once confirmation finishes 146 * @return true if confirmation launched 147 */ runKeyguardConfirmation(int request)148 private boolean runKeyguardConfirmation(int request) { 149 Resources res = getActivity().getResources(); 150 final ChooseLockSettingsHelper.Builder builder = 151 new ChooseLockSettingsHelper.Builder(getActivity(), this); 152 return builder.setRequestCode(request) 153 .setTitle(res.getText(R.string.main_clear_short_title)) 154 .show(); 155 } 156 157 @VisibleForTesting isValidRequestCode(int requestCode)158 boolean isValidRequestCode(int requestCode) { 159 return !((requestCode != KEYGUARD_REQUEST) && (requestCode != CREDENTIAL_CONFIRM_REQUEST)); 160 } 161 162 @Override onActivityResult(int requestCode, int resultCode, Intent data)163 public void onActivityResult(int requestCode, int resultCode, Intent data) { 164 super.onActivityResult(requestCode, resultCode, data); 165 onActivityResultInternal(requestCode, resultCode, data); 166 } 167 168 /* 169 * Internal method that allows easy testing without dealing with super references. 170 */ 171 @VisibleForTesting onActivityResultInternal(int requestCode, int resultCode, Intent data)172 void onActivityResultInternal(int requestCode, int resultCode, Intent data) { 173 if (!isValidRequestCode(requestCode)) { 174 return; 175 } 176 177 if (resultCode != Activity.RESULT_OK) { 178 establishInitialState(); 179 return; 180 } 181 182 Intent intent = null; 183 // If returning from a Keyguard request, try to show an account confirmation request if 184 // applciable. 185 if (CREDENTIAL_CONFIRM_REQUEST != requestCode 186 && (intent = getAccountConfirmationIntent()) != null) { 187 showAccountCredentialConfirmation(intent); 188 } else { 189 showFinalConfirmation(); 190 } 191 } 192 193 @VisibleForTesting showFinalConfirmation()194 void showFinalConfirmation() { 195 final Bundle args = new Bundle(); 196 args.putBoolean(ERASE_EXTERNAL_EXTRA, mExternalStorage.isChecked()); 197 args.putBoolean(ERASE_ESIMS_EXTRA, mEsimStorage.isChecked()); 198 final Intent intent = new Intent(); 199 intent.setClass(getContext(), 200 com.android.settings.Settings.FactoryResetConfirmActivity.class); 201 intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT, MainClearConfirm.class.getName()); 202 intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS, args); 203 intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE_RESID, 204 R.string.main_clear_confirm_title); 205 intent.putExtra(MetricsFeatureProvider.EXTRA_SOURCE_METRICS_CATEGORY, getMetricsCategory()); 206 getContext().startActivity(intent); 207 } 208 209 @VisibleForTesting showAccountCredentialConfirmation(Intent intent)210 void showAccountCredentialConfirmation(Intent intent) { 211 startActivityForResult(intent, CREDENTIAL_CONFIRM_REQUEST); 212 } 213 214 @VisibleForTesting getAccountConfirmationIntent()215 Intent getAccountConfirmationIntent() { 216 final Context context = getActivity(); 217 final String accountType = context.getString(R.string.account_type); 218 final String packageName = context.getString(R.string.account_confirmation_package); 219 final String className = context.getString(R.string.account_confirmation_class); 220 if (TextUtils.isEmpty(accountType) 221 || TextUtils.isEmpty(packageName) 222 || TextUtils.isEmpty(className)) { 223 Log.i(TAG, "Resources not set for account confirmation."); 224 return null; 225 } 226 final AccountManager am = AccountManager.get(context); 227 Account[] accounts = am.getAccountsByType(accountType); 228 if (accounts != null && accounts.length > 0) { 229 final Intent requestAccountConfirmation = new Intent() 230 .setPackage(packageName) 231 .setComponent(new ComponentName(packageName, className)); 232 // Check to make sure that the intent is supported. 233 final PackageManager pm = context.getPackageManager(); 234 final ResolveInfo resolution = pm.resolveActivity(requestAccountConfirmation, 0); 235 if (resolution != null 236 && resolution.activityInfo != null 237 && packageName.equals(resolution.activityInfo.packageName)) { 238 // Note that we need to check the packagename to make sure that an Activity resolver 239 // wasn't returned. 240 return requestAccountConfirmation; 241 } else { 242 Log.i(TAG, "Unable to resolve Activity: " + packageName + "/" + className); 243 } 244 } else { 245 Log.d(TAG, "No " + accountType + " accounts installed!"); 246 } 247 return null; 248 } 249 250 /** 251 * If the user clicks to begin the reset sequence, we next require a 252 * keyguard confirmation if the user has currently enabled one. If there 253 * is no keyguard available, we simply go to the final confirmation prompt. 254 * 255 * If the user is in demo mode, route to the demo mode app for confirmation. 256 */ 257 @VisibleForTesting 258 protected final Button.OnClickListener mInitiateListener = new Button.OnClickListener() { 259 260 public void onClick(View view) { 261 final Context context = view.getContext(); 262 if (Utils.isDemoUser(context)) { 263 final ComponentName componentName = Utils.getDeviceOwnerComponent(context); 264 if (componentName != null) { 265 final Intent requestFactoryReset = new Intent() 266 .setPackage(componentName.getPackageName()) 267 .setAction(Intent.ACTION_FACTORY_RESET); 268 context.startActivity(requestFactoryReset); 269 } 270 return; 271 } 272 273 final DynamicSystemManager dsuManager = (DynamicSystemManager) 274 getActivity().getSystemService(Context.DYNAMIC_SYSTEM_SERVICE); 275 if (dsuManager.isInUse()) { 276 AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 277 builder.setTitle(R.string.dsu_is_running); 278 builder.setPositiveButton(R.string.okay, new DialogInterface.OnClickListener() { 279 public void onClick(DialogInterface dialog, int id) {} 280 }); 281 AlertDialog dsuAlertdialog = builder.create(); 282 dsuAlertdialog.show(); 283 return; 284 } 285 286 if (runKeyguardConfirmation(KEYGUARD_REQUEST)) { 287 return; 288 } 289 290 Intent intent = getAccountConfirmationIntent(); 291 if (intent != null) { 292 showAccountCredentialConfirmation(intent); 293 } else { 294 showFinalConfirmation(); 295 } 296 } 297 }; 298 299 /** 300 * In its initial state, the activity presents a button for the user to 301 * click in order to initiate a confirmation sequence. This method is 302 * called from various other points in the code to reset the activity to 303 * this base state. 304 * 305 * <p>Reinflating views from resources is expensive and prevents us from 306 * caching widget pointers, so we use a single-inflate pattern: we lazy- 307 * inflate each view, caching all of the widget pointers we'll need at the 308 * time, then simply reuse the inflated views directly whenever we need 309 * to change contents. 310 */ 311 @VisibleForTesting establishInitialState()312 void establishInitialState() { 313 setUpActionBarAndTitle(); 314 setUpInitiateButton(); 315 316 mExternalStorageContainer = mContentView.findViewById(R.id.erase_external_container); 317 mExternalStorage = mContentView.findViewById(R.id.erase_external); 318 mEsimStorageContainer = mContentView.findViewById(R.id.erase_esim_container); 319 mEsimStorage = mContentView.findViewById(R.id.erase_esim); 320 if (mScrollView != null) { 321 mScrollView.getViewTreeObserver().removeOnGlobalLayoutListener(this); 322 } 323 mScrollView = mContentView.findViewById(R.id.main_clear_scrollview); 324 325 /* 326 * If the external storage is emulated, it will be erased with a factory 327 * reset at any rate. There is no need to have a separate option until 328 * we have a factory reset that only erases some directories and not 329 * others. 330 */ 331 if (Environment.isExternalStorageEmulated()) { 332 mExternalStorageContainer.setVisibility(View.GONE); 333 334 final View externalOption = mContentView.findViewById(R.id.erase_external_option_text); 335 externalOption.setVisibility(View.GONE); 336 337 final View externalAlsoErased = mContentView.findViewById(R.id.also_erases_external); 338 externalAlsoErased.setVisibility(View.VISIBLE); 339 340 mExternalStorage.setChecked(false); 341 } else { 342 mExternalStorageContainer.setOnClickListener(new View.OnClickListener() { 343 344 @Override 345 public void onClick(View v) { 346 mExternalStorage.toggle(); 347 } 348 }); 349 } 350 351 if (showWipeEuicc()) { 352 if (showWipeEuiccCheckbox()) { 353 mEsimStorageContainer.setVisibility(View.VISIBLE); 354 mEsimStorageContainer.setOnClickListener(new View.OnClickListener() { 355 @Override 356 public void onClick(View v) { 357 mEsimStorage.toggle(); 358 } 359 }); 360 } else { 361 final View esimAlsoErased = mContentView.findViewById(R.id.also_erases_esim); 362 esimAlsoErased.setVisibility(View.VISIBLE); 363 364 final View noCancelMobilePlan = mContentView.findViewById( 365 R.id.no_cancel_mobile_plan); 366 noCancelMobilePlan.setVisibility(View.VISIBLE); 367 mEsimStorage.setChecked(true /* checked */); 368 } 369 } else { 370 mEsimStorage.setChecked(false /* checked */); 371 } 372 373 final UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE); 374 loadAccountList(um); 375 final StringBuffer contentDescription = new StringBuffer(); 376 final View mainClearContainer = mContentView.findViewById(R.id.main_clear_container); 377 getContentDescription(mainClearContainer, contentDescription); 378 mainClearContainer.setContentDescription(contentDescription); 379 380 // Set the status of initiateButton based on scrollview 381 mScrollView.setOnScrollChangeListener(new OnScrollChangeListener() { 382 @Override 383 public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, 384 int oldScrollY) { 385 if (v instanceof ScrollView && hasReachedBottom((ScrollView) v)) { 386 mInitiateButton.setEnabled(true); 387 mScrollView.setOnScrollChangeListener(null); 388 } 389 } 390 }); 391 392 // Set the initial state of the initiateButton 393 mScrollView.getViewTreeObserver().addOnGlobalLayoutListener(this); 394 } 395 396 /** 397 * Whether to show any UI which is SIM related. 398 */ 399 @VisibleForTesting showAnySubscriptionInfo(Context context)400 boolean showAnySubscriptionInfo(Context context) { 401 return (context != null) && SubscriptionUtil.isSimHardwareVisible(context); 402 } 403 404 /** 405 * Whether to show strings indicating that the eUICC will be wiped. 406 * 407 * <p>We show the strings on any device which supports eUICC as long as the eUICC was ever 408 * provisioned (that is, at least one profile was ever downloaded onto it). 409 */ 410 @VisibleForTesting showWipeEuicc()411 boolean showWipeEuicc() { 412 Context context = getContext(); 413 if (!showAnySubscriptionInfo(context) || !isEuiccEnabled(context)) { 414 return false; 415 } 416 ContentResolver cr = context.getContentResolver(); 417 return Settings.Global.getInt(cr, Settings.Global.EUICC_PROVISIONED, 0) != 0 418 || DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(context); 419 } 420 421 @VisibleForTesting showWipeEuiccCheckbox()422 boolean showWipeEuiccCheckbox() { 423 return SystemProperties 424 .getBoolean(KEY_SHOW_ESIM_RESET_CHECKBOX, false /* def */); 425 } 426 427 @VisibleForTesting isEuiccEnabled(Context context)428 protected boolean isEuiccEnabled(Context context) { 429 EuiccManager euiccManager = (EuiccManager) context.getSystemService(Context.EUICC_SERVICE); 430 return euiccManager != null && euiccManager.isEnabled(); 431 } 432 433 @VisibleForTesting hasReachedBottom(final ScrollView scrollView)434 boolean hasReachedBottom(final ScrollView scrollView) { 435 if (scrollView.getChildCount() < 1) { 436 return true; 437 } 438 439 final View view = scrollView.getChildAt(0); 440 final int diff = view.getBottom() - (scrollView.getHeight() + scrollView.getScrollY()); 441 442 return diff <= 0; 443 } 444 setUpInitiateButton()445 private void setUpInitiateButton() { 446 if (mInitiateButton != null) { 447 return; 448 } 449 450 final GlifLayout layout = mContentView.findViewById(R.id.setup_wizard_layout); 451 final FooterBarMixin mixin = layout.getMixin(FooterBarMixin.class); 452 final Activity activity = getActivity(); 453 mixin.setPrimaryButton( 454 new FooterButton.Builder(activity) 455 .setText(R.string.main_clear_button_text) 456 .setListener(mInitiateListener) 457 .setButtonType(ButtonType.OTHER) 458 .setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Primary) 459 .build()); 460 if (Flags.showFactoryResetCancelButton()) { 461 mixin.setSecondaryButton( 462 new FooterButton.Builder(activity) 463 .setText(android.R.string.cancel) 464 .setListener(view -> activity.onBackPressed()) 465 .setButtonType(ButtonType.CANCEL) 466 .setTheme( 467 com.google.android.setupdesign.R.style.SudGlifButton_Secondary) 468 .build()); 469 } 470 mInitiateButton = mixin.getPrimaryButton(); 471 } 472 getContentDescription(View v, StringBuffer description)473 private void getContentDescription(View v, StringBuffer description) { 474 if (v.getVisibility() != View.VISIBLE) { 475 return; 476 } 477 if (v instanceof ViewGroup) { 478 ViewGroup vGroup = (ViewGroup) v; 479 for (int i = 0; i < vGroup.getChildCount(); i++) { 480 View nextChild = vGroup.getChildAt(i); 481 getContentDescription(nextChild, description); 482 } 483 } else if (v instanceof TextView) { 484 TextView vText = (TextView) v; 485 description.append(vText.getText()); 486 description.append(","); // Allow Talkback to pause between sections. 487 } 488 } 489 loadAccountList(final UserManager um)490 private void loadAccountList(final UserManager um) { 491 View accountsLabel = mContentView.findViewById(R.id.accounts_label); 492 LinearLayout contents = (LinearLayout) mContentView.findViewById(R.id.accounts); 493 contents.removeAllViews(); 494 495 Context context = getActivity(); 496 final List<UserInfo> profiles = um.getProfiles(UserHandle.myUserId()); 497 final int profilesSize = profiles.size(); 498 499 AccountManager mgr = AccountManager.get(context); 500 501 LayoutInflater inflater = (LayoutInflater) context.getSystemService( 502 Context.LAYOUT_INFLATER_SERVICE); 503 504 int accountsCount = 0; 505 for (int profileIndex = 0; profileIndex < profilesSize; profileIndex++) { 506 final UserInfo userInfo = profiles.get(profileIndex); 507 final int profileId = userInfo.id; 508 final UserHandle userHandle = new UserHandle(profileId); 509 if (Utils.shouldHideUser(userHandle, um)) { 510 continue; 511 } 512 Account[] accounts = mgr.getAccountsAsUser(profileId); 513 final int accountLength = accounts.length; 514 if (accountLength == 0) { 515 continue; 516 } 517 accountsCount += accountLength; 518 519 AuthenticatorDescription[] descs = AccountManager.get(context) 520 .getAuthenticatorTypesAsUser(profileId); 521 final int descLength = descs.length; 522 523 if (profilesSize > 1) { 524 View titleView = Utils.inflateCategoryHeader(inflater, contents); 525 titleView.setPadding(0 /* left */, titleView.getPaddingTop(), 526 0 /* right */, titleView.getPaddingBottom()); 527 final TextView titleText = (TextView) titleView.findViewById(android.R.id.title); 528 529 DevicePolicyManager devicePolicyManager = 530 context.getSystemService(DevicePolicyManager.class); 531 532 if (userInfo.isManagedProfile()) { 533 titleText.setText(devicePolicyManager.getResources().getString( 534 WORK_CATEGORY_HEADER, () -> getString( 535 com.android.settingslib.R.string.category_work))); 536 } else if (android.os.Flags.allowPrivateProfile() 537 && android.multiuser.Flags.enablePrivateSpaceFeatures() 538 && android.multiuser.Flags.handleInterleavedSettingsForPrivateSpace() 539 && userInfo.isPrivateProfile()) { 540 titleText.setText(devicePolicyManager.getResources().getString( 541 PRIVATE_CATEGORY_HEADER, () -> getString( 542 com.android.settingslib.R.string.category_private))); 543 } else { 544 titleText.setText(devicePolicyManager.getResources().getString( 545 PERSONAL_CATEGORY_HEADER, () -> getString( 546 com.android.settingslib.R.string.category_personal))); 547 } 548 contents.addView(titleView); 549 } 550 551 for (int i = 0; i < accountLength; i++) { 552 Account account = accounts[i]; 553 AuthenticatorDescription desc = null; 554 for (int j = 0; j < descLength; j++) { 555 if (account.type.equals(descs[j].type)) { 556 desc = descs[j]; 557 break; 558 } 559 } 560 if (desc == null) { 561 Log.w(TAG, "No descriptor for account name=" + account.name 562 + " type=" + account.type); 563 continue; 564 } 565 Drawable icon = null; 566 try { 567 if (desc.iconId != 0) { 568 Context authContext = context.createPackageContextAsUser(desc.packageName, 569 0, userHandle); 570 icon = context.getPackageManager().getUserBadgedIcon( 571 authContext.getDrawable(desc.iconId), userHandle); 572 } 573 } catch (PackageManager.NameNotFoundException e) { 574 Log.w(TAG, "Bad package name for account type " + desc.type); 575 } catch (Resources.NotFoundException e) { 576 Log.w(TAG, "Invalid icon id for account type " + desc.type, e); 577 } 578 if (icon == null) { 579 icon = context.getPackageManager().getDefaultActivityIcon(); 580 } 581 582 View child = inflater.inflate(R.layout.main_clear_account, contents, false); 583 ((ImageView) child.findViewById(android.R.id.icon)).setImageDrawable(icon); 584 ((TextView) child.findViewById(android.R.id.title)).setText(account.name); 585 contents.addView(child); 586 } 587 } 588 589 if (accountsCount > 0) { 590 accountsLabel.setVisibility(View.VISIBLE); 591 contents.setVisibility(View.VISIBLE); 592 } 593 // Checking for all other users and their profiles if any. 594 View otherUsers = mContentView.findViewById(R.id.other_users_present); 595 final boolean hasOtherUsers = (um.getUserCount() - profilesSize) > 0; 596 otherUsers.setVisibility(hasOtherUsers ? View.VISIBLE : View.GONE); 597 } 598 599 @Override onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)600 public View onCreateView(LayoutInflater inflater, ViewGroup container, 601 Bundle savedInstanceState) { 602 final Context context = getContext(); 603 final EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(context, 604 UserManager.DISALLOW_FACTORY_RESET, UserHandle.myUserId()); 605 final UserManager um = UserManager.get(context); 606 final boolean disallow = !um.isAdminUser() || RestrictedLockUtilsInternal 607 .hasBaseUserRestriction(context, UserManager.DISALLOW_FACTORY_RESET, 608 UserHandle.myUserId()); 609 if (disallow && !Utils.isDemoUser(context)) { 610 return inflater.inflate(R.layout.main_clear_disallowed_screen, null); 611 } else if (admin != null && !Utils.isDemoUser(context)) { 612 new ActionDisabledByAdminDialogHelper(getActivity()) 613 .prepareDialogBuilder(UserManager.DISALLOW_FACTORY_RESET, admin) 614 .setOnDismissListener(__ -> getActivity().finish()) 615 .show(); 616 return new View(getContext()); 617 } 618 619 mContentView = inflater.inflate(R.layout.main_clear, null); 620 621 establishInitialState(); 622 return mContentView; 623 } 624 625 @Override getMetricsCategory()626 public int getMetricsCategory() { 627 return SettingsEnums.MASTER_CLEAR; 628 } 629 } 630