Show managed profile under accounts rather than users

Also fixes overflow menu to update on remove/add managed profile.

Bug: 16234745
Bug: 16727076
Change-Id: I3283a8fa0096edfce5aad633e09ba3eed6d2174c
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 5b0950a..d745cb2 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4559,6 +4559,10 @@
     <string name="sync_is_failing">Sync is currently experiencing problems. It will be back shortly.</string>
     <!-- Button label to add an account [CHAR LIMIT=20] -->
     <string name="add_account_label">Add account</string>
+    <!-- Label for the state of the managed profile [CHAR LIMIT=80] -->
+    <string name="managed_profile_not_available_label">Work profile is not available yet</string>
+    <!-- Button label to remove the work profile [CHAR LIMIT=35] -->
+    <string name="remove_managed_profile_label">Remove work profile</string>
     <!-- Data synchronization settings screen, title of setting that controls whether background data should be used [CHAR LIMIT=30] -->
     <string name="background_data">Background data</string>
     <!-- Data synchronization settings screen, summary of setting that controls whether background data should be used [CHAR LIMIT=60] -->
@@ -5160,8 +5164,6 @@
     <string name="user_summary_restricted_profile">Restricted profile</string>
     <!-- User settings summary for a managed profile [CHAR LIMIT=50] -->
     <string name="user_summary_managed_profile">Managed profile</string>
-    <!-- User settings summary for an inactive managed profile [CHAR LIMIT=50] -->
-    <string name="user_summary_managed_profile_not_enabled">Managed profile (currently inactive)</string>
     <!-- User settings warning that restricted profile needs a screen lock [CHAR LIMIT=NONE] -->
     <string name="user_need_lock_message">Before you can create a restricted profile, you\'ll need to set up a screen lock to protect your apps and personal data.</string>
     <!-- User settings dialog button to set screen lock [CHAR LIMIT=25] -->
diff --git a/res/xml/account_settings.xml b/res/xml/account_settings.xml
index 7437b80..33f61a2 100644
--- a/res/xml/account_settings.xml
+++ b/res/xml/account_settings.xml
@@ -19,35 +19,4 @@
         android:key="account"
         android:title="@string/account_settings_title"
         settings:keywords="@string/keywords_accounts">
-
-        <Preference
-            android:key="add_account"
-            android:title="@string/add_account_label"
-            android:icon="@drawable/ic_menu_add_dark"
-            android:order="2147483648" />
-
-        <PreferenceCategory
-            android:key="account_personal"
-            android:title="@string/category_personal" >
-
-                <Preference
-                    android:key="add_account_personal"
-                    android:title="@string/add_account_label"
-                    android:icon="@drawable/ic_menu_add_dark"
-                    android:order="2147483648" />
-
-        </PreferenceCategory>
-
-        <PreferenceCategory
-            android:key="account_work"
-            android:title="@string/category_work" >
-
-                <Preference
-                    android:key="add_account_work"
-                    android:title="@string/add_account_label"
-                    android:icon="@drawable/ic_menu_add_dark"
-                    android:order="2147483648" />
-
-        </PreferenceCategory>
-
 </PreferenceScreen>
diff --git a/src/com/android/settings/accounts/AccountSettings.java b/src/com/android/settings/accounts/AccountSettings.java
index ffd6037..2eb89b0 100644
--- a/src/com/android/settings/accounts/AccountSettings.java
+++ b/src/com/android/settings/accounts/AccountSettings.java
@@ -29,10 +29,15 @@
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.UserInfo;
 import android.graphics.drawable.Drawable;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.BitmapDrawable;
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.os.Process;
 import android.util.Log;
 import android.util.SparseArray;
 import android.view.Menu;
@@ -41,6 +46,7 @@
 import android.preference.Preference;
 import android.preference.Preference.OnPreferenceClickListener;
 import android.preference.PreferenceGroup;
+import android.preference.PreferenceCategory;
 import android.preference.PreferenceScreen;
 
 import com.android.settings.R;
@@ -50,8 +56,10 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.List;
 
 import static android.content.Intent.EXTRA_USER;
