• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.overlay.FeatureFactory;
57 import com.android.settings.search.SearchIndexableRaw;
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 
66 import java.util.ArrayList;
67 import java.util.Collections;
68 import java.util.Comparator;
69 import java.util.List;
70 
71 public class AccountPreferenceController extends AbstractPreferenceController
72         implements PreferenceControllerMixin, AuthenticatorHelper.OnAccountsUpdateListener,
73         OnPreferenceClickListener, LifecycleObserver, OnPause, OnResume {
74 
75     private static final String TAG = "AccountPrefController";
76 
77     private static final int ORDER_ACCOUNT_PROFILES = 1;
78     private static final int ORDER_LAST = 1002;
79     private static final int ORDER_NEXT_TO_LAST = 1001;
80     private static final int ORDER_NEXT_TO_NEXT_TO_LAST = 1000;
81 
82     private UserManager mUm;
83     private SparseArray<ProfileData> mProfiles = new SparseArray<ProfileData>();
84     private ManagedProfileBroadcastReceiver mManagedProfileBroadcastReceiver
85                 = new ManagedProfileBroadcastReceiver();
86     private Preference mProfileNotAvailablePreference;
87     private String[] mAuthorities;
88     private int mAuthoritiesCount = 0;
89     private SettingsPreferenceFragment mParent;
90     private int mAccountProfileOrder = ORDER_ACCOUNT_PROFILES;
91     private AccountRestrictionHelper mHelper;
92     private MetricsFeatureProvider mMetricsFeatureProvider;
93 
94     /**
95      * Holds data related to the accounts belonging to one profile.
96      */
97     public static class ProfileData {
98         /**
99          * The preference that displays the accounts.
100          */
101         public PreferenceGroup preferenceGroup;
102         /**
103          * The preference that displays the add account button.
104          */
105         public RestrictedPreference addAccountPreference;
106         /**
107          * The preference that displays the button to remove the managed profile
108          */
109         public RestrictedPreference removeWorkProfilePreference;
110         /**
111          * The preference that displays managed profile settings.
112          */
113         public Preference managedProfilePreference;
114         /**
115          * The {@link AuthenticatorHelper} that holds accounts data for this profile.
116          */
117         public AuthenticatorHelper authenticatorHelper;
118         /**
119          * The {@link UserInfo} of the profile.
120          */
121         public UserInfo userInfo;
122         /**
123          * The {@link UserInfo} of the profile.
124          */
125         public boolean pendingRemoval;
126         /**
127          * The map from account key to account preference
128          */
129         public ArrayMap<String, AccountTypePreference> accountPreferences = new ArrayMap<>();
130     }
131 
AccountPreferenceController(Context context, SettingsPreferenceFragment parent, String[] authorities)132     public AccountPreferenceController(Context context, SettingsPreferenceFragment parent,
133         String[] authorities) {
134         this(context, parent, authorities, new AccountRestrictionHelper(context));
135     }
136 
137     @VisibleForTesting
AccountPreferenceController(Context context, SettingsPreferenceFragment parent, String[] authorities, AccountRestrictionHelper helper)138     AccountPreferenceController(Context context, SettingsPreferenceFragment parent,
139         String[] authorities, AccountRestrictionHelper helper) {
140         super(context);
141         mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
142         mAuthorities = authorities;
143         mParent = parent;
144         if (mAuthorities != null) {
145             mAuthoritiesCount = mAuthorities.length;
146         }
147         final FeatureFactory featureFactory = FeatureFactory.getFactory(mContext);
148         mMetricsFeatureProvider = featureFactory.getMetricsFeatureProvider();
149         mHelper = helper;
150     }
151 
152     @Override
isAvailable()153     public boolean isAvailable() {
154         return !mUm.isManagedProfile();
155     }
156 
157     @Override
getPreferenceKey()158     public String getPreferenceKey() {
159         return null;
160     }
161 
162     @Override
displayPreference(PreferenceScreen screen)163     public void displayPreference(PreferenceScreen screen) {
164         super.displayPreference(screen);
165         updateUi();
166     }
167 
168     @Override
updateRawDataToIndex(List<SearchIndexableRaw> rawData)169     public void updateRawDataToIndex(List<SearchIndexableRaw> rawData) {
170         if (!isAvailable()) {
171             return;
172         }
173         final Resources res = mContext.getResources();
174         final String screenTitle = res.getString(R.string.account_settings_title);
175 
176         List<UserInfo> profiles = mUm.getProfiles(UserHandle.myUserId());
177         final int profilesCount = profiles.size();
178         for (int i = 0; i < profilesCount; i++) {
179             UserInfo userInfo = profiles.get(i);
180             if (userInfo.isEnabled()) {
181                 if (!mHelper.hasBaseUserRestriction(DISALLOW_MODIFY_ACCOUNTS, userInfo.id)) {
182                     SearchIndexableRaw data = new SearchIndexableRaw(mContext);
183                     data.title = res.getString(R.string.add_account_label);
184                     data.screenTitle = screenTitle;
185                     rawData.add(data);
186                 }
187                 if (userInfo.isManagedProfile()) {
188                     if (!mHelper.hasBaseUserRestriction(DISALLOW_REMOVE_MANAGED_PROFILE,
189                         UserHandle.myUserId())) {
190                         SearchIndexableRaw data = new SearchIndexableRaw(mContext);
191                         data.title = res.getString(R.string.remove_managed_profile_label);
192                         data.screenTitle = screenTitle;
193                         rawData.add(data);
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     @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         // 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) {
234                 Intent intent = new Intent(ACTION_ADD_ACCOUNT);
235                 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());
249                 new SubSettingLauncher(mContext)
250                         .setSourceMetricsCategory(mParent.getMetricsCategory())
251                         .setDestination(ManagedProfileSettings.class.getName())
252                         .setTitleRes(R.string.managed_profile_settings_title)
253                         .setArguments(arguments)
254                         .launch();
255 
256                 return true;
257             }
258         }
259         return false;
260     }
261 
updateUi()262     private void updateUi() {
263         if (!isAvailable()) {
264             // This should not happen
265             Log.e(TAG, "We should not be showing settings for a managed profile");
266             return;
267         }
268 
269         for (int i = 0, size = mProfiles.size(); i < size; i++) {
270             mProfiles.valueAt(i).pendingRemoval = true;
271         }
272         if (mUm.isRestrictedProfile()) {
273             // 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();
279             for (int i = 0; i < profilesCount; i++) {
280                 updateProfileUi(profiles.get(i));
281             }
282         }
283         cleanUpPreferences();
284 
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 
updateProfileUi(final UserInfo userInfo)294     private void updateProfileUi(final UserInfo userInfo) {
295         if (mParent.getPreferenceManager() == null) {
296             return;
297         }
298         final ProfileData data = mProfiles.get(userInfo.id);
299         if (data != null) {
300             data.pendingRemoval = false;
301             data.userInfo = userInfo;
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 
newAddAccountPreference()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_add_24dp);
355         preference.setOnPreferenceClickListener(this);
356         preference.setOrder(ORDER_NEXT_TO_NEXT_TO_LAST);
357         return preference;
358     }
359 
newRemoveWorkProfilePreference()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 
newManagedProfileSettings()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 
getWorkGroupSummary(Context context, UserInfo userInfo)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 
cleanUpPreferences()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 
listenToAccountUpdates()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 
stopListeningToAccountUpdates()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 
updateAccountTypes(ProfileData profileData)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 
getAccountTypePreferences(AuthenticatorHelper helper, UserHandle userHandle, ArrayMap<String, AccountTypePreference> preferenceToRemove)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 
accountTypeHasAnyRequestedAuthorities(AuthenticatorHelper helper, String accountType)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 
isSingleProfile()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
onReceive(Context context, Intent intent)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 
register(Context context)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 
unregister(Context context)598         public void unregister(Context context) {
599             if (mListeningToManagedProfileEvents) {
600                 context.unregisterReceiver(this);
601                 mListeningToManagedProfileEvents = false;
602             }
603         }
604     }
605 }
606