Merge "Expose android.media.AudioManager.getProperty()" into jb-mr1-dev
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 61e5b4c..8711ad7 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -134,6 +134,7 @@
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/accessibilityservice/IAccessibilityServiceClient.P)
 $(call add-clean-step, rm -f $(PRODUCT_OUT)/system/media/video/Disco*)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/ImageProcessing_intermediates)
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/api/current.txt b/api/current.txt
index 3e9b7d9..b81a87b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -18794,6 +18794,7 @@
     field public static final java.lang.String DEVELOPMENT_SETTINGS_ENABLED = "development_settings_enabled";
     field public static final java.lang.String DEVICE_PROVISIONED = "device_provisioned";
     field public static final java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
+    field public static final java.lang.String MODE_RINGER = "mode_ringer";
     field public static final java.lang.String NETWORK_PREFERENCE = "network_preference";
     field public static final java.lang.String RADIO_BLUETOOTH = "bluetooth";
     field public static final java.lang.String RADIO_CELL = "cell";
@@ -18957,7 +18958,7 @@
     field public static final deprecated java.lang.String LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED = "lock_pattern_tactile_feedback_enabled";
     field public static final deprecated java.lang.String LOCK_PATTERN_VISIBLE = "lock_pattern_visible_pattern";
     field public static final deprecated java.lang.String LOGGING_ID = "logging_id";
-    field public static final java.lang.String MODE_RINGER = "mode_ringer";
+    field public static final deprecated java.lang.String MODE_RINGER = "mode_ringer";
     field public static final java.lang.String MODE_RINGER_STREAMS_AFFECTED = "mode_ringer_streams_affected";
     field public static final java.lang.String MUTE_STREAMS_AFFECTED = "mute_streams_affected";
     field public static final deprecated java.lang.String NETWORK_PREFERENCE = "network_preference";
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 9b82f2a..81d87659 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -52,6 +52,7 @@
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Debug;
+import android.os.DropBoxManager;
 import android.os.Environment;
 import android.os.Handler;
 import android.os.IBinder;
@@ -108,6 +109,7 @@
 import java.util.TimeZone;
 import java.util.regex.Pattern;
 
+import libcore.io.DropBox;
 import libcore.io.EventLogger;
 import libcore.io.IoUtils;
 
@@ -4831,7 +4833,10 @@
                         "Unable to instantiate Application():" + e.toString(), e);
             }
         }
-        
+
+        // add dropbox logging to libcore
+        DropBox.setReporter(new DropBoxReporter());
+
         ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
             public void onConfigurationChanged(Configuration newConfig) {
                 synchronized (mPackages) {
@@ -4887,6 +4892,25 @@
         }
     }
 
+    private class DropBoxReporter implements DropBox.Reporter {
+
+        private DropBoxManager dropBox;
+
+        public DropBoxReporter() {
+            dropBox = (DropBoxManager) getSystemContext().getSystemService(Context.DROPBOX_SERVICE);
+        }
+
+        @Override
+        public void addData(String tag, byte[] data, int flags) {
+            dropBox.addData(tag, data, flags);
+        }
+
+        @Override
+        public void addText(String tag, String data) {
+            dropBox.addText(tag, data);
+        }
+    }
+
     public static void main(String[] args) {
         SamplingProfilerIntegration.start();
 
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index cb83dc2..7896450 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1923,6 +1923,7 @@
                 contentView.setViewVisibility(rowId, View.GONE);
             }
 
+
             int i=0;
             while (i < mTexts.size() && i < rowIds.length) {
                 CharSequence str = mTexts.get(i);
@@ -1933,11 +1934,11 @@
                 i++;
             }
 
-            if  (mTexts.size() > rowIds.length) {
-                contentView.setViewVisibility(R.id.inbox_more, View.VISIBLE);
-            } else {
-                contentView.setViewVisibility(R.id.inbox_more, View.GONE);
-            }
+            contentView.setViewVisibility(R.id.inbox_end_pad,
+                    mTexts.size() > 0 ? View.VISIBLE : View.GONE);
+
+            contentView.setViewVisibility(R.id.inbox_more,
+                    mTexts.size() > rowIds.length ? View.VISIBLE : View.GONE);
 
             return contentView;
         }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index bb118b2..cc9abff 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -934,6 +934,7 @@
             MOVED_TO_GLOBAL.add(Settings.Global.POWER_SOUNDS_ENABLED);
             MOVED_TO_GLOBAL.add(Settings.Global.STAY_ON_WHILE_PLUGGED_IN);
             MOVED_TO_GLOBAL.add(Settings.Global.WIFI_SLEEP_POLICY);
+            MOVED_TO_GLOBAL.add(Settings.Global.MODE_RINGER);
         }
 
         private static void lazyInitCache() {
@@ -1497,6 +1498,12 @@
         @Deprecated
         public static final int WIFI_SLEEP_POLICY_NEVER = Global.WIFI_SLEEP_POLICY_NEVER;
 
+        /**
+         * @deprecated Use {@link android.provider.Settings.Global#MODE_RINGER} instead
+         */
+        @Deprecated
+        public static final String MODE_RINGER = Global.MODE_RINGER;
+
         //TODO: deprecate static IP constants
         /**
          * Whether to use static IP and other static network attributes.
@@ -1666,13 +1673,6 @@
         public static final String ALWAYS_FINISH_ACTIVITIES =
                 "always_finish_activities";
 
-
-        /**
-         * Ringer mode. This is used internally, changing this value will not
-         * change the ringer mode. See AudioManager.
-         */
-        public static final String MODE_RINGER = "mode_ringer";
-
         /**
          * Determines which streams are affected by ringer mode changes. The
          * stream type's bit should be set to 1 if it should be muted when going
@@ -5738,7 +5738,11 @@
         */
        public static final String WTF_IS_FATAL = "wtf_is_fatal";
 
-
+       /**
+        * Ringer mode. This is used internally, changing this value will not
+        * change the ringer mode. See AudioManager.
+        */
+       public static final String MODE_RINGER = "mode_ringer";
 
 
         // Populated lazily, guarded by class object:
diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java
index 0babcc5..1060bd8 100644
--- a/core/java/android/text/format/DateUtils.java
+++ b/core/java/android/text/format/DateUtils.java
@@ -45,7 +45,6 @@
 
     private static final String FAST_FORMAT_HMMSS = "%1$d:%2$02d:%3$02d";
     private static final String FAST_FORMAT_MMSS = "%1$02d:%2$02d";
-    private static final char TIME_PADDING = '0';
     private static final char TIME_SEPARATOR = ':';
 
 
@@ -648,33 +647,36 @@
         }
     }
 