+import static android.os.UserManager.DISALLOW_MODIFY_ACCOUNTS;
 
 /**
  * Settings screen for the account types on the device.
@@ -64,26 +72,20 @@
         implements AuthenticatorHelper.OnAccountsUpdateListener,
         OnPreferenceClickListener {
     public static final String TAG = "AccountSettings";
-    private static final String KEY_ACCOUNT = "account";
-    private static final String KEY_ADD_ACCOUNT = "add_account";
 
-    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_CATEGORY_WORK = "account_work";
-    private static final String KEY_ADD_ACCOUNT_WORK = "add_account_work";
+    private static final String KEY_ACCOUNT = "account";
 
     private static final String ADD_ACCOUNT_ACTION = "android.settings.ADD_ACCOUNT_SETTINGS";
-
-    private static final ArrayList<String> EMPTY_LIST = new ArrayList<String>();
-
     private static final String TAG_CONFIRM_AUTO_SYNC_CHANGE = "confirmAutoSyncChange";
 
+    private static final int ORDER_LAST = 1001;
+    private static final int ORDER_NEXT_TO_LAST = 1000;
 
     private UserManager mUm;
-    private SparseArray<ProfileData> mProfiles;
+    private SparseArray<ProfileData> mProfiles = new SparseArray<ProfileData>();
     private ManagedProfileBroadcastReceiver mManagedProfileBroadcastReceiver
                 = new ManagedProfileBroadcastReceiver();
-    private boolean mIsSingleProfileUi = true;
+    private Preference mProfileNotAvailablePreference;
 
     /**
      * Holds data related to the accounts belonging to one profile.
@@ -98,64 +100,59 @@
          */
         public Preference addAccountPreference;
         /**
-         * The user handle of the user that these accounts belong to.
+         * The preference that displays the button to remove the managed profile
          */
-        public UserHandle userHandle;
+        public Preference removeWorkProfilePreference;
         /**
          * The {@link AuthenticatorHelper} that holds accounts data for this profile.
          */
         public AuthenticatorHelper authenticatorHelper;
+        /**
+         * The {@link UserInfo} of the profile.
+         */
+        public UserInfo userInfo;
     }
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         mUm = (UserManager) getSystemService(Context.USER_SERVICE);
-        mProfiles = new SparseArray<ProfileData>(2);
         setHasOptionsMenu(true);
     }
 
     @Override
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
         inflater.inflate(R.menu.account_settings, menu);
-        final UserHandle currentProfile = UserHandle.getCallingUserHandle();
-        if (mIsSingleProfileUi) {
-            menu.findItem(R.id.account_settings_menu_auto_sync)
-                    .setVisible(true)
-                    .setOnMenuItemClickListener(new MasterSyncStateClickListener(currentProfile));
-            menu.removeItem(R.id.account_settings_menu_auto_sync_personal);
-            menu.removeItem(R.id.account_settings_menu_auto_sync_work);
-        } else {
-            final UserHandle managedProfile = Utils.getManagedProfile(mUm);
-
-            menu.findItem(R.id.account_settings_menu_auto_sync_personal)
-                    .setVisible(true)
-                    .setOnMenuItemClickListener(new MasterSyncStateClickListener(currentProfile));
-            menu.findItem(R.id.account_settings_menu_auto_sync_work)
-                    .setVisible(true)
-                    .setOnMenuItemClickListener(new MasterSyncStateClickListener(managedProfile));
-            menu.removeItem(R.id.account_settings_menu_auto_sync);
-        }
         super.onCreateOptionsMenu(menu, inflater);
     }
 
     @Override
     public void onPrepareOptionsMenu(Menu menu) {
-        final UserHandle currentProfile = UserHandle.getCallingUserHandle();
-        if (mIsSingleProfileUi) {
+        final UserHandle currentProfile = Process.myUserHandle();
+        if (mProfiles.size() == 1) {
             menu.findItem(R.id.account_settings_menu_auto_sync)
+                    .setVisible(true)
+                    .setOnMenuItemClickListener(new MasterSyncStateClickListener(currentProfile))
                     .setChecked(ContentResolver.getMasterSyncAutomaticallyAsUser(
                             currentProfile.getIdentifier()));
+            menu.findItem(R.id.account_settings_menu_auto_sync_personal).setVisible(false);
+            menu.findItem(R.id.account_settings_menu_auto_sync_work).setVisible(false);
         } else {
-            final UserHandle managedProfile = Utils.getManagedProfile(mUm);
+            // We assume there's only one managed profile, otherwise UI needs to change
+            final UserHandle managedProfile = mProfiles.valueAt(1).userInfo.getUserHandle();
 
             menu.findItem(R.id.account_settings_menu_auto_sync_personal)
+                    .setVisible(true)
+                    .setOnMenuItemClickListener(new MasterSyncStateClickListener(currentProfile))
                     .setChecked(ContentResolver.getMasterSyncAutomaticallyAsUser(
                             currentProfile.getIdentifier()));
             menu.findItem(R.id.account_settings_menu_auto_sync_work)
+                    .setVisible(true)
+                    .setOnMenuItemClickListener(new MasterSyncStateClickListener(managedProfile))
                     .setChecked(ContentResolver.getMasterSyncAutomaticallyAsUser(
                             managedProfile.getIdentifier()));
-            }
+            menu.findItem(R.id.account_settings_menu_auto_sync).setVisible(false);
+         }
     }
 
     @Override
