1 /*
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 
17 package com.android.settings.accounts;
18 
19 import static android.content.Intent.EXTRA_USER;
20 import static android.os.UserManager.DISALLOW_MODIFY_ACCOUNTS;
21 import static android.os.UserManager.DISALLOW_REMOVE_MANAGED_PROFILE;
22 import static android.provider.Settings.ACTION_ADD_ACCOUNT;
23 import static android.provider.Settings.EXTRA_AUTHORITIES;
24 
25 import android.accounts.Account;
26 import android.accounts.AccountManager;
27 import android.content.BroadcastReceiver;
28 import android.content.Context;
29 import android.content.Intent;
30 import android.content.IntentFilter;
31 import android.content.pm.ApplicationInfo;
32 import android.content.pm.PackageManager;
33 import android.content.pm.UserInfo;
34 import android.content.res.Resources;
35 import android.graphics.drawable.Drawable;
36 import android.os.Bundle;
37 import android.os.UserHandle;
38 import android.os.UserManager;
39 import android.text.BidiFormatter;
40 import android.util.ArrayMap;
41 import android.util.Log;
42 import android.util.SparseArray;
43 
44 import androidx.annotation.VisibleForTesting;
45 import androidx.preference.Preference;
46 import androidx.preference.Preference.OnPreferenceClickListener;
47 import androidx.preference.PreferenceGroup;
48 import androidx.preference.PreferenceScreen;
49 
50 import com.android.settings.AccessiblePreferenceCategory;
51 import com.android.settings.R;
52 import com.android.settings.SettingsPreferenceFragment;
53 import com.android.settings.Utils;
54 import com.android.settings.core.PreferenceControllerMixin;
55 import com.android.settings.core.SubSettingLauncher;
56 import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
57 import com.android.settings.overlay.FeatureFactory;
58 import com.android.settingslib.RestrictedPreference;
59 import com.android.settingslib.accounts.AuthenticatorHelper;
60 import com.android.settingslib.core.AbstractPreferenceController;
61 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
62 import com.android.settingslib.core.lifecycle.LifecycleObserver;
63 import com.android.settingslib.core.lifecycle.events.OnPause;
64 import com.android.settingslib.core.lifecycle.events.OnResume;
65 import com.android.settingslib.search.SearchIndexableRaw;
66 
67 import java.util.ArrayList;
68 import java.util.Collections;
69 import java.util.Comparator;
70 import java.util.List;
71 
72 public class AccountPreferenceController extends AbstractPreferenceController
73         implements PreferenceControllerMixin, AuthenticatorHelper.OnAccountsUpdateListener,
74         OnPreferenceClickListener, LifecycleObserver, OnPause, OnResume {
75 
76     private static final String TAG = "AccountPrefController";
77 
78     private static final int ORDER_ACCOUNT_PROFILES = 1;
79     private static final int ORDER_LAST = 1002;
80     private static final int ORDER_NEXT_TO_LAST = 1001;
81     private static final int ORDER_NEXT_TO_NEXT_TO_LAST = 1000;
82 
83     private static final String PREF_KEY_ADD_ACCOUNT = "add_account";
84     private static final String PREF_KEY_REMOVE_PROFILE = "remove_profile";
85     private static final String PREF_KEY_WORK_PROFILE_SETTING = "work_profile_setting";
86 
87     private UserManager mUm;
88     private SparseArray<ProfileData> mProfiles = new SparseArray<ProfileData>();
89     private ManagedProfileBroadcastReceiver mManagedProfileBroadcastReceiver =
90             new ManagedProfileBroadcastReceiver();
91     private Preference mProfileNotAvailablePreference;
92     private String[] mAuthorities;
93     private int mAuthoritiesCount = 0;
94     private SettingsPreferenceFragment mFragment;
95     private int mAccountProfileOrder = ORDER_ACCOUNT_PROFILES;
96     private AccountRestrictionHelper mHelper;
97     private MetricsFeatureProvider mMetricsFeatureProvider;
98     private @ProfileSelectFragment.ProfileType int mType;
99 
100     /**
101      * Holds data related to the accounts belonging to one profile.
102      */
103     public static class ProfileData {
104         /**
105          * The preference that displays the accounts.
106          */
107         public PreferenceGroup preferenceGroup;
108         /**
109          * The preference that displays the add account button.
110          */
111         public RestrictedPreference addAccountPreference;
112         /**
113          * The preference that displays the button to remove the managed profile
114          */
115         public RestrictedPreference removeWorkProfilePreference;
116         /**
117          * The preference that displays managed profile settings.
118          */
119         public Preference managedProfilePreference;
120         /**
121          * The {@link AuthenticatorHelper} that holds accounts data for this profile.
122          */
123         public AuthenticatorHelper authenticatorHelper;
124         /**
125          * The {@link UserInfo} of the profile.
126          */
127         public UserInfo userInfo;
128         /**
129          * The {@link UserInfo} of the profile.
130          */
131         public boolean pendingRemoval;
132         /**
133          * The map from account key to account preference
134          */
135         public ArrayMap<String, AccountTypePreference> accountPreferences = new ArrayMap<>();
136     }
137 
AccountPreferenceController(Context context, SettingsPreferenceFragment parent, String[] authorities, @ProfileSelectFragment.ProfileType int type)138     public AccountPreferenceController(Context context, SettingsPreferenceFragment parent,
139             String[] authorities, @ProfileSelectFragment.ProfileType int type) {
140         this(context, parent, authorities, new AccountRestrictionHelper(context), type);
141     }
142 
143     @VisibleForTesting
AccountPreferenceController(Context context, SettingsPreferenceFragment parent, String[] authorities, AccountRestrictionHelper helper, @ProfileSelectFragment.ProfileType int type)144     AccountPreferenceController(Context context, SettingsPreferenceFragment parent,
145             String[] authorities, AccountRestrictionHelper helper,
146             @ProfileSelectFragment.ProfileType int type) {
147         super(context);
148         mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
149         mAuthorities = authorities;
150         mFragment = parent;
151         if (mAuthorities != null) {
152             mAuthoritiesCount = mAuthorities.length;
153         }
154         final FeatureFactory featureFactory = FeatureFactory.getFactory(mContext);
155         mMetricsFeatureProvider = featureFactory.getMetricsFeatureProvider();
156         mHelper = helper;
157         mType = type;
158     }
159 
160     @Override
isAvailable()161     public boolean isAvailable() {
162         return !mUm.isManagedProfile();
163     }
164 
165     @Override
getPreferenceKey()166     public String getPreferenceKey() {
167         return null;
168     }
169 
170     @Override
displayPreference(PreferenceScreen screen)171     public void displayPreference(PreferenceScreen screen) {
172         super.displayPreference(screen);
173         updateUi();
174     }
175 
176     @Override
updateDynamicRawDataToIndex(List<SearchIndexableRaw> rawData)177     public void updateDynamicRawDataToIndex(List<SearchIndexableRaw> rawData) {
178         if (!isAvailable()) {
179             return;
180         }
181         final Resources res = mContext.getResources();
182         final String screenTitle = res.getString(R.string.account_settings_title);
183 
184         List<UserInfo> profiles = mUm.getProfiles(UserHandle.myUserId());
185         for (final UserInfo userInfo : profiles) {
186             if (userInfo.isEnabled() && userInfo.isManagedProfile()) {
187                 if (!mHelper.hasBaseUserRestriction(DISALLOW_REMOVE_MANAGED_PROFILE,
188                         UserHandle.myUserId())) {
189                     final SearchIndexableRaw data = new SearchIndexableRaw(mContext);
190                     data.key = PREF_KEY_REMOVE_PROFILE;
191                     data.title = res.getString(R.string.remove_managed_profile_label);
192                     data.screenTitle = screenTitle;
193                     rawData.add(data);
194                 }
195                 final SearchIndexableRaw data = new SearchIndexableRaw(mContext);
196                 data.key = PREF_KEY_WORK_PROFILE_SETTING;
197                 data.title = res.getString(R.string.managed_profile_settings_title);
198                 data.screenTitle = screenTitle;
199                 rawData.add(data);
200             }
201         }
202     }
203 
204     @Override
onResume()205     public void onResume() {
206         updateUi();
207         mManagedProfileBroadcastReceiver.register(mContext);
208         listenToAccountUpdates();
209     }
210 
211     @Override
onPause()212     public void onPause() {
213         stopListeningToAccountUpdates();
214         mManagedProfileBroadcastReceiver.unregister(mContext);
215     }
216 
217     @Override
onAccountsUpdate(UserHandle userHandle)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
onPreferenceClick(Preference preference)228     public boolean onPreferenceClick(Preference preference) {
229         final int metricsCategory = mFragment.getMetricsCategory();
230         // Check the preference
231         final int count = mProfiles.size();
232         for (int i = 0; i < count; i++) {
233             ProfileData profileData = mProfiles.valueAt(i);
234             if (preference == profileData.addAccountPreference) {
235                 mMetricsFeatureProvider.logClickedPreference(preference, metricsCategory);
236                 Intent intent = new Intent(ACTION_ADD_ACCOUNT);
237                 intent.putExtra(EXTRA_USER, profileData.userInfo.getUserHandle());
238                 intent.putExtra(EXTRA_AUTHORITIES, mAuthorities);
239                 mContext.startActivity(intent);
240                 return true;
241             }
242             if (preference == profileData.removeWorkProfilePreference) {
243                 mMetricsFeatureProvider.logClickedPreference(preference, metricsCategory);
244                 final int userId = profileData.userInfo.id;
245                 RemoveUserFragment.newInstance(userId).show(mFragment.getFragmentManager(),
246                         "removeUser");
247                 return true;
248             }
249             if (preference == profileData.managedProfilePreference) {
250                 mMetricsFeatureProvider.logClickedPreference(preference, metricsCategory);
251                 Bundle arguments = new Bundle();
252                 arguments.putParcelable(Intent.EXTRA_USER, profileData.userInfo.getUserHandle());
253                 new SubSettingLauncher(mContext)
254                         .setSourceMetricsCategory(metricsCategory)
255                         .setDestination(ManagedProfileSettings.class.getName())
256                         .setTitleRes(R.string.managed_profile_settings_title)
257                         .setArguments(arguments)
258                         .launch();
259 
260                 return true;
261             }
262         }
263         return false;
264     }
265 
updateUi()266     private void updateUi() {
267         if (!isAvailable()) {
268             // This should not happen
269             Log.e(TAG, "We should not be showing settings for a managed profile");
270             return;
271         }
272 
273         for (int i = 0, size = mProfiles.size(); i < size; i++) {
274             mProfiles.valueAt(i).pendingRemoval = true;
275         }
276         if (mUm.isRestrictedProfile()) {
277             // Restricted user or similar
278             UserInfo userInfo = mUm.getUserInfo(UserHandle.myUserId());
279             updateProfileUi(userInfo);
280         } else {
281             List<UserInfo> profiles = mUm.getProfiles(UserHandle.myUserId());
282             final int profilesCount = profiles.size();
283             for (int i = 0; i < profilesCount; i++) {
284                 if (profiles.get(i).isManagedProfile()
285                         && (mType & ProfileSelectFragment.ProfileType.WORK) != 0) {
286                     updateProfileUi(profiles.get(i));
287                 } else if (!profiles.get(i).isManagedProfile()
288                         && (mType & ProfileSelectFragment.ProfileType.PERSONAL) != 0) {
289                     updateProfileUi(profiles.get(i));
290                 }
291             }
292         }
293         cleanUpPreferences();
294 
295         // Add all preferences, starting with one for the primary profile.
296         // Note that we're relying on the ordering given by the SparseArray keys, and on the
297         // value of UserHandle.USER_OWNER being smaller than all the rest.
298         final int profilesCount = mProfiles.size();
299         for (int i = 0; i < profilesCount; i++) {
300             updateAccountTypes(mProfiles.valueAt(i));
301         }
302     }
303 
updateProfileUi(final UserInfo userInfo)304     private void updateProfileUi(final UserInfo userInfo) {
305         if (mFragment.getPreferenceManager() == null) {
306             return;
307         }
308         final ProfileData data = mProfiles.get(userInfo.id);
309         if (data != null) {
310             data.pendingRemoval = false;
311             data.userInfo = userInfo;
312             if (userInfo.isEnabled()) {
313                 // recreate the authentication helper to refresh the list of enabled accounts
314                 data.authenticatorHelper =
315                         new AuthenticatorHelper(mContext, userInfo.getUserHandle(), this);
316             }
317             return;
318         }
319         final Context context = mContext;
320         final ProfileData profileData = new ProfileData();
321         profileData.userInfo = userInfo;
322         AccessiblePreferenceCategory preferenceGroup =
323                 mHelper.createAccessiblePreferenceCategory(
324                         mFragment.getPreferenceManager().getContext());
325         preferenceGroup.setOrder(mAccountProfileOrder++);
326         if (isSingleProfile()) {
327             preferenceGroup.setTitle(context.getString(R.string.account_for_section_header,
328                     BidiFormatter.getInstance().unicodeWrap(userInfo.name)));
329             preferenceGroup.setContentDescription(
330                     mContext.getString(R.string.account_settings));
331         } else if (userInfo.isManagedProfile()) {
332             if (mType == ProfileSelectFragment.ProfileType.ALL) {
333                 preferenceGroup.setTitle(R.string.category_work);
334                 final String workGroupSummary = getWorkGroupSummary(context, userInfo);
335                 preferenceGroup.setSummary(workGroupSummary);
336                 preferenceGroup.setContentDescription(
337                         mContext.getString(R.string.accessibility_category_work, workGroupSummary));
338             }
339             profileData.removeWorkProfilePreference = newRemoveWorkProfilePreference();
340             mHelper.enforceRestrictionOnPreference(profileData.removeWorkProfilePreference,
341                     DISALLOW_REMOVE_MANAGED_PROFILE, UserHandle.myUserId());
342             profileData.managedProfilePreference = newManagedProfileSettings();
343         } else {
344             if (mType == ProfileSelectFragment.ProfileType.ALL) {
345                 preferenceGroup.setTitle(R.string.category_personal);
346                 preferenceGroup.setContentDescription(
347                         mContext.getString(R.string.accessibility_category_personal));
348             }
349         }
350         final PreferenceScreen screen = mFragment.getPreferenceScreen();
351         if (screen != null) {
352             screen.addPreference(preferenceGroup);
353         }
354         profileData.preferenceGroup = preferenceGroup;
355         if (userInfo.isEnabled()) {
356             profileData.authenticatorHelper = new AuthenticatorHelper(context,
357                     userInfo.getUserHandle(), this);
358             profileData.addAccountPreference = newAddAccountPreference();
359             mHelper.enforceRestrictionOnPreference(profileData.addAccountPreference,
360                     DISALLOW_MODIFY_ACCOUNTS, userInfo.id);
361         }
362         mProfiles.put(userInfo.id, profileData);
363     }
364 
newAddAccountPreference()365     private RestrictedPreference newAddAccountPreference() {
366         RestrictedPreference preference =
367                 new RestrictedPreference(mFragment.getPreferenceManager().getContext());
368         preference.setKey(PREF_KEY_ADD_ACCOUNT);
369         preference.setTitle(R.string.add_account_label);
370         preference.setIcon(R.drawable.ic_add_24dp);
371         preference.setOnPreferenceClickListener(this);
372         preference.setOrder(ORDER_NEXT_TO_NEXT_TO_LAST);
373         return preference;
374     }
375 
newRemoveWorkProfilePreference()376     private RestrictedPreference newRemoveWorkProfilePreference() {
377         RestrictedPreference preference = new RestrictedPreference(
378                 mFragment.getPreferenceManager().getContext());
379         preference.setKey(PREF_KEY_REMOVE_PROFILE);
380         preference.setTitle(R.string.remove_managed_profile_label);
381         preference.setIcon(R.drawable.ic_delete);
382         preference.setOnPreferenceClickListener(this);
383         preference.setOrder(ORDER_LAST);
384         return preference;
385     }
386 
387 
newManagedProfileSettings()388     private Preference newManagedProfileSettings() {
389         Preference preference = new Preference(mFragment.getPreferenceManager().getContext());
390         preference.setKey(PREF_KEY_WORK_PROFILE_SETTING);
391         preference.setTitle(R.string.managed_profile_settings_title);
392         preference.setIcon(R.drawable.ic_settings_24dp);
393         preference.setOnPreferenceClickListener(this);
394         preference.setOrder(ORDER_NEXT_TO_LAST);
395         return preference;
396     }
397 
getWorkGroupSummary(Context context, UserInfo userInfo)398     private String getWorkGroupSummary(Context context, UserInfo userInfo) {
399         PackageManager packageManager = context.getPackageManager();
400         ApplicationInfo adminApplicationInfo = Utils.getAdminApplicationInfo(context, userInfo.id);
401         if (adminApplicationInfo == null) {
402             return null;
403         }
404         CharSequence appLabel = packageManager.getApplicationLabel(adminApplicationInfo);
405         return mContext.getString(R.string.managing_admin, appLabel);
406     }
407 
cleanUpPreferences()408     void cleanUpPreferences() {
409         PreferenceScreen screen = mFragment.getPreferenceScreen();
410         if (screen == null) {
411             return;
412         }
413         final int count = mProfiles.size();
414         for (int i = count - 1; i >= 0; i--) {
415             final ProfileData data = mProfiles.valueAt(i);
416             if (data.pendingRemoval) {
417                 screen.removePreference(data.preferenceGroup);
418                 mProfiles.removeAt(i);
419             }
420         }
421     }
422 
listenToAccountUpdates()423     private void listenToAccountUpdates() {
424         final int count = mProfiles.size();
425         for (int i = 0; i < count; i++) {
426             AuthenticatorHelper authenticatorHelper = mProfiles.valueAt(i).authenticatorHelper;
427             if (authenticatorHelper != null) {
428                 authenticatorHelper.listenToAccountUpdates();
429             }
430         }
431     }
432 
stopListeningToAccountUpdates()433     private void stopListeningToAccountUpdates() {
434         final int count = mProfiles.size();
435         for (int i = 0; i < count; i++) {
436             AuthenticatorHelper authenticatorHelper = mProfiles.valueAt(i).authenticatorHelper;
437             if (authenticatorHelper != null) {
438                 authenticatorHelper.stopListeningToAccountUpdates();
439             }
440         }
441     }
442 
updateAccountTypes(ProfileData profileData)443     private void updateAccountTypes(ProfileData profileData) {
444         if (mFragment.getPreferenceManager() == null
445                 || profileData.preferenceGroup.getPreferenceManager() == null) {
446             // This could happen if activity is finishing
447             return;
448         }
449         if (profileData.userInfo.isEnabled()) {
450             final ArrayMap<String, AccountTypePreference> preferenceToRemove =
451                     new ArrayMap<>(profileData.accountPreferences);
452             final ArrayList<AccountTypePreference> preferences = getAccountTypePreferences(
453                     profileData.authenticatorHelper, profileData.userInfo.getUserHandle(),
454                     preferenceToRemove);
455             final int count = preferences.size();
456             for (int i = 0; i < count; i++) {
457                 final AccountTypePreference preference = preferences.get(i);
458                 preference.setOrder(i);
459                 final String key = preference.getKey();
460                 if (!profileData.accountPreferences.containsKey(key)) {
461                     profileData.preferenceGroup.addPreference(preference);
462                     profileData.accountPreferences.put(key, preference);
463                 }
464             }
465             if (profileData.addAccountPreference != null) {
466                 profileData.preferenceGroup.addPreference(profileData.addAccountPreference);
467             }
468             for (String key : preferenceToRemove.keySet()) {
469                 profileData.preferenceGroup.removePreference(
470                         profileData.accountPreferences.get(key));
471                 profileData.accountPreferences.remove(key);
472             }
473         } else {
474             profileData.preferenceGroup.removeAll();
475             // Put a label instead of the accounts list
476             if (mProfileNotAvailablePreference == null) {
477                 mProfileNotAvailablePreference =
478                         new Preference(mFragment.getPreferenceManager().getContext());
479             }
480             mProfileNotAvailablePreference.setEnabled(false);
481             mProfileNotAvailablePreference.setIcon(R.drawable.empty_icon);
482             mProfileNotAvailablePreference.setTitle(null);
483             mProfileNotAvailablePreference.setSummary(
484                     R.string.managed_profile_not_available_label);
485             profileData.preferenceGroup.addPreference(mProfileNotAvailablePreference);
486         }
487         if (profileData.removeWorkProfilePreference != null) {
488             profileData.preferenceGroup.addPreference(profileData.removeWorkProfilePreference);
489         }
490         if (profileData.managedProfilePreference != null) {
491             profileData.preferenceGroup.addPreference(profileData.managedProfilePreference);
492         }
493     }
494 
getAccountTypePreferences(AuthenticatorHelper helper, UserHandle userHandle, ArrayMap<String, AccountTypePreference> preferenceToRemove)495     private ArrayList<AccountTypePreference> getAccountTypePreferences(AuthenticatorHelper helper,
496             UserHandle userHandle, ArrayMap<String, AccountTypePreference> preferenceToRemove) {
497         final String[] accountTypes = helper.getEnabledAccountTypes();
498         final ArrayList<AccountTypePreference> accountTypePreferences =
499                 new ArrayList<>(accountTypes.length);
500 
501         for (int i = 0; i < accountTypes.length; i++) {
502             final String accountType = accountTypes[i];
503             // Skip showing any account that does not have any of the requested authorities
504             if (!accountTypeHasAnyRequestedAuthorities(helper, accountType)) {
505                 continue;
506             }
507             final CharSequence label = helper.getLabelForType(mContext, accountType);
508             if (label == null) {
509                 continue;
510             }
511             final String titleResPackageName = helper.getPackageForType(accountType);
512             final int titleResId = helper.getLabelIdForType(accountType);
513 
514             final Account[] accounts = AccountManager.get(mContext)
515                     .getAccountsByTypeAsUser(accountType, userHandle);
516             final Drawable icon = helper.getDrawableForType(mContext, accountType);
517             final Context prefContext = mFragment.getPreferenceManager().getContext();
518 
519             // Add a preference row for each individual account
520             for (Account account : accounts) {
521                 final AccountTypePreference preference =
522                         preferenceToRemove.remove(AccountTypePreference.buildKey(account));
523                 if (preference != null) {
524                     accountTypePreferences.add(preference);
525                     continue;
526                 }
527                 final ArrayList<String> auths =
528                         helper.getAuthoritiesForAccountType(account.type);
529                 if (!AccountRestrictionHelper.showAccount(mAuthorities, auths)) {
530                     continue;
531                 }
532                 final Bundle fragmentArguments = new Bundle();
533                 fragmentArguments.putParcelable(AccountDetailDashboardFragment.KEY_ACCOUNT,
534                         account);
535                 fragmentArguments.putParcelable(AccountDetailDashboardFragment.KEY_USER_HANDLE,
536                         userHandle);
537                 fragmentArguments.putString(AccountDetailDashboardFragment.KEY_ACCOUNT_TYPE,
538                         accountType);
539                 fragmentArguments.putString(AccountDetailDashboardFragment.KEY_ACCOUNT_LABEL,
540                         label.toString());
541                 fragmentArguments.putInt(AccountDetailDashboardFragment.KEY_ACCOUNT_TITLE_RES,
542                         titleResId);
543                 fragmentArguments.putParcelable(EXTRA_USER, userHandle);
544                 accountTypePreferences.add(new AccountTypePreference(
545                         prefContext, mMetricsFeatureProvider.getMetricsCategory(mFragment),
546                         account, titleResPackageName, titleResId, label,
547                         AccountDetailDashboardFragment.class.getName(), fragmentArguments, icon));
548             }
549             helper.preloadDrawableForType(mContext, accountType);
550         }
551         // Sort by label
552         Collections.sort(accountTypePreferences, new Comparator<AccountTypePreference>() {
553             @Override
554             public int compare(AccountTypePreference t1, AccountTypePreference t2) {
555                 int result = t1.getSummary().toString().compareTo(t2.getSummary().toString());
556                 return result != 0
557                         ? result : t1.getTitle().toString().compareTo(t2.getTitle().toString());
558             }
559         });
560         return accountTypePreferences;
561     }
562 
accountTypeHasAnyRequestedAuthorities(AuthenticatorHelper helper, String accountType)563     private boolean accountTypeHasAnyRequestedAuthorities(AuthenticatorHelper helper,
564             String accountType) {
565         if (mAuthoritiesCount == 0) {
566             // No authorities required
567             return true;
568         }
569         final ArrayList<String> authoritiesForType = helper.getAuthoritiesForAccountType(
570                 accountType);
571         if (authoritiesForType == null) {
572             Log.d(TAG, "No sync authorities for account type: " + accountType);
573             return false;
574         }
575         for (int j = 0; j < mAuthoritiesCount; j++) {
576             if (authoritiesForType.contains(mAuthorities[j])) {
577                 return true;
578             }
579         }
580         return false;
581     }
582 
isSingleProfile()583     private boolean isSingleProfile() {
584         return mUm.isLinkedUser() || mUm.getProfiles(UserHandle.myUserId()).size() == 1;
585     }
586 
587     private class ManagedProfileBroadcastReceiver extends BroadcastReceiver {
588         private boolean mListeningToManagedProfileEvents;
589 
590         @Override
onReceive(Context context, Intent intent)591         public void onReceive(Context context, Intent intent) {
592             final String action = intent.getAction();
593             Log.v(TAG, "Received broadcast: " + action);
594             if (action.equals(Intent.ACTION_MANAGED_PROFILE_REMOVED)
595                     || action.equals(Intent.ACTION_MANAGED_PROFILE_ADDED)) {
596                 if (mFragment instanceof AccountWorkProfileDashboardFragment) {
597                     mFragment.getActivity().finish();
598                 } else {
599                     // Clean old state
600                     stopListeningToAccountUpdates();
601                     // Build new state
602                     updateUi();
603                     listenToAccountUpdates();
604                 }
605                 return;
606             }
607             Log.w(TAG, "Cannot handle received broadcast: " + intent.getAction());
608         }
609 
register(Context context)610         public void register(Context context) {
611             if (!mListeningToManagedProfileEvents) {
612                 IntentFilter intentFilter = new IntentFilter();
613                 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
614                 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
615                 context.registerReceiver(this, intentFilter);
616                 mListeningToManagedProfileEvents = true;
617             }
618         }
619 
unregister(Context context)620         public void unregister(Context context) {
621             if (mListeningToManagedProfileEvents) {
622                 context.unregisterReceiver(this);
623                 mListeningToManagedProfileEvents = false;
624             }
625         }
626     }
627 }
628