+    private static void append(StringBuilder sb, long value, boolean pad, char zeroDigit) {
+        if (value < 10) {
+            if (pad) {
+                sb.append(zeroDigit);
+            }
+        } else {
+            sb.append((char) (zeroDigit + (value / 10)));
+        }
+        sb.append((char) (zeroDigit + (value % 10)));
+    }
+
     /**
-     * Fast formatting of h:mm:ss
+     * Fast formatting of h:mm:ss.
      */
     private static String formatElapsedTime(StringBuilder recycle, String format, long hours,
             long minutes, long seconds) {
         if (FAST_FORMAT_HMMSS.equals(format)) {
+            char zeroDigit = LocaleData.get(Locale.getDefault()).zeroDigit;
+
             StringBuilder sb = recycle;
             if (sb == null) {
                 sb = new StringBuilder(8);
             } else {
                 sb.setLength(0);
             }
-            sb.append(hours);
+            append(sb, hours, false, zeroDigit);
             sb.append(TIME_SEPARATOR);
-            if (minutes < 10) {
-                sb.append(TIME_PADDING);
-            } else {
-                sb.append(toDigitChar(minutes / 10));
-            }
-            sb.append(toDigitChar(minutes % 10));
+            append(sb, minutes, true, zeroDigit);
             sb.append(TIME_SEPARATOR);
-            if (seconds < 10) {
-                sb.append(TIME_PADDING);
-            } else {
-                sb.append(toDigitChar(seconds / 10));
-            }
-            sb.append(toDigitChar(seconds % 10));
+            append(sb, seconds, true, zeroDigit);
             return sb.toString();
         } else {
             return String.format(format, hours, minutes, seconds);
@@ -682,40 +684,28 @@
     }
 
     /**
-     * Fast formatting of m:ss
+     * Fast formatting of mm:ss.
      */
     private static String formatElapsedTime(StringBuilder recycle, String format, long minutes,
             long seconds) {
         if (FAST_FORMAT_MMSS.equals(format)) {
+            char zeroDigit = LocaleData.get(Locale.getDefault()).zeroDigit;
+
             StringBuilder sb = recycle;
             if (sb == null) {
                 sb = new StringBuilder(8);
             } else {
                 sb.setLength(0);
             }
-            if (minutes < 10) {
-                sb.append(TIME_PADDING);
-            } else {
-                sb.append(toDigitChar(minutes / 10));
-            }
-            sb.append(toDigitChar(minutes % 10));
+            append(sb, minutes, false, zeroDigit);
             sb.append(TIME_SEPARATOR);
-            if (seconds < 10) {
-                sb.append(TIME_PADDING);
-            } else {
-                sb.append(toDigitChar(seconds / 10));
-            }
-            sb.append(toDigitChar(seconds % 10));
+            append(sb, seconds, true, zeroDigit);
             return sb.toString();
         } else {
             return String.format(format, minutes, seconds);
         }
     }
 
-    private static char toDigitChar(long digit) {
-        return (char) (digit + '0');
-    }
-
     /**
      * Format a date / time such that if the then is on the same day as now, it shows
      * just the time and if it's a different day, it shows just the date.
@@ -1387,6 +1377,14 @@
         String endMonthDayString = isInstant ? null : endDate.format(MONTH_DAY_FORMAT);
         String endYearString = isInstant ? null : endDate.format(YEAR_FORMAT);
 
+        String startStandaloneMonthString = startMonthString;
+        String endStandaloneMonthString = endMonthString;
+        // We need standalone months for these strings in Persian (fa): http://b/6811327
+        if (!numericDate && !abbrevMonth && Locale.getDefault().getLanguage().equals("fa")) {
+            startStandaloneMonthString = startDate.format("%-B");
+            endStandaloneMonthString = endDate.format("%-B");
+        }
+
         if (startMonthNum != endMonthNum) {
             // Same year, different month.
             // Example: "October 28 - November 3"
@@ -1407,7 +1405,8 @@
                     startWeekDayString, startMonthString, startMonthDayString,
                     startYearString, startTimeString,
                     endWeekDayString, endMonthString, endMonthDayString,
-                    endYearString, endTimeString);
+                    endYearString, endTimeString,
+                    startStandaloneMonthString, endStandaloneMonthString);
         }
 
         if (startDay != endDay) {
@@ -1426,7 +1425,8 @@
                     startWeekDayString, startMonthString, startMonthDayString,
                     startYearString, startTimeString,
                     endWeekDayString, endMonthString, endMonthDayString,
-                    endYearString, endTimeString);
+                    endYearString, endTimeString,
+                    startStandaloneMonthString, endStandaloneMonthString);
         }
 
         // Same start and end day
diff --git a/core/java/android/text/format/Time.java b/core/java/android/text/format/Time.java
index 45d5a70..5ef86b1 100644
--- a/core/java/android/text/format/Time.java
+++ b/core/java/android/text/format/Time.java
@@ -151,6 +151,9 @@
     private static String sDateTimeFormat;
     private static String sAm;
     private static String sPm;
+    private static char sZeroDigit;
+
+    // Referenced by native code.
     private static String sDateCommand = "%a %b %e %H:%M:%S %Z %Y";
 
     /**
@@ -323,6 +326,7 @@
 
                 sAm = localeData.amPm[0];
                 sPm = localeData.amPm[1];
+                sZeroDigit = localeData.zeroDigit;
 
                 sShortMonths = localeData.shortMonthNames;
                 sLongMonths = localeData.longMonthNames;
@@ -338,12 +342,32 @@
                 sLocale = locale;
             }
 
-            return format1(format);
+            String result = format1(format);
+            if (sZeroDigit != '0') {
+                result = localizeDigits(result);
+            }
+            return result;
         }
     }
 
     native private String format1(String format);
 
+    // TODO: unify this with java.util.Formatter's copy.
+    private String localizeDigits(String s) {
+        int length = s.length();
+        int offsetToLocalizedDigits = sZeroDigit - '0';
+        StringBuilder result = new StringBuilder(length);
+        for (int i = 0; i < length; ++i) {
+            char ch = s.charAt(i);
+            if (ch >= '0' && ch <= '9') {
+                ch += offsetToLocalizedDigits;
+            }
+            result.append(ch);
+        }
+        return result.toString();
+    }
+
+
     /**
      * Return the current time in YYYYMMDDTHHMMSS<tz> format
      */
@@ -673,7 +697,7 @@
             int minutes = (offset % 3600) / 60;
             int hours = offset / 3600;
 
-            return String.format("%s%s%02d:%02d", base, sign, hours, minutes);
+            return String.format(Locale.US, "%s%s%02d:%02d", base, sign, hours, minutes);
         }
     }
 
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index ddc0319..33fe834 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -2528,6 +2528,9 @@
             adjust = (float) mContext.getResources().getDisplayMetrics().densityDpi
                     / mViewportDensityDpi;
         }
