Merge "Follow PackageManager refactoring."
diff --git a/res/layout/admin_support_details_dialog.xml b/res/layout/admin_support_details_dialog.xml
index 0d857df..d9f71ae 100644
--- a/res/layout/admin_support_details_dialog.xml
+++ b/res/layout/admin_support_details_dialog.xml
@@ -24,7 +24,7 @@
             android:orientation="horizontal"
             android:gravity="center_vertical"
             android:paddingBottom="@dimen/admin_details_dialog_padding">
-        <ImageView
+        <ImageView android:id="@+id/admin_support_icon"
                 android:layout_width="@dimen/admin_details_dialog_icon_size"
                 android:layout_height="@dimen/admin_details_dialog_icon_size"
                 android:src="@drawable/ic_settings_lock_outline"
@@ -46,25 +46,23 @@
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:orientation="vertical">
-            <TextView android:id="@+id/disabled_by_admin_msg"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:textAppearance="@android:style/TextAppearance.Material.Subhead"
-                    android:textColor="?android:attr/textColorSecondary" />
             <TextView android:id="@+id/admin_support_msg"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+                    android:text="@string/default_admin_support_msg"
+                    android:maxLength="200"
+                    android:autoLink="email|phone"
                     android:textColor="?android:attr/textColorSecondary" />
             <TextView android:id="@+id/admins_policies_list"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:paddingTop="@dimen/admin_details_dialog_link_padding_top"
-                    android:text="@string/list_of_administrators"
+                    android:text="@string/admin_support_more_info"
                     android:textAppearance="@android:style/TextAppearance.Material.Subhead"
                     android:textColor="?android:attr/colorAccent"
                     android:clickable="true"
                     android:background="?android:attr/selectableItemBackground" />
         </LinearLayout>
     </ScrollView>
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/res/layout/device_admin_add.xml b/res/layout/device_admin_add.xml
index 25b7f01..4e8a6ac 100644
--- a/res/layout/device_admin_add.xml
+++ b/res/layout/device_admin_add.xml
@@ -100,8 +100,10 @@
                 <TextView android:id="@+id/admin_warning"
                     android:layout_width="fill_parent"
                     android:layout_height="wrap_content"
+                    android:textAppearance="?android:attr/textAppearanceMedium"
                     android:layout_weight="1"
                     android:padding="10dip" />
+
                 <LinearLayout android:id="@+id/admin_policies"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
@@ -109,6 +111,13 @@
                     android:orientation="vertical"
                     android:paddingStart="16dip"
                     android:paddingEnd="12dip" />
+
+                <TextView android:id="@+id/admin_support_message"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:textAppearance="?android:attr/textAppearanceMedium"
+                    android:autoLink="email|phone"
+                    android:padding="10dip" />
             </LinearLayout>
 
         </LinearLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index b91a3fc..e7442ed 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4435,7 +4435,6 @@
     <!-- Message when there are no available device admins to display -->
     <string name="no_device_admins">No available device administrators</string>
     <!-- Message displayed when the device admin can only be disabled by deleting the work profile [CHAR_LIMIT=120] -->
-    <string name="managed_profile_device_admin_info">To stop <xliff:g id="app_name">%1$s</xliff:g> from accessing your work profile, remove the profile under Settings &gt; Accounts</string>
     <!-- Title for personal device admins on the list [CHAR_LIMIT=25] -->
     <string name="personal_device_admin_title">Personal</string>
     <!-- Title for managed device admins on the list [CHAR_LIMIT=25] -->
@@ -5130,8 +5129,12 @@
 
     <!-- User details remove user menu [CHAR LIMIT=20] -->
     <string name="user_remove_user_menu">Delete <xliff:g id="user_name">%1$s</xliff:g> from this device</string>
-    <!-- User menu to allow creating new users from lockscreen [CHAR LIMIT=30] -->
-    <string name="user_add_on_lockscreen_menu">Add users when device is locked</string>
+    <!-- User lock screen settings header[CHAR LIMIT=40] -->
+    <string name="user_lockscreen_settings">Lock screen settings</string>
+    <!-- User settings item to allow creating new users from locks creen [CHAR LIMIT=40] -->
+    <string name="user_add_on_lockscreen_menu">Add users</string>
+    <!-- User settings user_add_on_lockscreen_menu item summary [CHAR LIMIT=40] -->
+    <string name="user_add_on_lockscreen_menu_summary">when device is locked</string>
     <!-- User details new user name [CHAR LIMIT=30] -->
     <string name="user_new_user_name">New user</string>
     <!-- User details new restricted profile name [CHAR LIMIT=30] -->
@@ -6712,11 +6715,18 @@
     <string name="about_summary">Android <xliff:g id="version" example="6.0">%1$s</xliff:g></string>
 
     <!-- TODO: Update these strings with the finalized ones. -->
+    <!-- Title for dialog displayed when user clicks on a setting locked by an admin [CHAR LIMIT=30] -->
     <string name="disabled_by_policy_title">Disabled by policy</string>
