Merge "Application restrictions UI" into jb-mr2-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index abbd703..964650c 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -69,6 +69,7 @@
             android:taskAffinity=""
             android:theme="@android:style/Theme.Holo"
             android:hardwareAccelerated="true"
+            android:requiredForAllUsers="true"
             android:supportsRtl="true">
 
         <!-- Settings -->
@@ -85,6 +86,16 @@
             </intent-filter>
         </activity>
 
+        <!-- User Restrictions activity -->
+
+        <activity android:name=".users.UserRestrictionsActivity"
+                android:label="@string/user_restrictions_title">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
         <activity android:name=".SubSettings"
                 android:taskAffinity="com.android.settings"
                 android:parentActivityName="Settings">
@@ -734,6 +745,16 @@
             </intent-filter>
         </activity-alias>
 
+        <activity android:name=".users.AppRestrictionsFragment$Activity"
+                android:label="@string/application_info_label"
+                android:exported="true"
+                android:taskAffinity="">
+            <intent-filter>
+                <action android:name="com.android.settings.APP_RESTRICTIONS" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
         <!-- Provide direct entry into manage apps showing running services. -->
         <activity android:name="Settings$RunningServicesActivity"
                 android:label="@string/runningservices_settings_title"
@@ -1525,6 +1546,22 @@
                 android:resource="@id/display_settings" />
         </activity>
 
+        <activity android:name="Settings$UserSettingsActivity"
+                android:uiOptions="splitActionBarWhenNarrow"
+                android:label="@string/user_settings_title"
+                android:taskAffinity=""
+                android:excludeFromRecents="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <action android:name="android.settings.USER_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                android:value="com.android.settings.users.UserSettings" />
+            <meta-data android:name="com.android.settings.TOP_LEVEL_HEADER_ID"
+                android:resource="@id/user_settings" />
+        </activity>
+
         <receiver android:name=".widget.SettingsAppWidgetProvider"
                 android:label="@string/gadget_title"
                 android:exported="true"
@@ -1555,5 +1592,11 @@
             </intent-filter>
         </receiver>
 
+        <receiver android:name=".users.RestrictionsReceiver">
+            <intent-filter>
+                <action android:name="android.intent.action.GET_RESTRICTION_ENTRIES"/>
+            </intent-filter>
+        </receiver>
+
     </application>
 </manifest>
diff --git a/res/layout/preference_app_restrictions.xml b/res/layout/preference_app_restrictions.xml
new file mode 100644
index 0000000..a8a93d1
--- /dev/null
+++ b/res/layout/preference_app_restrictions.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeight"
+    android:gravity="center_vertical"
+    android:paddingStart="@*android:dimen/preference_item_padding_side"
+    android:paddingEnd="?android:attr/scrollbarSize">
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:id="@+id/app_restrictions_pref"
+        android:focusable="true"
+        android:clickable="true"
+        android:gravity="center_vertical"
+        android:background="?android:attr/selectableItemBackground" >
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:gravity="center"
+            android:minWidth="@*android:dimen/preference_icon_minWidth"
+            android:orientation="horizontal">
+            <ImageView
+                android:id="@+android:id/icon"
+                android:layout_width="48dp"
+                android:layout_height="48dp"
+                android:layout_gravity="center"
+                android:minWidth="48dp"
+                android:scaleType="centerInside"
+                android:layout_marginEnd="@*android:dimen/preference_item_padding_inner"
+                 />
+        </LinearLayout>
+        <RelativeLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginEnd="6dip"
+            android:layout_marginTop="6dip"
+            android:layout_marginBottom="6dip"
+            android:layout_weight="1">
+            <TextView
+                android:id="@+android:id/title"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:singleLine="true"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:ellipsize="marquee"
+                android:fadingEdge="horizontal"/>
+            <TextView
+                android:id="@android:id/summary"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_below="@android:id/title"
+                android:layout_alignStart="@android:id/title"
+                android:paddingBottom="3dip"
+                android:visibility="gone"
+                android:textAppearance="?android:attr/textAppearanceSmall"
+                android:textSize="13sp"
+                android:textColor="?android:attr/textColorSecondary"
+                android:focusable="false"
+                android:maxLines="4" />
+        </RelativeLayout>
+    </LinearLayout>
+    <ImageView
+        android:id="@+id/app_restrictions_settings"
+        android:layout_width="wrap_content"
+        android:layout_height="fill_parent"
+        android:paddingStart="12dip"
+        android:paddingEnd="12dp"
+        android:src="@drawable/ic_sysbar_quicksettings"
+        android:contentDescription="@string/apps_with_restrictions_settings_button"
+        android:layout_gravity="center"
+        android:clickable="true"
+        android:focusable="true"
+        android:background="?android:attr/selectableItemBackground" />
+    <View
+        android:id="@+id/settings_divider"
+        android:layout_width="1dip"
+        android:layout_height="match_parent"
+        android:layout_marginTop="5dip"
+        android:layout_marginBottom="5dip"
+        android:background="@android:drawable/divider_horizontal_dark" />
+
+    <LinearLayout
+        android:id="@android:id/widget_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:paddingRight="?android:attr/scrollbarSize"
+        android:gravity="center_vertical"
+        android:orientation="vertical" />
+</LinearLayout>
diff --git a/res/layout/preference_rename_widget.xml b/res/layout/preference_rename_widget.xml
new file mode 100644
index 0000000..81e401f
--- /dev/null
+++ b/res/layout/preference_rename_widget.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Layout for a text label in the user limits screen. -->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:text="@string/user_rename" />
diff --git a/res/layout/preference_user_delete_widget.xml b/res/layout/preference_user_delete_widget.xml
index 68355ba..57c240f 100644
--- a/res/layout/preference_user_delete_widget.xml
+++ b/res/layout/preference_user_delete_widget.xml
@@ -20,6 +20,16 @@
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
         android:orientation="horizontal">