+        // We make bad assumptions about multiplying and dividing by 100, force
+        // them to be true with this hack
+        adjust = ((int) (adjust * 100)) / 100.0f;
         // Remove any update density messages in flight.
         // If the density is indeed different from WebView's default scale,
         // a new message will be queued.
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index 80a6782..1d864e5 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -287,6 +287,7 @@
         if (!exceedsMinScaleIncrement(mMinZoomScale, mMaxZoomScale)) {
             mMaxZoomScale = mMinZoomScale;
         }
+        sanitizeMinMaxScales();
     }
 
     public final float getScale() {
@@ -909,6 +910,14 @@
         }
     }
 
+    private void sanitizeMinMaxScales() {
+        if (mMinZoomScale > mMaxZoomScale) {
+            Log.w(LOGTAG, "mMinZoom > mMaxZoom!!! " + mMinZoomScale + " > " + mMaxZoomScale,
+                    new Exception());
+            mMaxZoomScale = mMinZoomScale;
+        }
+    }
+
     public void onSizeChanged(int w, int h, int ow, int oh) {
         // reset zoom and anchor to the top left corner of the screen
         // unless we are already zooming
@@ -933,6 +942,7 @@
             if (mInitialScale > 0 && mInitialScale < mMinZoomScale) {
                 mMinZoomScale = mInitialScale;
             }
+            sanitizeMinMaxScales();
         }
 
         dismissZoomPicker();
@@ -1004,6 +1014,7 @@
         } else {
             mMaxZoomScale = viewState.mMaxScale;
         }
