1 /* 2 * Copyright 2019 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.car.settings.system; 18 19 import android.accounts.Account; 20 import android.accounts.AccountManager; 21 import android.accounts.AuthenticatorDescription; 22 import android.car.drivingstate.CarUxRestrictions; 23 import android.content.Context; 24 import android.content.pm.PackageManager; 25 import android.content.pm.UserInfo; 26 import android.content.res.Resources; 27 import android.graphics.drawable.Drawable; 28 import android.os.UserHandle; 29 import android.os.UserManager; 30 import android.util.ArrayMap; 31 32 import androidx.annotation.Nullable; 33 import androidx.preference.Preference; 34 import androidx.preference.PreferenceGroup; 35 36 import com.android.car.settings.R; 37 import com.android.car.settings.common.FragmentController; 38 import com.android.car.settings.common.Logger; 39 import com.android.car.settings.common.PreferenceController; 40 import com.android.car.ui.preference.CarUiPreference; 41 42 import java.util.HashSet; 43 import java.util.List; 44 import java.util.Map; 45 import java.util.Set; 46 47 /** 48 * Displays the currently signed in accounts on the vehicle to inform the user that they will be 49 * removed during a factory reset. 50 */ 51 public class FactoryResetAccountsPreferenceController 52 extends PreferenceController<PreferenceGroup> { 53 54 private static final Logger LOG = new Logger(FactoryResetAccountsPreferenceController.class); 55 56 private final Map<Account, Preference> mAccountPreferenceMap = new ArrayMap<>(); 57 FactoryResetAccountsPreferenceController(Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions)58 public FactoryResetAccountsPreferenceController(Context context, String preferenceKey, 59 FragmentController fragmentController, CarUxRestrictions uxRestrictions) { 60 super(context, preferenceKey, fragmentController, uxRestrictions); 61 } 62 63 @Override getPreferenceType()64 protected Class<PreferenceGroup> getPreferenceType() { 65 return PreferenceGroup.class; 66 } 67 68 @Override onCreateInternal()69 protected void onCreateInternal() { 70 getPreference().addPreference( 71 createPreference(getContext().getString(R.string.factory_reset_accounts), 72 /* icon= */ null)); 73 } 74 75 @Override updateState(PreferenceGroup preferenceGroup)76 protected void updateState(PreferenceGroup preferenceGroup) { 77 // Refresh the accounts in the off chance an account was added or removed while stopped. 78 Set<Account> accountsToRemove = new HashSet<>(mAccountPreferenceMap.keySet()); 79 List<UserInfo> profiles = UserManager.get(getContext()).getProfiles(UserHandle.myUserId()); 80 for (UserInfo profile : profiles) { 81 UserHandle userHandle = new UserHandle(profile.id); 82 AuthenticatorDescription[] descriptions = AccountManager.get( 83 getContext()).getAuthenticatorTypesAsUser(profile.id); 84 Account[] accounts = AccountManager.get(getContext()).getAccountsAsUser(profile.id); 85 for (Account account : accounts) { 86 AuthenticatorDescription description = null; 87 for (AuthenticatorDescription desc : descriptions) { 88 if (account.type.equals(desc.type)) { 89 description = desc; 90 break; 91 } 92 } 93 if (description == null) { 94 LOG.w("No descriptor for account name=" + account.name + " type=" 95 + account.type); 96 continue; 97 } 98 99 accountsToRemove.remove(account); 100 if (!mAccountPreferenceMap.containsKey(account)) { 101 Preference accountPref = createPreference(account.name, 102 getAccountIcon(description, userHandle)); 103 mAccountPreferenceMap.put(account, accountPref); 104 preferenceGroup.addPreference(accountPref); 105 } 106 } 107 } 108 109 for (Account accountToRemove : accountsToRemove) { 110 preferenceGroup.removePreference(mAccountPreferenceMap.get(accountToRemove)); 111 } 112 113 // If the only preference is the title, hide the group. 114 preferenceGroup.setVisible(preferenceGroup.getPreferenceCount() > 1); 115 } 116 getAccountIcon(AuthenticatorDescription description, UserHandle userHandle)117 private Drawable getAccountIcon(AuthenticatorDescription description, UserHandle userHandle) { 118 Drawable icon = null; 119 try { 120 if (description.iconId != 0) { 121 Context authContext = getContext().createPackageContextAsUser( 122 description.packageName, /* flags= */ 0, userHandle); 123 icon = getContext().getPackageManager().getUserBadgedIcon( 124 authContext.getDrawable(description.iconId), userHandle); 125 } 126 } catch (PackageManager.NameNotFoundException e) { 127 LOG.w("Bad package name for account type " + description.type, e); 128 } catch (Resources.NotFoundException e) { 129 LOG.w("Invalid icon id for account type " + description.type, e); 130 } 131 if (icon == null) { 132 icon = getContext().getPackageManager().getDefaultActivityIcon(); 133 } 134 return icon; 135 } 136 createPreference(String title, @Nullable Drawable icon)137 private Preference createPreference(String title, @Nullable Drawable icon) { 138 CarUiPreference preference = new CarUiPreference(getContext()); 139 preference.setTitle(title); 140 preference.setIcon(icon); 141 preference.setSelectable(false); 142 preference.setSingleLineTitle(false); 143 return preference; 144 } 145 } 146