+    <ImageView
+        android:id="@+id/manage_user"
+        android:layout_width="wrap_content"
+        android:layout_height="fill_parent"
+        android:paddingStart="12dip"
+        android:paddingEnd="12dip"
+        android:src="@drawable/ic_sysbar_quicksettings"
+        android:contentDescription="@string/user_delete_user_description"
+        android:layout_gravity="center"
+        android:background="?android:attr/selectableItemBackground" />
     <View
         android:layout_width="2dip"
         android:layout_height="match_parent"
@@ -30,8 +40,8 @@
         android:id="@+id/trash_user"
         android:layout_width="wrap_content"
         android:layout_height="fill_parent"
-        android:paddingStart="15dip"
-        android:paddingEnd="?android:attr/scrollbarSize"
+        android:paddingStart="12dip"
+        android:paddingEnd="12dip"
         android:src="@drawable/ic_menu_delete_holo_dark"
         android:contentDescription="@string/user_delete_user_description"
         android:layout_gravity="center"
diff --git a/res/layout/user_limits.xml b/res/layout/user_limits.xml
new file mode 100644
index 0000000..b242f0e
--- /dev/null
+++ b/res/layout/user_limits.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_height="match_parent"
+    android:layout_width="match_parent"
+    android:layout_marginStart="32dp"
+    android:layout_marginEnd="32dp"
+    android:orientation="vertical">
+
+    <fragment android:name="com.android.settings.users.AppRestrictionsFragment"
+            android:id="@+id/user_limits_fragment"
+            android:layout_weight="1"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            />
+    <RelativeLayout
+            android:id="@+id/button_bar"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_weight="0" >
+       <Button
+                android:id="@+id/back_button"
+                android:layout_width="150dip"
+                android:layout_height="wrap_content"
+                android:layout_alignParentStart="true"
+                android:layout_margin="5dip"
+                android:text="@string/wizard_back"
+                android:visibility="invisible"/>
+
+       <Button
+               android:id="@+id/next_button"
+               android:layout_width="150dip"
+               android:layout_height="wrap_content"
+               android:layout_margin="5dip"
+               android:layout_alignParentEnd="true"
+               android:text="@string/wizard_finish" />
+    </RelativeLayout>
+</LinearLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 4aab395..43259af 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4276,12 +4276,25 @@
     <string name="user_list_title">Other users</string>
     <!-- User settings add user menu [CHAR LIMIT=20] -->
     <string name="user_add_user_menu">Add user</string>
+    <!-- User settings add restricted user label [CHAR LIMIT=20] -->
+    <string name="user_add_restricted">Add limited user</string>
+    <!-- User settings summary for add restricted user [CHAR LIMIT=100] -->
+    <string name="user_add_restricted_summary">Limited users can only access the apps and content you select</string>
+    <!-- User settings add user label [CHAR LIMIT=20] -->
+    <string name="user_add_trusted">Add trusted user</string>
+    <!-- User settings summary for add trusted user [CHAR LIMIT=100] -->
+    <string name="user_add_trusted_summary">Trusted users have no restrictions</string>
+
     <!-- User summary to indicate that user is currently active in the background [CHAR LIMIT=100] -->
     <string name="user_summary_active">Active</string>
     <!-- User summary to indicate that user is currently inactive in the background [CHAR LIMIT=100] -->
     <string name="user_summary_inactive">Not active</string>
     <!-- User summary to indicate that user is currently not set up [CHAR LIMIT=100] -->
     <string name="user_summary_not_set_up">Not set up</string>
+    <!-- Summary text for a trusted user [CHAR LIMIT=50] -->
+    <string name="user_trusted">Trusted</string>
+    <!-- Summary text for a limited user [CHAR LIMIT=50] -->
+    <string name="user_limited">Limited</string>
     <!-- User information string to represent the owner of the device [CHAR LIMIT=25] -->
     <string name="user_owner">Owner</string>
     <!-- Title for the preference to enter the nickname of the userto display in the user switcher [CHAR LIMIT=25]-->
@@ -4328,6 +4341,13 @@
     <!-- Delete button text [CHAR LIMIT=25] -->
     <string name="user_delete_button">Delete</string>
 
+    <!-- Application Restrictions screen title [CHAR LIMIT=45] -->
+    <string name="application_restrictions">Allow apps and content</string>
+    <!-- Applications with restrictions header [CHAR LIMIT=45] -->
+    <string name="apps_with_restrictions_header">Applications with restrictions</string>
+    <!-- Applicaitons with restrictions - settings button [CHAR LIMIT=30] -->
+    <string name="apps_with_restrictions_settings_button">Expand settings for application</string>
+
     <!-- Warning message when changing a global setting for a tablet.[CHAR LIMIT=none] -->
     <string name="global_change_warning" product="tablet">This setting affects all users on this tablet.</string>
     <!-- Warning message when changing a global setting for a phone.[CHAR LIMIT=none] -->
@@ -4383,4 +4403,16 @@
     <string name="cell_broadcast_settings">Cell broadcasts</string>
     <!-- Cell Broadcast settings description [CHAR LIMIT=100] -->
     <string name="cell_broadcast_settings_summary">Select the types of emergency alerts to display.</string>
+
+    <!-- User app limits screen title [CHAR LIMIT=35] -->
+    <string name="user_restrictions_title">Allow apps and content</string>
+    <!-- User limits screen, user name rename text [CHAR LIMIT=15] -->
+    <string name="user_rename">RENAME</string>
+
+    <!-- Wizard back button label [CHAR LIMIT=25] -->
+    <string name="wizard_back">Back</string>
+    <!-- Wizard next button label [CHAR LIMIT=25] -->
+    <string name="wizard_next">Next</string>
+    <!-- Wizard next button label [CHAR LIMIT=25] -->
+    <string name="wizard_finish">Finish</string>
 </resources>
diff --git a/res/xml/app_restrictions.xml b/res/xml/app_restrictions.xml
new file mode 100644
index 0000000..df02907
--- /dev/null
+++ b/res/xml/app_restrictions.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+        android:title="@string/application_restrictions"
+        xmlns:settings="http://schemas.android.com/apk/res/com.android.settings">
+
+    <EditTextPreference
+            android:key="user_info"
+            android:order="0"
+            android:widgetLayout="@layout/preference_rename_widget" />
+
+</PreferenceScreen>
diff --git a/res/xml/user_settings.xml b/res/xml/user_settings.xml
index d97f1a6..3e61bd7 100644
--- a/res/xml/user_settings.xml
+++ b/res/xml/user_settings.xml
@@ -39,4 +39,15 @@
             android:title="@string/user_list_title">
     </PreferenceCategory>
 
