• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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.accounts;
18 
19 import android.accounts.AccountManager;
20 import android.accounts.AuthenticatorDescription;
21 import android.content.Context;
22 import android.content.pm.PackageManager;
23 import android.graphics.drawable.Drawable;
24 import android.os.UserHandle;
25 
26 import androidx.annotation.VisibleForTesting;
27 
28 import com.android.settingslib.accounts.AuthenticatorHelper;
29 
30 import java.util.Collections;
31 import java.util.HashSet;
32 import java.util.List;
33 import java.util.Objects;
34 import java.util.Set;
35 
36 /**
37  * Utility that maintains a set of authorized account types.
38  */
39 public class AccountTypesHelper {
40     /** Callback invoked when the set of authorized account types changes. */
41     public interface OnChangeListener {
42         /** Called when the set of authorized account types changes. */
onAuthorizedAccountTypesChanged()43         void onAuthorizedAccountTypesChanged();
44     }
45 
46     private final Context mContext;
47     private UserHandle mUserHandle;
48     private AuthenticatorHelper mAuthenticatorHelper;
49     private List<String> mAuthorities;
50     private Set<String> mAccountTypesFilter;
51     private Set<String> mAccountTypesExclusionFilter;
52     private Set<String> mAuthorizedAccountTypes;
53     private OnChangeListener mListener;
54 
AccountTypesHelper(Context context)55     public AccountTypesHelper(Context context) {
56         mContext = context;
57 
58         // Default to hardcoded Bluetooth account type.
59         mAccountTypesExclusionFilter = new HashSet<>();
60         mAccountTypesExclusionFilter.add("com.android.bluetooth.pbapsink");
61         setAccountTypesExclusionFilter(mAccountTypesExclusionFilter);
62 
63         mUserHandle = UserHandle.of(UserHandle.myUserId());
64         mAuthenticatorHelper = new AuthenticatorHelper(mContext, mUserHandle,
65                 userHandle -> {
66                     // Only force a refresh if accounts have changed for the current user.
67                     if (userHandle.equals(mUserHandle)) {
68                         updateAuthorizedAccountTypes(false /* isForced */);
69                     }
70                 });
71     }
72 
73     /** Sets the authorities that the user has. */
setAuthorities(List<String> authorities)74     public void setAuthorities(List<String> authorities) {
75         mAuthorities = authorities;
76     }
77 
78     /** Sets the filter for accounts that should be shown. */
setAccountTypesFilter(Set<String> accountTypesFilter)79     public void setAccountTypesFilter(Set<String> accountTypesFilter) {
80         mAccountTypesFilter = accountTypesFilter;
81     }
82 
83     /** Sets the filter for accounts that should NOT be shown. */
setAccountTypesExclusionFilter(Set<String> accountTypesExclusionFilter)84     protected void setAccountTypesExclusionFilter(Set<String> accountTypesExclusionFilter) {
85         mAccountTypesExclusionFilter = accountTypesExclusionFilter;
86     }
87 
88     /** Sets the callback invoked when the set of authorized account types changes. */
setOnChangeListener(OnChangeListener listener)89     public void setOnChangeListener(OnChangeListener listener) {
90         mListener = listener;
91     }
92 
93     /**
94      * Updates the set of authorized account types.
95      *
96      * <p>Derived from
97      * {@link com.android.settings.accounts.ChooseAccountActivity#onAuthDescriptionsUpdated}
98      */
99     @VisibleForTesting
updateAuthorizedAccountTypes(boolean isForced)100     void updateAuthorizedAccountTypes(boolean isForced) {
101         AccountManager accountManager = AccountManager.get(mContext);
102         AuthenticatorDescription[] authenticatorDescriptions =
103                 accountManager.getAuthenticatorTypesAsUser(mUserHandle.getIdentifier());
104 
105         Set<String> authorizedAccountTypes = new HashSet<>();
106         for (AuthenticatorDescription authenticatorDescription : authenticatorDescriptions) {
107             String accountType = authenticatorDescription.type;
108 
109             List<String> accountAuthorities =
110                     mAuthenticatorHelper.getAuthoritiesForAccountType(accountType);
111 
112             // If there are specific authorities required, we need to check whether they are
113             // included in the account type.
114             boolean authorized =
115                     (mAuthorities == null || mAuthorities.isEmpty() || accountAuthorities == null
116                             || !Collections.disjoint(accountAuthorities, mAuthorities));
117 
118             // If there is an account type filter, make sure this account type is included.
119             authorized = authorized && (mAccountTypesFilter == null
120                     || mAccountTypesFilter.contains(accountType));
121 
122             // Check if the account type is in the exclusion list.
123             authorized = authorized && (mAccountTypesExclusionFilter == null
124                     || !mAccountTypesExclusionFilter.contains(accountType));
125 
126             if (authorized) {
127                 authorizedAccountTypes.add(accountType);
128             }
129         }
130 
131         if (isForced || !Objects.equals(mAuthorizedAccountTypes, authorizedAccountTypes)) {
132             mAuthorizedAccountTypes = authorizedAccountTypes;
133             if (mListener != null) {
134                 mListener.onAuthorizedAccountTypesChanged();
135             }
136         }
137     }
138 
139     /** Returns the set of authorized account types, initializing the set first if necessary. */
getAuthorizedAccountTypes()140     public Set<String> getAuthorizedAccountTypes() {
141         if (mAuthorizedAccountTypes == null) {
142             updateAuthorizedAccountTypes(false /* isForced */);
143         }
144         return mAuthorizedAccountTypes;
145     }
146 
147     /** Forces an update of the authorized account types. */
forceUpdate()148     public void forceUpdate() {
149         updateAuthorizedAccountTypes(true /* isForced */);
150     }
151 
152     /** Starts listening for account updates. */
listenToAccountUpdates()153     public void listenToAccountUpdates() {
154         mAuthenticatorHelper.listenToAccountUpdates();
155     }
156 
157     /** Stops listening for account updates. */
stopListeningToAccountUpdates()158     public void stopListeningToAccountUpdates() {
159         mAuthenticatorHelper.stopListeningToAccountUpdates();
160     }
161 
162     /**
163      * Gets the label associated with a particular account type. Returns {@code null} if none found.
164      *
165      * @param accountType the type of account
166      */
getLabelForType(String accountType)167     public CharSequence getLabelForType(String accountType) {
168         return mAuthenticatorHelper.getLabelForType(mContext, accountType);
169     }
170 
171     /**
172      * Gets an icon associated with a particular account type. Returns a default icon if none found.
173      *
174      * @param accountType the type of account
175      * @return a drawable for the icon or a default icon returned by
176      *     {@link PackageManager#getDefaultActivityIcon} if one cannot be found.
177      */
getDrawableForType(String accountType)178     public Drawable getDrawableForType(String accountType) {
179         return mAuthenticatorHelper.getDrawableForType(mContext, accountType);
180     }
181 
182     /** Used for testing to trigger an account update. */
183     @VisibleForTesting
getAuthenticatorHelper()184     AuthenticatorHelper getAuthenticatorHelper() {
185         return mAuthenticatorHelper;
186     }
187 
188     @VisibleForTesting
setAuthenticatorHelper(AuthenticatorHelper helper)189     void setAuthenticatorHelper(AuthenticatorHelper helper) {
190         mAuthenticatorHelper = helper;
191     }
192 }
193