Merge "Removed extraneous string from strings.xml" into lmp-dev
diff --git a/res/layout/power_usage_details.xml b/res/layout/power_usage_details.xml
index a383a37..f711d9a 100644
--- a/res/layout/power_usage_details.xml
+++ b/res/layout/power_usage_details.xml
@@ -75,6 +75,21 @@
 
         </LinearLayout>
 
+        <LinearLayout
+                android:id="@+id/messages"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="vertical">
+
+            <TextView
+                    android:id="@+id/messages_title"
+                    style="?android:attr/listSeparatorTextViewStyle"
+                    android:layout_marginTop="6dip" />
+
+            <!-- Messages go here ... -->
+
+        </LinearLayout>
+
         <TextView
                 android:id="@+id/packages_section_title"
                 style="?android:attr/listSeparatorTextViewStyle"
diff --git a/res/layout/power_usage_message_item.xml b/res/layout/power_usage_message_item.xml
new file mode 100644
index 0000000..6f9e619
--- /dev/null
+++ b/res/layout/power_usage_message_item.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/message"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="2dip"
+        android:minHeight="?android:attr/listPreferredItemHeight"
+        android:paddingStart="4dip"
+        android:paddingEnd="?android:attr/scrollbarSize"
+        android:paddingBottom="4dip"
+        android:ellipsize="marquee"
+        android:textAppearance="?android:attr/textAppearanceMedium" />
diff --git a/res/layout/power_usage_package_item.xml b/res/layout/power_usage_package_item.xml
index d939229..6c31792 100644
--- a/res/layout/power_usage_package_item.xml
+++ b/res/layout/power_usage_package_item.xml
@@ -14,18 +14,13 @@
      limitations under the License.
 -->
 
-<RelativeLayout
+<TextView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content">
-    <!--Label for the item-->
-    <TextView
-        android:id="@+id/label"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-        android:singleLine="true"
-        android:layout_alignParentStart="true"
-        android:layout_marginBottom="2dip"
-        android:layout_marginTop="2dip" />
-</RelativeLayout>
+    android:id="@+id/label"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:textAppearance="?android:attr/textAppearanceMedium"
+    android:singleLine="true"
+    android:layout_alignParentStart="true"
+    android:layout_marginBottom="2dip"
+    android:layout_marginTop="2dip" />
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 5b6525e..ec4e13c 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -3874,12 +3874,11 @@
     <string name="usage_type_no_coverage">Time without a signal</string>
     <!-- Label for the total power capacity of the device's battery -->
     <string name="usage_type_total_battery_capacity">Total battery capacity</string>
-    <!-- Label for amount of power use that was computed -->
-    <string name="usage_type_computed_power">Computed power</string>
-    <!-- Label for minimum amount of actual power use -->
-    <string name="usage_type_min_actual_power">Min real power</string>
-    <!-- Label for maximum amount of power use -->
-    <string name="usage_type_max_actual_power">Max real power</string>
+    <!-- [CHAR_LIMIT=NONE] Label for amount of power use that was computed -->
+    <string name="usage_type_computed_power">Computed power use</string>
+    <!-- [CHAR_LIMIT=NONE] Label for amount of power use that was actually observed (though
+         the change in battery level) -->
+    <string name="usage_type_actual_power">Observed power use</string>
     <!-- Label for force stop action -->
     <string name="battery_action_stop">Force stop</string>
     <!-- Label for app details action -->
@@ -3906,6 +3905,9 @@
     <!-- Suggestion to switch to airplane mode to save power -->
     <string name="battery_sugg_radio">Switch to airplane mode to save power in areas with no cell coverage</string>
 
+    <!-- [CHAR_LIMIT=NONE] Description for power consumed by the flashlight -->
+    <string name="battery_desc_flashlight">Battery used by the flashlight</string>
+
     <!-- Description for power consumed by display -->
     <string name="battery_desc_display">Battery used by the display and backlight</string>
     <!-- Suggestion for reducing display power -->
@@ -3936,7 +3938,12 @@
     <string name="battery_desc_users">Battery used by user</string>
 
     <!-- [CHAR LIMIT=50] Description for unaccounted power use -->
-    <string name="battery_desc_unaccounted">Unknown power use</string>
+    <string name="battery_desc_unaccounted">Miscellaneous power use</string>
+    <!-- [CHAR LIMIT=NONE] Description for unaccounted power use -->
+    <string name="battery_msg_unaccounted">Battery use is an approximation of power
+        use and does not include every source of battery drain.  Miscellaneous is the difference
+        between the computed approximate power use and the actual drain observed on the
+        battery.</string>
     <!-- [CHAR LIMIT=50] Description for over-counted power use -->
     <string name="battery_desc_overcounted">Over-counted power use</string>
     <!-- Representation of a mAh value. [CHAR LIMIT=NONE] -->
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 8211816..d03305d 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -16,7 +16,11 @@
 
 package com.android.settings;
 
+import static android.content.Intent.EXTRA_USER;
+
+import android.annotation.Nullable;
 import android.app.ActivityManager;
+import android.app.ActivityManagerNative;
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.Fragment;
@@ -61,6 +65,7 @@
 import android.view.ViewGroup;
 import android.widget.ListView;
 import android.widget.TabWidget;
+
 import com.android.settings.dashboard.DashboardCategory;
 import com.android.settings.dashboard.DashboardTile;
 