+    <Preference
+            android:key="user_add_restricted"
+            android:title="@string/user_add_restricted"
+            android:summary="@string/user_add_restricted_summary"
+            android:icon="@drawable/ic_menu_add" />
+
+    <Preference
+            android:key="user_add_trusted"
+            android:title="@string/user_add_trusted"
+            android:summary="@string/user_add_trusted_summary"
+            android:icon="@drawable/ic_menu_add" />
 </PreferenceScreen>
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 962d042..be8e1cc 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -22,6 +22,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.RestrictionEntry;
 import android.content.SharedPreferences;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
@@ -56,6 +57,7 @@
 import com.android.settings.accounts.ManageAccountsSettings;
 import com.android.settings.bluetooth.BluetoothEnabler;
 import com.android.settings.bluetooth.BluetoothSettings;
+import com.android.settings.users.RestrictionsReceiver;
 import com.android.settings.wfd.WifiDisplaySettings;
 import com.android.settings.wifi.WifiEnabler;
 import com.android.settings.wifi.WifiSettings;
@@ -133,12 +135,16 @@
     private Header mLastHeader;
     private boolean mListeningToAccountUpdates;
 
+    private List<RestrictionEntry> mAppRestrictions;
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         if (getIntent().hasExtra(EXTRA_UI_OPTIONS)) {
             getWindow().setUiOptions(getIntent().getIntExtra(EXTRA_UI_OPTIONS, 0));
         }
 
+        mAppRestrictions = getApplicationRestrictions();
+
         mAuthenticatorHelper = new AuthenticatorHelper();
         mAuthenticatorHelper.updateAuthDescriptions(this);
         mAuthenticatorHelper.onAccountsUpdated(this, null);
@@ -408,7 +414,6 @@
                 DevelopmentSettings.PREF_SHOW,
                 android.os.Build.TYPE.equals("eng"));
         int i = 0;
-
         mHeaderIndexMap.clear();
         while (i < target.size()) {
             Header header = target.get(i);
@@ -450,6 +455,15 @@
                 if (!showDev) {
                     target.remove(i);
                 }
+            } else if (id == R.id.application_settings) {
+                if (mAppRestrictions != null) {
+                    for (RestrictionEntry entry : mAppRestrictions) {
+                        if (entry.key.equals(RestrictionsReceiver.KEY_ENABLE_APPS)
+                                && !entry.getBooleanValue()) {
+                            target.remove(i);
+                        }
+                    }
+                }
             }
 
             if (i < target.size() && target.get(i) == header
@@ -828,4 +842,5 @@
     public static class WifiDisplaySettingsActivity extends Settings { /* empty */ }
     public static class DreamSettingsActivity extends Settings { /* empty */ }
     public static class NotificationStationActivity extends Settings { /* empty */ }
+    public static class UserSettingsActivity extends Settings { /* empty */ }
 }
