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