@@ -192,10 +189,22 @@
             ProfileData profileData = mProfiles.valueAt(i);
             if (preference == profileData.addAccountPreference) {
                 Intent intent = new Intent(ADD_ACCOUNT_ACTION);
-                intent.putExtra(EXTRA_USER, profileData.userHandle);
+                intent.putExtra(EXTRA_USER, profileData.userInfo.getUserHandle());
                 startActivity(intent);
                 return true;
             }
+            if (preference == profileData.removeWorkProfilePreference) {
+                final int userId = profileData.userInfo.id;
+                Utils.createRemoveConfirmationDialog(getActivity(), userId,
+                        new DialogInterface.OnClickListener() {
+                            @Override
+                            public void onClick(DialogInterface dialog, int which) {
+                                mUm.removeUser(userId);
+                            }
+                        }
+                ).show();
+                return true;
+            }
         }
         return false;
     }
@@ -204,61 +213,82 @@
         // Load the preferences from an XML resource
         addPreferencesFromResource(R.xml.account_settings);
 
+        if (Utils.isManagedProfile(mUm)) {
+            // This should not happen
+            Log.e(TAG, "We should not be showing settings for a managed profile");
+            finish();
+            return;
+        }
+
+        final PreferenceScreen preferenceScreen = (PreferenceScreen) findPreference(KEY_ACCOUNT);
         if(mUm.isLinkedUser()) {
             // Restricted user or similar
-            updateSingleProfileUi();
+            UserInfo userInfo = mUm.getUserInfo(UserHandle.myUserId());
+            updateProfileUi(userInfo, false /* no category needed */, preferenceScreen);
         } else {
-            if (Utils.isManagedProfile(mUm)) {
-                // This should not happen
-                Log.w(TAG, "We should not be showing settings for a managed profile");
-                updateSingleProfileUi();
-            }
-            final UserHandle currentProfile = UserHandle.getCallingUserHandle();
-            final UserHandle managedProfile = Utils.getManagedProfile(mUm);
-            if (managedProfile == null) {
-                updateSingleProfileUi();
-            } else {
-                mIsSingleProfileUi = false;
-                updateProfileUi(currentProfile, KEY_CATEGORY_PERSONAL, KEY_ADD_ACCOUNT_PERSONAL,
-                        EMPTY_LIST);
-                final ArrayList<String> unusedPreferences = new ArrayList<String>(2);
-                unusedPreferences.add(KEY_ADD_ACCOUNT);
-                updateProfileUi(managedProfile, KEY_CATEGORY_WORK, KEY_ADD_ACCOUNT_WORK,
-                        unusedPreferences);
+            List<UserInfo> profiles = mUm.getProfiles(UserHandle.myUserId());
+            final int profilesCount = profiles.size();
+            final boolean addCategory = profilesCount > 1;
+            for (int i = 0; i < profilesCount; i++) {
+                updateProfileUi(profiles.get(i), addCategory, preferenceScreen);
             }
         }
-        final int count = mProfiles.size();
-        for (int i = 0; i < count; i++) {
-            updateAccountTypes(mProfiles.valueAt(i));
+
+        // Add all preferences, starting with one for the primary profile.
+        // Note that we're relying on the ordering given by the SparseArray keys, and on the
+        // value of UserHandle.USER_OWNER being smaller than all the rest.
+        final int profilesCount = mProfiles.size();
+        for (int i = 0; i < profilesCount; i++) {
+            ProfileData profileData = mProfiles.valueAt(i);
+            if (!profileData.preferenceGroup.equals(preferenceScreen)) {
+                preferenceScreen.addPreference(profileData.preferenceGroup);
+            }
+            updateAccountTypes(profileData);
         }
     }
 
-    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(final 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));
-        }
+    private void updateProfileUi(final UserInfo userInfo, boolean addCategory,
+            PreferenceScreen parent) {
+        final Context context = getActivity();
         final ProfileData profileData = new ProfileData();
-        profileData.preferenceGroup = (PreferenceGroup) findPreference(categoryKey);
-        if (mUm.hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, userHandle)) {
-            removePreference(addAccountKey);
+        profileData.userInfo = userInfo;
+        if (addCategory) {
+            profileData.preferenceGroup = new PreferenceCategory(context);
+            profileData.preferenceGroup.setTitle(userInfo.isManagedProfile()
+                    ? R.string.category_work : R.string.category_personal);
+            parent.addPreference(profileData.preferenceGroup);
         } else {
-            profileData.addAccountPreference = findPreference(addAccountKey);
-            profileData.addAccountPreference.setOnPreferenceClickListener(this);
+            profileData.preferenceGroup = parent;
         }
-        profileData.userHandle = userHandle;
-        profileData.authenticatorHelper = new AuthenticatorHelper(
-                getActivity(), userHandle, mUm, this);
-        mProfiles.put(userHandle.getIdentifier(), profileData);
+        if (userInfo.isEnabled()) {
+            profileData.authenticatorHelper = new AuthenticatorHelper(context,
+                    userInfo.getUserHandle(), mUm, this);
+            if (!mUm.hasUserRestriction(DISALLOW_MODIFY_ACCOUNTS, userInfo.getUserHandle())) {
+                profileData.addAccountPreference = newAddAccountPreference(context);
+            }
+        }
+        if (userInfo.isManagedProfile()) {
+            profileData.removeWorkProfilePreference = newRemoveWorkProfilePreference(context);
+        }
+        mProfiles.put(userInfo.id, profileData);
+    }
+
+    private Preference newAddAccountPreference(Context context) {
+        Preference preference = new Preference(context);
+        preference.setTitle(R.string.add_account_label);
+        preference.setIcon(R.drawable.ic_menu_add_dark);
+        preference.setOnPreferenceClickListener(this);
+        preference.setOrder(ORDER_NEXT_TO_LAST);
+        return preference;
+    }
+
+    private Preference newRemoveWorkProfilePreference(Context context) {
+        Preference preference = new Preference(context);
+        preference.setTitle(R.string.remove_managed_profile_label);
+        preference.setIcon(R.drawable.ic_menu_delete);
+        preference.setOnPreferenceClickListener(this);
+        preference.setOrder(ORDER_LAST);
+        return preference;
     }
 
     private void cleanUpPreferences() {
@@ -266,32 +296,57 @@
         if (preferenceScreen != null) {
             preferenceScreen.removeAll();
         }
+        mProfiles.clear();
     }
 
     private void listenToAccountUpdates() {
         final int count = mProfiles.size();
         for (int i = 0; i < count; i++) {
-            mProfiles.valueAt(i).authenticatorHelper.listenToAccountUpdates();
+            AuthenticatorHelper authenticatorHelper = mProfiles.valueAt(i).authenticatorHelper;
+            if (authenticatorHelper != null) {
+                authenticatorHelper.listenToAccountUpdates();
+            }
         }
     }
 
     private void stopListeningToAccountUpdates() {
         final int count = mProfiles.size();
         for (int i = 0; i < count; i++) {
-            mProfiles.valueAt(i).authenticatorHelper.stopListeningToAccountUpdates();
+            AuthenticatorHelper authenticatorHelper = mProfiles.valueAt(i).authenticatorHelper;
+            if (authenticatorHelper != null) {
+                authenticatorHelper.stopListeningToAccountUpdates();
+            }
         }
     }
 
     private void updateAccountTypes(ProfileData profileData) {
         profileData.preferenceGroup.removeAll();
-        final ArrayList<AccountPreference> preferences = getAccountTypePreferences(
-                profileData.authenticatorHelper, profileData.userHandle);
-        final int count = preferences.size();
-        for (int i = 0; i < count; i++) {
-            profileData.preferenceGroup.addPreference(preferences.get(i));
+        if (profileData.userInfo.isEnabled()) {
+            final ArrayList<AccountPreference> preferences = getAccountTypePreferences(
+                    profileData.authenticatorHelper, profileData.userInfo.getUserHandle());
+            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);
+            }
+        } else {
+            // Put a label instead of the accounts list
+            synchronized (this) {
+                if (mProfileNotAvailablePreference == null) {
+                    mProfileNotAvailablePreference = new Preference(getActivity());
+                    mProfileNotAvailablePreference.setEnabled(false);
+                    mProfileNotAvailablePreference.setIcon(R.drawable.empty_icon);
+                    mProfileNotAvailablePreference.setTitle(null);
+                    mProfileNotAvailablePreference.setSummary(
+                            R.string.managed_profile_not_available_label);
+                }
+            }
+            profileData.preferenceGroup.addPreference(mProfileNotAvailablePreference);
         }
