Add work account settings.

Bug: 15467756
Change-Id: I13b5a0bb3967611d0d24b575bfc15d9bfaad4cfa
This commit is contained in:
Alexandra Gherghina
2014-06-04 10:02:55 +01:00
parent c0ac943eb6
commit 3939cd70b1
6 changed files with 351 additions and 144 deletions

View File

@@ -127,7 +127,8 @@ public class SettingsActivity extends Activity
PreferenceFragment.OnPreferenceStartFragmentCallback, PreferenceFragment.OnPreferenceStartFragmentCallback,
ButtonBarHandler, OnAccountsUpdateListener, FragmentManager.OnBackStackChangedListener, ButtonBarHandler, OnAccountsUpdateListener, FragmentManager.OnBackStackChangedListener,
SearchView.OnQueryTextListener, SearchView.OnCloseListener, SearchView.OnQueryTextListener, SearchView.OnCloseListener,
MenuItem.OnActionExpandListener { MenuItem.OnActionExpandListener,
AuthenticatorHelper.OnAccountsUpdateListener {
private static final String LOG_TAG = "Settings"; private static final String LOG_TAG = "Settings";
@@ -466,10 +467,13 @@ public class SettingsActivity extends Activity
if (intent.hasExtra(EXTRA_UI_OPTIONS)) { if (intent.hasExtra(EXTRA_UI_OPTIONS)) {
getWindow().setUiOptions(intent.getIntExtra(EXTRA_UI_OPTIONS, 0)); getWindow().setUiOptions(intent.getIntExtra(EXTRA_UI_OPTIONS, 0));
} }
// TODO: Delete accounts tile once we have the new screen working
mAuthenticatorHelper = new AuthenticatorHelper(); // See: http://b/15815948
final UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
mAuthenticatorHelper = new AuthenticatorHelper(
this, UserHandle.getCallingUserHandle(), um, this);
mAuthenticatorHelper.updateAuthDescriptions(this); mAuthenticatorHelper.updateAuthDescriptions(this);
mAuthenticatorHelper.onAccountsUpdated(this, null); mAuthenticatorHelper.onAccountsUpdated(null);
mDevelopmentPreferences = getSharedPreferences(DevelopmentSettings.PREF_FILE, mDevelopmentPreferences = getSharedPreferences(DevelopmentSettings.PREF_FILE,
Context.MODE_PRIVATE); Context.MODE_PRIVATE);
@@ -1263,7 +1267,11 @@ public class SettingsActivity extends Activity
public void onAccountsUpdated(Account[] accounts) { public void onAccountsUpdated(Account[] accounts) {
// TODO: watch for package upgrades to invalidate cache; see 7206643 // TODO: watch for package upgrades to invalidate cache; see 7206643
mAuthenticatorHelper.updateAuthDescriptions(this); mAuthenticatorHelper.updateAuthDescriptions(this);
mAuthenticatorHelper.onAccountsUpdated(this, accounts); invalidateCategories();
}
@Override
public void onAccountsUpdate(UserHandle userHandle) {
invalidateCategories(); invalidateCategories();
} }

View File

@@ -56,12 +56,14 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ListView; import android.widget.ListView;
import android.widget.TabWidget; import android.widget.TabWidget;
import com.android.settings.dashboard.DashboardCategory; import com.android.settings.dashboard.DashboardCategory;
import com.android.settings.dashboard.DashboardTile; import com.android.settings.dashboard.DashboardTile;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
@@ -579,4 +581,31 @@ public final class Utils {
intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_AS_SHORTCUT, isShortcut); intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_AS_SHORTCUT, isShortcut);
return intent; return intent;
} }
/**
* Returns the managed profile of the current user or null if none found.
*/
public static UserHandle getManagedProfile(UserManager userManager) {
List<UserHandle> userProfiles = userManager.getUserProfiles();
final int count = userProfiles.size();
for (int i = 0; i < count; i++) {
final UserHandle profile = userProfiles.get(i);
if (profile.getIdentifier() == userManager.getUserHandle()) {
continue;
}
final UserInfo userInfo = userManager.getUserInfo(profile.getIdentifier());
if (userInfo.isManagedProfile()) {
return profile;
}
}
return null;
}
/**
* Returns true if the current profile is a managed one.
*/
public static boolean isManagedProfile(UserManager userManager) {
UserInfo currentUser = userManager.getUserInfo(userManager.getUserHandle());
return currentUser.isManagedProfile();
}
} }