+        sanitizeMinMaxScales();
     }
 
     /**
@@ -1033,6 +1044,7 @@
         if (!mMinZoomScaleFixed || settings.getUseWideViewPort()) {
             mMinZoomScale = newZoomOverviewScale;
             mMaxZoomScale = Math.max(mMaxZoomScale, mMinZoomScale);
+            sanitizeMinMaxScales();
         }
         // fit the content width to the current view for the first new picture
         // after first layout.
@@ -1113,6 +1125,7 @@
             mMinZoomScale = (mInitialScale > 0) ?
                     Math.min(mInitialScale, overviewScale) : overviewScale;
             mMaxZoomScale = Math.max(mMaxZoomScale, mMinZoomScale);
+            sanitizeMinMaxScales();
         }
 
         if (!mWebView.drawHistory()) {
diff --git a/core/res/res/layout/notification_action_list.xml b/core/res/res/layout/notification_action_list.xml
index 591c9ea..400decc 100644
--- a/core/res/res/layout/notification_action_list.xml
+++ b/core/res/res/layout/notification_action_list.xml
@@ -21,6 +21,7 @@
     android:layout_height="wrap_content"
     android:orientation="horizontal"
     android:visibility="gone"
+    android:layout_marginBottom="8dp"
     android:showDividers="middle"
     android:divider="?android:attr/listDivider"
     android:dividerPadding="12dp"
diff --git a/core/res/res/layout/notification_template_big_text.xml b/core/res/res/layout/notification_template_big_text.xml
index 988a81f..01f1acf 100644
--- a/core/res/res/layout/notification_template_big_text.xml
+++ b/core/res/res/layout/notification_template_big_text.xml
@@ -34,13 +34,14 @@
         android:layout_gravity="fill_vertical"
         android:layout_marginStart="@dimen/notification_large_icon_width"
         android:orientation="vertical"
-        android:paddingTop="2dp"
+        android:paddingTop="0dp"
         android:paddingBottom="2dp"
         android:gravity="top"
         >
         <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            android:minHeight="@dimen/notification_large_icon_height"
             android:orientation="vertical"
             android:layout_marginStart="8dp"
             android:layout_marginEnd="8dp"
@@ -50,7 +51,7 @@
                 android:id="@+id/line1"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:paddingTop="6dp"
+                android:paddingTop="8dp"
                 android:orientation="horizontal"
                 android:layout_gravity="top"
                 android:layout_weight="0"
diff --git a/core/res/res/layout/notification_template_inbox.xml b/core/res/res/layout/notification_template_inbox.xml
index 6ebb443..1b7e659 100644
--- a/core/res/res/layout/notification_template_inbox.xml
+++ b/core/res/res/layout/notification_template_inbox.xml
@@ -36,163 +36,178 @@
         android:layout_marginStart="@dimen/notification_large_icon_width"
         android:minHeight="@dimen/notification_large_icon_height"
         android:orientation="vertical"
-        android:paddingTop="2dp"
+        android:paddingTop="0dp"
         android:paddingBottom="2dp"
         android:gravity="top"
         >
         <LinearLayout
-            android:id="@+id/line1"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginStart="8dp"
-            android:layout_marginEnd="8dp"
-            android:paddingTop="6dp"
-            android:orientation="horizontal"
-            android:layout_weight="0"
+            android:minHeight="@dimen/notification_large_icon_height"
+            android:paddingTop="2dp"
+            android:orientation="vertical"
             >
-            <TextView android:id="@+id/title"
-                android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Title"
+            <LinearLayout
+                android:id="@+id/line1"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:paddingTop="6dp"
+                android:orientation="horizontal"
+                android:layout_weight="0"
+                >
+                <TextView android:id="@+id/title"
+                    android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Title"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:singleLine="true"
+                    android:ellipsize="marquee"
+                    android:fadingEdge="horizontal"
+                    android:layout_weight="1"
+                    />
+                <ViewStub android:id="@+id/time"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center"
+                    android:layout_weight="0"
+                    android:visibility="gone"
+                    android:layout="@layout/notification_template_part_time"
+                    />
+                <ViewStub android:id="@+id/chronometer"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center"
+                    android:layout_weight="0"
+                    android:visibility="gone"
+                    android:layout="@layout/notification_template_part_chronometer"
+                    />
+            </LinearLayout>
+            <TextView android:id="@+id/text2"
+                android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Line2"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="-2dp"
+                android:layout_marginBottom="-2dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
                 android:singleLine="true"
-                android:ellipsize="marquee"
                 android:fadingEdge="horizontal"
+                android:ellipsize="marquee"
+                android:visibility="gone"
+                android:layout_weight="0"
+                />
+            <ProgressBar
+                android:id="@android:id/progress"
+                android:layout_width="match_parent"
+                android:layout_height="12dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:visibility="gone"
+                android:layout_weight="0"
+                style="?android:attr/progressBarStyleHorizontal"
+                />
+            <TextView android:id="@+id/inbox_text0"
+                android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
                 android:layout_weight="1"
                 />
-            <ViewStub android:id="@+id/time"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center"
-                android:layout_weight="0"
+            <TextView android:id="@+id/inbox_text1"
+                android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
                 android:visibility="gone"
-                android:layout="@layout/notification_template_part_time"
+                android:layout_weight="1"
                 />
-            <ViewStub android:id="@+id/chronometer"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center"
-                android:layout_weight="0"
+            <TextView android:id="@+id/inbox_text2"
+                android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
                 android:visibility="gone"
-                android:layout="@layout/notification_template_part_chronometer"
+                android:layout_weight="1"
                 />
+            <TextView android:id="@+id/inbox_text3"
+                android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                />
+            <TextView android:id="@+id/inbox_text4"
+                android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                />
+            <TextView android:id="@+id/inbox_text5"
+                android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                />
+            <TextView android:id="@+id/inbox_text6"
+                android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                />
+            <TextView android:id="@+id/inbox_more"
+                android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                android:text="@android:string/ellipsis"
+                />
+            <FrameLayout 
+                android:id="@+id/inbox_end_pad"
+                android:layout_width="match_parent"
+                android:layout_height="8dip"
+                android:visibility="gone"
+                android:layout_weight="0"
+            />
         </LinearLayout>
-        <TextView android:id="@+id/text2"
-            android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Line2"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="-2dp"
-            android:layout_marginBottom="-2dp"
-            android:layout_marginStart="8dp"
-            android:layout_marginEnd="8dp"
-            android:singleLine="true"
-            android:fadingEdge="horizontal"
-            android:ellipsize="marquee"
-            android:visibility="gone"
-            android:layout_weight="0"
-            />
-        <ProgressBar
-            android:id="@android:id/progress"
-            android:layout_width="match_parent"
-            android:layout_height="12dp"
-            android:layout_marginStart="8dp"
-            android:layout_marginEnd="8dp"
-            android:visibility="gone"
-            android:layout_weight="0"
-            style="?android:attr/progressBarStyleHorizontal"
-            />
-        <TextView android:id="@+id/inbox_text0"
-            android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
-            android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:layout_marginStart="8dp"
-            android:layout_marginEnd="8dp"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:visibility="gone"
-            android:layout_weight="1"
-            />
-        <TextView android:id="@+id/inbox_text1"
-            android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
-            android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:layout_marginStart="8dp"
-            android:layout_marginEnd="8dp"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:visibility="gone"
-            android:layout_weight="1"
-            />
-        <TextView android:id="@+id/inbox_text2"
-            android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
-            android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:layout_marginStart="8dp"
-            android:layout_marginEnd="8dp"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:visibility="gone"
-            android:layout_weight="1"
-            />
-        <TextView android:id="@+id/inbox_text3"
-            android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
-            android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:layout_marginStart="8dp"
-            android:layout_marginEnd="8dp"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:visibility="gone"
-            android:layout_weight="1"
-            />
-        <TextView android:id="@+id/inbox_text4"
-            android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
-            android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:layout_marginStart="8dp"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:visibility="gone"
-            android:layout_weight="1"
-            />
-        <TextView android:id="@+id/inbox_text5"
-            android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
-            android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:layout_marginStart="8dp"
-            android:layout_marginEnd="8dp"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:visibility="gone"
-            android:layout_weight="1"
-            />
-        <TextView android:id="@+id/inbox_text6"
-            android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
-            android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:layout_marginStart="8dp"
-            android:layout_marginEnd="8dp"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:visibility="gone"
-            android:layout_weight="1"
-            />
-        <TextView android:id="@+id/inbox_more"
-            android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
-            android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:layout_marginStart="8dp"
-            android:layout_marginEnd="8dp"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:visibility="gone"
-            android:layout_weight="1"
-            android:text="@android:string/ellipsis"
-            />
         <ImageView
             android:layout_width="match_parent"
-            android:layout_height="1px"
+            android:layout_height="1dip"
+            android:layout_marginTop="-1px"
             android:id="@+id/action_divider"
-            android:visibility="gone"
             android:background="?android:attr/dividerHorizontal" />
         <include
             layout="@layout/notification_action_list"
@@ -202,9 +217,9 @@
             />
         <ImageView
             android:layout_width="match_parent"
-            android:layout_height="1px"
+            android:layout_height="1dip"
+            android:layout_marginTop="-1px"
             android:id="@+id/overflow_divider"
-            android:layout_marginTop="8dp"
             android:visibility="visible"
             android:background="?android:attr/dividerHorizontal" />
         <LinearLayout
diff --git a/core/res/res/values-fa/donottranslate-cldr.xml b/core/res/res/values-fa/donottranslate-cldr.xml
index b05268e..402311a 100644
--- a/core/res/res/values-fa/donottranslate-cldr.xml
+++ b/core/res/res/values-fa/donottranslate-cldr.xml
@@ -37,22 +37,22 @@
     <string name="time_wday_date">%1$s،‏ %2$s %3$s</string>
     <string name="wday_date">%2$s %3$s</string>
     <string name="time_wday">%1$s،‏ %2$s</string>
-    <string name="same_year_md1_md2">%3$s LLLL تا %8$s LLLL</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s LLLL تا %6$s %8$s LLLL</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s،‏ %3$s LLLL تا %10$s،‏ %8$s LLLL</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s،‏ %3$s LLLL تا %10$s،‏ %8$s LLLL</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s،‏ %1$s %3$s LLLL تا %10$s،‏ %6$s %8$s LLLL</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s،‏ %1$s %3$s LLLL تا %10$s،‏ %6$s %8$s LLLL</string>
+    <string name="same_year_md1_md2">%3$s %11$s تا %8$s %12$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %11$s تا %6$s %8$s %12$s</string>
+    <string name="same_year_md1_time1_md2_time2">%5$s،‏ %3$s %11$s تا %10$s،‏ %8$s %12$s</string>
+    <string name="same_month_md1_time1_md2_time2">%5$s،‏ %3$s %11$s تا %10$s،‏ %8$s %12$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s،‏ %1$s %3$s %11$s تا %10$s،‏ %6$s %8$s %12$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s،‏ %1$s %3$s %11$s تا %10$s،‏ %6$s %8$s %12$s</string>
     <string name="same_year_mdy1_time1_mdy2_time2">%5$s،‏ %3$s %2$s %4$s تا %10$s،‏ %8$s %7$s %9$s</string>
     <string name="same_month_mdy1_time1_mdy2_time2">%5$s،‏ %3$s %2$s %4$s تا %10$s،‏ %8$s %7$s %9$s</string>
     <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s،‏ %1$s %3$s %2$s %4$s تا %10$s،‏ %6$s %8$s %7$s %9$s</string>
     <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s،‏ %1$s %3$s %2$s %4$s تا %10$s،‏ %6$s %8$s %7$s %9$s</string>
     <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s %4$s تا %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_md1_md2">%3$s تا %8$s LLL</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s LLLL تا %6$s %8$s LLLL</string>
-    <string name="same_year_mdy1_mdy2">%3$s LLL تا %8$s %2$s %9$s</string>
+    <string name="same_month_md1_md2">%3$s تا %8$s %11$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %11$s تا %6$s %8$s %12$s</string>
+    <string name="same_year_mdy1_mdy2">%3$s %11$s تا %8$s %7$s %9$s</string>
     <string name="same_month_mdy1_mdy2">%3$s تا %8$s %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s LLL تا %6$s %8$s %2$s %9$s</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s %11$s تا %6$s %8$s %7$s %9$s</string>
     <string name="short_format_month">%b</string>
     <string name="full_wday_month_day_no_year">E d LLLL</string>
     <string name="abbrev_wday_month_day_no_year">E d LLLL</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ffc1a04..a424135 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -208,6 +208,7 @@
   <java-symbol type="id" name="inbox_text5" />
   <java-symbol type="id" name="inbox_text6" />
   <java-symbol type="id" name="inbox_more" />
+  <java-symbol type="id" name="inbox_end_pad" />
   <java-symbol type="id" name="status_bar_latest_event_content" />
   <java-symbol type="id" name="action_divider" />
   <java-symbol type="id" name="overflow_divider" />
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 3a398a1..5b3350a 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -480,6 +480,7 @@
         intentFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
         intentFilter.addAction(Intent.ACTION_SCREEN_ON);
         intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
+        intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
 
         // Register a configuration change listener only if requested by system properties
         // to monitor orientation changes (off by default)
@@ -608,7 +609,7 @@
         final ContentResolver cr = mContentResolver;
 
         int ringerModeFromSettings =
-                System.getInt(cr, System.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL);
+                Settings.Global.getInt(cr, System.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL);
         int ringerMode = ringerModeFromSettings;
         // sanity check in case the settings are restored from a device with incompatible
         // ringer modes
@@ -619,7 +620,7 @@
             ringerMode = AudioManager.RINGER_MODE_SILENT;
         }
         if (ringerMode != ringerModeFromSettings) {
-            System.putInt(cr, System.MODE_RINGER, ringerMode);
+            Settings.Global.putInt(cr, System.MODE_RINGER, ringerMode);
         }
         synchronized(mSettingsLock) {
             mRingerMode = ringerMode;
@@ -638,23 +639,30 @@
 
         // make sure settings for ringer mode are consistent with device type: non voice capable
         // devices (tablets) include media stream in silent mode whereas phones don't.
-        mRingerModeAffectedStreams = Settings.System.getInt(cr,
+        mRingerModeAffectedStreams = Settings.System.getIntForUser(cr,
                 Settings.System.MODE_RINGER_STREAMS_AFFECTED,
                 ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)|
-                 (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)));
+                 (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)),
+                 UserHandle.USER_CURRENT);
         if (mVoiceCapable) {
             mRingerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_MUSIC);
         } else {
             mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_MUSIC);
         }
-        Settings.System.putInt(cr,
-                Settings.System.MODE_RINGER_STREAMS_AFFECTED, mRingerModeAffectedStreams);
+        Settings.System.putIntForUser(cr,
+                Settings.System.MODE_RINGER_STREAMS_AFFECTED,
+                mRingerModeAffectedStreams,
+                UserHandle.USER_CURRENT);
 
-        mMuteAffectedStreams = System.getInt(cr,
+        mMuteAffectedStreams = System.getIntForUser(cr,
                 System.MUTE_STREAMS_AFFECTED,
-                ((1 << AudioSystem.STREAM_MUSIC)|(1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_SYSTEM)));
+                ((1 << AudioSystem.STREAM_MUSIC)|
+                 (1 << AudioSystem.STREAM_RING)|
+                 (1 << AudioSystem.STREAM_SYSTEM)),
+                 UserHandle.USER_CURRENT);
 
-        boolean masterMute = System.getInt(cr, System.VOLUME_MASTER_MUTE, 0) == 1;
+        boolean masterMute = System.getIntForUser(cr, System.VOLUME_MASTER_MUTE,
+                                                  0, UserHandle.USER_CURRENT) == 1;
         AudioSystem.setMasterMute(masterMute);
         broadcastMasterMuteStatus(masterMute);
 
@@ -1237,8 +1245,8 @@
 
     private void restoreMasterVolume() {
         if (mUseMasterVolume) {
-            float volume = Settings.System.getFloat(mContentResolver,
-                    Settings.System.VOLUME_MASTER, -1.0f);
+            float volume = Settings.System.getFloatForUser(mContentResolver,
+                    Settings.System.VOLUME_MASTER, -1.0f, UserHandle.USER_CURRENT);
             if (volume >= 0.0f) {
                 AudioSystem.setMasterVolume(volume);
             }
@@ -1674,6 +1682,10 @@
 
     /** @see AudioManager#reloadAudioSettings() */
     public void reloadAudioSettings() {
+        readAudioSettings(false /*userSwitch*/);
+    }
+
+    private void readAudioSettings(boolean userSwitch) {
         // restore ringer mode, ringer mode affected streams, mute affected streams and vibrate settings
         readPersistedSettings();
 
@@ -1682,6 +1694,10 @@
         for (int streamType = 0; streamType < numStreamTypes; streamType++) {
             VolumeStreamState streamState = mStreamStates[streamType];
 
+            if (userSwitch && mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) {
+                continue;
+            }
+
             synchronized (streamState) {
                 streamState.readSettings();
 
@@ -2536,7 +2552,8 @@
                 // device, continue otherwise
                 int defaultIndex = (device == AudioSystem.DEVICE_OUT_DEFAULT) ?
                                         AudioManager.DEFAULT_STREAM_VOLUME[mStreamType] : -1;
-                int index = Settings.System.getInt(mContentResolver, name, defaultIndex);
+                int index = Settings.System.getIntForUser(
+                        mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT);
                 if (index == -1) {
                     continue;
                 }
@@ -2547,7 +2564,8 @@
                 // or default index
                 defaultIndex = (index > 0) ?
                                     index : AudioManager.DEFAULT_STREAM_VOLUME[mStreamType];
-                int lastAudibleIndex = Settings.System.getInt(mContentResolver, name, defaultIndex);
+                int lastAudibleIndex = Settings.System.getIntForUser(
+                        mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT);
 
                 // a last audible index of 0 should never be stored for ring and notification
                 // streams on phones (voice capable devices).
@@ -2959,19 +2977,21 @@
                                    int persistType,
                                    int device) {
             if ((persistType & PERSIST_CURRENT) != 0) {
-                System.putInt(mContentResolver,
+                System.putIntForUser(mContentResolver,
                           streamState.getSettingNameForDevice(false /* lastAudible */, device),
-                          (streamState.getIndex(device, false /* lastAudible */) + 5)/ 10);
+                          (streamState.getIndex(device, false /* lastAudible */) + 5)/ 10,
+                          UserHandle.USER_CURRENT);
             }
             if ((persistType & PERSIST_LAST_AUDIBLE) != 0) {
-                System.putInt(mContentResolver,
+                System.putIntForUser(mContentResolver,
                         streamState.getSettingNameForDevice(true /* lastAudible */, device),
-                        (streamState.getIndex(device, true  /* lastAudible */) + 5) / 10);
+                        (streamState.getIndex(device, true  /* lastAudible */) + 5) / 10,
+                        UserHandle.USER_CURRENT);
             }
         }
 
         private void persistRingerMode(int ringerMode) {
-            System.putInt(mContentResolver, System.MODE_RINGER, ringerMode);
+            Settings.Global.putInt(mContentResolver, System.MODE_RINGER, ringerMode);
         }
 
         private void playSoundEffect(int effectType, int volume) {
@@ -3021,8 +3041,10 @@
         }
 
         private void onHandlePersistMediaButtonReceiver(ComponentName receiver) {
-            Settings.System.putString(mContentResolver, Settings.System.MEDIA_BUTTON_RECEIVER,
-                    receiver == null ? "" : receiver.flattenToString());
+            Settings.System.putStringForUser(mContentResolver,
+                                             Settings.System.MEDIA_BUTTON_RECEIVER,
+                                             receiver == null ? "" : receiver.flattenToString(),
+                                             UserHandle.USER_CURRENT);
         }
 
         private void cleanupPlayer(MediaPlayer mp) {
@@ -3058,13 +3080,17 @@
                     break;
 
                 case MSG_PERSIST_MASTER_VOLUME:
-                    Settings.System.putFloat(mContentResolver, Settings.System.VOLUME_MASTER,
-                            (float)msg.arg1 / (float)1000.0);
+                    Settings.System.putFloatForUser(mContentResolver,
+                                                    Settings.System.VOLUME_MASTER,
+                                                    (float)msg.arg1 / (float)1000.0,
+                                                    UserHandle.USER_CURRENT);
                     break;
 
                 case MSG_PERSIST_MASTER_VOLUME_MUTE:
-                    Settings.System.putInt(mContentResolver, Settings.System.VOLUME_MASTER_MUTE,
-                            msg.arg1);
+                    Settings.System.putIntForUser(mContentResolver,
+                                                 Settings.System.VOLUME_MASTER_MUTE,
+                                                 msg.arg1,
+                                                 UserHandle.USER_CURRENT);
                     break;
 
                 case MSG_PERSIST_RINGER_MODE:
@@ -3248,10 +3274,11 @@
             //       and mRingerModeAffectedStreams, so will leave this synchronized for now.
             //       mRingerModeMutedStreams and mMuteAffectedStreams are safe (only accessed once).
             synchronized (mSettingsLock) {
-                int ringerModeAffectedStreams = Settings.System.getInt(mContentResolver,
+                int ringerModeAffectedStreams = Settings.System.getIntForUser(mContentResolver,
                        Settings.System.MODE_RINGER_STREAMS_AFFECTED,
                        ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)|
-                       (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)));
+                       (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)),
+                       UserHandle.USER_CURRENT);
                 if (mVoiceCapable) {
                     ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_MUSIC);
                 } else {
@@ -3673,6 +3700,15 @@
                 AudioSystem.setParameters("screen_state=off");
             } else if (action.equalsIgnoreCase(Intent.ACTION_CONFIGURATION_CHANGED)) {
                 handleConfigurationChanged(context);
+            } else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
+                readAudioSettings(true /*userSwitch*/);
+                // preserve STREAM_MUSIC volume from one user to the next.
+                sendMsg(mAudioHandler,
+                        MSG_SET_ALL_VOLUMES,
+                        SENDMSG_QUEUE,
+                        0,
+                        0,
+                        mStreamStates[AudioSystem.STREAM_MUSIC], 0);
             }
         }
     }