-    <string name="disabled_by_admin_msg">Disabled by your <xliff:g id="organisation_name" example="organisation">%s</xliff:g>\'s administrator.</string>
-    <string name="default_organisation_name">organisation</string>
-    <string name="default_admin_support_msg">Contact them to learn more.</string>
-    <string name="list_of_administrators">List of administrators</string>
+    <!-- Shown when the user tries to change a settings locked by an admin [CHAR LIMIT=200] -->
+    <string name="default_admin_support_msg">Disabled by your organisation\'s administrator.\nContact them to learn more.</string>
+    <!-- Shown in dialog to allow user to see more information about the device admin [CHAR LIMIT=30] -->
+    <string name="admin_support_more_info">More details</string>
+    <!-- Shown in admin details page to warn user about policies the admin can set in a work profile. [CHAR LIMIT=NONE] -->
+    <string name="admin_profile_owner_message">Your administrator has the ability to monitor and manage settings, corporate access, apps, permissions, and data associated with the profile, including network activity and your device\'s location information.</string>
+    <!-- Shown in admin details page to warn user about policies the admin can set on a user. [CHAR LIMIT=NONE] -->
+    <string name="admin_profile_owner_user_message">Your administrator has the ability to monitor and manage settings, corporate access, apps, permissions, and data associated with this user, including network activity and your device\'s location information.</string>
+    <!-- Shown in admin details page to warn user about policies the admin can set on a device. [CHAR LIMIT=NONE] -->
+    <string name="admin_device_owner_message">Your administrator has the ability to monitor and manage settings, corporate access, apps, permissions, and data associated with this device, including network activity and your device\'s location information.</string>
 
     <!-- Turn off a conditional state of the device (e.g. airplane mode, or hotspot) [CHAR LIMIT=30] -->
     <string name="condition_turn_off">Turn off</string>
diff --git a/res/xml/user_settings.xml b/res/xml/user_settings.xml
index f33177c..d7189de 100644
--- a/res/xml/user_settings.xml
+++ b/res/xml/user_settings.xml
@@ -28,4 +28,10 @@
             android:title="@string/user_add_user_or_profile_menu"
             android:icon="@drawable/ic_menu_add_dark" />
 
+    <PreferenceCategory
+            android:key="lock_screen_settings"
+            android:title="@string/user_lockscreen_settings">
+        <SwitchPreference android:key="add_users_when_locked"  android:title="@string/user_add_on_lockscreen_menu"
+                            android:summary="@string/user_add_on_lockscreen_menu_summary" />
+    </PreferenceCategory>
 </PreferenceScreen>
diff --git a/src/com/android/settings/ChooseLockSettingsHelper.java b/src/com/android/settings/ChooseLockSettingsHelper.java
index ab81455..53fbb7f 100644
--- a/src/com/android/settings/ChooseLockSettingsHelper.java
+++ b/src/com/android/settings/ChooseLockSettingsHelper.java
@@ -197,18 +197,10 @@
         if (external) {
             intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
             if (mFragment != null) {
-                IntentSender intentSender = mFragment.getActivity().getIntent()
-                        .getParcelableExtra(Intent.EXTRA_INTENT);
-                if (intentSender != null) {
-                    intent.putExtra(Intent.EXTRA_INTENT, intentSender);
-                }
+                copyOptionalExtras(mFragment.getActivity().getIntent(), intent);
                 mFragment.startActivity(intent);
             } else {
-                IntentSender intentSender = mActivity.getIntent()
-                        .getParcelableExtra(Intent.EXTRA_INTENT);
-                if (intentSender != null) {
-                    intent.putExtra(Intent.EXTRA_INTENT, intentSender);
-                }
+                copyOptionalExtras(mActivity.getIntent(), intent);
                 mActivity.startActivity(intent);
             }
         } else {
@@ -220,4 +212,22 @@
         }
         return true;
     }
+
+    private void copyOptionalExtras(Intent inIntent, Intent outIntent) {
+        IntentSender intentSender = inIntent.getParcelableExtra(Intent.EXTRA_INTENT);
+        if (intentSender != null) {
+            outIntent.putExtra(Intent.EXTRA_INTENT, intentSender);
+        }
+        int taskId = inIntent.getIntExtra(Intent.EXTRA_TASK_ID, -1);
+        if (taskId != -1) {
+            outIntent.putExtra(Intent.EXTRA_TASK_ID, taskId);
+        }
+        // If we will launch another activity once credentials are confirmed, exclude from recents.
+        // This is a workaround to a framework bug where affinity is incorrect for activities
+        // that are started from a no display activity, as is ConfirmDeviceCredentialActivity.
+        // TODO: Remove once that bug is fixed.
+        if (intentSender != null || taskId != -1) {
+            outIntent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+        }
+    }
 }
diff --git a/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java b/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
index e04f86f..0a22d45 100644
--- a/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
+++ b/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
@@ -17,9 +17,15 @@
 package com.android.settings;
 
 import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.ActivityManagerNative;
+import android.app.ActivityOptions;
+import android.app.IActivityManager;
+import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
 import android.os.Bundle;
+import android.os.RemoteException;
 import android.view.View;
 import android.widget.Button;
 import android.widget.ImageView;