View File

@@ -16,19 +16,9 @@
package com.android.settings.accounts; package com.android.settings.accounts;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.android.settings.SettingsPreferenceFragment;
import com.google.android.collect.Maps; import com.google.android.collect.Maps;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AuthenticatorDescription; import android.accounts.AuthenticatorDescription;
import android.accounts.OnAccountsUpdateListener;
import android.app.Activity; import android.app.Activity;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
@@ -40,28 +30,47 @@ import android.content.res.Resources.Theme;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.UserHandle;
import android.os.UserManager;
import android.preference.PreferenceScreen; import android.preference.PreferenceScreen;
import android.text.format.DateFormat; import android.text.format.DateFormat;
import android.util.Log; import android.util.Log;
import android.view.ContextThemeWrapper; import android.view.ContextThemeWrapper;
import com.android.settings.SettingsPreferenceFragment;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
class AccountPreferenceBase extends SettingsPreferenceFragment class AccountPreferenceBase extends SettingsPreferenceFragment
implements OnAccountsUpdateListener { implements AuthenticatorHelper.OnAccountsUpdateListener {
protected static final String TAG = "AccountSettings"; protected static final String TAG = "AccountSettings";
public static final String AUTHORITIES_FILTER_KEY = "authorities"; public static final String AUTHORITIES_FILTER_KEY = "authorities";
public static final String ACCOUNT_TYPES_FILTER_KEY = "account_types"; public static final String ACCOUNT_TYPES_FILTER_KEY = "account_types";
private final Handler mHandler = new Handler(); private final Handler mHandler = new Handler();
private UserManager mUm;
private Object mStatusChangeListenerHandle; private Object mStatusChangeListenerHandle;
private HashMap<String, ArrayList<String>> mAccountTypeToAuthorities = null; private HashMap<String, ArrayList<String>> mAccountTypeToAuthorities = null;
private AuthenticatorHelper mAuthenticatorHelper = new AuthenticatorHelper(); protected AuthenticatorHelper mAuthenticatorHelper;
private java.text.DateFormat mDateFormat; private java.text.DateFormat mDateFormat;
private java.text.DateFormat mTimeFormat; private java.text.DateFormat mTimeFormat;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
// TODO: This needs to handle different users, get the user id from the intent
mUm = (UserManager) getSystemService(Context.USER_SERVICE);
mAuthenticatorHelper = new AuthenticatorHelper(
getActivity(), UserHandle.getCallingUserHandle(), mUm, this);
}
/** /**
* Overload to handle account updates. * Overload to handle account updates.
*/ */
public void onAccountsUpdated(Account[] accounts) { @Override
public void onAccountsUpdate(UserHandle userHandle) {
} }

View File

@@ -19,11 +19,17 @@ package com.android.settings.accounts;
import android.accounts.Account; import android.accounts.Account;
import android.accounts.AccountManager; import android.accounts.AccountManager;
import android.accounts.OnAccountsUpdateListener; import android.accounts.OnAccountsUpdateListener;
import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.UserInfo;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Bundle; import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.util.Log;
import android.util.SparseArray;
import android.preference.Preference; import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener; import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceGroup; import android.preference.PreferenceGroup;
@@ -33,16 +39,17 @@ import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils; import com.android.settings.Utils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.List;
/** /**
* Settings screen for the account types on the device. * Settings screen for the account types on the device.
* This shows all account types available for personal and work profiles. * This shows all account types available for personal and work profiles.
*/ */
public class AccountSettings extends SettingsPreferenceFragment public class AccountSettings extends SettingsPreferenceFragment
implements OnAccountsUpdateListener, OnPreferenceClickListener { implements AuthenticatorHelper.OnAccountsUpdateListener,
OnPreferenceClickListener {
public static final String TAG = "AccountSettings"; public static final String TAG = "AccountSettings";
private static final String KEY_ACCOUNT = "account"; private static final String KEY_ACCOUNT = "account";
@@ -51,128 +58,183 @@ public class AccountSettings extends SettingsPreferenceFragment
private static final String KEY_CATEGORY_PERSONAL = "account_personal"; private static final String KEY_CATEGORY_PERSONAL = "account_personal";
private static final String KEY_ADD_ACCOUNT_PERSONAL = "add_account_personal"; private static final String KEY_ADD_ACCOUNT_PERSONAL = "add_account_personal";
private static final String KEY_CATEGORY_WORK = "account_work"; private static final String KEY_CATEGORY_WORK = "account_work";
private static final String KEY_ADD_ACCOUNT_WORK = "add_account_work";
private AuthenticatorHelper mAuthenticatorHelper; private static final String ADD_ACCOUNT_ACTION = "android.settings.ADD_ACCOUNT_SETTINGS";
private boolean mListeningToAccountUpdates;
private PreferenceGroup mAccountTypesForUser;
private Preference mAddAccountForUser;
private UserManager mUm; private UserManager mUm;
private SparseArray<ProfileData> mProfiles;
private ManagedProfileBroadcastReceiver mManagedProfileBroadcastReceiver;
/**
* Holds data related to the accounts belonging to one profile.
*/
private static class ProfileData {
/**
* The preference that displays the accounts.
*/
public PreferenceGroup preferenceGroup;
/**
* The preference that displays the add account button.
*/
public Preference addAccountPreference;
/**
* The user handle of the user that these accounts belong to.
*/
public UserHandle userHandle;
/**
* The {@link AuthenticatorHelper} that holds accounts data for this profile.
*/
public AuthenticatorHelper authenticatorHelper;
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
mUm = (UserManager) getSystemService(Context.USER_SERVICE); mUm = (UserManager) getSystemService(Context.USER_SERVICE);
mProfiles = new SparseArray<ProfileData>(2);
updateUi();
}
mAuthenticatorHelper = new AuthenticatorHelper(); void updateUi() {
mAuthenticatorHelper.updateAuthDescriptions(getActivity());
mAuthenticatorHelper.onAccountsUpdated(getActivity(), null);
// Load the preferences from an XML resource // Load the preferences from an XML resource
addPreferencesFromResource(R.xml.account_settings); addPreferencesFromResource(R.xml.account_settings);
if(mUm.isLinkedUser()) { if(mUm.isLinkedUser()) {
// Restricted user or similar // Restricted user or similar
// TODO: Do we disallow modifying accounts for restricted profiles? updateSingleProfileUi();
mAccountTypesForUser = (PreferenceGroup) findPreference(KEY_ACCOUNT);
if (mUm.hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS)) {
removePreference(KEY_ADD_ACCOUNT);
} else {
mAddAccountForUser = findPreference(KEY_ADD_ACCOUNT);
mAddAccountForUser.setOnPreferenceClickListener(this);
}
removePreference(KEY_CATEGORY_PERSONAL);
removePreference(KEY_CATEGORY_WORK);
} else { } else {
mAccountTypesForUser = (PreferenceGroup) findPreference(KEY_CATEGORY_PERSONAL); if (Utils.isManagedProfile(mUm)) {
mAddAccountForUser = findPreference(KEY_ADD_ACCOUNT_PERSONAL); // This should not happen
mAddAccountForUser.setOnPreferenceClickListener(this); Log.w(TAG, "We should not be showing settings for a managed profile");
updateSingleProfileUi();
// TODO: Show the work accounts also }
// TODO: Handle the case where there is only one account final UserHandle currentProfile = UserHandle.getCallingUserHandle();
removePreference(KEY_CATEGORY_WORK); final UserHandle managedProfile = Utils.getManagedProfile(mUm);
removePreference(KEY_ADD_ACCOUNT); if (managedProfile == null) {
updateSingleProfileUi();
} else {
updateProfileUi(currentProfile,
KEY_CATEGORY_PERSONAL, KEY_ADD_ACCOUNT_PERSONAL, new ArrayList<String>());
final ArrayList<String> unusedPreferences = new ArrayList<String>(1);
unusedPreferences.add(KEY_ADD_ACCOUNT);
updateProfileUi(managedProfile,
KEY_CATEGORY_WORK, KEY_ADD_ACCOUNT_WORK, unusedPreferences);
mManagedProfileBroadcastReceiver = new ManagedProfileBroadcastReceiver();
mManagedProfileBroadcastReceiver.register(getActivity());
}
} }
updateAccountTypes(mAccountTypesForUser); final int count = mProfiles.size();
for (int i = 0; i < count; i++) {
updateAccountTypes(mProfiles.valueAt(i));
}
}
private void updateSingleProfileUi() {
final ArrayList<String> unusedPreferences = new ArrayList<String>(2);
unusedPreferences.add(KEY_CATEGORY_PERSONAL);
unusedPreferences.add(KEY_CATEGORY_WORK);
updateProfileUi(UserHandle.getCallingUserHandle(), KEY_ACCOUNT, KEY_ADD_ACCOUNT,
unusedPreferences);
}
private void updateProfileUi(UserHandle userHandle, String categoryKey, String addAccountKey,
ArrayList<String> unusedPreferences) {
final int count = unusedPreferences.size();
for (int i = 0; i < count; i++) {
removePreference(unusedPreferences.get(i));
}
final ProfileData profileData = new ProfileData();
profileData.preferenceGroup = (PreferenceGroup) findPreference(categoryKey);
if (mUm.hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS)) {
removePreference(addAccountKey);
} else {
profileData.addAccountPreference = findPreference(addAccountKey);
profileData.addAccountPreference.setOnPreferenceClickListener(this);
}
profileData.userHandle = userHandle;
profileData.authenticatorHelper = new AuthenticatorHelper(
getActivity(), userHandle, mUm, this);
mProfiles.put(userHandle.getIdentifier(), profileData);
profileData.authenticatorHelper.listenToAccountUpdates();
} }
@Override @Override
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
stopListeningToAccountUpdates(); cleanUp();
}
void cleanUp() {
if (mManagedProfileBroadcastReceiver != null) {
mManagedProfileBroadcastReceiver.unregister(getActivity());
}
final int count = mProfiles.size();
for (int i = 0; i < count; i++) {
mProfiles.valueAt(i).authenticatorHelper.stopListeningToAccountUpdates();
}
} }
@Override @Override
public void onAccountsUpdated(Account[] accounts) { public void onAccountsUpdate(UserHandle userHandle) {
// TODO: watch for package upgrades to invalidate cache; see 7206643 final ProfileData profileData = mProfiles.get(userHandle.getIdentifier());
mAuthenticatorHelper.updateAuthDescriptions(getActivity()); if (profileData != null) {
mAuthenticatorHelper.onAccountsUpdated(getActivity(), accounts); updateAccountTypes(profileData);
listenToAccountUpdates(); } else {
updateAccountTypes(mAccountTypesForUser); Log.w(TAG, "Missing Settings screen for: " + userHandle.getIdentifier());
}
@Override
public boolean onPreferenceClick(Preference preference) {
// Check the preference
if (preference == mAddAccountForUser) {
Intent intent = new Intent("android.settings.ADD_ACCOUNT_SETTINGS");
startActivity(intent);
return true;
}
return false;
}
private void updateAccountTypes(PreferenceGroup preferenceGroup) {
preferenceGroup.removeAll();
preferenceGroup.setOrderingAsAdded(true);
for (AccountPreference preference : getAccountTypePreferences()) {
preferenceGroup.addPreference(preference);
}
if (mAddAccountForUser != null) {
preferenceGroup.addPreference(mAddAccountForUser);
} }
} }
private List<AccountPreference> getAccountTypePreferences() { private void updateAccountTypes(ProfileData profileData) {
String[] accountTypes = mAuthenticatorHelper.getEnabledAccountTypes(); profileData.preferenceGroup.removeAll();
List<AccountPreference> accountTypePreferences = final ArrayList<AccountPreference> preferences = getAccountTypePreferences(
profileData.authenticatorHelper);
final int count = preferences.size();
for (int i = 0; i < count; i++) {
profileData.preferenceGroup.addPreference(preferences.get(i));
}
if (profileData.addAccountPreference != null) {
profileData.preferenceGroup.addPreference(profileData.addAccountPreference);
}
}
private ArrayList<AccountPreference> getAccountTypePreferences(AuthenticatorHelper helper) {
final String[] accountTypes = helper.getEnabledAccountTypes();
final ArrayList<AccountPreference> accountTypePreferences =
new ArrayList<AccountPreference>(accountTypes.length); new ArrayList<AccountPreference>(accountTypes.length);
for (String accountType : accountTypes) {
CharSequence label = mAuthenticatorHelper.getLabelForType(getActivity(), accountType); for (int i = 0; i < accountTypes.length; i++) {
final String accountType = accountTypes[i];
final CharSequence label = helper.getLabelForType(getActivity(), accountType);
if (label == null) { if (label == null) {
continue; continue;
} }
Account[] accounts = AccountManager.get(getActivity()).getAccountsByType(accountType); final Account[] accounts = AccountManager.get(getActivity())
boolean skipToAccount = accounts.length == 1 .getAccountsByType(accountType);
&& !mAuthenticatorHelper.hasAccountPreferences(accountType); final boolean skipToAccount = accounts.length == 1
&& !helper.hasAccountPreferences(accountType);
if (skipToAccount) { if (skipToAccount) {
Bundle fragmentArguments = new Bundle(); final Bundle fragmentArguments = new Bundle();
fragmentArguments.putParcelable(AccountSyncSettings.ACCOUNT_KEY, fragmentArguments.putParcelable(AccountSyncSettings.ACCOUNT_KEY,
accounts[0]); accounts[0]);
accountTypePreferences.add(new AccountPreference( accountTypePreferences.add(new AccountPreference(getActivity(), label,
getActivity(), AccountSyncSettings.class.getName(), fragmentArguments,
label, helper.getDrawableForType(getActivity(), accountType)));
accountType,
AccountSyncSettings.class.getName(),
fragmentArguments));
} else { } else {
Bundle fragmentArguments = new Bundle(); final Bundle fragmentArguments = new Bundle();
fragmentArguments.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE, accountType); fragmentArguments.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE, accountType);
fragmentArguments.putString(ManageAccountsSettings.KEY_ACCOUNT_LABEL, fragmentArguments.putString(ManageAccountsSettings.KEY_ACCOUNT_LABEL,
label.toString()); label.toString());
accountTypePreferences.add(new AccountPreference( accountTypePreferences.add(new AccountPreference(getActivity(), label,
getActivity(), ManageAccountsSettings.class.getName(), fragmentArguments,
label, helper.getDrawableForType(getActivity(), accountType)));
accountType,
ManageAccountsSettings.class.getName(),
fragmentArguments));
} }
mAuthenticatorHelper.preloadDrawableForType(getActivity(), accountType); helper.preloadDrawableForType(getActivity(), accountType);
} }
// Sort by label // Sort by label
Collections.sort(accountTypePreferences, new Comparator<AccountPreference>() { Collections.sort(accountTypePreferences, new Comparator<AccountPreference>() {
@@ -184,18 +246,20 @@ public class AccountSettings extends SettingsPreferenceFragment
return accountTypePreferences; return accountTypePreferences;
} }
private void listenToAccountUpdates() { @Override
if (!mListeningToAccountUpdates) { public boolean onPreferenceClick(Preference preference) {
AccountManager.get(getActivity()).addOnAccountsUpdatedListener(this, null, true); // Check the preference
mListeningToAccountUpdates = true; final int count = mProfiles.size();
} for (int i = 0; i < count; i++) {
} ProfileData profileData = mProfiles.valueAt(i);
if (preference == profileData.addAccountPreference) {
private void stopListeningToAccountUpdates() { Intent intent = new Intent(ADD_ACCOUNT_ACTION);
if (mListeningToAccountUpdates) { intent.putExtra(Intent.EXTRA_USER_HANDLE, profileData.userHandle);
AccountManager.get(getActivity()).removeOnAccountsUpdatedListener(this); startActivity(intent);
mListeningToAccountUpdates = false; return true;
}
} }
return false;
} }
private class AccountPreference extends Preference implements OnPreferenceClickListener { private class AccountPreference extends Preference implements OnPreferenceClickListener {
@@ -218,18 +282,16 @@ public class AccountSettings extends SettingsPreferenceFragment
*/ */
private final Bundle mFragmentArguments; private final Bundle mFragmentArguments;
public AccountPreference(Context context, CharSequence title, String fragment,
public AccountPreference(Context context, CharSequence title, Bundle fragmentArguments, Drawable icon) {
String accountType, String fragment, Bundle fragmentArguments) {
super(context); super(context);
mTitle = title; mTitle = title;
mFragment = fragment; mFragment = fragment;
mFragmentArguments = fragmentArguments; mFragmentArguments = fragmentArguments;
setWidgetLayoutResource(R.layout.account_type_preference); setWidgetLayoutResource(R.layout.account_type_preference);
Drawable drawable = mAuthenticatorHelper.getDrawableForType(context, accountType);
setTitle(title); setTitle(title);
setIcon(drawable); setIcon(icon);
setOnPreferenceClickListener(this); setOnPreferenceClickListener(this);
} }
@@ -244,6 +306,39 @@ public class AccountSettings extends SettingsPreferenceFragment
return false; return false;
} }
} }
private class ManagedProfileBroadcastReceiver extends BroadcastReceiver {
private boolean listeningToManagedProfileEvents;
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_MANAGED_PROFILE_REMOVED)
|| intent.getAction().equals(Intent.ACTION_MANAGED_PROFILE_ADDED)) {
Log.v(TAG, "Received broadcast: " + intent.getAction());
cleanUp();
updateUi();
return;
}
Log.w(TAG, "Cannot handle received broadcast: " + intent.getAction());
}
public void register(Context context) {
if (!listeningToManagedProfileEvents) {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
context.registerReceiver(this, intentFilter);
listeningToManagedProfileEvents = true;
}
}
public void unregister(Context context) {
if (listeningToManagedProfileEvents) {
context.unregisterReceiver(this);
listeningToManagedProfileEvents = false;
}
}
}
// TODO Implement a {@link SearchIndexProvider} to allow Indexing and Search of account types // TODO Implement a {@link SearchIndexProvider} to allow Indexing and Search of account types
// See http://b/15403806 // See http://b/15403806
} }