@@ -4547,8 +4583,8 @@
      * Restore remote control receiver from the system settings.
      */
     private void restoreMediaButtonReceiver() {
-        String receiverName = Settings.System.getString(mContentResolver,
-                Settings.System.MEDIA_BUTTON_RECEIVER);
+        String receiverName = Settings.System.getStringForUser(mContentResolver,
+                Settings.System.MEDIA_BUTTON_RECEIVER, UserHandle.USER_CURRENT);
         if ((null != receiverName) && !receiverName.isEmpty()) {
             ComponentName eventReceiver = ComponentName.unflattenFromString(receiverName);
             // construct a PendingIntent targeted to the restored component name
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 2792704..6c5a4e2 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -148,6 +148,7 @@
         NetworkTimeUpdateService networkTimeUpdater = null;
         CommonTimeManagementService commonTimeMgmtService = null;
         InputManagerService inputManager = null;
+        TelephonyRegistry telephonyRegistry = null;
 
         // Create a shared handler thread for UI within the system server.
         // This thread is used by at least the following components:
@@ -218,7 +219,8 @@
             ServiceManager.addService(Context.DISPLAY_SERVICE, display, true);
 
             Slog.i(TAG, "Telephony Registry");
-            ServiceManager.addService("telephony.registry", new TelephonyRegistry(context));
+            telephonyRegistry = new TelephonyRegistry(context);
+            ServiceManager.addService("telephony.registry", telephonyRegistry);
 
             Slog.i(TAG, "Scheduling Policy");
             ServiceManager.addService(Context.SCHEDULING_POLICY_SERVICE,
@@ -844,6 +846,7 @@
         final StatusBarManagerService statusBarF = statusBar;
         final DreamManagerService dreamyF = dreamy;
         final InputManagerService inputManagerF = inputManager;
+        final TelephonyRegistry telephonyRegistryF = telephonyRegistry;
 
         // We now tell the activity manager it is okay to run third party
         // code.  It will call back into us once it has gotten to the state
@@ -971,6 +974,11 @@
                 } catch (Throwable e) {
                     reportWtf("making InputManagerService ready", e);
                 }
+                try {
+                    if (telephonyRegistryF != null) telephonyRegistryF.systemReady();
+                } catch (Throwable e) {
+                    reportWtf("making TelephonyRegistry ready", e);
+                }
             }
         });
 
diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java
index 8361477..26684de 100644
--- a/services/java/com/android/server/TelephonyRegistry.java
+++ b/services/java/com/android/server/TelephonyRegistry.java
@@ -16,14 +16,19 @@
 
 package com.android.server;
 
+import android.app.ActivityManager;
+import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.net.LinkCapabilities;
 import android.net.LinkProperties;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.Handler;
 import android.os.IBinder;
+import android.os.Message;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.telephony.CellLocation;
@@ -39,13 +44,11 @@
 import java.util.List;
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.net.NetworkInterface;
 
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.telephony.ITelephonyRegistry;
 import com.android.internal.telephony.IPhoneStateListener;
 import com.android.internal.telephony.DefaultPhoneNotifier;
-import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.ServiceStateTracker;
 import com.android.internal.telephony.TelephonyIntents;
@@ -58,6 +61,7 @@
 class TelephonyRegistry extends ITelephonyRegistry.Stub {
     private static final String TAG = "TelephonyRegistry";
     private static final boolean DBG = false;
+    private static final boolean DBG_LOC = false;
 
     private static class Record {
         String pkgForDebug;
@@ -66,7 +70,15 @@
 
         IPhoneStateListener callback;
 
+        int callerUid;
+
         int events;
+
+        @Override
+        public String toString() {
+            return "{pkgForDebug=" + pkgForDebug + " callerUid=" + callerUid +
+                    " events=" + Integer.toHexString(events) + "}";
+        }
     }
 
     private final Context mContext;
@@ -120,6 +132,32 @@
                 PhoneStateListener.LISTEN_DATA_CONNECTION_STATE |
                 PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR;
 
+    private static final int MSG_USER_SWITCHED = 1;
+
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_USER_SWITCHED: {
+                    Slog.d(TAG, "MSG_USER_SWITCHED userId=" + msg.arg1);
+                    TelephonyRegistry.this.notifyCellLocation(mCellLocation);
+                    break;
+                }
+            }
+        }
+    };
+
+    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHED,
+                       intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0));
+            }
+        }
+    };
+
     // we keep a copy of all of the state so we can send it out when folks
     // register for it
     //