@@ -127,6 +133,18 @@
     }
 
     protected void checkForPendingIntent() {
+        int taskId = getActivity().getIntent().getIntExtra(Intent.EXTRA_TASK_ID, -1);
+        if (taskId != -1) {
+            try {
+                IActivityManager activityManager = ActivityManagerNative.getDefault();
+                final ActivityOptions options = ActivityOptions.makeBasic();
+                options.setLaunchStackId(ActivityManager.StackId.INVALID_STACK_ID);
+                activityManager.startActivityFromRecents(taskId, options.toBundle());
+                return;
+            } catch (RemoteException e) {
+                // Do nothing.
+            }
+        }
         IntentSender intentSender = getActivity().getIntent()
                 .getParcelableExtra(Intent.EXTRA_INTENT);
         if (intentSender != null) {
diff --git a/src/com/android/settings/DevelopmentSettings.java b/src/com/android/settings/DevelopmentSettings.java
index ac6a319..d1a030b 100644
--- a/src/com/android/settings/DevelopmentSettings.java
+++ b/src/com/android/settings/DevelopmentSettings.java
@@ -1413,14 +1413,8 @@
         final String size = (newValue != null) ?
                 newValue.toString() : DEFAULT_LOG_RING_BUFFER_SIZE_IN_BYTES;
         SystemProperties.set(SELECT_LOGD_SIZE_PROPERTY, size);
+        SystemProperties.set("ctl.start", "logd-reinit");
         pokeSystemProperties();
-        try {
-            Process p = Runtime.getRuntime().exec("logcat -b all -G " + size);
-            p.waitFor();
-            Log.i(TAG, "Logcat ring buffer sizes set to: " + size);
-        } catch (Exception e) {
-            Log.w(TAG, "Cannot set logcat ring buffer sizes", e);
-        }
         updateLogdSizeValues();
     }
 
diff --git a/src/com/android/settings/DeviceAdminAdd.java b/src/com/android/settings/DeviceAdminAdd.java
index acd8c3b..3067ca2 100644
--- a/src/com/android/settings/DeviceAdminAdd.java
+++ b/src/com/android/settings/DeviceAdminAdd.java
@@ -34,6 +34,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
+import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.os.Binder;
 import android.os.Bundle;
@@ -42,6 +43,7 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.text.TextUtils;
 import android.text.TextUtils.TruncateAt;
 import android.util.EventLog;
 import android.util.Log;
@@ -55,6 +57,8 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import com.android.settings.users.UserDialogs;
+
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
@@ -86,6 +90,7 @@
     ImageView mAddMsgExpander;
     boolean mAddMsgEllipsized = true;
     TextView mAdminWarning;
+    TextView mSupportMessage;
     ViewGroup mAdminPolicies;
     Button mActionButton;
     Button mCancelButton;
@@ -279,6 +284,7 @@
 
         mAdminWarning = (TextView) findViewById(R.id.admin_warning);
         mAdminPolicies = (ViewGroup) findViewById(R.id.admin_policies);
+        mSupportMessage = (TextView) findViewById(R.id.admin_support_message);
         mCancelButton = (Button) findViewById(R.id.cancel_button);
         mCancelButton.setFilterTouchesWhenObscured(true);
         mCancelButton.setOnClickListener(new View.OnClickListener() {
@@ -294,6 +300,19 @@
             public void onClick(View v) {
                 if (mAdding) {
                     addAndFinish();
+                } else if (isManagedProfile(mDeviceAdmin)
+                        && mDeviceAdmin.getComponent().equals(mDPM.getProfileOwner())) {
+                    final int userId = UserHandle.myUserId();
+                    UserDialogs.createRemoveDialog(DeviceAdminAdd.this, userId,
+                            new DialogInterface.OnClickListener() {
+                                @Override
+                                public void onClick(DialogInterface dialog, int which) {
+                                    UserManager um = UserManager.get(DeviceAdminAdd.this);
+                                    um.removeUser(userId);
+                                    finish();
+                                }
+                            }
+                            ).show();
                 } else if (!mWaitingForRemoveMsg) {
                     try {
                         // Don't allow the admin to put a dialog up in front
@@ -451,12 +470,42 @@
         }
         if (!mRefreshing && !mAddingProfileOwner
                 && mDPM.isAdminActive(mDeviceAdmin.getComponent())) {
-            addDeviceAdminPolicies(false /* showDescription */);
-            mAdminWarning.setText(getString(R.string.device_admin_status,
-                    mDeviceAdmin.getActivityInfo().applicationInfo.loadLabel(getPackageManager())));
-            setTitle(getText(R.string.active_device_admin_msg));
-            mActionButton.setText(getText(R.string.remove_device_admin));
             mAdding = false;
+            final boolean isProfileOwner =
+                    mDeviceAdmin.getComponent().equals(mDPM.getProfileOwner());
+            final boolean isManagedProfile = isManagedProfile(mDeviceAdmin);
+            if (isProfileOwner && isManagedProfile) {
+                // Profile owner in a managed profile, user can remove profile to disable admin.
+                mAdminWarning.setText(R.string.admin_profile_owner_message);
+                mActionButton.setText(R.string.remove_managed_profile_label);
+            } else if (isProfileOwner || mDeviceAdmin.getComponent().equals(
+                            mDPM.getDeviceOwnerComponentOnCallingUser())) {
+                // Profile owner in a user or device owner, user can't disable admin.
+                if (isProfileOwner) {
+                    // Show profile owner in a user description.
+                    mAdminWarning.setText(R.string.admin_profile_owner_user_message);
+                } else {
+                    // Show device owner description.
+                    mAdminWarning.setText(R.string.admin_device_owner_message);
+                }
+                mActionButton.setText(R.string.remove_device_admin);
+                mActionButton.setEnabled(false);
+            } else {
+                addDeviceAdminPolicies(false /* showDescription */);
+                mAdminWarning.setText(getString(R.string.device_admin_status,
+                        mDeviceAdmin.getActivityInfo().applicationInfo.loadLabel(
+                        getPackageManager())));
+                setTitle(R.string.active_device_admin_msg);
+                mActionButton.setText(R.string.remove_device_admin);
+            }
+            String supportMessage = mDPM.getLongSupportMessageForUser(
+                    mDeviceAdmin.getComponent(), UserHandle.myUserId());
+            if (!TextUtils.isEmpty(supportMessage)) {
+                mSupportMessage.setText(supportMessage);
+                mSupportMessage.setVisibility(View.VISIBLE);
+            } else {
+                mSupportMessage.setVisibility(View.GONE);
+            }
         } else {
             addDeviceAdminPolicies(true /* showDescription */);
             mAdminWarning.setText(getString(R.string.device_admin_warning,
@@ -467,6 +516,7 @@
                 setTitle(getText(R.string.add_device_admin_msg));
             }
             mActionButton.setText(getText(R.string.add_device_admin));
+            mSupportMessage.setVisibility(View.GONE);
             mAdding = true;
         }
     }
@@ -505,4 +555,13 @@
             MAX_ADD_MSG_LINES_PORTRAIT : MAX_ADD_MSG_LINES_LANDSCAPE;
     }
 
+    /**
+     * @return true if adminInfo is running in a managed profile.
+     */
+    private boolean isManagedProfile(DeviceAdminInfo adminInfo) {
+        UserManager um = UserManager.get(this);
+        UserInfo info = um.getUserInfo(
+                UserHandle.getUserId(adminInfo.getActivityInfo().applicationInfo.uid));
+        return info != null ? info.isManagedProfile() : false;
+    }
 }
diff --git a/src/com/android/settings/DeviceAdminSettings.java b/src/com/android/settings/DeviceAdminSettings.java
index 25123b1..9791160 100644
--- a/src/com/android/settings/DeviceAdminSettings.java
+++ b/src/com/android/settings/DeviceAdminSettings.java
@@ -59,12 +59,29 @@
     private DevicePolicyManager mDPM;
     private UserManager mUm;
 
+
+    private static class DeviceAdminListItem implements Comparable<DeviceAdminListItem> {
+        public DeviceAdminInfo info;
+
+        // These aren't updated so they keep a stable sort order if user activates / de-activates
+        // an admin.
+        public String name;
+        public boolean active;
+
+        public int compareTo(DeviceAdminListItem other)  {
+            // Sort active admins first, then by name.
+            if (this.active != other.active) {
+                return this.active ? -1 : 1;
+            }
+            return this.name.compareTo(other.name);
+        }
+    }
     /**
      * Internal collection of device admin info objects for all profiles associated with the current
      * user.
      */
-    private final SparseArray<ArrayList<DeviceAdminInfo>>
-            mAdminsByProfile = new SparseArray<ArrayList<DeviceAdminInfo>>();
+    private final ArrayList<DeviceAdminListItem>
+            mAdmins = new ArrayList<DeviceAdminListItem>();
 
     private String mDeviceOwnerPkg;
     private SparseArray<ComponentName> mProfileOwnerComponents = new SparseArray<ComponentName>();
@@ -133,7 +150,7 @@
      * current user.
      */
     void updateList() {
-        mAdminsByProfile.clear();
+        mAdmins.clear();
 
         final List<UserHandle> profiles = mUm.getUserProfiles();
         final int profilesSize = profiles.size();
@@ -141,6 +158,7 @@
             final int profileId = profiles.get(i).getIdentifier();
             updateAvailableAdminsForProfile(profileId);
         }
+        Collections.sort(mAdmins);
 
         getListView().setAdapter(new PolicyListAdapter());
     }
@@ -148,25 +166,12 @@
     @Override
     public void onListItemClick(ListView l, View v, int position, long id) {
         Object o = l.getAdapter().getItem(position);
-        if (!(o instanceof DeviceAdminInfo)) {
-            // race conditions may cause this
-            return;
-        }
         DeviceAdminInfo dpi = (DeviceAdminInfo) o;
+        final UserHandle user = new UserHandle(getUserId(dpi));
         final Activity activity = getActivity();
-        final int userId = getUserId(dpi);
-        if (userId == UserHandle.myUserId() || !isProfileOwner(dpi)) {
-            Intent intent = new Intent();
-            intent.setClass(activity, DeviceAdminAdd.class);
-            intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, dpi.getComponent());
-            activity.startActivityAsUser(intent, new UserHandle(userId));
-        } else {
-            AlertDialog.Builder builder = new AlertDialog.Builder(activity);
-            builder.setMessage(getString(R.string.managed_profile_device_admin_info,
-                    dpi.loadLabel(activity.getPackageManager())));
-            builder.setPositiveButton(android.R.string.ok, null);
-            builder.create().show();
-        }
+        Intent intent = new Intent(activity, DeviceAdminAdd.class);
+        intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, dpi.getComponent());
+        activity.startActivityAsUser(intent, user);
     }
 
     static class ViewHolder {
@@ -191,55 +196,17 @@
 
         @Override
         public int getCount() {
-            int adminCount = 0;
-            final int profileCount = mAdminsByProfile.size();
-            for (int i = 0; i < profileCount; ++i) {
-                adminCount += mAdminsByProfile.valueAt(i).size();
-            }
-            // Add 'profileCount' for title items.
-            return adminCount + profileCount;
+            return mAdmins.size();
         }
 
         /**
          * The item for the given position in the list.
          *
-         * @return a String object for title items and a DeviceAdminInfo object for actual device
-         *         admins.
+         * @return DeviceAdminInfo object for actual device admins.
          */
         @Override
         public Object getItem(int position) {
-            if (position < 0) {
-                throw new ArrayIndexOutOfBoundsException();
-            }
-            // The position of the item in the list of admins.
-            // We start from the given position and discount the length of the upper lists until we
-            // get the one for the right profile
-            int adminPosition = position;
-            final int n = mAdminsByProfile.size();
-            int i = 0;
-            for (; i < n; ++i) {
-                // The elements in that section including the title item (that's why adding one).
-                final int listSize = mAdminsByProfile.valueAt(i).size() + 1;
-                if (adminPosition < listSize) {
-                    break;
-                }
-                adminPosition -= listSize;
-            }
-            if (i == n) {
-                throw new ArrayIndexOutOfBoundsException();
-            }
-            // If countdown == 0 that means the title item
-            if (adminPosition == 0) {
-                Resources res = getActivity().getResources();
-                if (mAdminsByProfile.keyAt(i) == UserHandle.myUserId()) {
-                    return res.getString(R.string.personal_device_admin_title);
-                } else {
-                    return res.getString(R.string.managed_device_admin_title);
-                }
-            } else {
-                // Subtracting one for the title.
-                return mAdminsByProfile.valueAt(i).get(adminPosition - 1);
-            }
+            return ((DeviceAdminListItem) (mAdmins.get(position))).info;
         }
 
         @Override
@@ -257,16 +224,15 @@
          */
         @Override
         public int getViewTypeCount() {
-            return 2;
+            return 1;
         }
 
         /**
-         * Returns 1 for title items and 0 for anything else.
+         * Returns 0 for all types.
          */
         @Override
         public int getItemViewType(int position) {
-            Object o = getItem(position);
-            return (o instanceof String) ? 1 : 0;
+            return 0;
         }
 
         @Override
@@ -276,15 +242,7 @@
         }
 
         private boolean isEnabled(Object o) {
-            if (!(o instanceof DeviceAdminInfo)) {
-                // Title item
-                return false;
-            }
             DeviceAdminInfo info = (DeviceAdminInfo) o;
-            if (isActiveAdmin(info) && getUserId(info) == UserHandle.myUserId()
-                    && (isDeviceOwner(info) || isProfileOwner(info))) {
-                return false;
-            }
             // Disable item if admin is being removed
             if (isRemovingAdmin(info)) {
                 return false;
@@ -295,28 +253,20 @@
         @Override
         public View getView(int position, View convertView, ViewGroup parent) {
             Object o = getItem(position);
-            if (o instanceof DeviceAdminInfo) {
-                if (convertView == null) {
-                    convertView = newDeviceAdminView(parent);
-                }
-                bindView(convertView, (DeviceAdminInfo) o);
-            } else {
-                if (convertView == null) {
-                    convertView = Utils.inflateCategoryHeader(mInflater, parent);
-                }
-                final TextView title = (TextView) convertView.findViewById(android.R.id.title);
-                title.setText((String)o);
+            if (convertView == null) {
+                convertView = newDeviceAdminView(parent);
             }
+            bindView(convertView, (DeviceAdminInfo) o);
             return convertView;
         }
 
         private View newDeviceAdminView(ViewGroup parent) {
             View v = mInflater.inflate(R.layout.device_admin_item, parent, false);
             ViewHolder h = new ViewHolder();
-            h.icon = (ImageView)v.findViewById(R.id.icon);
-            h.name = (TextView)v.findViewById(R.id.name);
-            h.checkbox = (CheckBox)v.findViewById(R.id.checkbox);
-            h.description = (TextView)v.findViewById(R.id.description);
+            h.icon = (ImageView) v.findViewById(R.id.icon);
+            h.name = (TextView) v.findViewById(R.id.name);
+            h.checkbox = (CheckBox) v.findViewById(R.id.checkbox);
+            h.description = (TextView) v.findViewById(R.id.description);
             v.setTag(h);
             return v;
         }
@@ -399,10 +349,6 @@
             enabledForProfile = Collections.emptyList();
         }
         final int n = enabledForProfile.size();
-        ArrayList<DeviceAdminInfo> deviceAdmins = mAdminsByProfile.get(profileId);
-        if (deviceAdmins == null) {
-            deviceAdmins = new ArrayList<DeviceAdminInfo>(n);
-        }
         for (int i = 0; i < n; ++i) {
             ResolveInfo resolveInfo = enabledForProfile.get(i);
             ComponentName riComponentName =
@@ -410,16 +356,18 @@
                             resolveInfo.activityInfo.name);
             if (alreadyAddedComponents == null
                     || !alreadyAddedComponents.contains(riComponentName)) {
-                DeviceAdminInfo deviceAdminInfo = createDeviceAdminInfo(resolveInfo);
+                DeviceAdminInfo deviceAdminInfo =  createDeviceAdminInfo(resolveInfo);
                 // add only visible ones (note: active admins are added regardless of visibility)
                 if (deviceAdminInfo != null && deviceAdminInfo.isVisible()) {
-                    deviceAdmins.add(deviceAdminInfo);
+                    DeviceAdminListItem item = new DeviceAdminListItem();
+                    item.info = deviceAdminInfo;
+                    item.name = deviceAdminInfo.loadLabel(pm).toString();
+                    // Active ones already added.
+                    item.active = false;
+                    mAdmins.add(item);
                 }
             }
         }
-        if (!deviceAdmins.isEmpty()) {
-            mAdminsByProfile.put(profileId, deviceAdmins);
-        }
     }
 
     /**
@@ -433,7 +381,6 @@
         if (activeAdmins != null) {
             final PackageManager packageManager = getActivity().getPackageManager();
             final int n = activeAdmins.size();
-            ArrayList<DeviceAdminInfo> deviceAdmins = new ArrayList<DeviceAdminInfo>(n);
             for (int i = 0; i < n; ++i) {
                 ComponentName activeAdmin = activeAdmins.get(i);
                 List<ResolveInfo> resolved = packageManager.queryBroadcastReceiversAsUser(
@@ -444,14 +391,15 @@
                     for (int j = 0; j < resolvedMax; ++j) {
                         DeviceAdminInfo deviceAdminInfo = createDeviceAdminInfo(resolved.get(j));
                         if (deviceAdminInfo != null) {
-                            deviceAdmins.add(deviceAdminInfo);
+                            DeviceAdminListItem item = new DeviceAdminListItem();
+                            item.info = deviceAdminInfo;
+                            item.name = deviceAdminInfo.loadLabel(packageManager).toString();
+                            item.active = true;
+                            mAdmins.add(item);
                         }
                     }
                 }
             }
-            if (!deviceAdmins.isEmpty()) {
-                mAdminsByProfile.put(profileId, deviceAdmins);
-            }
         }
     }
 
diff --git a/src/com/android/settings/RestrictedPreferenceHelper.java b/src/com/android/settings/RestrictedPreferenceHelper.java
index 0918887..385a8a2 100644
--- a/src/com/android/settings/RestrictedPreferenceHelper.java
+++ b/src/com/android/settings/RestrictedPreferenceHelper.java
@@ -53,10 +53,7 @@
         mContext = context;
         mPreference = preference;
 
-        mRestrictedPadlock = mContext.getDrawable(R.drawable.ic_settings_lock_outline);
-        final int iconSize = mContext.getResources().getDimensionPixelSize(
-                R.dimen.restricted_lock_icon_size);
-        mRestrictedPadlock.setBounds(0, 0, iconSize, iconSize);
+        mRestrictedPadlock = getRestrictedPadlock(mContext);
         mRestrictedPadlockPadding = mContext.getResources().getDimensionPixelSize(
                 R.dimen.restricted_lock_icon_padding);
 
@@ -192,4 +189,15 @@
     public boolean isDisabledByAdmin() {
         return mDisabledByAdmin;
     }
+
+    /**
+     * @return drawables for displaying with settings that are locked by a device admin.
+     */
+    public static Drawable getRestrictedPadlock(Context context) {
+        Drawable restrictedPadlock = context.getDrawable(R.drawable.ic_settings_lock_outline);
+        final int iconSize = context.getResources().getDimensionPixelSize(
+                R.dimen.restricted_lock_icon_size);
+        restrictedPadlock.setBounds(0, 0, iconSize, iconSize);
+        return restrictedPadlock;
+    }
 }