-        if (profileData.addAccountPreference != null) {
-            profileData.preferenceGroup.addPreference(profileData.addAccountPreference);
+        if (profileData.removeWorkProfilePreference != null) {
+            profileData.preferenceGroup.addPreference(profileData.removeWorkProfilePreference);
         }
     }
 
@@ -404,6 +459,9 @@
                 // Build new state
                 updateUi();
                 listenToAccountUpdates();
+                // Force the menu to update. Note that #onPrepareOptionsMenu uses data built by
+                // #updateUi so we must call this later
+                getActivity().invalidateOptionsMenu();
                 return;
             }
             Log.w(TAG, "Cannot handle received broadcast: " + intent.getAction());
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index 7dc83ef..ba93931 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -741,6 +741,10 @@
         final boolean voiceCapable = Utils.isVoiceCapable(context);
         final ArrayList<Integer> missingIcons = new ArrayList<Integer>();
         for (UserInfo user : users) {
+            if (user.isManagedProfile()) {
+                // Managed profiles appear under Accounts Settings instead
+                continue;
+            }
             Preference pref;
             if (user.id == UserHandle.myUserId()) {
                 pref = mMePreference;
@@ -773,19 +777,11 @@
             if (!isInitialized(user)) {
                 if (user.isRestricted()) {
                     pref.setSummary(R.string.user_summary_restricted_not_set_up);
-                } else if (user.isManagedProfile()) {
-                    pref.setSummary(R.string.user_summary_managed_profile_not_set_up);
                 } else {
                     pref.setSummary(R.string.user_summary_not_set_up);
                 }
             } else if (user.isRestricted()) {
                 pref.setSummary(R.string.user_summary_restricted_profile);
-            } else if (user.isManagedProfile()) {
-                if (user.isEnabled()) {
-                    pref.setSummary(R.string.user_summary_managed_profile);
-                } else {
-                    pref.setSummary(R.string.user_summary_managed_profile_not_enabled);
-                }
             }
             if (user.iconPath != null) {
                 if (mUserIcons.get(user.id) == null) {
@@ -911,8 +907,6 @@
                 if (!isInitialized(user)) {
                     mHandler.sendMessage(mHandler.obtainMessage(
                             MESSAGE_SETUP_USER, user.id, user.serialNumber));
-                } else if (!user.isManagedProfile()) {
-                    switchUserNow(userId);
                 }
             }
         } else if (pref == mAddUser) {