@@ -140,10 +178,24 @@
         mConnectedApns = new ArrayList<String>();
     }
 
+    public void systemReady() {
+        // Watch for interesting updates
+        final IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_USER_SWITCHED);
+        filter.addAction(Intent.ACTION_USER_REMOVED);
+        mContext.registerReceiver(mBroadcastReceiver, filter);
+    }
+
+    @Override
     public void listen(String pkgForDebug, IPhoneStateListener callback, int events,
             boolean notifyNow) {
-        // Slog.d(TAG, "listen pkg=" + pkgForDebug + " events=0x" +
-        // Integer.toHexString(events));
+        int callerUid = UserHandle.getCallingUserId();
+        int myUid = UserHandle.myUserId();
+        if (DBG) {
+            Slog.d(TAG, "listen: E pkg=" + pkgForDebug + " events=0x" + Integer.toHexString(events)
+                + " myUid=" + myUid
+                + " callerUid=" + callerUid);
+        }
         if (events != 0) {
             /* Checks permission and throws Security exception */
             checkListenerPermission(events);
@@ -164,7 +216,9 @@
                     r.binder = b;
                     r.callback = callback;
                     r.pkgForDebug = pkgForDebug;
+                    r.callerUid = callerUid;
                     mRecords.add(r);
+                    if (DBG) Slog.i(TAG, "listen: add new record=" + r);
                 }
                 int send = events & (events ^ r.events);
                 r.events = events;
@@ -199,8 +253,9 @@
                             remove(r.binder);
                         }
                     }
-                    if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
+                    if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) {
                         try {
+                            if (DBG_LOC) Slog.d(TAG, "listen: mCellLocation=" + mCellLocation);
                             r.callback.onCellLocationChanged(new Bundle(mCellLocation));
                         } catch (RemoteException ex) {
                             remove(r.binder);
@@ -242,8 +297,9 @@
                             remove(r.binder);
                         }
                     }