diff --git a/src/com/android/settings/ShowAdminSupportDetailsDialog.java b/src/com/android/settings/ShowAdminSupportDetailsDialog.java
index 42e8f05..85e90cf 100644
--- a/src/com/android/settings/ShowAdminSupportDetailsDialog.java
+++ b/src/com/android/settings/ShowAdminSupportDetailsDialog.java
@@ -17,24 +17,57 @@
 package com.android.settings;
 
 import android.app.Activity;
+import android.app.ActivityManagerNative;
 import android.app.AlertDialog;
+import android.app.AppGlobals;
+import android.app.IActivityManager;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
 import android.content.DialogInterface;
 import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.graphics.drawable.Drawable;
 import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.widget.ImageView;
 import android.widget.TextView;
 
 public class ShowAdminSupportDetailsDialog extends Activity
         implements DialogInterface.OnDismissListener {
 
+    private final String TAG = "AdminSupportDialog";
+
+    private DevicePolicyManager mDpm;
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
+        mDpm = getSystemService(DevicePolicyManager.class);
+        ComponentName admin = null;
+        int userId = UserHandle.myUserId();
+        Intent intent = getIntent();
+        if (intent != null) {
+            IActivityManager am = ActivityManagerNative.getDefault();
+            try {
+                int uid = am.getLaunchedFromUid(getActivityToken());
+                // Only allow system to specify admin and user.
+                if (UserHandle.isSameApp(uid, android.os.Process.myUid())) {
+                    admin = intent.getParcelableExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN);
+                    userId = intent.getIntExtra(Intent.EXTRA_USER_ID, UserHandle.myUserId());
+                }
+            } catch (RemoteException e) {
+                Log.e(TAG, "Could not talk to activity manager.", e);
+            }
+        }
+
         View rootView = LayoutInflater.from(this).inflate(
                 R.layout.admin_support_details_dialog, null);
