blob: d9562c09c6a2434cb616d6b02091a1aedd89a29d [file] [log] [blame]
Doris Lingbfac31b2016-11-10 15:12:52 -08001/*
2 * Copyright (C) 2016 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
17package com.android.settings.accounts;
18
Tony Mantler1c9e2f62017-06-13 15:16:50 -070019import static android.content.Intent.EXTRA_USER;
20import static android.os.UserManager.DISALLOW_MODIFY_ACCOUNTS;
21import static android.os.UserManager.DISALLOW_REMOVE_MANAGED_PROFILE;
22import static android.provider.Settings.ACTION_ADD_ACCOUNT;
23import static android.provider.Settings.EXTRA_AUTHORITIES;
24
Doris Lingbfac31b2016-11-10 15:12:52 -080025import android.accounts.Account;
26import android.accounts.AccountManager;
27import android.content.BroadcastReceiver;
28import android.content.Context;
29import android.content.Intent;
30import android.content.IntentFilter;
31import android.content.pm.ApplicationInfo;
32import android.content.pm.PackageManager;
33import android.content.pm.UserInfo;
34import android.content.res.Resources;
Doris Ling20d4b042016-11-22 16:37:06 -080035import android.graphics.drawable.Drawable;
Doris Lingbfac31b2016-11-10 15:12:52 -080036import android.os.Bundle;
37import android.os.UserHandle;
38import android.os.UserManager;
Doris Lingbfac31b2016-11-10 15:12:52 -080039import android.support.v7.preference.Preference;
40import android.support.v7.preference.Preference.OnPreferenceClickListener;
41import android.support.v7.preference.PreferenceGroup;
42import android.support.v7.preference.PreferenceScreen;
Doris Ling633250b2017-05-02 11:28:14 -070043import android.util.ArrayMap;
Doris Lingbfac31b2016-11-10 15:12:52 -080044import android.util.Log;
45import android.util.SparseArray;
46
47import com.android.internal.annotations.VisibleForTesting;
48import com.android.settings.AccessiblePreferenceCategory;
Doris Lingbfac31b2016-11-10 15:12:52 -080049import com.android.settings.R;
Doris Lingf074f0f2017-02-24 15:20:05 -080050import com.android.settings.SettingsPreferenceFragment;
Doris Lingbfac31b2016-11-10 15:12:52 -080051import com.android.settings.Utils;
Tony Mantler1d583e12017-06-13 13:09:25 -070052import com.android.settings.core.PreferenceControllerMixin;
Fan Zhang7cf99f52018-02-16 10:37:37 -080053import com.android.settings.core.SubSettingLauncher;
Doris Lingbfac31b2016-11-10 15:12:52 -080054import com.android.settings.overlay.FeatureFactory;
Tony Mantler1c9e2f62017-06-13 15:16:50 -070055import com.android.settings.search.SearchIndexableRaw;
Doris Lingbfac31b2016-11-10 15:12:52 -080056import com.android.settingslib.RestrictedPreference;
57import com.android.settingslib.accounts.AuthenticatorHelper;
Tony Mantler1d583e12017-06-13 13:09:25 -070058import com.android.settingslib.core.AbstractPreferenceController;
Leif Hendrik Wilden28dee1f2018-01-11 10:15:36 -080059import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
Juan Lang777ed252017-05-09 15:42:36 -070060import com.android.settingslib.core.lifecycle.LifecycleObserver;
61import com.android.settingslib.core.lifecycle.events.OnPause;
62import com.android.settingslib.core.lifecycle.events.OnResume;
Doris Lingbfac31b2016-11-10 15:12:52 -080063
64import java.util.ArrayList;
65import java.util.Collections;
66import java.util.Comparator;
67import java.util.List;
68
Tony Mantler1d583e12017-06-13 13:09:25 -070069public class AccountPreferenceController extends AbstractPreferenceController
70 implements PreferenceControllerMixin, AuthenticatorHelper.OnAccountsUpdateListener,
Doris Lingbfac31b2016-11-10 15:12:52 -080071 OnPreferenceClickListener, LifecycleObserver, OnPause, OnResume {
72
73 private static final String TAG = "AccountPrefController";
Doris Lingbfac31b2016-11-10 15:12:52 -080074
75 private static final int ORDER_ACCOUNT_PROFILES = 1;
76 private static final int ORDER_LAST = 1002;
77 private static final int ORDER_NEXT_TO_LAST = 1001;
78 private static final int ORDER_NEXT_TO_NEXT_TO_LAST = 1000;
79
80 private UserManager mUm;
81 private SparseArray<ProfileData> mProfiles = new SparseArray<ProfileData>();
82 private ManagedProfileBroadcastReceiver mManagedProfileBroadcastReceiver
83 = new ManagedProfileBroadcastReceiver();
84 private Preference mProfileNotAvailablePreference;
85 private String[] mAuthorities;
86 private int mAuthoritiesCount = 0;
Doris Lingf074f0f2017-02-24 15:20:05 -080087 private SettingsPreferenceFragment mParent;
Doris Lingbfac31b2016-11-10 15:12:52 -080088 private int mAccountProfileOrder = ORDER_ACCOUNT_PROFILES;
89 private AccountRestrictionHelper mHelper;
Fan Zhangc6ca3142017-02-14 15:02:35 -080090 private MetricsFeatureProvider mMetricsFeatureProvider;
Doris Lingbfac31b2016-11-10 15:12:52 -080091
92 /**
93 * Holds data related to the accounts belonging to one profile.
94 */
95 public static class ProfileData {
96 /**
97 * The preference that displays the accounts.
98 */
99 public PreferenceGroup preferenceGroup;
100 /**
101 * The preference that displays the add account button.
102 */
Fan Zhang12b03b22017-10-29 13:57:29 -0700103 public RestrictedPreference addAccountPreference;
Doris Lingbfac31b2016-11-10 15:12:52 -0800104 /**
105 * The preference that displays the button to remove the managed profile
106 */
107 public RestrictedPreference removeWorkProfilePreference;
108 /**
109 * The preference that displays managed profile settings.
110 */
111 public Preference managedProfilePreference;
112 /**
113 * The {@link AuthenticatorHelper} that holds accounts data for this profile.
114 */
115 public AuthenticatorHelper authenticatorHelper;
116 /**
117 * The {@link UserInfo} of the profile.
118 */
119 public UserInfo userInfo;
Doris Ling633250b2017-05-02 11:28:14 -0700120 /**
121 * The {@link UserInfo} of the profile.
122 */
123 public boolean pendingRemoval;
124 /**
Fan Zhangc754f592017-05-17 12:32:59 -0700125 * The map from account key to account preference
Doris Ling633250b2017-05-02 11:28:14 -0700126 */
Fan Zhangc754f592017-05-17 12:32:59 -0700127 public ArrayMap<String, AccountTypePreference> accountPreferences = new ArrayMap<>();
Doris Lingbfac31b2016-11-10 15:12:52 -0800128 }
129
Doris Lingf074f0f2017-02-24 15:20:05 -0800130 public AccountPreferenceController(Context context, SettingsPreferenceFragment parent,
Doris Lingbfac31b2016-11-10 15:12:52 -0800131 String[] authorities) {
132 this(context, parent, authorities, new AccountRestrictionHelper(context));
133 }
134
135 @VisibleForTesting
Doris Lingf074f0f2017-02-24 15:20:05 -0800136 AccountPreferenceController(Context context, SettingsPreferenceFragment parent,
Doris Lingbfac31b2016-11-10 15:12:52 -0800137 String[] authorities, AccountRestrictionHelper helper) {
138 super(context);
139 mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
140 mAuthorities = authorities;
141 mParent = parent;
142 if (mAuthorities != null) {
143 mAuthoritiesCount = mAuthorities.length;
144 }
Fan Zhangc6ca3142017-02-14 15:02:35 -0800145 final FeatureFactory featureFactory = FeatureFactory.getFactory(mContext);
Fan Zhangc6ca3142017-02-14 15:02:35 -0800146 mMetricsFeatureProvider = featureFactory.getMetricsFeatureProvider();
Doris Lingbfac31b2016-11-10 15:12:52 -0800147 mHelper = helper;
148 }
149
150 @Override
151 public boolean isAvailable() {
152 return !mUm.isManagedProfile();
153 }
154
155 @Override
Doris Lingbfac31b2016-11-10 15:12:52 -0800156 public String getPreferenceKey() {
157 return null;
158 }
159
160 @Override
Doris Ling633250b2017-05-02 11:28:14 -0700161 public void displayPreference(PreferenceScreen screen) {
162 super.displayPreference(screen);
163 updateUi();
164 }
165
166 @Override
Doris Lingbfac31b2016-11-10 15:12:52 -0800167 public void updateRawDataToIndex(List<SearchIndexableRaw> rawData) {
168 if (!isAvailable()) {
169 return;
170 }
171 final Resources res = mContext.getResources();
172 final String screenTitle = res.getString(R.string.account_settings_title);
173
174 List<UserInfo> profiles = mUm.getProfiles(UserHandle.myUserId());
175 final int profilesCount = profiles.size();
176 for (int i = 0; i < profilesCount; i++) {
177 UserInfo userInfo = profiles.get(i);
178 if (userInfo.isEnabled()) {
179 if (!mHelper.hasBaseUserRestriction(DISALLOW_MODIFY_ACCOUNTS, userInfo.id)) {
180 SearchIndexableRaw data = new SearchIndexableRaw(mContext);
181 data.title = res.getString(R.string.add_account_label);
182 data.screenTitle = screenTitle;
183 rawData.add(data);
184 }
185 if (userInfo.isManagedProfile()) {
Esteban Talavera50e515e2016-11-30 22:14:00 +0000186 if (!mHelper.hasBaseUserRestriction(DISALLOW_REMOVE_MANAGED_PROFILE,
Doris Lingbfac31b2016-11-10 15:12:52 -0800187 UserHandle.myUserId())) {
188 SearchIndexableRaw data = new SearchIndexableRaw(mContext);
189 data.title = res.getString(R.string.remove_managed_profile_label);
190 data.screenTitle = screenTitle;
191 rawData.add(data);
192 }
193 {
194 SearchIndexableRaw data = new SearchIndexableRaw(mContext);
195 data.title = res.getString(R.string.managed_profile_settings_title);
196 data.screenTitle = screenTitle;
197 rawData.add(data);
198 }
199 }
200 }
201 }
202 }
203
204 @Override
205 public void onResume() {
Doris Lingbfac31b2016-11-10 15:12:52 -0800206 updateUi();
207 mManagedProfileBroadcastReceiver.register(mContext);
208 listenToAccountUpdates();
209 }
210
211 @Override
212 public void onPause() {
213 stopListeningToAccountUpdates();
214 mManagedProfileBroadcastReceiver.unregister(mContext);
215 }
216
217 @Override
218 public void onAccountsUpdate(UserHandle userHandle) {
219 final ProfileData profileData = mProfiles.get(userHandle.getIdentifier());
220 if (profileData != null) {
221 updateAccountTypes(profileData);
222 } else {
223 Log.w(TAG, "Missing Settings screen for: " + userHandle.getIdentifier());
224 }
225 }
226
227 @Override
228 public boolean onPreferenceClick(Preference preference) {
229 // Check the preference
230 final int count = mProfiles.size();
231 for (int i = 0; i < count; i++) {
232 ProfileData profileData = mProfiles.valueAt(i);
233 if (preference == profileData.addAccountPreference) {
Tony Mantler1c9e2f62017-06-13 15:16:50 -0700234 Intent intent = new Intent(ACTION_ADD_ACCOUNT);
Doris Lingbfac31b2016-11-10 15:12:52 -0800235 intent.putExtra(EXTRA_USER, profileData.userInfo.getUserHandle());
236 intent.putExtra(EXTRA_AUTHORITIES, mAuthorities);
237 mContext.startActivity(intent);
238 return true;
239 }
240 if (preference == profileData.removeWorkProfilePreference) {
241 final int userId = profileData.userInfo.id;
242 RemoveUserFragment.newInstance(userId).show(mParent.getFragmentManager(),
243 "removeUser");
244 return true;
245 }
246 if (preference == profileData.managedProfilePreference) {
247 Bundle arguments = new Bundle();
248 arguments.putParcelable(Intent.EXTRA_USER, profileData.userInfo.getUserHandle());
Fan Zhang7cf99f52018-02-16 10:37:37 -0800249 new SubSettingLauncher(mContext)
250 .setSourceMetricsCategory(mParent.getMetricsCategory())
251 .setDestination(ManagedProfileSettings.class.getName())
252 .setTitle(R.string.managed_profile_settings_title)
253 .setArguments(arguments)
254 .launch();
255
Doris Lingbfac31b2016-11-10 15:12:52 -0800256 return true;
257 }
258 }
259 return false;
260 }
261
Doris Lingbfac31b2016-11-10 15:12:52 -0800262 private void updateUi() {
Doris Lingbfac31b2016-11-10 15:12:52 -0800263 if (!isAvailable()) {
264 // This should not happen
265 Log.e(TAG, "We should not be showing settings for a managed profile");
Doris Lingbfac31b2016-11-10 15:12:52 -0800266 return;
267 }
268
Doris Ling633250b2017-05-02 11:28:14 -0700269 for (int i = 0, size = mProfiles.size(); i < size; i++) {
270 mProfiles.valueAt(i).pendingRemoval = true;
271 }
James Lemieux22a39c22018-02-26 00:51:42 -0800272 if (mUm.isRestrictedProfile()) {
Doris Lingbfac31b2016-11-10 15:12:52 -0800273 // Restricted user or similar
274 UserInfo userInfo = mUm.getUserInfo(UserHandle.myUserId());
275 updateProfileUi(userInfo);
276 } else {
277 List<UserInfo> profiles = mUm.getProfiles(UserHandle.myUserId());
278 final int profilesCount = profiles.size();
Doris Lingbfac31b2016-11-10 15:12:52 -0800279 for (int i = 0; i < profilesCount; i++) {
280 updateProfileUi(profiles.get(i));
281 }
282 }
Doris Ling633250b2017-05-02 11:28:14 -0700283 cleanUpPreferences();
Doris Lingbfac31b2016-11-10 15:12:52 -0800284
285 // Add all preferences, starting with one for the primary profile.
286 // Note that we're relying on the ordering given by the SparseArray keys, and on the
287 // value of UserHandle.USER_OWNER being smaller than all the rest.
288 final int profilesCount = mProfiles.size();
289 for (int i = 0; i < profilesCount; i++) {
290 updateAccountTypes(mProfiles.valueAt(i));
291 }
292 }
293
294 private void updateProfileUi(final UserInfo userInfo) {
Fan Zhang81a030f2017-01-11 10:46:45 -0800295 if (mParent.getPreferenceManager() == null) {
296 return;
297 }
Doris Ling633250b2017-05-02 11:28:14 -0700298 final ProfileData data = mProfiles.get(userInfo.id);
299 if (data != null) {
300 data.pendingRemoval = false;
Doris Ling71090672017-05-16 17:23:55 -0700301 if (userInfo.isEnabled()) {
302 // recreate the authentication helper to refresh the list of enabled accounts
303 data.authenticatorHelper =
304 new AuthenticatorHelper(mContext, userInfo.getUserHandle(), this);
305 }
Doris Ling633250b2017-05-02 11:28:14 -0700306 return;
307 }
Doris Lingbfac31b2016-11-10 15:12:52 -0800308 final Context context = mContext;
309 final ProfileData profileData = new ProfileData();
310 profileData.userInfo = userInfo;
311 AccessiblePreferenceCategory preferenceGroup =
312 mHelper.createAccessiblePreferenceCategory(mParent.getPreferenceManager().getContext());
313 preferenceGroup.setOrder(mAccountProfileOrder++);
314 if (isSingleProfile()) {
Doris Ling829d3aa2017-02-03 15:06:56 -0800315 preferenceGroup.setTitle(context.getString(R.string.account_for_section_header,
316 userInfo.name));
Doris Lingbfac31b2016-11-10 15:12:52 -0800317 preferenceGroup.setContentDescription(
318 mContext.getString(R.string.account_settings));
319 } else if (userInfo.isManagedProfile()) {
Doris Lingbfac31b2016-11-10 15:12:52 -0800320 preferenceGroup.setTitle(R.string.category_work);
321 String workGroupSummary = getWorkGroupSummary(context, userInfo);
322 preferenceGroup.setSummary(workGroupSummary);
323 preferenceGroup.setContentDescription(
324 mContext.getString(R.string.accessibility_category_work, workGroupSummary));
Fan Zhang12b03b22017-10-29 13:57:29 -0700325 profileData.removeWorkProfilePreference = newRemoveWorkProfilePreference();
Doris Lingbfac31b2016-11-10 15:12:52 -0800326 mHelper.enforceRestrictionOnPreference(profileData.removeWorkProfilePreference,
Esteban Talavera50e515e2016-11-30 22:14:00 +0000327 DISALLOW_REMOVE_MANAGED_PROFILE, UserHandle.myUserId());
Doris Lingbfac31b2016-11-10 15:12:52 -0800328 profileData.managedProfilePreference = newManagedProfileSettings();
329 } else {
330 preferenceGroup.setTitle(R.string.category_personal);
331 preferenceGroup.setContentDescription(
332 mContext.getString(R.string.accessibility_category_personal));
333 }
Fan Zhang424443b2017-01-10 11:50:01 -0800334 final PreferenceScreen screen = mParent.getPreferenceScreen();
335 if (screen != null) {
336 screen.addPreference(preferenceGroup);
337 }
Doris Lingbfac31b2016-11-10 15:12:52 -0800338 profileData.preferenceGroup = preferenceGroup;
339 if (userInfo.isEnabled()) {
340 profileData.authenticatorHelper = new AuthenticatorHelper(context,
341 userInfo.getUserHandle(), this);
Fan Zhang12b03b22017-10-29 13:57:29 -0700342 profileData.addAccountPreference = newAddAccountPreference();
Doris Lingbfac31b2016-11-10 15:12:52 -0800343 mHelper.enforceRestrictionOnPreference(profileData.addAccountPreference,
344 DISALLOW_MODIFY_ACCOUNTS, userInfo.id);
345 }
346 mProfiles.put(userInfo.id, profileData);
Doris Lingbfac31b2016-11-10 15:12:52 -0800347 }
348
Fan Zhang12b03b22017-10-29 13:57:29 -0700349 private RestrictedPreference newAddAccountPreference() {
350 RestrictedPreference preference =
351 new RestrictedPreference(mParent.getPreferenceManager().getContext());
Doris Lingbfac31b2016-11-10 15:12:52 -0800352 preference.setTitle(R.string.add_account_label);
353 preference.setIcon(R.drawable.ic_menu_add);
354 preference.setOnPreferenceClickListener(this);
355 preference.setOrder(ORDER_NEXT_TO_NEXT_TO_LAST);
356 return preference;
357 }
358
Fan Zhang12b03b22017-10-29 13:57:29 -0700359 private RestrictedPreference newRemoveWorkProfilePreference() {
Doris Lingbfac31b2016-11-10 15:12:52 -0800360 RestrictedPreference preference = new RestrictedPreference(
361 mParent.getPreferenceManager().getContext());
362 preference.setTitle(R.string.remove_managed_profile_label);
363 preference.setIcon(R.drawable.ic_menu_delete);
364 preference.setOnPreferenceClickListener(this);
365 preference.setOrder(ORDER_LAST);
366 return preference;
367 }
368
369
370 private Preference newManagedProfileSettings() {
371 Preference preference = new Preference(mParent.getPreferenceManager().getContext());
372 preference.setTitle(R.string.managed_profile_settings_title);
373 preference.setIcon(R.drawable.ic_settings);
374 preference.setOnPreferenceClickListener(this);
375 preference.setOrder(ORDER_NEXT_TO_LAST);
376 return preference;
377 }
378
379 private String getWorkGroupSummary(Context context, UserInfo userInfo) {
380 PackageManager packageManager = context.getPackageManager();
381 ApplicationInfo adminApplicationInfo = Utils.getAdminApplicationInfo(context, userInfo.id);
382 if (adminApplicationInfo == null) {
383 return null;
384 }
385 CharSequence appLabel = packageManager.getApplicationLabel(adminApplicationInfo);
386 return mContext.getString(R.string.managing_admin, appLabel);
387 }
388
389 void cleanUpPreferences() {
390 PreferenceScreen screen = mParent.getPreferenceScreen();
Fan Zhang424443b2017-01-10 11:50:01 -0800391 if (screen == null) {
392 return;
393 }
Doris Ling633250b2017-05-02 11:28:14 -0700394 final int count = mProfiles.size();
395 for (int i = count-1; i >= 0; i--) {
396 final ProfileData data = mProfiles.valueAt(i);
397 if (data.pendingRemoval) {
398 screen.removePreference(data.preferenceGroup);
399 mProfiles.removeAt(i);
400 }
Doris Lingbfac31b2016-11-10 15:12:52 -0800401 }
Doris Lingbfac31b2016-11-10 15:12:52 -0800402 }
403
404 private void listenToAccountUpdates() {
405 final int count = mProfiles.size();
406 for (int i = 0; i < count; i++) {
407 AuthenticatorHelper authenticatorHelper = mProfiles.valueAt(i).authenticatorHelper;
408 if (authenticatorHelper != null) {
409 authenticatorHelper.listenToAccountUpdates();
410 }
411 }
412 }
413
414 private void stopListeningToAccountUpdates() {
415 final int count = mProfiles.size();
416 for (int i = 0; i < count; i++) {
417 AuthenticatorHelper authenticatorHelper = mProfiles.valueAt(i).authenticatorHelper;
418 if (authenticatorHelper != null) {
419 authenticatorHelper.stopListeningToAccountUpdates();
420 }
421 }
422 }
423
424 private void updateAccountTypes(ProfileData profileData) {
Fan Zhangc7804c12017-01-13 14:57:01 -0800425 if (mParent.getPreferenceManager() == null
426 || profileData.preferenceGroup.getPreferenceManager() == null) {
Fan Zhang81a030f2017-01-11 10:46:45 -0800427 // This could happen if activity is finishing
428 return;
429 }
Doris Lingbfac31b2016-11-10 15:12:52 -0800430 if (profileData.userInfo.isEnabled()) {
Fan Zhangc754f592017-05-17 12:32:59 -0700431 final ArrayMap<String, AccountTypePreference> preferenceToRemove =
Doris Ling633250b2017-05-02 11:28:14 -0700432 new ArrayMap<>(profileData.accountPreferences);
Doris Ling20d4b042016-11-22 16:37:06 -0800433 final ArrayList<AccountTypePreference> preferences = getAccountTypePreferences(
Doris Ling633250b2017-05-02 11:28:14 -0700434 profileData.authenticatorHelper, profileData.userInfo.getUserHandle(),
435 preferenceToRemove);
Doris Lingbfac31b2016-11-10 15:12:52 -0800436 final int count = preferences.size();
437 for (int i = 0; i < count; i++) {
Doris Ling633250b2017-05-02 11:28:14 -0700438 final AccountTypePreference preference = preferences.get(i);
439 preference.setOrder(i);
Fan Zhangc754f592017-05-17 12:32:59 -0700440 final String key = preference.getKey();
441 if (!profileData.accountPreferences.containsKey(key)) {
442 profileData.preferenceGroup.addPreference(preference);
443 profileData.accountPreferences.put(key, preference);
Doris Ling633250b2017-05-02 11:28:14 -0700444 }
Doris Lingbfac31b2016-11-10 15:12:52 -0800445 }
446 if (profileData.addAccountPreference != null) {
447 profileData.preferenceGroup.addPreference(profileData.addAccountPreference);
448 }
Fan Zhangc754f592017-05-17 12:32:59 -0700449 for (String key : preferenceToRemove.keySet()) {
Doris Ling633250b2017-05-02 11:28:14 -0700450 profileData.preferenceGroup.removePreference(
Fan Zhangc754f592017-05-17 12:32:59 -0700451 profileData.accountPreferences.get(key));
452 profileData.accountPreferences.remove(key);
Doris Ling633250b2017-05-02 11:28:14 -0700453 }
Doris Lingbfac31b2016-11-10 15:12:52 -0800454 } else {
Doris Ling633250b2017-05-02 11:28:14 -0700455 profileData.preferenceGroup.removeAll();
Doris Lingbfac31b2016-11-10 15:12:52 -0800456 // Put a label instead of the accounts list
457 if (mProfileNotAvailablePreference == null) {
458 mProfileNotAvailablePreference =
459 new Preference(mParent.getPreferenceManager().getContext());
460 }
461 mProfileNotAvailablePreference.setEnabled(false);
462 mProfileNotAvailablePreference.setIcon(R.drawable.empty_icon);
463 mProfileNotAvailablePreference.setTitle(null);
464 mProfileNotAvailablePreference.setSummary(
465 R.string.managed_profile_not_available_label);
466 profileData.preferenceGroup.addPreference(mProfileNotAvailablePreference);
467 }
468 if (profileData.removeWorkProfilePreference != null) {
469 profileData.preferenceGroup.addPreference(profileData.removeWorkProfilePreference);
470 }
471 if (profileData.managedProfilePreference != null) {
472 profileData.preferenceGroup.addPreference(profileData.managedProfilePreference);
473 }
474 }
475
Doris Ling20d4b042016-11-22 16:37:06 -0800476 private ArrayList<AccountTypePreference> getAccountTypePreferences(AuthenticatorHelper helper,
Fan Zhangc754f592017-05-17 12:32:59 -0700477 UserHandle userHandle, ArrayMap<String, AccountTypePreference> preferenceToRemove) {
Doris Lingbfac31b2016-11-10 15:12:52 -0800478 final String[] accountTypes = helper.getEnabledAccountTypes();
Doris Ling20d4b042016-11-22 16:37:06 -0800479 final ArrayList<AccountTypePreference> accountTypePreferences =
Fan Zhangc6ca3142017-02-14 15:02:35 -0800480 new ArrayList<>(accountTypes.length);
Doris Lingbfac31b2016-11-10 15:12:52 -0800481
482 for (int i = 0; i < accountTypes.length; i++) {
483 final String accountType = accountTypes[i];
484 // Skip showing any account that does not have any of the requested authorities
485 if (!accountTypeHasAnyRequestedAuthorities(helper, accountType)) {
486 continue;
487 }
488 final CharSequence label = helper.getLabelForType(mContext, accountType);
489 if (label == null) {
490 continue;
491 }
492 final String titleResPackageName = helper.getPackageForType(accountType);
493 final int titleResId = helper.getLabelIdForType(accountType);
494
495 final Account[] accounts = AccountManager.get(mContext)
496 .getAccountsByTypeAsUser(accountType, userHandle);
Doris Ling20d4b042016-11-22 16:37:06 -0800497 final Drawable icon = helper.getDrawableForType(mContext, accountType);
498 final Context prefContext = mParent.getPreferenceManager().getContext();
Doris Lingbfac31b2016-11-10 15:12:52 -0800499
Doris Lingf074f0f2017-02-24 15:20:05 -0800500 // Add a preference row for each individual account
501 for (Account account : accounts) {
Fan Zhangc754f592017-05-17 12:32:59 -0700502 final AccountTypePreference preference =
503 preferenceToRemove.remove(AccountTypePreference.buildKey(account));
Doris Ling633250b2017-05-02 11:28:14 -0700504 if (preference != null) {
505 accountTypePreferences.add(preference);
506 continue;
507 }
Doris Lingf074f0f2017-02-24 15:20:05 -0800508 final ArrayList<String> auths =
509 helper.getAuthoritiesForAccountType(account.type);
510 if (!AccountRestrictionHelper.showAccount(mAuthorities, auths)) {
511 continue;
Doris Ling20d4b042016-11-22 16:37:06 -0800512 }
Doris Lingbfac31b2016-11-10 15:12:52 -0800513 final Bundle fragmentArguments = new Bundle();
Doris Lingf074f0f2017-02-24 15:20:05 -0800514 fragmentArguments.putParcelable(AccountDetailDashboardFragment.KEY_ACCOUNT,
515 account);
516 fragmentArguments.putParcelable(AccountDetailDashboardFragment.KEY_USER_HANDLE,
517 userHandle);
518 fragmentArguments.putString(AccountDetailDashboardFragment.KEY_ACCOUNT_TYPE,
519 accountType);
520 fragmentArguments.putString(AccountDetailDashboardFragment.KEY_ACCOUNT_LABEL,
521 label.toString());
522 fragmentArguments.putInt(AccountDetailDashboardFragment.KEY_ACCOUNT_TITLE_RES,
523 titleResId);
Doris Lingbfac31b2016-11-10 15:12:52 -0800524 fragmentArguments.putParcelable(EXTRA_USER, userHandle);
Doris Ling20d4b042016-11-22 16:37:06 -0800525 accountTypePreferences.add(new AccountTypePreference(
Doris Lingf074f0f2017-02-24 15:20:05 -0800526 prefContext, mMetricsFeatureProvider.getMetricsCategory(mParent),
Fan Zhangc754f592017-05-17 12:32:59 -0700527 account, titleResPackageName, titleResId, label,
Doris Lingf074f0f2017-02-24 15:20:05 -0800528 AccountDetailDashboardFragment.class.getName(), fragmentArguments, icon));
Doris Lingbfac31b2016-11-10 15:12:52 -0800529 }
530 helper.preloadDrawableForType(mContext, accountType);
531 }
532 // Sort by label
Doris Ling20d4b042016-11-22 16:37:06 -0800533 Collections.sort(accountTypePreferences, new Comparator<AccountTypePreference>() {
Doris Lingbfac31b2016-11-10 15:12:52 -0800534 @Override
Doris Ling20d4b042016-11-22 16:37:06 -0800535 public int compare(AccountTypePreference t1, AccountTypePreference t2) {
Doris Lingf074f0f2017-02-24 15:20:05 -0800536 int result = t1.getSummary().toString().compareTo(t2.getSummary().toString());
Doris Ling20d4b042016-11-22 16:37:06 -0800537 return result != 0
538 ? result : t1.getTitle().toString().compareTo(t2.getTitle().toString());
Doris Lingbfac31b2016-11-10 15:12:52 -0800539 }
540 });
541 return accountTypePreferences;
542 }
543
544 private boolean accountTypeHasAnyRequestedAuthorities(AuthenticatorHelper helper,
545 String accountType) {
546 if (mAuthoritiesCount == 0) {
547 // No authorities required
548 return true;
549 }
550 final ArrayList<String> authoritiesForType = helper.getAuthoritiesForAccountType(
551 accountType);
552 if (authoritiesForType == null) {
553 Log.d(TAG, "No sync authorities for account type: " + accountType);
554 return false;
555 }
556 for (int j = 0; j < mAuthoritiesCount; j++) {
557 if (authoritiesForType.contains(mAuthorities[j])) {
558 return true;
559 }
560 }
561 return false;
562 }
563
564 private boolean isSingleProfile() {
565 return mUm.isLinkedUser() || mUm.getProfiles(UserHandle.myUserId()).size() == 1;
566 }
567
568 private class ManagedProfileBroadcastReceiver extends BroadcastReceiver {
569 private boolean mListeningToManagedProfileEvents;
570
571 @Override
572 public void onReceive(Context context, Intent intent) {
573 final String action = intent.getAction();
574 Log.v(TAG, "Received broadcast: " + action);
575 if (action.equals(Intent.ACTION_MANAGED_PROFILE_REMOVED)
576 || action.equals(Intent.ACTION_MANAGED_PROFILE_ADDED)) {
577 // Clean old state
578 stopListeningToAccountUpdates();
Doris Lingbfac31b2016-11-10 15:12:52 -0800579 // Build new state
580 updateUi();
581 listenToAccountUpdates();
582 return;
583 }
584 Log.w(TAG, "Cannot handle received broadcast: " + intent.getAction());
585 }
586
587 public void register(Context context) {
588 if (!mListeningToManagedProfileEvents) {
589 IntentFilter intentFilter = new IntentFilter();
590 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
591 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
592 context.registerReceiver(this, intentFilter);
593 mListeningToManagedProfileEvents = true;
594 }
595 }
596
597 public void unregister(Context context) {
598 if (mListeningToManagedProfileEvents) {
599 context.unregisterReceiver(this);
600 mListeningToManagedProfileEvents = false;
601 }
602 }
603 }
604}