-                    if ((events & PhoneStateListener.LISTEN_CELL_INFO) != 0) {
+                    if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO)) {
                         try {
+                            if (DBG_LOC) Slog.d(TAG, "listen: mCellInfo=" + mCellInfo);
                             r.callback.onCellInfoChanged(mCellInfo);
                         } catch (RemoteException ex) {
                             remove(r.binder);
@@ -346,8 +402,11 @@
         synchronized (mRecords) {
             mCellInfo = cellInfo;
             for (Record r : mRecords) {
-                if ((r.events & PhoneStateListener.LISTEN_CELL_INFO) != 0) {
+                if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO)) {
                     try {
+                        if (DBG_LOC) {
+                            Slog.d(TAG, "notifyCellInfo: mCellInfo=" + mCellInfo + " r=" + r);
+                        }
                         r.callback.onCellInfoChanged(cellInfo);
                     } catch (RemoteException ex) {
                         mRemoveList.add(r.binder);
@@ -424,7 +483,8 @@
         if (DBG) {
             Slog.i(TAG, "notifyDataConnection: state=" + state + " isDataConnectivityPossible="
                 + isDataConnectivityPossible + " reason='" + reason
-                + "' apn='" + apn + "' apnType=" + apnType + " networkType=" + networkType);
+                + "' apn='" + apn + "' apnType=" + apnType + " networkType=" + networkType
+                + " mRecords.size()=" + mRecords.size() + " mRecords=" + mRecords);
         }
         synchronized (mRecords) {
             boolean modified = false;
@@ -506,8 +566,12 @@
         synchronized (mRecords) {
             mCellLocation = cellLocation;
             for (Record r : mRecords) {
-                if ((r.events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
+                if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) {
                     try {
+                        if (DBG_LOC) {
+                            Slog.d(TAG, "notifyCellLocation: mCellLocation=" + mCellLocation
+                                    + " r=" + r);
+                        }
                         r.callback.onCellLocationChanged(new Bundle(cellLocation));
                     } catch (RemoteException ex) {
                         mRemoveList.add(r.binder);
@@ -712,4 +776,22 @@
             mRemoveList.clear();
         }
     }
+
+    private boolean validateEventsAndUserLocked(Record r, int events) {
+        int foregroundUser;
+        long callingIdentity = Binder.clearCallingIdentity();
+        boolean valid = false;
+        try {
+            foregroundUser = ActivityManager.getCurrentUser();
+            valid = r.callerUid ==  foregroundUser && (r.events & events) != 0;
+            if (DBG | DBG_LOC) {
+                Slog.d(TAG, "validateEventsAndUserLocked: valid=" + valid
+                        + " r.callerUid=" + r.callerUid + " foregroundUser=" + foregroundUser
+                        + " r.events=" + r.events + " events=" + events);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(callingIdentity);
+        }
+        return valid;
+    }
 }
diff --git a/services/java/com/android/server/updates/ConfigUpdateInstallReceiver.java b/services/java/com/android/server/updates/ConfigUpdateInstallReceiver.java
index a74a648..e07230d 100644
--- a/services/java/com/android/server/updates/ConfigUpdateInstallReceiver.java
+++ b/services/java/com/android/server/updates/ConfigUpdateInstallReceiver.java
@@ -89,8 +89,7 @@
                     // get the hash of the currently used value
                     String currentHash = getCurrentHash(getCurrentContent());
                     if (!verifyVersion(currentVersion, altVersion)) {
-                        EventLog.writeEvent(EventLogTags.CONFIG_INSTALL_FAILED,
-                                            "New version is not greater than current version");
+                        Slog.i(TAG, "Not installing, new version is <= current version");
                     } else if (!verifyPreviousHash(currentHash, altRequiredHash)) {
                         EventLog.writeEvent(EventLogTags.CONFIG_INSTALL_FAILED,
                                             "Current hash did not match required value");
@@ -224,7 +223,7 @@
         return signer.verify(Base64.decode(signature.getBytes(), Base64.DEFAULT));
     }
 
-    private void writeUpdate(File dir, File file, String content) {
+    private void writeUpdate(File dir, File file, String content) throws IOException {
         FileOutputStream out = null;
         File tmp = null;
         try {
@@ -248,8 +247,6 @@
             if (!tmp.renameTo(file)) {
                 throw new IOException("Failed to atomically rename " + file.getCanonicalPath());
             }
-        } catch (IOException e) {
-            Slog.e(TAG, "Failed to write update", e);
         } finally {
             if (tmp != null) {
                 tmp.delete();
@@ -258,7 +255,7 @@
         }
     }
 
-    private void install(String content, int version) {
+    private void install(String content, int version) throws IOException {
         writeUpdate(updateDir, updateContent, content);
         writeUpdate(updateDir, updateVersion, Long.toString(version));
     }
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 15ffd63..2fa41e7 100755
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -220,6 +220,7 @@
     public CellLocation getCellLocation() {
         try {
             Bundle bundle = getITelephony().getCellLocation();
+            if (bundle.isEmpty()) return null;
             CellLocation cl = CellLocation.newFromBundle(bundle);
             if (cl.isEmpty())
                 return null;
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java
index 4d6fd10..c585065 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java
@@ -70,6 +70,7 @@
         unitTests.add(new UT_unsigned(this, mRes, mCtx));
         unitTests.add(new UT_array_init(this, mRes, mCtx));
         unitTests.add(new UT_array_alloc(this, mRes, mCtx));
+        unitTests.add(new UT_kernel(this, mRes, mCtx));
         unitTests.add(new UT_clamp(this, mRes, mCtx));
         unitTests.add(new UT_clamp_relaxed(this, mRes, mCtx));
         unitTests.add(new UT_convert(this, mRes, mCtx));
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_kernel.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_kernel.java
new file mode 100644
index 0000000..e0bd33e
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_kernel.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2012 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.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.util.Log;
+
+public class UT_kernel extends UnitTest {
+    private Resources mRes;
+    private Allocation A;
+    private Allocation B;
+
+    protected UT_kernel(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Kernels (pass-by-value)", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_kernel s) {
+        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        int X = 5;
+        s.set_dimX(X);
+        typeBuilder.setX(X);
+        A = Allocation.createTyped(RS, typeBuilder.create());
+        s.bind_ain(A);
+        B = Allocation.createTyped(RS, typeBuilder.create());
+        s.bind_aout(B);
+
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_kernel s = new ScriptC_kernel(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.forEach_init_vars(A);
+        s.forEach_root(A, B);
+        s.invoke_verify_root();
+        s.invoke_kernel_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/kernel.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/kernel.rs
new file mode 100644
index 0000000..d6c9df3
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/kernel.rs
@@ -0,0 +1,47 @@
+#include "shared.rsh"
+
+int *ain;
+int *aout;
+int dimX;
+static bool failed = false;
+
+void init_vars(int *out) {
+    *out = 7;
+}
+
+
+int __attribute__((kernel)) root(int ain, uint32_t x) {
+    _RS_ASSERT(ain == 7);
+    return ain + x;
+}
+
+static bool test_root_output() {
+    bool failed = false;
+    int i;
+
+    for (i = 0; i < dimX; i++) {
+        _RS_ASSERT(aout[i] == (i + ain[i]));
+    }
+
+    if (failed) {
+        rsDebug("test_root_output FAILED", 0);
+    }
+    else {
+        rsDebug("test_root_output PASSED", 0);
+    }
+
+    return failed;
+}
+
+void verify_root() {
+    failed |= test_root_output();
+}
+
+void kernel_test() {
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}