-        setAdminSupportDetails(rootView);
+        setAdminSupportDetails(rootView, admin, userId);
 
         new AlertDialog.Builder(this)
                 .setView(rootView)
@@ -43,24 +76,47 @@
                 .show();
     }
 
-    private void setAdminSupportDetails(View root) {
-        CharSequence adminDisabledMsg = getString(R.string.disabled_by_admin_msg,
-                getString(R.string.default_organisation_name));
-        TextView textView = (TextView) root.findViewById(R.id.disabled_by_admin_msg);
-        textView.setText(adminDisabledMsg);
+    private void setAdminSupportDetails(View root, final ComponentName admin, final int userId) {
+        if (admin != null) {
+            CharSequence supportMessage = mDpm.getShortSupportMessageForUser(admin, userId);
+            if (supportMessage != null) {
+                TextView textView = (TextView) root.findViewById(R.id.admin_support_msg);
+                textView.setText(supportMessage);
+            }
 
-        CharSequence adminSupportDetails = getString(R.string.default_admin_support_msg);
-        textView = (TextView) root.findViewById(R.id.admin_support_msg);
-        textView.setText(adminSupportDetails);
+            ActivityInfo ai = null;
+            try {
+                ai = AppGlobals.getPackageManager().getReceiverInfo(admin, 0 /* flags */, userId);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Missing reciever info" , e);
+            }
+            if (ai != null) {
+                Drawable icon = ai.loadIcon(getPackageManager());
+                Drawable badgedIcon = getPackageManager().getUserBadgedIcon(
+                        icon, new UserHandle(userId));
+                ((ImageView) root.findViewById(R.id.admin_support_icon)).setImageDrawable(
+                        badgedIcon);
+            }
+        }
 
         root.findViewById(R.id.admins_policies_list).setOnClickListener(
                 new View.OnClickListener() {
                     @Override
                     public void onClick(View view) {
                         Intent intent = new Intent();
-                        intent.setClass(ShowAdminSupportDetailsDialog.this,
-                                Settings.DeviceAdminSettingsActivity.class);
-                        startActivity(intent);
+                        if (admin != null) {
+                            intent.setClass(ShowAdminSupportDetailsDialog.this,
+                                    DeviceAdminAdd.class);
+                            intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, admin);
+                            // DeviceAdminAdd class may need to run as managed profile.
+                            startActivityAsUser(intent, new UserHandle(userId));
+                        } else {
+                            intent.setClass(ShowAdminSupportDetailsDialog.this,
+                                    Settings.DeviceAdminSettingsActivity.class);
+                            // Activity merges both managed profile and parent users
+                            // admins so show as same user as this activity.
+                            startActivity(intent);
+                        }
                         finish();
                     }
                 });
@@ -70,4 +126,4 @@
     public void onDismiss(DialogInterface dialog) {
         finish();
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/settings/users/UserDialogs.java b/src/com/android/settings/users/UserDialogs.java
index 23012b3..3ed383a 100644
--- a/src/com/android/settings/users/UserDialogs.java
+++ b/src/com/android/settings/users/UserDialogs.java
@@ -55,13 +55,7 @@
         AlertDialog.Builder builder = new AlertDialog.Builder(context)
                 .setPositiveButton(R.string.user_delete_button, onConfirmListener)
                 .setNegativeButton(android.R.string.cancel, null);
-        if (UserHandle.myUserId() == removingUserId) {
-            builder.setTitle(R.string.user_confirm_remove_self_title);
-            builder.setMessage(R.string.user_confirm_remove_self_message);
-        } else if (userInfo.isRestricted()) {
-            builder.setTitle(R.string.user_profile_confirm_remove_title);
-            builder.setMessage(R.string.user_profile_confirm_remove_message);
-        } else if (userInfo.isManagedProfile()) {
+        if (userInfo.isManagedProfile()) {
             builder.setTitle(R.string.work_profile_confirm_remove_title);
             View view = createRemoveManagedUserDialogView(context, removingUserId);
             if (view != null) {
@@ -69,6 +63,12 @@
             } else {
                 builder.setMessage(R.string.work_profile_confirm_remove_message);
             }
+        } else if (UserHandle.myUserId() == removingUserId) {
+            builder.setTitle(R.string.user_confirm_remove_self_title);
+            builder.setMessage(R.string.user_confirm_remove_self_message);
+        } else if (userInfo.isRestricted()) {
+            builder.setTitle(R.string.user_profile_confirm_remove_title);
+            builder.setMessage(R.string.user_profile_confirm_remove_message);
         } else {
             builder.setTitle(R.string.user_confirm_remove_title);
             builder.setMessage(R.string.user_confirm_remove_message);
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index 3e2ac87..7e0711e 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -39,6 +39,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+import android.support.v14.preference.SwitchPreference;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.Preference.OnPreferenceClickListener;
 import android.support.v7.preference.PreferenceGroup;
@@ -97,7 +98,6 @@
     private static final String KEY_ADD_USER = "user_add";
 
     private static final int MENU_REMOVE_USER = Menu.FIRST;
-    private static final int MENU_ADD_ON_LOCKSCREEN = Menu.FIRST + 1;
 
     private static final int DIALOG_CONFIRM_REMOVE = 1;
     private static final int DIALOG_ADD_USER = 2;
@@ -126,8 +126,9 @@
 
     private PreferenceGroup mUserListCategory;
     private UserPreference mMePreference;
-    private SelectableEditTextPreference mNicknamePreference;
     private Preference mAddUser;
+    private PreferenceGroup mLockScreenSettings;
+    private SwitchPreference mAddUserWhenLocked;
     private int mRemovingUserId = -1;
     private int mAddedUserId = 0;
     private boolean mAddingUser;
@@ -221,6 +222,8 @@
                 mAddUser.setTitle(R.string.user_add_user_menu);
             }
         }
+        mLockScreenSettings = (PreferenceGroup) findPreference("lock_screen_settings");
+        mAddUserWhenLocked = (SwitchPreference) findPreference("add_users_when_locked");
         loadProfile();
         setHasOptionsMenu(true);
         IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED);
@@ -272,13 +275,6 @@
                     getResources().getString(R.string.user_remove_user_menu, nickname));
             removeThisUser.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
         }