diff --git a/src/com/android/settings/users/AppRestrictionsFragment.java b/src/com/android/settings/users/AppRestrictionsFragment.java
new file mode 100644
index 0000000..9757f30
--- /dev/null
+++ b/src/com/android/settings/users/AppRestrictionsFragment.java
@@ -0,0 +1,463 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.users;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.RestrictionEntry;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.content.pm.UserInfo;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.preference.CheckBoxPreference;
+import android.preference.EditTextPreference;
+import android.preference.ListPreference;
+import android.preference.MultiSelectListPreference;
+import android.preference.Preference;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceCategory;
+import android.preference.Preference.OnPreferenceChangeListener;
+import android.preference.Preference.OnPreferenceClickListener;
+import android.preference.PreferenceGroup;
+import android.preference.SwitchPreference;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.Switch;
+
+import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import libcore.util.CollectionUtils;
+
+public class AppRestrictionsFragment extends SettingsPreferenceFragment implements
+        OnPreferenceChangeListener, OnClickListener, OnPreferenceClickListener {
+
+    private static final String TAG = AppRestrictionsFragment.class.getSimpleName();
+
+    private static final String PKG_PREFIX = "pkg_";
+    private static final String KEY_USER_INFO = "user_info";
+
+    private UserManager mUserManager;
+    private UserHandle mUser;
+
+    private EditTextPreference mUserPreference;
+    private PreferenceGroup mAppList;
+
+    private static final int MAX_APP_RESTRICTIONS = 100;
+
+    private static final String DELIMITER = ";";
+    private List<ResolveInfo> mApps;
+    HashMap<String,Boolean> mSelectedPackages = new HashMap<String,Boolean>();
+    private boolean mFirstTime = true;
+    private boolean mNewUser;
+
+    public static class Activity extends PreferenceActivity {
+        @Override
+        public Intent getIntent() {
+            Intent modIntent = new Intent(super.getIntent());
+            modIntent.putExtra(EXTRA_SHOW_FRAGMENT, AppRestrictionsFragment.class.getName());
+            modIntent.putExtra(EXTRA_NO_HEADERS, true);
+            return modIntent;
+        }
+    }
+
+    static class AppRestrictionsPreference extends SwitchPreference {
+        private boolean hasSettings;
+        private OnClickListener listener;
+        private ArrayList<RestrictionEntry> restrictions;
+        boolean panelOpen;
+        private boolean required;
+        List<Preference> childPreferences = new ArrayList<Preference>();
+
+        AppRestrictionsPreference(Context context, OnClickListener listener) {
+            super(context);
+            setLayoutResource(R.layout.preference_app_restrictions);
+            this.listener = listener;
+        }
+
+        private void setSettingsEnabled(boolean enable) {
+            hasSettings = enable;
+        }
+
+        void setRestrictions(ArrayList<RestrictionEntry> restrictions) {
+            this.restrictions = restrictions;
+        }
+
+        void setRequired(boolean required) {
+            this.required = required;
+        }
+
+        boolean isRequired() {
+            return required;
+        }
+
+        RestrictionEntry getRestriction(String key) {
+            if (restrictions == null) return null;
+            for (RestrictionEntry entry : restrictions) {
+                if (entry.key.equals(key)) {
+                    return entry;
+                }
+            }
+            return null;
+        }
+
+        ArrayList<RestrictionEntry> getRestrictions() {
+            return restrictions;
+        }
+
+        @Override
+        protected void onBindView(View view) {
+            super.onBindView(view);
+
+            View appRestrictionsSettings = view.findViewById(R.id.app_restrictions_settings);
+            appRestrictionsSettings.setVisibility(hasSettings ? View.VISIBLE : View.GONE);
+            view.findViewById(R.id.settings_divider).setVisibility(
+                    hasSettings ? View.VISIBLE : View.GONE);
+            appRestrictionsSettings.setOnClickListener(listener);
+            appRestrictionsSettings.setTag(this);
+
+            View appRestrictionsPref = view.findViewById(R.id.app_restrictions_pref);
+            appRestrictionsPref.setOnClickListener(listener);
+            appRestrictionsPref.setTag(this);
+
+            ViewGroup widget = (ViewGroup) view.findViewById(android.R.id.widget_frame);
+            widget.setEnabled(!isRequired());
+            if (widget.getChildCount() > 0) {
+                final Switch switchView = (Switch) widget.getChildAt(0);
+                switchView.setEnabled(!isRequired());
+                switchView.setTag(this);
+                switchView.setOnCheckedChangeListener(new OnCheckedChangeListener() {
+                    @Override
+                    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+                        listener.onClick(switchView);
+                    }
+                });
+            }
+        }
+    }
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        mUserManager = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
+        addPreferencesFromResource(R.xml.app_restrictions);
+        mAppList = getPreferenceScreen();
+        mUserPreference = (EditTextPreference) findPreference(KEY_USER_INFO);
+        mUserPreference.setOnPreferenceChangeListener(this);
+        setHasOptionsMenu(true);
+    }
+
+    void setUser(UserHandle user, boolean newUser) {
+        mUser = user;
+        mNewUser = newUser;
+    }
+
+    public void onResume() {
+        super.onResume();
+        if (mFirstTime) {
+            mFirstTime = false;
+            populateApps();
+        }
+        UserInfo info = mUserManager.getUserInfo(mUser.getIdentifier());
+        mUserPreference.setTitle(info.name);
+        mUserPreference.setIcon(
+                new BitmapDrawable(mUserManager.getUserIcon(mUser.getIdentifier())));
+        mUserPreference.setText(info.name);
+    }
+
+    private void populateApps() {
+        mAppList.setOrderingAsAdded(false);
+
+        // TODO: Do this asynchronously since it can be a long operation
+        final Context context = getActivity();
+        PackageManager pm = context.getPackageManager();
+        Intent launcherIntent = new Intent(Intent.ACTION_MAIN);
+        launcherIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+        mApps = pm.queryIntentActivities(launcherIntent, 0);
+        Collections.sort(mApps, new AppLabelComparator(pm));
+
+        Intent restrictionsIntent = new Intent(Intent.ACTION_GET_RESTRICTION_ENTRIES);
+        final List<ResolveInfo> receivers = pm.queryBroadcastReceivers(restrictionsIntent, 0);
+        final List<ResolveInfo> existingApps = pm.queryIntentActivitiesAsUser(launcherIntent,
+                0, mUser.getIdentifier());
+        int i = 0;
+        if (receivers != null && receivers.size() > 0) {
+            for (ResolveInfo app : mApps) {
+                if (app.activityInfo == null || app.activityInfo.packageName == null) continue;
+                String packageName = app.activityInfo.packageName;
+                Drawable icon = app.loadIcon(pm);
+                CharSequence label = app.loadLabel(pm);
+                AppRestrictionsPreference p = new AppRestrictionsPreference(context, this);
+                p.setIcon(icon);
+                p.setTitle(label);
+                p.setKey(PKG_PREFIX + packageName);
+                p.setSettingsEnabled(hasPackage(receivers, packageName));
+                p.setPersistent(false);
+                p.setOnPreferenceChangeListener(this);
+                p.setOnPreferenceClickListener(this);
+                try {
+                    PackageInfo pi = pm.getPackageInfo(packageName, 0);
+                    if (pi.requiredForAllUsers) {
+                        p.setChecked(true);
+                        p.setRequired(true);
+                    } else if (!mNewUser && hasPackage(existingApps, packageName)) {
+                        p.setChecked(true);
+                    }
+                } catch (NameNotFoundException re) {
+                    // This would be bad
+                }
+
+                mAppList.addPreference(p);
+                if (packageName.equals(getActivity().getPackageName())) {
+                    p.setOrder(MAX_APP_RESTRICTIONS * 1);
+                } else {
+                    p.setOrder(MAX_APP_RESTRICTIONS * (i + 2));
+                }
+                mSelectedPackages.put(packageName, p.isChecked());
+                i++;
+            }
+        }
+    }
+
+    private class AppLabelComparator implements Comparator<ResolveInfo> {
+
+        PackageManager pm;
+
+        private AppLabelComparator(PackageManager pm) {
+            this.pm = pm;
+        }
+
+        private CharSequence getLabel(ResolveInfo info) {
+            // TODO: Optimize this with a cache
+            return info.activityInfo.loadLabel(pm);
+        }
+
+        @Override
+        public int compare(ResolveInfo lhs, ResolveInfo rhs) {
+            String lhsLabel = getLabel(lhs).toString();
+            String rhsLabel = getLabel(rhs).toString();
+            return lhsLabel.compareTo(rhsLabel);
+        }
+    }
+
+    private boolean hasPackage(List<ResolveInfo> receivers, String packageName) {
+        for (ResolveInfo info : receivers) {
+            if (info.activityInfo.packageName.equals(packageName)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (v.getTag() instanceof AppRestrictionsPreference) {
+            AppRestrictionsPreference pref = (AppRestrictionsPreference) v.getTag();
+            if (v.getId() == R.id.app_restrictions_settings) {
+                handleSettingsClick(pref);
+            } else if (!pref.isRequired()) {
+                pref.setChecked(!pref.isChecked());
+                mSelectedPackages.put(pref.getKey().substring(PKG_PREFIX.length()),
+                        pref.isChecked());
+            }
+        }
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        String key = preference.getKey();
+        if (key != null && key.contains(DELIMITER)) {
+            StringTokenizer st = new StringTokenizer(key, DELIMITER);
+            final String packageName = st.nextToken();
+            final String restrictionKey = st.nextToken();
+            AppRestrictionsPreference appPref = (AppRestrictionsPreference)
+                    mAppList.findPreference(PKG_PREFIX+packageName);
+            ArrayList<RestrictionEntry> restrictions = appPref.getRestrictions();
+            if (restrictions != null) {
+                for (RestrictionEntry entry : restrictions) {
+                    if (entry.key.equals(restrictionKey)) {
+                        switch (entry.type) {
+                        case RestrictionEntry.TYPE_BOOLEAN:
+                            entry.setValue((Boolean) newValue);
+                            break;
+                        case RestrictionEntry.TYPE_CHOICE:
+                        case RestrictionEntry.TYPE_CHOICE_LEVEL:
+                            ListPreference listPref = (ListPreference) preference;
+                            entry.setValue((String) newValue);
+                            for (int i = 0; i < listPref.getEntryValues().length; i++) {
+                                if (entry.values[i].equals(newValue)) {
+                                    listPref.setSummary(entry.choices[i]);
+                                    break;
+                                }
+                            }
+                            break;
+                        case RestrictionEntry.TYPE_MULTI_SELECT:
+                            MultiSelectListPreference msListPref =
+                                    (MultiSelectListPreference) preference;
+                            Set<String> set = (Set<String>) newValue;
+                            String [] selectedValues = new String[set.size()];
+                            set.toArray(selectedValues);
+                            entry.setMultipleValues(selectedValues);
+                            break;
+                        default:
+                            continue;
+                        }
+                        mUserManager.setApplicationRestrictions(packageName, restrictions,
+                                mUser);
+                        break;
+                    }
+                }
+            }
+        } else if (preference == mUserPreference) {
+            String userName = ((CharSequence) newValue).toString();
+            if (!TextUtils.isEmpty(userName)) {
+                mUserManager.setUserName(mUser.getIdentifier(), userName);
+                mUserPreference.setTitle(userName);
+            }
+        }
+        return true;
+    }
+
+    private void handleSettingsClick(AppRestrictionsPreference preference) {
+        if (preference.getKey().startsWith(PKG_PREFIX)) {
+            if (preference.panelOpen) {
+                for (Preference p : preference.childPreferences) {
+                    mAppList.removePreference(p);
+                }
+                preference.childPreferences.clear();
+            } else {
+                String packageName = preference.getKey().substring(PKG_PREFIX.length());
+                List<RestrictionEntry> oldEntries =
+                        mUserManager.getApplicationRestrictions(packageName, mUser);
+                Intent intent = new Intent(Intent.ACTION_GET_RESTRICTION_ENTRIES);
+                intent.putParcelableArrayListExtra(Intent.EXTRA_RESTRICTIONS,
+                        new ArrayList<RestrictionEntry>(oldEntries));
+                getActivity().sendOrderedBroadcast(intent, null,
+                        new RestrictionsResultReceiver(packageName, preference),
+                        null, Activity.RESULT_OK, null, null);
+            }
+            preference.panelOpen = !preference.panelOpen;
+        }
+    }
+
+    class RestrictionsResultReceiver extends BroadcastReceiver {
+
+        String packageName;
+        AppRestrictionsPreference preference;
+
+        RestrictionsResultReceiver(String packageName, AppRestrictionsPreference preference) {
+            super();
+            this.packageName = packageName;
+            this.preference = preference;
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            ArrayList<RestrictionEntry> restrictions = getResultExtras(true).getParcelableArrayList(
+                    Intent.EXTRA_RESTRICTIONS);
+            if (restrictions != null) {
+                int count = 1;
+                for (RestrictionEntry entry : restrictions) {
+                    Preference p = null;
+                    switch (entry.type) {
+                    case RestrictionEntry.TYPE_BOOLEAN:
+                        p = new CheckBoxPreference(context);
+                        p.setTitle(entry.title);
+                        p.setSummary(entry.description);
+                        ((CheckBoxPreference)p).setChecked(entry.getBooleanValue());
+                        break;
+                    case RestrictionEntry.TYPE_CHOICE:
+                    case RestrictionEntry.TYPE_CHOICE_LEVEL:
+                        p = new ListPreference(context);
+                        p.setTitle(entry.title);
+                        String value = entry.getStringValue();
+                        if (value == null) {
+                            value = entry.description;
+                        }
+                        p.setSummary(value);
+                        ((ListPreference)p).setEntryValues(entry.values);
+                        ((ListPreference)p).setEntries(entry.choices);
+                        ((ListPreference)p).setValue(entry.getStringValue());
+                        break;
+                    case RestrictionEntry.TYPE_MULTI_SELECT:
+                        p = new MultiSelectListPreference(context);
+                        p.setTitle(entry.title);
+                        ((MultiSelectListPreference)p).setEntryValues(entry.values);
+                        ((MultiSelectListPreference)p).setEntries(entry.choices);
+                        HashSet<String> set = new HashSet<String>();
+                        for (String s : entry.getMultipleValues()) {
+                            set.add(s);
+                        }
+                        ((MultiSelectListPreference)p).setValues(set);
+                        break;
+                    case RestrictionEntry.TYPE_NULL:
+                    default:
+                    }
+                    if (p != null) {
+                        p.setPersistent(false);
+                        p.setOrder(preference.getOrder() + count);
+                        // Store the restrictions key string as a key for the preference
+                        p.setKey(preference.getKey().substring(PKG_PREFIX.length()) + DELIMITER
+                                + entry.key);
+                        mAppList.addPreference(p);
+                        p.setOnPreferenceChangeListener(AppRestrictionsFragment.this);
+                        preference.childPreferences.add(p);
+                        count++;
+                    }
+                }
+                preference.setRestrictions(restrictions);
+            }
+            mUserManager.setApplicationRestrictions(packageName, restrictions, mUser);
+        }
+    }
+
+    @Override
+    public boolean onPreferenceClick(Preference preference) {
+        if (preference.getKey().startsWith(PKG_PREFIX)) {
+            AppRestrictionsPreference arp = (AppRestrictionsPreference) preference;
+            if (!arp.isRequired()) {
+                arp.setChecked(!arp.isChecked());
+                mSelectedPackages.put(arp.getKey().substring(PKG_PREFIX.length()), arp.isChecked());
+            }
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/src/com/android/settings/users/RestrictionsReceiver.java b/src/com/android/settings/users/RestrictionsReceiver.java
new file mode 100644
index 0000000..0eeb7cd
--- /dev/null
+++ b/src/com/android/settings/users/RestrictionsReceiver.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.users;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.RestrictionEntry;
+import android.os.Bundle;
+import android.util.Log;
+
+import com.android.settings.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/** Test class, to demonstrate the features. TODO: Remove or modify with real restrictions */
+public class RestrictionsReceiver extends BroadcastReceiver {
+
+    private static final String TAG = RestrictionsReceiver.class.getSimpleName();
+
+    public static final String KEY_VERSION = "version";
+    public static final String KEY_ENABLE_APPS = "enable_apps";
+    public static final String KEY_SECTIONS_TO_SHOW = "enable_sections";
+    public static final String KEY_CONTENT_RATING = "content_rating";
+
+    private static final int[] SECTION_IDS = {
+        R.id.wifi_settings,
+        R.id.bluetooth_settings,
+        R.id.data_usage_settings,
+        R.id.app_settings,
+        R.id.date_time_settings,
+        R.id.about_settings
+    };
+
+    private static final int[] SECTION_TITLE_IDS = {
+        R.string.wifi_settings,
+        R.string.bluetooth_settings,
+        R.string.data_usage_summary_title,
+        R.string.manageapplications_settings_title,
+        R.string.date_and_time,
+        R.string.about_settings
+    };
+
+    @Override
+    public void onReceive(final Context context, Intent intent) {
+        final PendingResult result = goAsync();
+        final ArrayList<RestrictionEntry> oldRestrictions =
+                intent.getParcelableArrayListExtra(Intent.EXTRA_RESTRICTIONS);
+        Log.i(TAG, "oldRestrictions = " + oldRestrictions);
+        new Thread() {
+            public void run() {
+                createRestrictions(context, result, oldRestrictions);
+            }
+        }.start();
+    }
+
+    private void createRestrictions(Context context,
+            PendingResult result, List<RestrictionEntry> old) {
+        ArrayList<RestrictionEntry> newRestrictions = new ArrayList<RestrictionEntry>();
+        boolean oldEnableApps = false;
+        String oldContentRating = "";
+        String[] oldEnabledSections = new String[0];
+        if (old != null) {
+            for (RestrictionEntry r : old) {
+                if (r.key.equals(KEY_ENABLE_APPS)) {
+                    oldEnableApps = r.getBooleanValue();
+                } else if (r.key.equals(KEY_CONTENT_RATING)) {
+                    oldContentRating = r.getStringValue();
+                } else if (r.key.equals(KEY_SECTIONS_TO_SHOW)) {
+                    oldEnabledSections = r.getMultipleValues();
+                }
+            }
+        }
+
+        RestrictionEntry r0 = new RestrictionEntry(KEY_VERSION, "1");
+        newRestrictions.add(r0);
+
+        RestrictionEntry r1 = new RestrictionEntry(KEY_ENABLE_APPS,
+                Boolean.toString(oldEnableApps));
+        r1.title = "Enable apps";
+        r1.description = "Show the Apps section in Settings";
+        r1.type = RestrictionEntry.TYPE_BOOLEAN;
+        newRestrictions.add(r1);
+
+        RestrictionEntry r2 = new RestrictionEntry(KEY_CONTENT_RATING, oldContentRating);
+        r2.title = "Test: Content rating";
+        r2.description = "Limit content to chosen rating and lower";
+        r2.type = RestrictionEntry.TYPE_CHOICE_LEVEL;
+        r2.values = new String[] { "G", "PG", "PG13", "R", "NR" };
+        r2.choices = new String[] { "G", "PG", "PG-13", "Restricted", "Not Rated" };
+        newRestrictions.add(r2);
+
+        String [] values = new String[SECTION_IDS.length];
+        String [] choices = new String[SECTION_IDS.length];
+        int i = 0;
+        for (int sectionId : SECTION_IDS) {
+            values[i] = Integer.toString(sectionId);
+            choices[i] = context.getString(SECTION_TITLE_IDS[i]);
+            i++;
+        }
+        RestrictionEntry r3 = new RestrictionEntry(KEY_SECTIONS_TO_SHOW, oldEnabledSections);
+        r3.type = RestrictionEntry.TYPE_MULTI_SELECT;
+        r3.choices = choices;
+        r3.values = values;
+        r3.title = "Test: Sections to show";
+        newRestrictions.add(r3);
+
+        Bundle extras = new Bundle();
+        extras.putParcelableArrayList(Intent.EXTRA_RESTRICTIONS, newRestrictions);
+        result.setResult(0, null, extras);
+        result.finish();
+    }
+}
diff --git a/src/com/android/settings/users/UserPreference.java b/src/com/android/settings/users/UserPreference.java
index 23cca73..6889747 100644
--- a/src/com/android/settings/users/UserPreference.java
+++ b/src/com/android/settings/users/UserPreference.java
@@ -20,6 +20,7 @@
 import com.android.settings.R;
 
 import android.content.Context;
+import android.os.UserHandle;
 import android.os.UserManager;
 import android.preference.Preference;
 import android.util.AttributeSet;
@@ -31,21 +32,32 @@
     public static final int USERID_UNKNOWN = -10;
 
     private OnClickListener mDeleteClickListener;
+    private OnClickListener mSettingsClickListener;
     private int mSerialNumber = -1;
     private int mUserId = USERID_UNKNOWN;
+    private boolean mRestricted;
+    static final int SETTINGS_ID = R.id.manage_user;
+    static final int DELETE_ID = R.id.trash_user;
 
     public UserPreference(Context context, AttributeSet attrs) {
-        this(context, attrs, USERID_UNKNOWN, false, null);
+        this(context, attrs, USERID_UNKNOWN, false, null, null);
     }
 
-    UserPreference(Context context, AttributeSet attrs, int userId, boolean showDelete,
-            OnClickListener deleteListener) {
+    UserPreference(Context context, AttributeSet attrs, int userId,
+            boolean showOptions, OnClickListener deleteListener,
+            OnClickListener settingsListener) {
         super(context, attrs);
-        if (showDelete) {
+        if (showOptions) {
             setWidgetLayoutResource(R.layout.preference_user_delete_widget);
             mDeleteClickListener = deleteListener;
+            mSettingsClickListener = settingsListener;
         }
         mUserId = userId;
+        if (mUserId > UserHandle.USER_OWNER) {
+            mRestricted = ((UserManager) getContext().getSystemService(Context.USER_SERVICE))
+                    .getUserInfo(mUserId).isRestricted();
+        }
+        setSummary(mRestricted ? R.string.user_limited : R.string.user_trusted);
     }
 
     @Override
@@ -55,6 +67,15 @@
             deleteView.setOnClickListener(mDeleteClickListener);
             deleteView.setTag(this);
         }
+        View settingsView = view.findViewById(R.id.manage_user);
+        if (settingsView != null) {
+            if (mRestricted) {
+                settingsView.setOnClickListener(mSettingsClickListener);
+                settingsView.setTag(this);
+            } else {
+                settingsView.setVisibility(View.INVISIBLE);
+            }
+        }
         super.onBindView(view);
     }
 
diff --git a/src/com/android/settings/users/UserRestrictionsActivity.java b/src/com/android/settings/users/UserRestrictionsActivity.java
new file mode 100644
index 0000000..5f377f3
--- /dev/null
+++ b/src/com/android/settings/users/UserRestrictionsActivity.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.users;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.app.Activity;
+import android.content.Context;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+import com.android.settings.R;
+
+import java.util.Map;
+
+public class UserRestrictionsActivity extends Activity implements OnClickListener {
+
+    private static final String TAG = UserRestrictionsActivity.class.getSimpleName();
+
+    static final String EXTRA_USER_NAME = "user_name";
+    static final String EXTRA_USER_ID = "user_id";
+    static final String EXTRA_ACCOUNTS = "accounts";
+
+    private Button mFinishButton;
+    private Button mBackButton;
+    private AppRestrictionsFragment mAppsFragment;
+    private UserInfo mUserInfo;
+    private boolean mNewUser;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.user_limits);
+
+        mBackButton = (Button) findViewById(R.id.back_button);
+        if (mBackButton != null) {
+            mBackButton.setOnClickListener(this);
+        }
+        mFinishButton = (Button) findViewById(R.id.next_button);
+        if (mFinishButton != null) {
+            mFinishButton.setOnClickListener(this);
+        }
+        mAppsFragment = (AppRestrictionsFragment)
+                getFragmentManager().findFragmentById(R.id.user_limits_fragment);
+
+        UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
+        String name = getIntent().getStringExtra(EXTRA_USER_NAME);
+        int userId = getIntent().getIntExtra(EXTRA_USER_ID, -1);
+        // Create the user so we have an id
+        if (userId == -1) {
+            mNewUser = true;
+            mUserInfo = um.createUser(name, UserInfo.FLAG_RESTRICTED);
+            um.setUserRestriction(UserManager.ALLOW_MODIFY_ACCOUNTS, false,
+                    new UserHandle(mUserInfo.id));
+
+            Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
+                    UserSettings.USER_DRAWABLES[
+                            mUserInfo.id % UserSettings.USER_DRAWABLES.length]);
+            um.setUserIcon(mUserInfo.id, bitmap);
+        } else {
+            mUserInfo = um.getUserInfo(userId);
+        }
+        if (mAppsFragment != null) {
+            mAppsFragment.setUser(new UserHandle(mUserInfo.id), mNewUser);
+        }
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (v == mFinishButton) {
+            if (mNewUser) {
+                AccountManager am = AccountManager.get(this);
+                Account [] accounts = am.getAccounts();
+                if (accounts != null) {
+                    for (Account account : accounts) {
+                        am.addSharedAccount(account,
+                                new UserHandle(mUserInfo.id));
+                    }
+                }
+            }
+
+            IPackageManager ipm = IPackageManager.Stub.asInterface(
+                    ServiceManager.getService("package"));
+            for (Map.Entry<String,Boolean> entry : mAppsFragment.mSelectedPackages.entrySet()) {
+                if (entry.getValue()) {
+                    // Enable selected apps
+                    try {
+                        ipm.installExistingPackageAsUser(entry.getKey(), mUserInfo.id);
+                    } catch (RemoteException re) {
+                    }
+                } else {
+                    // Blacklist all other apps, system or downloaded
+                    try {
+                        ipm.deletePackageAsUser(entry.getKey(), null, mUserInfo.id,
+                                PackageManager.DELETE_SYSTEM_APP);
+                    } catch (RemoteException re) {
+                    }
+                }
+            }
+            setResult(RESULT_OK);
+            mUserInfo = null;
+            finish();
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+
+        if (mUserInfo != null && mNewUser) {
+            UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
+            um.removeUser(mUserInfo.id);
+        }
+    }
+}
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index dbaaf37..b6385c8 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.users;
 
+import android.accounts.Account;
+import android.accounts.AccountManager;
 import android.app.ActivityManagerNative;
 import android.app.AlertDialog;
 import android.app.Dialog;
@@ -76,6 +78,8 @@
     private static final String KEY_USER_NICKNAME = "user_nickname";
     private static final String KEY_USER_LIST = "user_list";
     private static final String KEY_USER_ME = "user_me";
+    private static final String KEY_ADD_RESTRICTED_USER = "user_add_restricted";
+    private static final String KEY_ADD_TRUSTED_USER = "user_add_trusted";
 
     private static final int MENU_ADD_USER = Menu.FIRST;
     private static final int MENU_REMOVE_USER = Menu.FIRST+1;
@@ -91,7 +95,7 @@
     private static final String KEY_ADD_USER_LONG_MESSAGE_DISPLAYED =
             "key_add_user_long_message_displayed";
 
-    private static final int[] USER_DRAWABLES = {
+    static final int[] USER_DRAWABLES = {
         R.drawable.avatar_default_1,
         R.drawable.avatar_default_2,
         R.drawable.avatar_default_3,
@@ -105,6 +109,8 @@
     private PreferenceGroup mUserListCategory;
     private Preference mMePreference;
     private SelectableEditTextPreference mNicknamePreference;
+    private Preference mAddRestrictedUser;
+    private Preference mAddTrustedUser;
     private int mRemovingUserId = -1;
     private int mAddedUserId = 0;
     private boolean mAddingUser;
@@ -176,6 +182,14 @@
                 InputType.TYPE_TEXT_VARIATION_NORMAL | InputType.TYPE_TEXT_FLAG_CAP_WORDS);
         mNicknamePreference.setInitialSelectionMode(
                 SelectableEditTextPreference.SELECTION_SELECT_ALL);
+        mAddRestrictedUser = findPreference(KEY_ADD_RESTRICTED_USER);
+        mAddTrustedUser = findPreference(KEY_ADD_TRUSTED_USER);
+        mAddRestrictedUser.setOnPreferenceClickListener(this);
+        mAddTrustedUser.setOnPreferenceClickListener(this);
+        if (!mIsOwner || UserManager.getMaxSupportedUsers() < 2) {
+            removePreference(KEY_ADD_RESTRICTED_USER);
+            removePreference(KEY_ADD_TRUSTED_USER);
+        }
         loadProfile();
         setHasOptionsMenu(true);
         IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED);
@@ -207,13 +221,7 @@
 
     @Override
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
-        if (mIsOwner) {
-            if (UserManager.getMaxSupportedUsers() > mUserManager.getUsers(false).size()) {
-                MenuItem addUserItem = menu.add(0, MENU_ADD_USER, 0, R.string.user_add_user_menu);
-                addUserItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM
-                        | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
-            }
-        } else {
+        if (!mIsOwner) {
             String nickname = mUserManager.getUserName();
             MenuItem removeThisUser = menu.add(0, MENU_REMOVE_USER, 0,
                     getResources().getString(R.string.user_remove_user_menu, nickname));
@@ -284,6 +292,13 @@
         }
     }
 
+    private void onManageUserClicked(int userId) {
+        Intent appsChooser = new Intent();
+        appsChooser.setClass(getActivity(), UserRestrictionsActivity.class);
+        appsChooser.putExtra(UserRestrictionsActivity.EXTRA_USER_ID, userId);
+        startActivity(appsChooser);
+    }
+
     private void onUserCreated(int userId) {
         mAddedUserId = userId;
         showDialog(DIALOG_SETUP_USER);
@@ -438,7 +453,7 @@
                 mNicknamePreference.setSummary(user.name);
             } else {
                 pref = new UserPreference(getActivity(), null, user.id,
-                        UserHandle.myUserId() == UserHandle.USER_OWNER, this);
+                        UserHandle.myUserId() == UserHandle.USER_OWNER, this, this);
                 pref.setOnPreferenceClickListener(this);
                 pref.setKey("id=" + user.id);
                 mUserListCategory.addPreference(pref);
@@ -446,9 +461,9 @@
                     pref.setSummary(R.string.user_owner);
                 }
                 pref.setTitle(user.name);
-                if (!isInitialized(user)) {
-                    pref.setSummary(R.string.user_summary_not_set_up);
-                }
+//                if (!isInitialized(user)) {
+//                    pref.setSummary(R.string.user_summary_not_set_up);
+//                }
             }
             if (user.iconPath != null) {
                 if (mUserIcons.get(user.id) == null) {
@@ -462,10 +477,10 @@
         // Add a temporary entry for the user being created
         if (mAddingUser) {
             Preference pref = new UserPreference(getActivity(), null, UserPreference.USERID_UNKNOWN,
-                    false, null);
+                    false, null, null);
             pref.setEnabled(false);
             pref.setTitle(R.string.user_new_user_name);
-            pref.setSummary(R.string.user_adding_new_user);
+            //pref.setSummary(R.string.user_adding_new_user);
             pref.setIcon(R.drawable.avatar_default_1);
             mUserListCategory.addPreference(pref);
         }
@@ -557,6 +572,17 @@
                             MESSAGE_SETUP_USER, user.id, user.serialNumber));
                 }
             }
+        } else if (pref == mAddTrustedUser) {
+            onAddUserClicked();
+        } else if (pref == mAddRestrictedUser) {
+            Account[] accounts = ((AccountManager) getSystemService(Context.ACCOUNT_SERVICE))
+                    .getAccounts();
+            Intent intent = new Intent(getActivity(), UserRestrictionsActivity.class);
+            intent.putExtra(UserRestrictionsActivity.EXTRA_USER_NAME,
+                    getResources().getString(R.string.user_new_user_name));
+            intent.putExtra(UserRestrictionsActivity.EXTRA_ACCOUNTS,
+                    accounts);
+            startActivity(intent);
         }
         return false;
     }
@@ -569,7 +595,14 @@
     public void onClick(View v) {
         if (v.getTag() instanceof UserPreference) {
             int userId = ((UserPreference) v.getTag()).getUserId();
-            onRemoveUserClicked(userId);
+            switch (v.getId()) {
+            case UserPreference.DELETE_ID:
+                onRemoveUserClicked(userId);
+                break;
+            case UserPreference.SETTINGS_ID:
+                onManageUserClicked(userId);
+                break;
+            }
         }
     }