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