-        if (mUserCaps.mIsAdmin && !um.hasUserRestriction(UserManager.DISALLOW_ADD_USER)) {
-            MenuItem allowAddOnLockscreen = menu.add(0, MENU_ADD_ON_LOCKSCREEN, pos++,
-                    R.string.user_add_on_lockscreen_menu);
-            allowAddOnLockscreen.setCheckable(true);
-            allowAddOnLockscreen.setChecked(Settings.Global.getInt(getContentResolver(),
-                    Settings.Global.ADD_USERS_WHEN_LOCKED, 0) == 1);
-        }
         super.onCreateOptionsMenu(menu, inflater);
     }
 
@@ -288,12 +284,6 @@
         if (itemId == MENU_REMOVE_USER) {
             onRemoveUserClicked(UserHandle.myUserId());
             return true;
-        } else if (itemId == MENU_ADD_ON_LOCKSCREEN) {
-            final boolean isChecked = item.isChecked();
-            Settings.Global.putInt(getContentResolver(), Settings.Global.ADD_USERS_WHEN_LOCKED,
-                    isChecked ? 0 : 1);
-            item.setChecked(!isChecked);
-            return true;
         } else {
             return super.onOptionsItemSelected(item);
         }
@@ -809,6 +799,13 @@
                 mAddUser.setSummary(null);
             }
         }
