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