@@ -73,6 +78,7 @@
 
 public final class Utils {
     private static final String TAG = "Settings";
+
     /**
      * Set the preference's title to the matching activity's label.
      */
@@ -110,6 +116,8 @@
      */
     private static final String META_DATA_PREFERENCE_SUMMARY = "com.android.settings.summary";
 
+    private static final String SETTINGS_PACKAGE_NAME = "com.android.settings";
+
     /**
      * Finds a matching activity for a preference's intent. If a matching
      * activity is not found, it will remove the preference.
@@ -613,28 +621,100 @@
     }
 
     /**
-     * Returns the {@link UserHandle} of the profile that a settings screen should refer to.
+     * Returns the target user for a Settings activity.
      *
-     * <p> This takes into account the id of the user that triggered the settings screen.
+     * The target user can be either the current user, the user that launched this activity or
+     * the user contained as an extra in the arguments or intent extras.
+     *
+     * Note: This is secure in the sense that it only returns a target user different to the current
+     * one if the app launching this activity is the Settings app itself, running in the same user
+     * or in one that is in the same profile group, or if the user id is provided by the system.
      */
-   public static UserHandle getProfileToDisplay(IActivityManager am, IBinder activityToken,
-           Bundle arguments) {
-       int currentUser = UserHandle.getCallingUserId();
-       // Check to see if it was called from a different user
+    public static UserHandle getSecureTargetUser(IBinder activityToken,
+           UserManager um, @Nullable Bundle arguments, @Nullable Bundle intentExtras) {
+        UserHandle currentUser = new UserHandle(UserHandle.myUserId());
+        IActivityManager am = ActivityManagerNative.getDefault();
+        try {
+            String launchedFromPackage = am.getLaunchedFromPackage(activityToken);
+            boolean launchedFromSettingsApp = SETTINGS_PACKAGE_NAME.equals(launchedFromPackage);
+
+            UserHandle launchedFromUser = new UserHandle(UserHandle.getUserId(
+                    am.getLaunchedFromUid(activityToken)));
+            if (launchedFromUser != null && !launchedFromUser.equals(currentUser)) {
+                // Check it's secure
+                if (isProfileOf(um, launchedFromUser)) {
+                    return launchedFromUser;
+                }
+            }
+            UserHandle extrasUser = intentExtras != null
+                    ? (UserHandle) intentExtras.getParcelable(EXTRA_USER) : null;
+            if (extrasUser != null && !extrasUser.equals(currentUser)) {
+                // Check it's secure
+                if (launchedFromSettingsApp && isProfileOf(um, extrasUser)) {
+                    return extrasUser;
+                }
+            }
+            UserHandle argumentsUser = arguments != null
+                    ? (UserHandle) arguments.getParcelable(EXTRA_USER) : null;
+            if (argumentsUser != null && !argumentsUser.equals(currentUser)) {
+                // Check it's secure
+                if (launchedFromSettingsApp && isProfileOf(um, argumentsUser)) {
+                    return argumentsUser;
+                }
+            }
+        } catch (RemoteException e) {
+            // Should not happen
+            Log.v(TAG, "Could not talk to activity manager.", e);
+        }
+        return currentUser;
+   }
+
+    /**
+     * Returns the target user for a Settings activity.
+     *
+     * The target user can be either the current user, the user that launched this activity or
+     * the user contained as an extra in the arguments or intent extras.
+     *
+     * You should use {@link #getSecureTargetUser(IBinder, UserManager, Bundle, Bundle)} if
+     * possible.
+     *
+     * @see #getInsecureTargetUser(IBinder, Bundle, Bundle)
+     */
+   public static UserHandle getInsecureTargetUser(IBinder activityToken, @Nullable Bundle arguments,
+           @Nullable Bundle intentExtras) {
+       UserHandle currentUser = new UserHandle(UserHandle.myUserId());
+       IActivityManager am = ActivityManagerNative.getDefault();
        try {
-           int launchedFromUser = UserHandle.getUserId(am.getLaunchedFromUid(activityToken));
-           if (launchedFromUser != currentUser) {
-               // This is a forwarded intent
-               return new UserHandle(launchedFromUser);
+           UserHandle launchedFromUser = new UserHandle(UserHandle.getUserId(
+                   am.getLaunchedFromUid(activityToken)));
+           if (launchedFromUser != null && !launchedFromUser.equals(currentUser)) {
+               return launchedFromUser;
+           }
+           UserHandle extrasUser = intentExtras != null
+                   ? (UserHandle) intentExtras.getParcelable(EXTRA_USER) : null;
+           if (extrasUser != null && !extrasUser.equals(currentUser)) {
+               return extrasUser;
+           }
+           UserHandle argumentsUser = arguments != null
+                   ? (UserHandle) arguments.getParcelable(EXTRA_USER) : null;
+           if (argumentsUser != null && !argumentsUser.equals(currentUser)) {
+               return argumentsUser;
            }
        } catch (RemoteException e) {
            // Should not happen
-           Log.v(TAG, "Could not get launching user.");
+           Log.v(TAG, "Could not talk to activity manager.", e);
+           return null;
        }
-       // TODO: Check fragment arguments. See: http://b/15466880
+       return currentUser;
+   }
 
-       // Default to current profile
-       return new UserHandle(currentUser);
+   /**
+    * Returns true if the user provided is in the same profiles group as the current user.
+    */
+   private static boolean isProfileOf(UserManager um, UserHandle otherUser) {
+       if (um == null || otherUser == null) return false;
+       return (UserHandle.myUserId() == otherUser.getIdentifier())
+               || um.getUserProfiles().contains(otherUser);
    }
 
     /**
diff --git a/src/com/android/settings/accounts/AccountPreferenceBase.java b/src/com/android/settings/accounts/AccountPreferenceBase.java
index 6125adc..28da591 100644
--- a/src/com/android/settings/accounts/AccountPreferenceBase.java
+++ b/src/com/android/settings/accounts/AccountPreferenceBase.java
@@ -1,4 +1,5 @@
 /*
+
  * Copyright (C) 2008 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -21,6 +22,7 @@
 import android.accounts.AuthenticatorDescription;
 import android.app.Activity;
 import android.app.ActivityManagerNative;
+import android.app.IActivityManager;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.SyncAdapterType;
@@ -68,9 +70,10 @@
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
         mUm = (UserManager) getSystemService(Context.USER_SERVICE);
-        mUserHandle = Utils.getProfileToDisplay(ActivityManagerNative.getDefault(),
-                getActivity().getActivityToken(), icicle);
-        mAuthenticatorHelper = new AuthenticatorHelper(getActivity(), mUserHandle, mUm, this);
+        final Activity activity = getActivity();
+        mUserHandle = Utils.getSecureTargetUser(activity.getActivityToken(), mUm, getArguments(),
+                activity.getIntent().getExtras());
+        mAuthenticatorHelper = new AuthenticatorHelper(activity, mUserHandle, mUm, this);
     }
 
     /**
@@ -135,7 +138,8 @@
     public ArrayList<String> getAuthoritiesForAccountType(String type) {
         if (mAccountTypeToAuthorities == null) {
             mAccountTypeToAuthorities = Maps.newHashMap();
-            SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypes();
+            SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypesAsUser(
+                    mUserHandle.getIdentifier());
             for (int i = 0, n = syncAdapters.length; i < n; i++) {
                 final SyncAdapterType sa = syncAdapters[i];
                 ArrayList<String> authorities = mAccountTypeToAuthorities.get(sa.accountType);
@@ -172,8 +176,8 @@
                     // correct text colors. Control colors will still be wrong,
                     // but there's not much we can do about it since we can't
                     // reference local color resources.
-                    final Context targetCtx = getActivity().createPackageContext(
-                            desc.packageName, 0);
+                    final Context targetCtx = getActivity().createPackageContextAsUser(
+                            desc.packageName, 0, mUserHandle);
                     final Theme baseTheme = getResources().newTheme();
                     baseTheme.applyStyle(com.android.settings.R.style.Theme_SettingsBase, true);
                     final Context themedCtx = new ContextThemeWrapper(targetCtx, 0);
diff --git a/src/com/android/settings/accounts/AccountSettings.java b/src/com/android/settings/accounts/AccountSettings.java
index e60bed9..13878d7 100644
--- a/src/com/android/settings/accounts/AccountSettings.java
+++ b/src/com/android/settings/accounts/AccountSettings.java
@@ -16,14 +16,13 @@
 
 package com.android.settings.accounts;
 
+
 import android.accounts.Account;
 import android.accounts.AccountManager;
-import android.accounts.OnAccountsUpdateListener;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.pm.UserInfo;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.UserHandle;
@@ -39,13 +38,17 @@
 import com.android.settings.Utils;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
 
+import static android.content.Intent.EXTRA_USER;
+
 /**
  * Settings screen for the account types on the device.
  * This shows all account types available for personal and work profiles.
+ *
+ * An extra {@link UserHandle} can be specified in the intent as {@link EXTRA_USER}, if the user for
+ * which the action needs to be performed is different to the one the Settings App will run in.
  */
 public class AccountSettings extends SettingsPreferenceFragment
         implements AuthenticatorHelper.OnAccountsUpdateListener,
@@ -146,7 +149,7 @@
         }
         final ProfileData profileData = new ProfileData();
         profileData.preferenceGroup = (PreferenceGroup) findPreference(categoryKey);
-        if (mUm.hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS)) {
+        if (mUm.hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, userHandle)) {
             removePreference(addAccountKey);
         } else {
             profileData.addAccountPreference = findPreference(addAccountKey);
@@ -189,7 +192,7 @@
     private void updateAccountTypes(ProfileData profileData) {
         profileData.preferenceGroup.removeAll();
         final ArrayList<AccountPreference> preferences = getAccountTypePreferences(
-                profileData.authenticatorHelper);
+                profileData.authenticatorHelper, profileData.userHandle);
         final int count = preferences.size();
         for (int i = 0; i < count; i++) {
             profileData.preferenceGroup.addPreference(preferences.get(i));
@@ -199,7 +202,8 @@
         }
     }
 
-    private ArrayList<AccountPreference> getAccountTypePreferences(AuthenticatorHelper helper) {
+    private ArrayList<AccountPreference> getAccountTypePreferences(AuthenticatorHelper helper,
+            UserHandle userHandle) {
         final String[] accountTypes = helper.getEnabledAccountTypes();
         final ArrayList<AccountPreference> accountTypePreferences =
                 new ArrayList<AccountPreference>(accountTypes.length);
@@ -212,7 +216,7 @@
             }
 
             final Account[] accounts = AccountManager.get(getActivity())
-                    .getAccountsByType(accountType);
+                    .getAccountsByTypeAsUser(accountType, userHandle);
             final boolean skipToAccount = accounts.length == 1
                     && !helper.hasAccountPreferences(accountType);
 
@@ -220,6 +224,7 @@
                 final Bundle fragmentArguments = new Bundle();
                 fragmentArguments.putParcelable(AccountSyncSettings.ACCOUNT_KEY,
                         accounts[0]);
+                fragmentArguments.putParcelable(EXTRA_USER, userHandle);
 
                 accountTypePreferences.add(new AccountPreference(getActivity(), label,
                         AccountSyncSettings.class.getName(), fragmentArguments,
@@ -229,6 +234,7 @@
                 fragmentArguments.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE, accountType);
                 fragmentArguments.putString(ManageAccountsSettings.KEY_ACCOUNT_LABEL,
                         label.toString());
+                fragmentArguments.putParcelable(EXTRA_USER, userHandle);
 
                 accountTypePreferences.add(new AccountPreference(getActivity(), label,
                         ManageAccountsSettings.class.getName(), fragmentArguments,
@@ -254,7 +260,7 @@
             ProfileData profileData = mProfiles.valueAt(i);
             if (preference == profileData.addAccountPreference) {
                 Intent intent = new Intent(ADD_ACCOUNT_ACTION);
-                intent.putExtra(Intent.EXTRA_USER_HANDLE, profileData.userHandle);
+                intent.putExtra(EXTRA_USER, profileData.userHandle);
                 startActivity(intent);
                 return true;
             }
diff --git a/src/com/android/settings/accounts/AccountSyncSettings.java b/src/com/android/settings/accounts/AccountSyncSettings.java
index 458adca..1bde8a3 100644
--- a/src/com/android/settings/accounts/AccountSyncSettings.java
+++ b/src/com/android/settings/accounts/AccountSyncSettings.java
@@ -90,6 +90,8 @@
                         new DialogInterface.OnClickListener() {
                     @Override
                     public void onClick(DialogInterface dialog, int which) {
+                        // TODO: We need an API to remove an account from a different user.
+                        // See: http://b/15466880
                         AccountManager.get(AccountSyncSettings.this.getActivity())
                                 .removeAccount(mAccount,
                                 new AccountManagerCallback<Boolean>() {
diff --git a/src/com/android/settings/accounts/AddAccountSettings.java b/src/com/android/settings/accounts/AddAccountSettings.java
index 34b6c8d..0af0260 100644
--- a/src/com/android/settings/accounts/AddAccountSettings.java
+++ b/src/com/android/settings/accounts/AddAccountSettings.java
@@ -22,22 +22,25 @@
 import android.accounts.AuthenticatorException;
 import android.accounts.OperationCanceledException;
 import android.app.Activity;
+import android.app.ActivityManagerNative;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
+import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.Log;
 import android.widget.Toast;
 
 import com.android.settings.R;
-import com.android.settings.Settings;
 import com.android.settings.Utils;
 
 import java.io.IOException;
 
+import static android.content.Intent.EXTRA_USER;
+
 /**
- * Entry point Actiivty for account setup. Works as follows
+ * Entry point Activity for account setup. Works as follows
  *
  * 1) When the other Activities launch this Activity, it launches {@link ChooseAccountActivity}
  *    without showing anything.
@@ -50,6 +53,9 @@
  * currently delegate the work to the other Activity. When we let this Activity do that work, users
  * would see the list of account types when leaving this Activity, since the UI is already ready
  * when returning from each account setup, which doesn't look good.
+ *
+ * An extra {@link UserHandle} can be specified in the intent as {@link EXTRA_USER}, if the user for
+ * which the action needs to be performed is different to the one the Settings App will run in.
  */
 public class AddAccountSettings extends Activity {
     /**
@@ -90,6 +96,7 @@
                     addAccountOptions.putParcelable(KEY_CALLER_IDENTITY, mPendingIntent);
                     addAccountOptions.putBoolean(EXTRA_HAS_MULTIPLE_USERS,
                             Utils.hasMultipleUsers(AddAccountSettings.this));
+                    addAccountOptions.putParcelable(EXTRA_USER, mUserHandle);
                     intent.putExtras(addAccountOptions);
                     startActivityForResult(intent, ADD_ACCOUNT_REQUEST);
                 } else {
@@ -116,6 +123,7 @@
     };
 
     private boolean mAddAccountCalled = false;
+    private UserHandle mUserHandle;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
@@ -127,7 +135,9 @@
         }
 
         final UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
-        if (um.hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS)) {
+        mUserHandle = Utils.getSecureTargetUser(getActivityToken(), um, null /* arguments */,
+                getIntent().getExtras());
+        if (um.hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, mUserHandle)) {
             // We aren't allowed to add an account.
             Toast.makeText(this, R.string.user_cannot_add_accounts_message, Toast.LENGTH_LONG)
                     .show();
@@ -150,6 +160,7 @@
         if (accountTypes != null) {
             intent.putExtra(AccountPreferenceBase.ACCOUNT_TYPES_FILTER_KEY, accountTypes);
         }
+        intent.putExtra(EXTRA_USER, mUserHandle);
         startActivityForResult(intent, CHOOSE_ACCOUNT_REQUEST);
     }
 
@@ -188,6 +199,14 @@
         mPendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(), 0);
         addAccountOptions.putParcelable(KEY_CALLER_IDENTITY, mPendingIntent);
         addAccountOptions.putBoolean(EXTRA_HAS_MULTIPLE_USERS, Utils.hasMultipleUsers(this));
+        // TODO: We need an API to add an account to a different user. See: http://b/15466880
+        int userId = mUserHandle.getIdentifier();
+        int callingUserId = UserHandle.getCallingUserId();
+        if (userId != callingUserId) {
+            Log.w(TAG, "Cannot add an account for user " + userId + " from " + callingUserId + ".");
+            finish();
+            return;
+        }
         AccountManager.get(this).addAccount(
                 accountType,
                 null, /* authTokenType */
diff --git a/src/com/android/settings/accounts/ChooseAccountActivity.java b/src/com/android/settings/accounts/ChooseAccountActivity.java
index 631fe47..7c0dbdb 100644
--- a/src/com/android/settings/accounts/ChooseAccountActivity.java
+++ b/src/com/android/settings/accounts/ChooseAccountActivity.java
@@ -18,6 +18,7 @@
 
 import android.accounts.AccountManager;
 import android.accounts.AuthenticatorDescription;
+import android.app.ActivityManagerNative;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -26,13 +27,18 @@
 import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.preference.Preference;
 import android.preference.PreferenceActivity;
 import android.preference.PreferenceGroup;
 import android.preference.PreferenceScreen;
 import android.util.Log;
+
 import com.android.internal.util.CharSequences;
 import com.android.settings.R;
+import com.android.settings.Utils;
+
 import com.google.android.collect.Maps;
 
 import java.util.ArrayList;
@@ -41,8 +47,13 @@
 import java.util.HashSet;
 import java.util.Map;
 
+import static android.content.Intent.EXTRA_USER;
+
 /**
  * Activity asking a user to select an account to be set up.
+ *
+ * An extra {@link UserHandle} can be specified in the intent as {@link EXTRA_USER}, if the user for
+ * which the action needs to be performed is different to the one the Settings App will run in.
  */
 public class ChooseAccountActivity extends PreferenceActivity {
 
@@ -55,7 +66,10 @@
     private HashMap<String, ArrayList<String>> mAccountTypeToAuthorities = null;
     private Map<String, AuthenticatorDescription> mTypeToAuthDescription
             = new HashMap<String, AuthenticatorDescription>();
-    
+    // The UserHandle of the user we are choosing an account for
+    private UserHandle mUserHandle;
+    private UserManager mUm;
+
     private static class ProviderEntry implements Comparable<ProviderEntry> {
         private final CharSequence name;
         private final String type;
@@ -92,6 +106,9 @@
             }
         }
         mAddAccountGroup = getPreferenceScreen();
+        mUm = UserManager.get(this);
+        mUserHandle = Utils.getSecureTargetUser(getActivityToken(), mUm, null /* arguments */,
+                getIntent().getExtras());
         updateAuthDescriptions();
     }
 
@@ -100,7 +117,8 @@
      * and update any UI that depends on AuthenticatorDescriptions in onAuthDescriptionsUpdated().
      */
     private void updateAuthDescriptions() {
-        mAuthDescs = AccountManager.get(this).getAuthenticatorTypes();
+        mAuthDescs = AccountManager.get(this).getAuthenticatorTypesAsUser(
+                mUserHandle.getIdentifier());
         for (int i = 0; i < mAuthDescs.length; i++) {
             mTypeToAuthDescription.put(mAuthDescs[i].type, mAuthDescs[i]);
         }
@@ -168,7 +186,8 @@
     public ArrayList<String> getAuthoritiesForAccountType(String type) {
         if (mAccountTypeToAuthorities == null) {
             mAccountTypeToAuthorities = Maps.newHashMap();
-            SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypes();
+            SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypesAsUser(
+                    mUserHandle.getIdentifier());
             for (int i = 0, n = syncAdapters.length; i < n; i++) {
                 final SyncAdapterType sa = syncAdapters[i];
                 ArrayList<String> authorities = mAccountTypeToAuthorities.get(sa.accountType);
@@ -196,8 +215,9 @@
         if (mTypeToAuthDescription.containsKey(accountType)) {
             try {
                 AuthenticatorDescription desc = mTypeToAuthDescription.get(accountType);
-                Context authContext = createPackageContext(desc.packageName, 0);
-                icon = authContext.getResources().getDrawable(desc.iconId);
+                Context authContext = createPackageContextAsUser(desc.packageName, 0, mUserHandle);
+                icon = mUm.getBadgedDrawableForUser(
+                        authContext.getResources().getDrawable(desc.iconId), mUserHandle);
             } catch (PackageManager.NameNotFoundException e) {
                 // TODO: place holder icon for missing account icons?
                 Log.w(TAG, "No icon name for account type " + accountType);
@@ -219,7 +239,7 @@
         if (mTypeToAuthDescription.containsKey(accountType)) {
             try {
                 AuthenticatorDescription desc = mTypeToAuthDescription.get(accountType);
-                Context authContext = createPackageContext(desc.packageName, 0);
+                Context authContext = createPackageContextAsUser(desc.packageName, 0, mUserHandle);
                 label = authContext.getResources().getText(desc.labelId);
             } catch (PackageManager.NameNotFoundException e) {
                 Log.w(TAG, "No label name for account type " + accountType);
@@ -245,6 +265,7 @@
     private void finishWithAccountType(String accountType) {
         Intent intent = new Intent();
         intent.putExtra(AddAccountSettings.EXTRA_SELECTED_ACCOUNT, accountType);
+        intent.putExtra(EXTRA_USER, mUserHandle);
         setResult(RESULT_OK, intent);
         finish();
     }
diff --git a/src/com/android/settings/accounts/ManageAccountsSettings.java b/src/com/android/settings/accounts/ManageAccountsSettings.java
index b5a6579..b69bf3f 100644
--- a/src/com/android/settings/accounts/ManageAccountsSettings.java
+++ b/src/com/android/settings/accounts/ManageAccountsSettings.java
@@ -18,7 +18,6 @@
 
 import android.accounts.Account;
 import android.accounts.AccountManager;
-import android.accounts.OnAccountsUpdateListener;
 import android.app.ActionBar;
 import android.app.Activity;
 import android.content.ContentResolver;
@@ -30,7 +29,9 @@
 import android.content.pm.ResolveInfo;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
+import android.os.UserHandle;
 import android.preference.Preference;
+import android.preference.Preference.OnPreferenceClickListener;
 import android.preference.PreferenceScreen;
 import android.util.Log;
 import android.view.LayoutInflater;
@@ -51,10 +52,13 @@
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.HashSet;
+import java.util.List;
+
+import static android.content.Intent.EXTRA_USER;
 
 /** Manages settings for Google Account. */
 public class ManageAccountsSettings extends AccountPreferenceBase
-        implements OnAccountsUpdateListener {
+        implements AuthenticatorHelper.OnAccountsUpdateListener {
     private static final String ACCOUNT_KEY = "account"; // to pass to auth settings
     public static final String KEY_ACCOUNT_TYPE = "account_type";
     public static final String KEY_ACCOUNT_LABEL = "account_label";
@@ -92,8 +96,7 @@
     @Override
     public void onStart() {
         super.onStart();
-        Activity activity = getActivity();
-        AccountManager.get(activity).addOnAccountsUpdatedListener(this, null, true);
+        mAuthenticatorHelper.listenToAccountUpdates();
     }
 
     @Override
@@ -122,13 +125,14 @@
             getActivity().setTitle(args.getString(KEY_ACCOUNT_LABEL));
         }
         updateAuthDescriptions();
+        showAccountsIfNeeded();
     }
 
     @Override
     public void onStop() {
         super.onStop();
         final Activity activity = getActivity();
-        AccountManager.get(activity).removeOnAccountsUpdatedListener(this);
+        mAuthenticatorHelper.stopListeningToAccountUpdates();
         activity.getActionBar().setDisplayOptions(0, ActionBar.DISPLAY_SHOW_CUSTOM);
         activity.getActionBar().setCustomView(null);
     }
@@ -146,6 +150,7 @@
     private void startAccountSettings(AccountPreference acctPref) {
         Bundle args = new Bundle();
         args.putParcelable(AccountSyncSettings.ACCOUNT_KEY, acctPref.getAccount());
+        args.putParcelable(EXTRA_USER, mUserHandle);
         ((SettingsActivity) getActivity()).startPreferencePanel(
                 AccountSyncSettings.class.getCanonicalName(), args,
                 R.string.account_sync_settings_title, acctPref.getAccount().name,
@@ -166,7 +171,8 @@
     @Override
     public void onPrepareOptionsMenu(Menu menu) {
         super.onPrepareOptionsMenu(menu);
-        boolean syncActive = ContentResolver.getCurrentSync() != null;
+        boolean syncActive = ContentResolver.getCurrentSyncsAsUser(
+                mUserHandle.getIdentifier()).isEmpty();
         menu.findItem(MENU_SYNC_NOW_ID).setVisible(!syncActive && mFirstAccount != null);
         menu.findItem(MENU_SYNC_CANCEL_ID).setVisible(syncActive && mFirstAccount != null);
     }
@@ -185,7 +191,8 @@
     }
 
     private void requestOrCancelSyncForAccounts(boolean sync) {
-        SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypes();
+        final int userId = mUserHandle.getIdentifier();
+        SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypesAsUser(userId);
         Bundle extras = new Bundle();
         extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
         int count = getPreferenceScreen().getPreferenceCount();
@@ -198,11 +205,13 @@
                 for (int j = 0; j < syncAdapters.length; j++) {
                     SyncAdapterType sa = syncAdapters[j];
                     if (syncAdapters[j].accountType.equals(mAccountType)
-                            && ContentResolver.getSyncAutomatically(account, sa.authority)) {
+                            && ContentResolver.getSyncAutomaticallyAsUser(account, sa.authority,
+                                    userId)) {
                         if (sync) {
-                            ContentResolver.requestSync(account, sa.authority, extras);
+                            ContentResolver.requestSyncAsUser(account, sa.authority, userId,
+                                    extras);
                         } else {
-                            ContentResolver.cancelSync(account, sa.authority);
+                            ContentResolver.cancelSyncAsUser(account, sa.authority, userId);
                         }
                     }
                 }
@@ -212,17 +221,23 @@
 
     @Override
     protected void onSyncStateUpdated() {
+        showSyncState();
+    }
+
+    private void showSyncState() {
         // Catch any delayed delivery of update messages
         if (getActivity() == null) return;
 
+        final int userId = mUserHandle.getIdentifier();
+
         // iterate over all the preferences, setting the state properly for each
-        SyncInfo currentSync = ContentResolver.getCurrentSync();
+        List<SyncInfo> currentSyncs = ContentResolver.getCurrentSyncsAsUser(userId);
 
         boolean anySyncFailed = false; // true if sync on any account failed
         Date date = new Date();
 
         // only track userfacing sync adapters when deciding if account is synced or not
-        final SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypes();
+        final SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypesAsUser(userId);
         HashSet<String> userFacing = new HashSet<String>();
         for (int k = 0, n = syncAdapters.length; k < n; k++) {
             final SyncAdapterType sa = syncAdapters[k];
@@ -245,15 +260,11 @@
             boolean syncingNow = false;
             if (authorities != null) {
                 for (String authority : authorities) {
-                    SyncStatusInfo status = ContentResolver.getSyncStatus(account, authority);
-                    boolean syncEnabled = ContentResolver.getSyncAutomatically(account, authority)
-                            && ContentResolver.getMasterSyncAutomatically()
-                            && (ContentResolver.getIsSyncable(account, authority) > 0);
+                    SyncStatusInfo status = ContentResolver.getSyncStatusAsUser(account, authority,
+                            userId);
+                    boolean syncEnabled = isSyncEnabled(userId, account, authority);
                     boolean authorityIsPending = ContentResolver.isSyncPending(account, authority);
-                    boolean activelySyncing = currentSync != null
-                            && currentSync.authority.equals(authority)
-                            && new Account(currentSync.account.name, currentSync.account.type)
-                                    .equals(account);
+                    boolean activelySyncing = isSyncing(currentSyncs, account, authority);
                     boolean lastSyncFailed = status != null
                             && syncEnabled
                             && status.lastFailureTime != 0
@@ -299,9 +310,34 @@
         mErrorInfoView.setVisibility(anySyncFailed ? View.VISIBLE : View.GONE);
     }
 
+
+    private boolean isSyncing(List<SyncInfo> currentSyncs, Account account, String authority) {
+        final int count = currentSyncs.size();
+        for (int i = 0; i < count;  i++) {
+            SyncInfo syncInfo = currentSyncs.get(i);
+            if (syncInfo.account.equals(account) && syncInfo.authority.equals(authority)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean isSyncEnabled(int userId, Account account, String authority) {
+        return ContentResolver.getSyncAutomaticallyAsUser(account, authority, userId)
+                && ContentResolver.getMasterSyncAutomaticallyAsUser(userId)
+                && (ContentResolver.getIsSyncableAsUser(account, authority, userId) > 0);
+    }
+
     @Override
-    public void onAccountsUpdated(Account[] accounts) {
+    public void onAccountsUpdate(UserHandle userHandle) {
+        showAccountsIfNeeded();
+        onSyncStateUpdated();
+    }
+
+    private void showAccountsIfNeeded() {
         if (getActivity() == null) return;
+        Account[] accounts = AccountManager.get(getActivity()).getAccountsAsUser(
+                mUserHandle.getIdentifier());
         getPreferenceScreen().removeAll();
         mFirstAccount = null;
         addPreferencesFromResource(R.xml.manage_accounts_settings);
@@ -341,7 +377,6 @@
             settingsTop.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
             getActivity().startActivity(settingsTop);
         }
-        onSyncStateUpdated();
     }
 
     private void addAuthenticatorSettings() {
@@ -415,13 +450,22 @@
                             LocationSettings.class.getName(),
                             R.string.location_settings_title));
                 } else {
-                    ResolveInfo ri = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
+                    ResolveInfo ri = pm.resolveActivityAsUser(intent,
+                            PackageManager.MATCH_DEFAULT_ONLY, mUserHandle.getIdentifier());
                     if (ri == null) {
                         prefs.removePreference(pref);
                         continue;
                     } else {
                         intent.putExtra(ACCOUNT_KEY, mFirstAccount);
                         intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
+                        pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+                            @Override
+                            public boolean onPreferenceClick(Preference preference) {
+                                getActivity().startActivityAsUser(preference.getIntent(),
+                                        mUserHandle);
+                                return true;
+                            }
+                        });
                     }
                 }
             }
diff --git a/src/com/android/settings/bluetooth/MessageAccessSettings.java b/src/com/android/settings/bluetooth/MessageAccessSettings.java
index bef59c8..913357c 100644
--- a/src/com/android/settings/bluetooth/MessageAccessSettings.java
+++ b/src/com/android/settings/bluetooth/MessageAccessSettings.java
@@ -54,8 +54,9 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        mUserHandle = Utils.getProfileToDisplay(ActivityManagerNative.getDefault(),
-                getActivity().getActivityToken(), savedInstanceState);
+
+        // TODO: Define behavior for managed profile. See: http://b/16287773
+        mUserHandle = new UserHandle(UserHandle.myUserId());
 
         addPreferencesFromResource(R.xml.bluetooth_message_access);
     }
diff --git a/src/com/android/settings/fuelgauge/BatteryHistoryChart.java b/src/com/android/settings/fuelgauge/BatteryHistoryChart.java
index 60e73f5..d88c516 100644
--- a/src/com/android/settings/fuelgauge/BatteryHistoryChart.java
+++ b/src/com/android/settings/fuelgauge/BatteryHistoryChart.java
@@ -154,6 +154,7 @@
     BatteryStats mStats;
     Intent mBatteryBroadcast;
     long mStatsPeriod;
+    int mBatteryLevel;
     String mMaxPercentLabelString;
     String mMinPercentLabelString;
     String mDurationString;
@@ -493,7 +494,7 @@
         mMinPercentLabelString = getContext().getResources().getString(
                 R.string.percentage, 0);
 
-        int batteryLevel = com.android.settings.Utils.getBatteryLevel(mBatteryBroadcast);
+        mBatteryLevel = com.android.settings.Utils.getBatteryLevel(mBatteryBroadcast);
         long remainingTimeUs = 0;
         mDischarging = true;
         if (mBatteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) == 0) {
@@ -503,10 +504,10 @@
                 String timeString = Formatter.formatShortElapsedTime(getContext(),
                         drainTime / 1000);
                 mChargeLabelString = getContext().getResources().getString(
-                        R.string.power_discharging_duration, batteryLevel, timeString);
+                        R.string.power_discharging_duration, mBatteryLevel, timeString);
             } else {
                 mChargeLabelString = getContext().getResources().getString(
-                        R.string.power_discharging, batteryLevel);
+                        R.string.power_discharging, mBatteryLevel);
             }
         } else {
             final long chargeTime = mStats.computeChargeTimeRemaining(elapsedRealtimeUs);
@@ -531,10 +532,10 @@
                     resId = R.string.power_charging_duration;
                 }
                 mChargeLabelString = getContext().getResources().getString(
-                        resId, batteryLevel, timeString);
+                        resId, mBatteryLevel, timeString);
             } else {
                 mChargeLabelString = getContext().getResources().getString(
-                        R.string.power_charging, batteryLevel, statusLabel);
+                        R.string.power_charging, mBatteryLevel, statusLabel);
             }
         }
         mDrainString = "";
@@ -772,14 +773,11 @@
         mDateLabels.clear();
 
         final long walltimeStart = mStartWallTime;
-        final long walltimeChange = mEndWallTime-walltimeStart;
+        final long walltimeChange = mEndWallTime > walltimeStart
+                ? (mEndWallTime-walltimeStart) : 1;
         long curWalltime = 0;
         long lastRealtime = 0;
 
-        if (walltimeChange == 0) {
-            return;
-        }
-
         final int batLow = mBatLow;
         final int batChange = mBatHigh-mBatLow;
 
@@ -967,8 +965,26 @@
             }
         }
 
-        // Figure out where the actual data ends on the screen.
-        x = mLevelLeft + (int)(((mEndDataWallTime-walltimeStart)*levelWidth)/walltimeChange);
+        if (lastY < 0 || lastX < 0) {
+            // Didn't get any data...
+            x = lastX = mLevelLeft;
+            y = lastY = mLevelTop + levelh - ((mBatteryLevel-batLow)*(levelh-1))/batChange;
+            Path path;
+            byte value = (byte)mBatteryLevel;
+            if (value <= mBatteryCriticalLevel) path = mBatCriticalPath;
+            else if (value <= mBatteryWarnLevel) path = mBatWarnPath;
+            else path = null; //mBatGoodPath;
+            if (path != null) {
+                path.moveTo(x, y);
+                lastLinePath = path;
+            }
+            mBatLevelPath.moveTo(x, y);
+            curLevelPath = mBatLevelPath;
+            x = w;
+        } else {
+            // Figure out where the actual data ends on the screen.
+            x = mLevelLeft + (int)(((mEndDataWallTime-walltimeStart)*levelWidth)/walltimeChange);
+        }
 
         finishPaths(x, h, levelh, startX, lastY, curLevelPath, lastX,
                 lastCharging, lastScreenOn, lastGpsOn, lastWifiRunning,
diff --git a/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java b/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java
index fd7d87a..e7326b1 100644
--- a/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java
+++ b/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java
@@ -22,6 +22,7 @@
 import android.os.BatteryStats;
 import android.preference.Preference;
 import android.view.View;
+import android.view.ViewGroup;
 import android.widget.ImageView;
 import android.widget.TextView;
 
@@ -39,6 +40,7 @@
 
     private boolean mHideLabels;
     private View mLabelHeader;
+    private BatteryHistoryChart mChart;
 
     public BatteryHistoryPreference(Context context, BatteryStats stats, Intent batteryBroadcast) {
         super(context);
@@ -66,7 +68,21 @@
 
         BatteryHistoryChart chart = (BatteryHistoryChart)view.findViewById(
                 R.id.battery_history_chart);
-        chart.setStats(mStats, mBatteryBroadcast);
+        if (mChart == null) {
+            // First time: use and initialize this chart.
+            chart.setStats(mStats, mBatteryBroadcast);
+            mChart = chart;
+        } else {
+            // All future times: forget the newly inflated chart, re-use the
+            // already initialized chart from last time.
+            ViewGroup parent = (ViewGroup)chart.getParent();
+            int index = parent.indexOfChild(chart);
+            parent.removeViewAt(index);
+            if (mChart.getParent() != null) {
+                ((ViewGroup)mChart.getParent()).removeView(mChart);
+            }
+            parent.addView(mChart, index);
+        }
         mLabelHeader = view.findViewById(R.id.labelsHeader);
         mLabelHeader.setVisibility(mHideLabels ? View.GONE : View.VISIBLE);
     }
diff --git a/src/com/android/settings/fuelgauge/PowerUsageDetail.java b/src/com/android/settings/fuelgauge/PowerUsageDetail.java
index d4624c4..fe4fd81 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageDetail.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageDetail.java
@@ -72,6 +72,7 @@
         R.string.battery_desc_voice,
         R.string.battery_desc_wifi,
         R.string.battery_desc_bluetooth,
+        R.string.battery_desc_flashlight,
         R.string.battery_desc_display,
         R.string.battery_desc_apps,
         R.string.battery_desc_users,
@@ -217,18 +218,28 @@
                 };
             } break;
             case UNACCOUNTED:
-            case OVERCOUNTED:
             {
                 types = new int[] {
                     R.string.usage_type_total_battery_capacity,
                     R.string.usage_type_computed_power,
-                    R.string.usage_type_min_actual_power,
-                    R.string.usage_type_max_actual_power,
+                    R.string.usage_type_actual_power,
                 };
                 values = new double[] {
                     helper.getPowerProfile().getBatteryCapacity(),
                     helper.getComputedPower(),
                     helper.getMinDrainedPower(),
+                };
+            } break;
+            case OVERCOUNTED:
+            {
+                types = new int[] {
+                    R.string.usage_type_total_battery_capacity,
+                    R.string.usage_type_computed_power,
+                    R.string.usage_type_actual_power,
+                };
+                values = new double[] {
+                    helper.getPowerProfile().getBatteryCapacity(),
+                    helper.getComputedPower(),
                     helper.getMaxDrainedPower(),
                 };
             } break;
@@ -290,6 +301,7 @@
     private Button mReportButton;
     private ViewGroup mDetailsParent;
     private ViewGroup mControlsParent;
+    private ViewGroup mMessagesParent;
     private long mStartTime;
     private BatterySipper.DrainType mDrainType;
     private Drawable mAppIcon;
@@ -390,10 +402,12 @@
 
         mDetailsParent = (ViewGroup)mRootView.findViewById(R.id.details);
         mControlsParent = (ViewGroup)mRootView.findViewById(R.id.controls);
+        mMessagesParent = (ViewGroup)mRootView.findViewById(R.id.messages);
 
         fillDetailsSection();
         fillPackagesSection(mUid);
         fillControlsSection(mUid);
+        fillMessagesSection(mUid);
         
         if (mUid >= Process.FIRST_APPLICATION_UID) {
             mForceStopButton.setText(R.string.force_stop);
@@ -497,8 +511,7 @@
                         break;
                     case R.string.usage_type_total_battery_capacity:
                     case R.string.usage_type_computed_power:
-                    case R.string.usage_type_min_actual_power:
-                    case R.string.usage_type_max_actual_power:
+                    case R.string.usage_type_actual_power:
                         value = getActivity().getString(R.string.mah, (long)(mValues[i]));
                         break;
                     case R.string.usage_type_gps:
@@ -591,6 +604,28 @@
         actionButton.setTag(new Integer(action));
     }
 
+    private void fillMessagesSection(int uid) {
+        boolean removeHeader = true;
+        switch (mDrainType) {
+            case UNACCOUNTED:
+                addMessage(R.string.battery_msg_unaccounted);
+                removeHeader = false;
+                break;
+        }
+        if (removeHeader) {
+            mMessagesParent.setVisibility(View.GONE);
+        }
+    }
+
+    private void addMessage(int message) {
+        final Resources res = getResources();
+        LayoutInflater inflater = getActivity().getLayoutInflater();
+        View item = inflater.inflate(R.layout.power_usage_message_item, null);
+        mMessagesParent.addView(item);
+        TextView messageView = (TextView) item.findViewById(R.id.message);
+        messageView.setText(res.getText(message));
+    }
+
     private void removePackagesSection() {
         View view;
         if ((view = mRootView.findViewById(R.id.packages_section_title)) != null) {
@@ -703,8 +738,7 @@
                 //if (ai.icon != 0) {
                 //    icon = ai.loadIcon(pm);
                 //}
-                ViewGroup item = (ViewGroup) inflater.inflate(R.layout.power_usage_package_item,
-                        null);
+                View item = inflater.inflate(R.layout.power_usage_package_item, null);
                 packagesParent.addView(item);
                 TextView labelView = (TextView) item.findViewById(R.id.label);
                 labelView.setText(mPackages[i]);
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index 70e9176..a691d4d 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -272,6 +272,26 @@
                 if (((int) (percentOfTotal + .5)) < 1) {
                     continue;
                 }
+                if (sipper.drainType == BatterySipper.DrainType.OVERCOUNTED) {
+                    // Don't show over-counted unless it is at least 2/3 the size of
+                    // the largest real entry, and its percent of total is more significant
+                    if (sipper.value < ((mStatsHelper.getMaxRealPower()*2)/3)) {
+                        continue;
+                    }
+                    if (percentOfTotal < 10) {
+                        continue;
+                    }
+                }
+                if (sipper.drainType == BatterySipper.DrainType.UNACCOUNTED) {
+                    // Don't show over-counted unless it is at least 1/2 the size of
+                    // the largest real entry, and its percent of total is more significant
+                    if (sipper.value < (mStatsHelper.getMaxRealPower()/2)) {
+                        continue;
+                    }
+                    if (percentOfTotal < 5) {
+                        continue;
+                    }
+                }
                 final UserHandle userHandle = new UserHandle(UserHandle.getUserId(sipper.getUid()));
                 final BatteryEntry entry = new BatteryEntry(getActivity(), mHandler, mUm, sipper);
                 final PowerGaugePreference pref = new PowerGaugePreference(getActivity(),
diff --git a/src/com/android/settings/users/UserDetailsSettings.java b/src/com/android/settings/users/UserDetailsSettings.java
index d342fad..fa559c3 100644
--- a/src/com/android/settings/users/UserDetailsSettings.java
+++ b/src/com/android/settings/users/UserDetailsSettings.java
@@ -83,8 +83,8 @@
                 throw new RuntimeException("Arguments to this fragment must contain the user id");
             }
             mUserInfo = mUserManager.getUserInfo(userId);
-            mPhonePref.setChecked(!mUserManager.hasUserRestriction(UserManager.DISALLOW_TELEPHONY,
-                    new UserHandle(userId)));
+            mPhonePref.setChecked(!mUserManager.hasUserRestriction(
+                    UserManager.DISALLOW_OUTGOING_CALLS, new UserHandle(userId)));
             mRemoveUserPref.setOnPreferenceClickListener(this);
         } else {
             // These are not for an existing user, just general Guest settings.
@@ -93,7 +93,7 @@
             mPhonePref.setTitle(R.string.user_enable_calling);
             mDefaultGuestRestrictions = mUserManager.getDefaultGuestRestrictions();
             mPhonePref.setChecked(
-                    !mDefaultGuestRestrictions.getBoolean(UserManager.DISALLOW_TELEPHONY));
+                    !mDefaultGuestRestrictions.getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
         }
         mPhonePref.setOnPreferenceChangeListener(this);
     }
@@ -114,13 +114,18 @@
     public boolean onPreferenceChange(Preference preference, Object newValue) {
         if (mGuestUser) {
             // TODO: Show confirmation dialog: b/15761405
-            mDefaultGuestRestrictions.putBoolean(UserManager.DISALLOW_TELEPHONY,
+            mDefaultGuestRestrictions.putBoolean(UserManager.DISALLOW_OUTGOING_CALLS,
                     !((Boolean) newValue));
+            // SMS is always disabled for guest
+            mDefaultGuestRestrictions.putBoolean(UserManager.DISALLOW_SMS, true);
             mUserManager.setDefaultGuestRestrictions(mDefaultGuestRestrictions);
         } else {
             // TODO: Show confirmation dialog: b/15761405
-            mUserManager.setUserRestriction(UserManager.DISALLOW_TELEPHONY, !((Boolean) newValue),
-                    new UserHandle(mUserInfo.id));
+            UserHandle userHandle = new UserHandle(mUserInfo.id);
+            mUserManager.setUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS,
+                    !((Boolean) newValue), userHandle);
+            mUserManager.setUserRestriction(UserManager.DISALLOW_SMS,
+                    !((Boolean) newValue), userHandle);
         }
         return true;
     }