+        if (mUserCaps.mIsAdmin && !mUserCaps.mDisallowAddUser) {
+            mLockScreenSettings.setOrder(Preference.DEFAULT_ORDER);
+            preferenceScreen.addPreference(mLockScreenSettings);
+            mAddUserWhenLocked.setChecked(Settings.Global.getInt(getContentResolver(),
+                    Settings.Global.ADD_USERS_WHEN_LOCKED, 0) == 1);
+            mAddUserWhenLocked.setOnPreferenceChangeListener(this);
+        }
     }
 
     private int getMaxRealUsers() {
@@ -871,12 +868,6 @@
         }
     }
 
-    private void setUserName(String name) {
-        mUserManager.setUserName(UserHandle.myUserId(), name);
-        mNicknamePreference.setSummary(name);
-        getActivity().invalidateOptionsMenu();
-    }
-
     @Override
     public boolean onPreferenceClick(Preference pref) {
         if (pref == mMePreference) {
@@ -974,14 +965,13 @@
 
     @Override
     public boolean onPreferenceChange(Preference preference, Object newValue) {
-        if (preference == mNicknamePreference) {
-            String value = (String) newValue;
-            if (preference == mNicknamePreference && value != null
-                    && value.length() > 0) {
-                setUserName(value);
-            }
+        if (preference == mAddUserWhenLocked) {
+            Boolean value = (Boolean) newValue;
+            Settings.Global.putInt(getContentResolver(), Settings.Global.ADD_USERS_WHEN_LOCKED,
+                    value != null && value ? 1 : 0);
             return true;
         }
+
         return false;
     }
 
@@ -1007,6 +997,7 @@
         boolean mIsAdmin;
         boolean mIsGuest;
         boolean mCanAddGuest;
+        boolean mDisallowAddUser;
 
         private UserCapabilities() {}
 
@@ -1021,11 +1012,11 @@
             final UserInfo myUserInfo = userManager.getUserInfo(UserHandle.myUserId());
             caps.mIsGuest = myUserInfo.isGuest();
             caps.mIsAdmin = myUserInfo.isAdmin();
-            final boolean disallowAddUser = userManager.hasUserRestriction(
+            caps.mDisallowAddUser = userManager.hasUserRestriction(
                     UserManager.DISALLOW_ADD_USER);
             if (!caps.mIsAdmin || UserManager.getMaxSupportedUsers() < 2
                     || !UserManager.supportsMultipleUsers()
-                    || disallowAddUser) {
+                    || caps.mDisallowAddUser) {
                 caps.mCanAddUser = false;
             }
             DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
@@ -1037,7 +1028,7 @@
 
             final boolean canAddUsersWhenLocked = caps.mIsAdmin || Settings.Global.getInt(
                     context.getContentResolver(), Settings.Global.ADD_USERS_WHEN_LOCKED, 0) == 1;
-            caps.mCanAddGuest = !caps.mIsGuest && !disallowAddUser && canAddUsersWhenLocked;
+            caps.mCanAddGuest = !caps.mIsGuest && !caps.mDisallowAddUser && canAddUsersWhenLocked;
             return caps;
         }