View File

@@ -16,13 +16,15 @@
package com.android.settings.accounts; package com.android.settings.accounts;
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
import android.accounts.Account; import android.accounts.Account;
import android.accounts.AccountManager; import android.accounts.AccountManager;
import android.accounts.AccountManagerCallback; import android.accounts.AccountManagerCallback;
import android.accounts.AccountManagerFuture; import android.accounts.AccountManagerFuture;
import android.accounts.AuthenticatorException; import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException; import android.accounts.OperationCanceledException;
import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Dialog; import android.app.Dialog;
import android.content.ContentResolver; import android.content.ContentResolver;
@@ -34,6 +36,7 @@ import android.content.SyncStatusInfo;
import android.content.pm.ProviderInfo; import android.content.pm.ProviderInfo;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.os.Bundle; import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.preference.Preference; import android.preference.Preference;
import android.preference.PreferenceScreen; import android.preference.PreferenceScreen;
@@ -51,8 +54,6 @@ import android.widget.TextView;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.Utils; import com.android.settings.Utils;
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@@ -193,10 +194,9 @@ public class AccountSyncSettings extends AccountPreferenceBase {
@Override @Override
public void onResume() { public void onResume() {
final Activity activity = getActivity(); mAuthenticatorHelper.listenToAccountUpdates();
AccountManager.get(activity).addOnAccountsUpdatedListener(this, null, false);
updateAuthDescriptions(); updateAuthDescriptions();
onAccountsUpdated(AccountManager.get(activity).getAccounts()); onAccountsUpdate(UserHandle.getCallingUserHandle());
super.onResume(); super.onResume();
} }
@@ -204,7 +204,7 @@ public class AccountSyncSettings extends AccountPreferenceBase {
@Override @Override
public void onPause() { public void onPause() {
super.onPause(); super.onPause();
AccountManager.get(getActivity()).removeOnAccountsUpdatedListener(this); mAuthenticatorHelper.stopListeningToAccountUpdates();
} }
private void addSyncStateCheckBox(Account account, String authority) { private void addSyncStateCheckBox(Account account, String authority) {
@@ -436,10 +436,10 @@ public class AccountSyncSettings extends AccountPreferenceBase {
} }
@Override @Override
public void onAccountsUpdated(Account[] accounts) { public void onAccountsUpdate(final UserHandle userHandle) {
super.onAccountsUpdated(accounts); super.onAccountsUpdate(userHandle);
mAccounts = accounts; mAccounts = AccountManager.get(getActivity()).getAccounts();
updateAccountCheckboxes(accounts); updateAccountCheckboxes(mAccounts);
onSyncStateUpdated(); onSyncStateUpdated();
} }

View File

@@ -19,27 +19,58 @@ package com.android.settings.accounts;
import android.accounts.Account; import android.accounts.Account;
import android.accounts.AccountManager; import android.accounts.AccountManager;
import android.accounts.AuthenticatorDescription; import android.accounts.AuthenticatorDescription;
import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log; import android.util.Log;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
public class AuthenticatorHelper { /**
* Helper class for monitoring accounts on the device for a given user.
*
* Classes using this helper should implement {@link OnAccountsUpdateListener}.
* {@link OnAccountsUpdateListener#onAccountsUpdate(UserHandle)} will then be
* called once accounts get updated. For setting up listening for account
* updates, {@link #listenToAccountUpdates()} and
* {@link #stopListeningToAccountUpdates()} should be used.
*/
final public class AuthenticatorHelper extends BroadcastReceiver {
private static final String TAG = "AuthenticatorHelper"; private static final String TAG = "AuthenticatorHelper";
private Map<String, AuthenticatorDescription> mTypeToAuthDescription private Map<String, AuthenticatorDescription> mTypeToAuthDescription
= new HashMap<String, AuthenticatorDescription>(); = new HashMap<String, AuthenticatorDescription>();
private AuthenticatorDescription[] mAuthDescs; private AuthenticatorDescription[] mAuthDescs;
private ArrayList<String> mEnabledAccountTypes = new ArrayList<String>(); private ArrayList<String> mEnabledAccountTypes = new ArrayList<String>();
private Map<String, Drawable> mAccTypeIconCache = new HashMap<String, Drawable>(); private Map<String, Drawable> mAccTypeIconCache = new HashMap<String, Drawable>();
public AuthenticatorHelper() { private final UserHandle mUserHandle;
private final UserManager mUm;
private final Context mContext;
private final OnAccountsUpdateListener mListener;
private boolean mListeningToAccountUpdates;
public interface OnAccountsUpdateListener {
void onAccountsUpdate(UserHandle userHandle);
}
public AuthenticatorHelper(Context context, UserHandle userHandle, UserManager userManager,
OnAccountsUpdateListener listener) {
mContext = context;
mUm = userManager;
mUserHandle = userHandle;
mListener = listener;
// This guarantees that the helper is ready to use once constructed
onAccountsUpdated(null);
} }
public String[] getEnabledAccountTypes() { public String[] getEnabledAccountTypes() {
@@ -72,7 +103,8 @@ public class AuthenticatorHelper {
try { try {
AuthenticatorDescription desc = mTypeToAuthDescription.get(accountType); AuthenticatorDescription desc = mTypeToAuthDescription.get(accountType);
Context authContext = context.createPackageContext(desc.packageName, 0); Context authContext = context.createPackageContext(desc.packageName, 0);
icon = authContext.getResources().getDrawable(desc.iconId); icon = mUm.getBadgedDrawableForUser(
authContext.getResources().getDrawable(desc.iconId), mUserHandle);
synchronized (mAccTypeIconCache) { synchronized (mAccTypeIconCache) {
mAccTypeIconCache.put(accountType, icon); mAccTypeIconCache.put(accountType, icon);
} }
@@ -112,25 +144,13 @@ public class AuthenticatorHelper {
* and update any UI that depends on AuthenticatorDescriptions in onAuthDescriptionsUpdated(). * and update any UI that depends on AuthenticatorDescriptions in onAuthDescriptionsUpdated().
*/ */
public void updateAuthDescriptions(Context context) { public void updateAuthDescriptions(Context context) {
mAuthDescs = AccountManager.get(context).getAuthenticatorTypes(); mAuthDescs = AccountManager.get(context)
.getAuthenticatorTypesAsUser(mUserHandle.getIdentifier());
for (int i = 0; i < mAuthDescs.length; i++) { for (int i = 0; i < mAuthDescs.length; i++) {
mTypeToAuthDescription.put(mAuthDescs[i].type, mAuthDescs[i]); mTypeToAuthDescription.put(mAuthDescs[i].type, mAuthDescs[i]);
} }
} }
public void onAccountsUpdated(Context context, Account[] accounts) {
if (accounts == null) {
accounts = AccountManager.get(context).getAccounts();
}
mEnabledAccountTypes.clear();
mAccTypeIconCache.clear();
for (Account account: accounts) {
if (!mEnabledAccountTypes.contains(account.type)) {
mEnabledAccountTypes.add(account.type);
}
}
}
public boolean containsAccountType(String accountType) { public boolean containsAccountType(String accountType) {
return mTypeToAuthDescription.containsKey(accountType); return mTypeToAuthDescription.containsKey(accountType);
} }
@@ -148,4 +168,50 @@ public class AuthenticatorHelper {
} }
return false; return false;
} }
public void onAccountsUpdated(Account[] accounts) {
// TODO: Revert to non-public once no longer needed in SettingsActivity
// See http://b/15819268
updateAuthDescriptions(mContext);
if (accounts == null) {
accounts = AccountManager.get(mContext).getAccounts();
}
mEnabledAccountTypes.clear();
mAccTypeIconCache.clear();
for (int i = 0; i < accounts.length; i++) {
final Account account = accounts[i];
if (!mEnabledAccountTypes.contains(account.type)) {
mEnabledAccountTypes.add(account.type);
}
}
if (mListeningToAccountUpdates) {
mListener.onAccountsUpdate(mUserHandle);
}
}
@Override
public void onReceive(final Context context, final Intent intent) {
final Account[] accounts = AccountManager.get(mContext)
.getAccountsAsUser(mUserHandle.getIdentifier());
onAccountsUpdated(accounts);
}
public void listenToAccountUpdates() {
if (!mListeningToAccountUpdates) {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION);
// At disk full, certain actions are blocked (such as writing the accounts to storage).
// It is useful to also listen for recovery from disk full to avoid bugs.
intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_OK);
mContext.registerReceiverAsUser(this, mUserHandle, intentFilter, null, null);
mListeningToAccountUpdates = true;
}
}
public void stopListeningToAccountUpdates() {
if (mListeningToAccountUpdates) {
mContext.unregisterReceiver(this);
mListeningToAccountUpdates = false;
}
}
} }