AccountSettings.java revision 39b467482d1bf256a111c757e9b7621c6f523271
1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.settings.accounts;
18
19
20import android.accounts.Account;
21import android.accounts.AccountManager;
22import android.app.ActivityManager;
23import android.app.AlertDialog;
24import android.app.Dialog;
25import android.app.DialogFragment;
26import android.content.BroadcastReceiver;
27import android.content.ContentResolver;
28import android.content.Context;
29import android.content.DialogInterface;
30import android.content.Intent;
31import android.content.IntentFilter;
32import android.content.pm.ApplicationInfo;
33import android.content.pm.PackageManager;
34import android.content.pm.UserInfo;
35import android.content.res.Resources;
36import android.graphics.drawable.Drawable;
37import android.os.Bundle;
38import android.os.Process;
39import android.os.UserHandle;
40import android.os.UserManager;
41import android.provider.SearchIndexableResource;
42import android.support.v7.preference.Preference;
43import android.support.v7.preference.Preference.OnPreferenceClickListener;
44import android.support.v7.preference.PreferenceGroup;
45import android.support.v7.preference.PreferenceScreen;
46import android.util.Log;
47import android.util.SparseArray;
48import android.view.Menu;
49import android.view.MenuInflater;
50import android.view.MenuItem;
51
52import com.android.internal.logging.MetricsLogger;
53import com.android.settings.AccessiblePreferenceCategory;
54import com.android.settings.R;
55import com.android.settings.SettingsPreferenceFragment;
56import com.android.settings.Utils;
57import com.android.settings.search.BaseSearchIndexProvider;
58import com.android.settings.search.Index;
59import com.android.settings.search.Indexable;
60import com.android.settings.search.SearchIndexableRaw;
61import com.android.settings.users.UserDialogs;
62
63import java.util.ArrayList;
64import java.util.Arrays;
65import java.util.Collections;
66import java.util.Comparator;
67import java.util.List;
68
69import static android.content.Intent.EXTRA_USER;
70import static android.os.UserManager.DISALLOW_MODIFY_ACCOUNTS;
71import static android.provider.Settings.EXTRA_AUTHORITIES;
72
73/**
74 * Settings screen for the account types on the device.
75 * This shows all account types available for personal and work profiles.
76 *
77 * An extra {@link UserHandle} can be specified in the intent as {@link EXTRA_USER}, if the user for
78 * which the action needs to be performed is different to the one the Settings App will run in.
79 */
80public class AccountSettings extends SettingsPreferenceFragment
81        implements AuthenticatorHelper.OnAccountsUpdateListener,
82        OnPreferenceClickListener, Indexable {
83    public static final String TAG = "AccountSettings";
84
85    private static final String KEY_ACCOUNT = "account";
86
87    private static final String ADD_ACCOUNT_ACTION = "android.settings.ADD_ACCOUNT_SETTINGS";
88    private static final String TAG_CONFIRM_AUTO_SYNC_CHANGE = "confirmAutoSyncChange";
89
90    private static final int ORDER_LAST = 1001;
91    private static final int ORDER_NEXT_TO_LAST = 1000;
92
93    private UserManager mUm;
94    private SparseArray<ProfileData> mProfiles = new SparseArray<ProfileData>();
95    private ManagedProfileBroadcastReceiver mManagedProfileBroadcastReceiver
96                = new ManagedProfileBroadcastReceiver();
97    private Preference mProfileNotAvailablePreference;
98    private String[] mAuthorities;
99    private int mAuthoritiesCount = 0;
100
101    /**
102     * Holds data related to the accounts belonging to one profile.
103     */
104    private static class ProfileData {
105        /**
106         * The preference that displays the accounts.
107         */
108        public PreferenceGroup preferenceGroup;
109        /**
110         * The preference that displays the add account button.
111         */
112        public Preference addAccountPreference;
113        /**
114         * The preference that displays the button to remove the managed profile
115         */
116        public Preference removeWorkProfilePreference;
117        /**
118         * The {@link AuthenticatorHelper} that holds accounts data for this profile.
119         */
120        public AuthenticatorHelper authenticatorHelper;
121        /**
122         * The {@link UserInfo} of the profile.
123         */
124        public UserInfo userInfo;
125    }
126
127    @Override
128    protected int getMetricsCategory() {
129        return MetricsLogger.ACCOUNT;
130    }
131
132    @Override
133    public void onCreate(Bundle savedInstanceState) {
134        super.onCreate(savedInstanceState);
135        mUm = (UserManager) getSystemService(Context.USER_SERVICE);
136        mProfileNotAvailablePreference = new Preference(getPrefContext());
137        mAuthorities = getActivity().getIntent().getStringArrayExtra(EXTRA_AUTHORITIES);
138        if (mAuthorities != null) {
139            mAuthoritiesCount = mAuthorities.length;
140        }
141        setHasOptionsMenu(true);
142    }
143
144    @Override
145    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
146        inflater.inflate(R.menu.account_settings, menu);
147        super.onCreateOptionsMenu(menu, inflater);
148    }
149
150    @Override
151    public void onPrepareOptionsMenu(Menu menu) {
152        final UserHandle currentProfile = Process.myUserHandle();
153        if (mProfiles.size() == 1) {
154            menu.findItem(R.id.account_settings_menu_auto_sync)
155                    .setVisible(true)
156                    .setOnMenuItemClickListener(new MasterSyncStateClickListener(currentProfile))
157                    .setChecked(ContentResolver.getMasterSyncAutomaticallyAsUser(
158                            currentProfile.getIdentifier()));
159            menu.findItem(R.id.account_settings_menu_auto_sync_personal).setVisible(false);
160            menu.findItem(R.id.account_settings_menu_auto_sync_work).setVisible(false);
161        } else if (mProfiles.size() > 1) {
162            // We assume there's only one managed profile, otherwise UI needs to change
163            final UserHandle managedProfile = mProfiles.valueAt(1).userInfo.getUserHandle();
164
165            menu.findItem(R.id.account_settings_menu_auto_sync_personal)
166                    .setVisible(true)
167                    .setOnMenuItemClickListener(new MasterSyncStateClickListener(currentProfile))
168                    .setChecked(ContentResolver.getMasterSyncAutomaticallyAsUser(
169                            currentProfile.getIdentifier()));
170            menu.findItem(R.id.account_settings_menu_auto_sync_work)
171                    .setVisible(true)
172                    .setOnMenuItemClickListener(new MasterSyncStateClickListener(managedProfile))
173                    .setChecked(ContentResolver.getMasterSyncAutomaticallyAsUser(
174                            managedProfile.getIdentifier()));
175            menu.findItem(R.id.account_settings_menu_auto_sync).setVisible(false);
176         } else {
177             Log.w(TAG, "Method onPrepareOptionsMenu called before mProfiles was initialized");
178         }
179    }
180
181    @Override
182    public void onResume() {
183        super.onResume();
184        updateUi();
185        mManagedProfileBroadcastReceiver.register(getActivity());
186        listenToAccountUpdates();
187    }
188
189    @Override
190    public void onPause() {
191        super.onPause();
192        stopListeningToAccountUpdates();
193        mManagedProfileBroadcastReceiver.unregister(getActivity());
194        cleanUpPreferences();
195    }
196
197    @Override
198    public void onAccountsUpdate(UserHandle userHandle) {
199        final ProfileData profileData = mProfiles.get(userHandle.getIdentifier());
200        if (profileData != null) {
201            updateAccountTypes(profileData);
202        } else {
203            Log.w(TAG, "Missing Settings screen for: " + userHandle.getIdentifier());
204        }
205    }
206
207    @Override
208    public boolean onPreferenceClick(Preference preference) {
209        // Check the preference
210        final int count = mProfiles.size();
211        for (int i = 0; i < count; i++) {
212            ProfileData profileData = mProfiles.valueAt(i);
213            if (preference == profileData.addAccountPreference) {
214                Intent intent = new Intent(ADD_ACCOUNT_ACTION);
215                intent.putExtra(EXTRA_USER, profileData.userInfo.getUserHandle());
216                intent.putExtra(EXTRA_AUTHORITIES, mAuthorities);
217                startActivity(intent);
218                return true;
219            }
220            if (preference == profileData.removeWorkProfilePreference) {
221                final int userId = profileData.userInfo.id;
222                UserDialogs.createRemoveDialog(getActivity(), userId,
223                        new DialogInterface.OnClickListener() {
224                            @Override
225                            public void onClick(DialogInterface dialog, int which) {
226                                mUm.removeUser(userId);
227                            }
228                        }
229                ).show();
230                return true;
231            }
232        }
233        return false;
234    }
235
236    void updateUi() {
237        // Load the preferences from an XML resource
238        addPreferencesFromResource(R.xml.account_settings);
239
240        if (Utils.isManagedProfile(mUm)) {
241            // This should not happen
242            Log.e(TAG, "We should not be showing settings for a managed profile");
243            finish();
244            return;
245        }
246
247        final PreferenceScreen preferenceScreen = (PreferenceScreen) findPreference(KEY_ACCOUNT);
248        if(mUm.isLinkedUser()) {
249            // Restricted user or similar
250            UserInfo userInfo = mUm.getUserInfo(UserHandle.myUserId());
251            updateProfileUi(userInfo, false /* no category needed */, preferenceScreen);
252        } else {
253            List<UserInfo> profiles = mUm.getProfiles(UserHandle.myUserId());
254            final int profilesCount = profiles.size();
255            final boolean addCategory = profilesCount > 1;
256            for (int i = 0; i < profilesCount; i++) {
257                updateProfileUi(profiles.get(i), addCategory, preferenceScreen);
258            }
259        }
260
261        // Add all preferences, starting with one for the primary profile.
262        // Note that we're relying on the ordering given by the SparseArray keys, and on the
263        // value of UserHandle.USER_OWNER being smaller than all the rest.
264        final int profilesCount = mProfiles.size();
265        for (int i = 0; i < profilesCount; i++) {
266            ProfileData profileData = mProfiles.valueAt(i);
267            if (!profileData.preferenceGroup.equals(preferenceScreen)) {
268                preferenceScreen.addPreference(profileData.preferenceGroup);
269            }
270            updateAccountTypes(profileData);
271        }
272    }
273
274    private void updateProfileUi(final UserInfo userInfo, boolean addCategory,
275            PreferenceScreen parent) {
276        final Context context = getActivity();
277        final ProfileData profileData = new ProfileData();
278        profileData.userInfo = userInfo;
279        if (addCategory) {
280            profileData.preferenceGroup = new AccessiblePreferenceCategory(getPrefContext());
281            if (userInfo.isManagedProfile()) {
282                profileData.preferenceGroup.setLayoutResource(R.layout.work_profile_category);
283                profileData.preferenceGroup.setTitle(R.string.category_work);
284                String workGroupSummary = getWorkGroupSummary(context, userInfo);
285                profileData.preferenceGroup.setSummary(workGroupSummary);
286                ((AccessiblePreferenceCategory) profileData.preferenceGroup).setContentDescription(
287                        getString(R.string.accessibility_category_work, workGroupSummary));
288                profileData.removeWorkProfilePreference = newRemoveWorkProfilePreference(context);
289            } else {
290                profileData.preferenceGroup.setTitle(R.string.category_personal);
291                ((AccessiblePreferenceCategory) profileData.preferenceGroup).setContentDescription(
292                        getString(R.string.accessibility_category_personal));
293            }
294            parent.addPreference(profileData.preferenceGroup);
295        } else {
296            profileData.preferenceGroup = parent;
297        }
298        if (userInfo.isEnabled()) {
299            profileData.authenticatorHelper = new AuthenticatorHelper(context,
300                    userInfo.getUserHandle(), mUm, this);
301            if (!mUm.hasUserRestriction(DISALLOW_MODIFY_ACCOUNTS, userInfo.getUserHandle())) {
302                profileData.addAccountPreference = newAddAccountPreference(context);
303            }
304        }
305        mProfiles.put(userInfo.id, profileData);
306        Index.getInstance(getActivity()).updateFromClassNameResource(
307                AccountSettings.class.getName(), true, true);
308    }
309
310    private Preference newAddAccountPreference(Context context) {
311        Preference preference = new Preference(getPrefContext());
312        preference.setTitle(R.string.add_account_label);
313        preference.setIcon(R.drawable.ic_menu_add);
314        preference.setOnPreferenceClickListener(this);
315        preference.setOrder(ORDER_NEXT_TO_LAST);
316        return preference;
317    }
318
319    private Preference newRemoveWorkProfilePreference(Context context) {
320        Preference preference = new Preference(getPrefContext());
321        preference.setTitle(R.string.remove_managed_profile_label);
322        preference.setIcon(R.drawable.ic_menu_delete);
323        preference.setOnPreferenceClickListener(this);
324        preference.setOrder(ORDER_LAST);
325        return preference;
326    }
327
328    private String getWorkGroupSummary(Context context, UserInfo userInfo) {
329        PackageManager packageManager = context.getPackageManager();
330        ApplicationInfo adminApplicationInfo = Utils.getAdminApplicationInfo(context, userInfo.id);
331        if (adminApplicationInfo == null) {
332            return null;
333        }
334        CharSequence appLabel = packageManager.getApplicationLabel(adminApplicationInfo);
335        return getString(R.string.managing_admin, appLabel);
336    }
337
338    private void cleanUpPreferences() {
339        PreferenceScreen preferenceScreen = getPreferenceScreen();
340        if (preferenceScreen != null) {
341            preferenceScreen.removeAll();
342        }
343        mProfiles.clear();
344    }
345
346    private void listenToAccountUpdates() {
347        final int count = mProfiles.size();
348        for (int i = 0; i < count; i++) {
349            AuthenticatorHelper authenticatorHelper = mProfiles.valueAt(i).authenticatorHelper;
350            if (authenticatorHelper != null) {
351                authenticatorHelper.listenToAccountUpdates();
352            }
353        }
354    }
355
356    private void stopListeningToAccountUpdates() {
357        final int count = mProfiles.size();
358        for (int i = 0; i < count; i++) {
359            AuthenticatorHelper authenticatorHelper = mProfiles.valueAt(i).authenticatorHelper;
360            if (authenticatorHelper != null) {
361                authenticatorHelper.stopListeningToAccountUpdates();
362            }
363        }
364    }
365
366    private void updateAccountTypes(ProfileData profileData) {
367        profileData.preferenceGroup.removeAll();
368        if (profileData.userInfo.isEnabled()) {
369            final ArrayList<AccountPreference> preferences = getAccountTypePreferences(
370                    profileData.authenticatorHelper, profileData.userInfo.getUserHandle());
371            final int count = preferences.size();
372            for (int i = 0; i < count; i++) {
373                profileData.preferenceGroup.addPreference(preferences.get(i));
374            }
375            if (profileData.addAccountPreference != null) {
376                profileData.preferenceGroup.addPreference(profileData.addAccountPreference);
377            }
378        } else {
379            // Put a label instead of the accounts list
380            mProfileNotAvailablePreference.setEnabled(false);
381            mProfileNotAvailablePreference.setIcon(R.drawable.empty_icon);
382            mProfileNotAvailablePreference.setTitle(null);
383            mProfileNotAvailablePreference.setSummary(
384                    R.string.managed_profile_not_available_label);
385            profileData.preferenceGroup.addPreference(mProfileNotAvailablePreference);
386        }
387        if (profileData.removeWorkProfilePreference != null) {
388            profileData.preferenceGroup.addPreference(profileData.removeWorkProfilePreference);
389        }
390    }
391
392    private ArrayList<AccountPreference> getAccountTypePreferences(AuthenticatorHelper helper,
393            UserHandle userHandle) {
394        final String[] accountTypes = helper.getEnabledAccountTypes();
395        final ArrayList<AccountPreference> accountTypePreferences =
396                new ArrayList<AccountPreference>(accountTypes.length);
397
398        for (int i = 0; i < accountTypes.length; i++) {
399            final String accountType = accountTypes[i];
400            // Skip showing any account that does not have any of the requested authorities
401            if (!accountTypeHasAnyRequestedAuthorities(helper, accountType)) {
402                continue;
403            }
404            final CharSequence label = helper.getLabelForType(getActivity(), accountType);
405            if (label == null) {
406                continue;
407            }
408            final String titleResPackageName = helper.getPackageForType(accountType);
409            final int titleResId = helper.getLabelIdForType(accountType);
410
411            final Account[] accounts = AccountManager.get(getActivity())
412                    .getAccountsByTypeAsUser(accountType, userHandle);
413            final boolean skipToAccount = accounts.length == 1
414                    && !helper.hasAccountPreferences(accountType);
415
416            if (skipToAccount) {
417                final Bundle fragmentArguments = new Bundle();
418                fragmentArguments.putParcelable(AccountSyncSettings.ACCOUNT_KEY,
419                        accounts[0]);
420                fragmentArguments.putParcelable(EXTRA_USER, userHandle);
421
422                accountTypePreferences.add(new AccountPreference(getPrefContext(), label,
423                        titleResPackageName, titleResId, AccountSyncSettings.class.getName(),
424                        fragmentArguments,
425                        helper.getDrawableForType(getActivity(), accountType)));
426            } else {
427                final Bundle fragmentArguments = new Bundle();
428                fragmentArguments.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE, accountType);
429                fragmentArguments.putString(ManageAccountsSettings.KEY_ACCOUNT_LABEL,
430                        label.toString());
431                fragmentArguments.putParcelable(EXTRA_USER, userHandle);
432
433                accountTypePreferences.add(new AccountPreference(getPrefContext(), label,
434                        titleResPackageName, titleResId, ManageAccountsSettings.class.getName(),
435                        fragmentArguments,
436                        helper.getDrawableForType(getActivity(), accountType)));
437            }
438            helper.preloadDrawableForType(getActivity(), accountType);
439        }
440        // Sort by label
441        Collections.sort(accountTypePreferences, new Comparator<AccountPreference>() {
442            @Override
443            public int compare(AccountPreference t1, AccountPreference t2) {
444                return t1.mTitle.toString().compareTo(t2.mTitle.toString());
445            }
446        });
447        return accountTypePreferences;
448    }
449
450    private boolean accountTypeHasAnyRequestedAuthorities(AuthenticatorHelper helper,
451            String accountType) {
452        if (mAuthoritiesCount == 0) {
453            // No authorities required
454            return true;
455        }
456        final ArrayList<String> authoritiesForType = helper.getAuthoritiesForAccountType(
457                accountType);
458        if (authoritiesForType == null) {
459            Log.d(TAG, "No sync authorities for account type: " + accountType);
460            return false;
461        }
462        for (int j = 0; j < mAuthoritiesCount; j++) {
463            if (authoritiesForType.contains(mAuthorities[j])) {
464                return true;
465            }
466        }
467        return false;
468    }
469
470    private class AccountPreference extends Preference implements OnPreferenceClickListener {
471        /**
472         * Title of the tile that is shown to the user.
473         * @attr ref android.R.styleable#PreferenceHeader_title
474         */
475        private final CharSequence mTitle;
476
477        /**
478         * Packange name used to resolve the resources of the title shown to the user in the new
479         * fragment.
480         */
481        private final String mTitleResPackageName;
482
483        /**
484         * Resource id of the title shown to the user in the new fragment.
485         */
486        private final int mTitleResId;
487
488        /**
489         * Full class name of the fragment to display when this tile is
490         * selected.
491         * @attr ref android.R.styleable#PreferenceHeader_fragment
492         */
493        private final String mFragment;
494
495        /**
496         * Optional arguments to supply to the fragment when it is
497         * instantiated.
498         */
499        private final Bundle mFragmentArguments;
500
501        public AccountPreference(Context context, CharSequence title, String titleResPackageName,
502                int titleResId, String fragment, Bundle fragmentArguments,
503                Drawable icon) {
504            super(context);
505            mTitle = title;
506            mTitleResPackageName = titleResPackageName;
507            mTitleResId = titleResId;
508            mFragment = fragment;
509            mFragmentArguments = fragmentArguments;
510            setWidgetLayoutResource(R.layout.account_type_preference);
511
512            setTitle(title);
513            setIcon(icon);
514
515            setOnPreferenceClickListener(this);
516        }
517
518        @Override
519        public boolean onPreferenceClick(Preference preference) {
520            if (mFragment != null) {
521                Utils.startWithFragment(getContext(), mFragment, mFragmentArguments,
522                        null /* resultTo */, 0 /* resultRequestCode */, mTitleResPackageName,
523                        mTitleResId, null /* title */);
524                return true;
525            }
526            return false;
527        }
528    }
529
530    private class ManagedProfileBroadcastReceiver extends BroadcastReceiver {
531        private boolean listeningToManagedProfileEvents;
532
533        @Override
534        public void onReceive(Context context, Intent intent) {
535            if (intent.getAction().equals(Intent.ACTION_MANAGED_PROFILE_REMOVED)
536                    || intent.getAction().equals(Intent.ACTION_MANAGED_PROFILE_ADDED)) {
537                Log.v(TAG, "Received broadcast: " + intent.getAction());
538                // Clean old state
539                stopListeningToAccountUpdates();
540                cleanUpPreferences();
541                // Build new state
542                updateUi();
543                listenToAccountUpdates();
544                // Force the menu to update. Note that #onPrepareOptionsMenu uses data built by
545                // #updateUi so we must call this later
546                getActivity().invalidateOptionsMenu();
547                return;
548            }
549            Log.w(TAG, "Cannot handle received broadcast: " + intent.getAction());
550        }
551
552        public void register(Context context) {
553            if (!listeningToManagedProfileEvents) {
554                IntentFilter intentFilter = new IntentFilter();
555                intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
556                intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
557                context.registerReceiver(this, intentFilter);
558                listeningToManagedProfileEvents = true;
559            }
560        }
561
562        public void unregister(Context context) {
563            if (listeningToManagedProfileEvents) {
564                context.unregisterReceiver(this);
565                listeningToManagedProfileEvents = false;
566            }
567        }
568    }
569
570    private class MasterSyncStateClickListener implements MenuItem.OnMenuItemClickListener {
571        private final UserHandle mUserHandle;
572
573        public MasterSyncStateClickListener(UserHandle userHandle) {
574            mUserHandle = userHandle;
575        }
576
577        @Override
578        public boolean onMenuItemClick(MenuItem item) {
579            if (ActivityManager.isUserAMonkey()) {
580                Log.d(TAG, "ignoring monkey's attempt to flip sync state");
581            } else {
582                ConfirmAutoSyncChangeFragment.show(AccountSettings.this, !item.isChecked(),
583                        mUserHandle);
584            }
585            return true;
586        }
587    }
588
589    /**
590     * Dialog to inform user about changing auto-sync setting
591     */
592    public static class ConfirmAutoSyncChangeFragment extends DialogFragment {
593        private static final String SAVE_ENABLING = "enabling";
594        private static final String SAVE_USER_HANDLE = "userHandle";
595        private boolean mEnabling;
596        private UserHandle mUserHandle;
597
598        public static void show(AccountSettings parent, boolean enabling, UserHandle userHandle) {
599            if (!parent.isAdded()) return;
600
601            final ConfirmAutoSyncChangeFragment dialog = new ConfirmAutoSyncChangeFragment();
602            dialog.mEnabling = enabling;
603            dialog.mUserHandle = userHandle;
604            dialog.setTargetFragment(parent, 0);
605            dialog.show(parent.getFragmentManager(), TAG_CONFIRM_AUTO_SYNC_CHANGE);
606        }
607
608        @Override
609        public Dialog onCreateDialog(Bundle savedInstanceState) {
610            final Context context = getActivity();
611            if (savedInstanceState != null) {
612                mEnabling = savedInstanceState.getBoolean(SAVE_ENABLING);
613                mUserHandle = (UserHandle) savedInstanceState.getParcelable(SAVE_USER_HANDLE);
614            }
615
616            final AlertDialog.Builder builder = new AlertDialog.Builder(context);
617            if (!mEnabling) {
618                builder.setTitle(R.string.data_usage_auto_sync_off_dialog_title);
619                builder.setMessage(R.string.data_usage_auto_sync_off_dialog);
620            } else {
621                builder.setTitle(R.string.data_usage_auto_sync_on_dialog_title);
622                builder.setMessage(R.string.data_usage_auto_sync_on_dialog);
623            }
624
625            builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
626                @Override
627                public void onClick(DialogInterface dialog, int which) {
628                    ContentResolver.setMasterSyncAutomaticallyAsUser(mEnabling,
629                            mUserHandle.getIdentifier());
630                }
631            });
632            builder.setNegativeButton(android.R.string.cancel, null);
633
634            return builder.create();
635        }
636
637        @Override
638        public void onSaveInstanceState(Bundle outState) {
639            super.onSaveInstanceState(outState);
640            outState.putBoolean(SAVE_ENABLING, mEnabling);
641            outState.putParcelable(SAVE_USER_HANDLE, mUserHandle);
642        }
643    }
644
645    public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
646            new BaseSearchIndexProvider() {
647        @Override
648        public List<SearchIndexableResource> getXmlResourcesToIndex(
649                Context context, boolean enabled) {
650            final SearchIndexableResource sir = new SearchIndexableResource(context);
651            sir.xmlResId = R.xml.account_settings;
652            return Arrays.asList(sir);
653        }
654
655        @Override
656        public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
657            final List<SearchIndexableRaw> result = new ArrayList<SearchIndexableRaw>();
658            final Resources res = context.getResources();
659            final String screenTitle = res.getString(R.string.account_settings_title);
660
661            final UserManager um = UserManager.get(context);
662            List<UserInfo> profiles = um.getProfiles(UserHandle.myUserId());
663            final int profilesCount = profiles.size();
664            for (int i = 0; i < profilesCount; i++) {
665                UserInfo userInfo = profiles.get(i);
666                if (userInfo.isEnabled()) {
667                    if (!um.hasUserRestriction(
668                            DISALLOW_MODIFY_ACCOUNTS, userInfo.getUserHandle())) {
669                        SearchIndexableRaw data = new SearchIndexableRaw(context);
670                        data = new SearchIndexableRaw(context);
671                        data.title = res.getString(R.string.add_account_label);
672                        data.screenTitle = screenTitle;
673                        result.add(data);
674                    }
675                    if (userInfo.isManagedProfile()) {
676                        SearchIndexableRaw data = new SearchIndexableRaw(context);
677                        data = new SearchIndexableRaw(context);
678                        data.title = res.getString(R.string.remove_managed_profile_label);
679                        data.screenTitle = screenTitle;
680                        result.add(data);
681                    }
682                }
683            }
684            return result;
685        }
686    };
687}
688