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