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