Merge "Adding callback for widget size changed, and potentially other extra info"
diff --git a/api/current.txt b/api/current.txt
index c4d8968..56a34d6 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4069,10 +4069,12 @@
     method public void setWallpaperOffsetSteps(float, float);
     method public void setWallpaperOffsets(android.os.IBinder, float, float);
     method public void suggestDesiredDimensions(int, int);
+    field public static final java.lang.String ACTION_CHANGE_LIVE_WALLPAPER = "android.service.wallpaper.CHANGE_LIVE_WALLPAPER";
     field public static final java.lang.String ACTION_LIVE_WALLPAPER_CHOOSER = "android.service.wallpaper.LIVE_WALLPAPER_CHOOSER";
     field public static final java.lang.String COMMAND_DROP = "android.home.drop";
     field public static final java.lang.String COMMAND_SECONDARY_TAP = "android.wallpaper.secondaryTap";
     field public static final java.lang.String COMMAND_TAP = "android.wallpaper.tap";
+    field public static final java.lang.String EXTRA_LIVE_WALLPAPER_COMPONENT = "android.service.wallpaper.extra.LIVE_WALLPAPER_COMPONENT";
     field public static final java.lang.String WALLPAPER_PREVIEW_META_DATA = "android.wallpaper.preview";
   }
 
@@ -10984,8 +10986,8 @@
     method public java.nio.ByteBuffer[] getInputBuffers();
     method public java.nio.ByteBuffer[] getOutputBuffers();
     method public final java.util.Map<java.lang.String, java.lang.Object> getOutputFormat();
-    method public final void queueInputBuffer(int, int, int, long, int);
-    method public final void queueSecureInputBuffer(int, int, android.media.MediaCodec.CryptoInfo, long, int);
+    method public final void queueInputBuffer(int, int, int, long, int) throws android.media.MediaCodec.CryptoException;
+    method public final void queueSecureInputBuffer(int, int, android.media.MediaCodec.CryptoInfo, long, int) throws android.media.MediaCodec.CryptoException;
     method public final void release();
     method public final void releaseOutputBuffer(int, boolean);
     method public final void start();
@@ -11010,6 +11012,11 @@
     field public int size;
   }
 
+  public static final class MediaCodec.CryptoException extends java.lang.RuntimeException {
+    ctor public MediaCodec.CryptoException(int, java.lang.String);
+    method public int getErrorCode();
+  }
+
   public static final class MediaCodec.CryptoInfo {
     ctor public MediaCodec.CryptoInfo();
     method public void set(int, int[], int[], byte[], byte[], int);
@@ -13087,6 +13094,7 @@
     field public static final java.lang.String EXTRA_WIFI_P2P_DEVICE = "wifiP2pDevice";
     field public static final java.lang.String EXTRA_WIFI_P2P_INFO = "wifiP2pInfo";
     field public static final java.lang.String EXTRA_WIFI_STATE = "wifi_p2p_state";
+    field public static final int NO_SERVICE_REQUESTS = 3; // 0x3
     field public static final int P2P_UNSUPPORTED = 1; // 0x1
     field public static final java.lang.String WIFI_P2P_CONNECTION_CHANGED_ACTION = "android.net.wifi.p2p.CONNECTION_STATE_CHANGE";
     field public static final java.lang.String WIFI_P2P_DISCOVERY_CHANGED_ACTION = "android.net.wifi.p2p.DISCOVERY_STATE_CHANGE";
@@ -16326,9 +16334,11 @@
   public final class CalendarContract {
     field public static final java.lang.String ACCOUNT_TYPE_LOCAL = "LOCAL";
     field public static final java.lang.String ACTION_EVENT_REMINDER = "android.intent.action.EVENT_REMINDER";
+    field public static final java.lang.String ACTION_HANDLE_CUSTOM_EVENT = "android.provider.calendar.action.HANDLE_CUSTOM_EVENT";
     field public static final java.lang.String AUTHORITY = "com.android.calendar";
     field public static final java.lang.String CALLER_IS_SYNCADAPTER = "caller_is_syncadapter";
     field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String EXTRA_CUSTOM_APP_URI = "customAppUri";
     field public static final java.lang.String EXTRA_EVENT_ALL_DAY = "allDay";
     field public static final java.lang.String EXTRA_EVENT_BEGIN_TIME = "beginTime";
     field public static final java.lang.String EXTRA_EVENT_END_TIME = "endTime";
@@ -16490,6 +16500,8 @@
     field public static final int AVAILABILITY_TENTATIVE = 2; // 0x2
     field public static final java.lang.String CALENDAR_ID = "calendar_id";
     field public static final java.lang.String CAN_INVITE_OTHERS = "canInviteOthers";
+    field public static final java.lang.String CUSTOM_APP_PACKAGE = "customAppPackage";
+    field public static final java.lang.String CUSTOM_APP_URI = "customAppUri";
     field public static final java.lang.String DESCRIPTION = "description";
     field public static final java.lang.String DISPLAY_COLOR = "displayColor";
     field public static final java.lang.String DTEND = "dtend";
@@ -22548,6 +22560,7 @@
   }
 
   public class Display {
+    method public void getCurrentSizeRange(android.graphics.Point, android.graphics.Point);
     method public int getDisplayId();
     method public deprecated int getHeight();
     method public void getMetrics(android.util.DisplayMetrics);
@@ -26033,10 +26046,12 @@
     method public void setMimeType(java.lang.String);
   }
 
-  public class WebSettings {
+  public abstract class WebSettings {
     method public boolean enableSmoothTransition();
     method public boolean getAllowContentAccess();
     method public boolean getAllowFileAccess();
+    method public abstract boolean getAllowFileAccessFromFileURLs();
+    method public abstract boolean getAllowUniversalAccessFromFileURLs();
     method public synchronized boolean getBlockNetworkImage();
     method public synchronized boolean getBlockNetworkLoads();
     method public boolean getBuiltInZoomControls();
@@ -26078,6 +26093,8 @@
     method public synchronized java.lang.String getUserAgentString();
     method public void setAllowContentAccess(boolean);
     method public void setAllowFileAccess(boolean);
+    method public abstract void setAllowFileAccessFromFileURLs(boolean);
+    method public abstract void setAllowUniversalAccessFromFileURLs(boolean);
     method public synchronized void setAppCacheEnabled(boolean);
     method public synchronized void setAppCacheMaxSize(long);
     method public synchronized void setAppCachePath(java.lang.String);
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 53a0186..8cd8900 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -194,6 +194,12 @@
                 String key = nextArgRequired();
                 String value = nextArgRequired();
                 intent.putExtra(key, Uri.parse(value));
+            } else if (opt.equals("--ecn")) {
+                String key = nextArgRequired();
+                String value = nextArgRequired();
+                ComponentName cn = ComponentName.unflattenFromString(value);
+                if (cn == null) throw new IllegalArgumentException("Bad component name: " + value);
+                intent.putExtra(key, cn);
             } else if (opt.equals("--eia")) {
                 String key = nextArgRequired();
                 String value = nextArgRequired();
@@ -1366,6 +1372,7 @@
                 "    [--el <EXTRA_KEY> <EXTRA_LONG_VALUE> ...]\n" +
                 "    [--ef <EXTRA_KEY> <EXTRA_FLOAT_VALUE> ...]\n" +
                 "    [--eu <EXTRA_KEY> <EXTRA_URI_VALUE> ...]\n" +
+                "    [--ecn <EXTRA_KEY> <EXTRA_COMPONENT_NAME_VALUE>]\n" +
                 "    [--eia <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]\n" +
                 "    [--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]\n" +
                 "    [--efa <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]]\n" +
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index c057d66..6f19934 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -67,6 +67,23 @@
             = "android.service.wallpaper.LIVE_WALLPAPER_CHOOSER";
 
     /**
+     * Directly launch live wallpaper preview, allowing the user to immediately
+     * confirm to switch to a specific live wallpaper.  You must specify
+     * {@link #EXTRA_LIVE_WALLPAPER_COMPONENT} with the ComponentName of
+     * a live wallpaper component that is to be shown.
+     */
+    public static final String ACTION_CHANGE_LIVE_WALLPAPER
+            = "android.service.wallpaper.CHANGE_LIVE_WALLPAPER";
+
+    /**
+     * Extra in {@link #ACTION_CHANGE_LIVE_WALLPAPER} that specifies the
+     * ComponentName of a live wallpaper that should be shown as a preview,
+     * for the user to confirm.
+     */
+    public static final String EXTRA_LIVE_WALLPAPER_COMPONENT
+            = "android.service.wallpaper.extra.LIVE_WALLPAPER_COMPONENT";
+
+    /**
      * Manifest entry for activities that respond to {@link Intent#ACTION_SET_WALLPAPER}
      * which allows them to provide a custom large icon associated with this action.
      */
diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java
index c4aa691..593762a 100644
--- a/core/java/android/provider/CalendarContract.java
+++ b/core/java/android/provider/CalendarContract.java
@@ -19,6 +19,7 @@
 
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.app.Activity;
 import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.content.ContentProviderClient;
@@ -98,6 +99,32 @@
     public static final String ACTION_EVENT_REMINDER = "android.intent.action.EVENT_REMINDER";
 
     /**
+     * Activity Action: Display the event to the user in the custom app as
+     * specified in {@link EventsColumns#CUSTOM_APP_PACKAGE}. The custom app
+     * will be started via {@link Activity#startActivityForResult(Intent, int)}
+     * and it should call {@link Activity#setResult(int)} with
+     * {@link Activity#RESULT_OK} or {@link Activity#RESULT_CANCELED} to
+     * acknowledge whether the action was handled or not.
+     * <p>
+     * Input: {@link Intent#getData} has the event URI. The extra
+     * {@link #EXTRA_EVENT_BEGIN_TIME} has the start time of the instance. The
+     * extra {@link #EXTRA_CUSTOM_APP_URI} will have the
+     * {@link EventsColumns#CUSTOM_APP_URI}.
+     * <p>
+     * Output: {@link Activity#RESULT_OK} if this was handled; otherwise
+     * {@link Activity#RESULT_CANCELED}
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_HANDLE_CUSTOM_EVENT =
+        "android.provider.calendar.action.HANDLE_CUSTOM_EVENT";
+
+    /**
+     * Intent Extras key: {@link EventsColumns#CUSTOM_APP_URI} for the event in
+     * the {@link #ACTION_HANDLE_CUSTOM_EVENT} intent
+     */
+    public static final String EXTRA_CUSTOM_APP_URI = "customAppUri";
+
+    /**
      * Intent Extras key: The start time of an event or an instance of a
      * recurring event. (milliseconds since epoch)
      */
@@ -1176,6 +1203,22 @@
          * <P>Type: INTEGER (boolean, readonly)</P>
          */
         public static final String CAN_INVITE_OTHERS = "canInviteOthers";
+
+        /**
+         * The package name of the custom app that can provide a richer
+         * experience for the event. See the ACTION TYPE
+         * {@link CalendarContract#ACTION_HANDLE_CUSTOM_EVENT} for details.
+         * Column name.
+         * <P> Type: TEXT </P>
+         */
+        public static final String CUSTOM_APP_PACKAGE = "customAppPackage";
+
+        /**
+         * The URI used by the custom app for the event. Column name.
+         * <P>Type: TEXT</P>
+         */
+        public static final String CUSTOM_APP_URI = "customAppUri";
+
     }
 
     /**
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 9612151..19d8d5c 100755
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -1816,6 +1816,181 @@
         public static final String BEARER = "bearer";
     }
 
+    /**
+     * Contains received SMS cell broadcast messages.
+     */
+    public static final class CellBroadcasts implements BaseColumns {
+
+        /** Not instantiable. */
+        private CellBroadcasts() {}
+
+        /**
+         * The content:// style URL for this table
+         */
+        public static final Uri CONTENT_URI =
+            Uri.parse("content://cellbroadcasts");
+
+        /**
+         * Message geographical scope.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String GEOGRAPHICAL_SCOPE = "geo_scope";
+
+        /**
+         * Message serial number.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String SERIAL_NUMBER = "serial_number";
+
+        /**
+         * PLMN of broadcast sender. (SERIAL_NUMBER + PLMN + LAC + CID) uniquely identifies a
+         * broadcast for duplicate detection purposes.
+         * <P>Type: TEXT</P>
+         */
+        public static final String PLMN = "plmn";
+
+        /**
+         * Location Area (GSM) or Service Area (UMTS) of broadcast sender. Unused for CDMA.
+         * Only included if Geographical Scope of message is not PLMN wide (01).
+         * <P>Type: INTEGER</P>
+         */
+        public static final String LAC = "lac";
+
+        /**
+         * Cell ID of message sender (GSM/UMTS). Unused for CDMA. Only included when the
+         * Geographical Scope of message is cell wide (00 or 11).
+         * <P>Type: INTEGER</P>
+         */
+        public static final String CID = "cid";
+
+        /**
+         * Message code (OBSOLETE: merged into SERIAL_NUMBER).
+         * <P>Type: INTEGER</P>
+         */
+        public static final String V1_MESSAGE_CODE = "message_code";
+
+        /**
+         * Message identifier (OBSOLETE: renamed to SERVICE_CATEGORY).
+         * <P>Type: INTEGER</P>
+         */
+        public static final String V1_MESSAGE_IDENTIFIER = "message_id";
+
+        /**
+         * Service category (GSM/UMTS message identifier, CDMA service category).
+         * <P>Type: INTEGER</P>
+         */
+        public static final String SERVICE_CATEGORY = "service_category";
+
+        /**
+         * Message language code.
+         * <P>Type: TEXT</P>
+         */
+        public static final String LANGUAGE_CODE = "language";
+
+        /**
+         * Message body.
+         * <P>Type: TEXT</P>
+         */
+        public static final String MESSAGE_BODY = "body";
+
+        /**
+         * Message delivery time.
+         * <P>Type: INTEGER (long)</P>
+         */
+        public static final String DELIVERY_TIME = "date";
+
+        /**
+         * Has the message been viewed?
+         * <P>Type: INTEGER (boolean)</P>
+         */
+        public static final String MESSAGE_READ = "read";
+
+        /**
+         * Message format (3GPP or 3GPP2).
+         * <P>Type: INTEGER</P>
+         */
+        public static final String MESSAGE_FORMAT = "format";
+
+        /**
+         * Message priority (including emergency).
+         * <P>Type: INTEGER</P>
+         */
+        public static final String MESSAGE_PRIORITY = "priority";
+
+        /**
+         * ETWS warning type (ETWS alerts only).
+         * <P>Type: INTEGER</P>
+         */
+        public static final String ETWS_WARNING_TYPE = "etws_warning_type";
+
+        /**
+         * CMAS message class (CMAS alerts only).
+         * <P>Type: INTEGER</P>
+         */
+        public static final String CMAS_MESSAGE_CLASS = "cmas_message_class";
+
+        /**
+         * CMAS category (CMAS alerts only).
+         * <P>Type: INTEGER</P>
+         */
+        public static final String CMAS_CATEGORY = "cmas_category";
+
+        /**
+         * CMAS response type (CMAS alerts only).
+         * <P>Type: INTEGER</P>
+         */
+        public static final String CMAS_RESPONSE_TYPE = "cmas_response_type";
+
+        /**
+         * CMAS severity (CMAS alerts only).
+         * <P>Type: INTEGER</P>
+         */
+        public static final String CMAS_SEVERITY = "cmas_severity";
+
+        /**
+         * CMAS urgency (CMAS alerts only).
+         * <P>Type: INTEGER</P>
+         */
+        public static final String CMAS_URGENCY = "cmas_urgency";
+
+        /**
+         * CMAS certainty (CMAS alerts only).
+         * <P>Type: INTEGER</P>
+         */
+        public static final String CMAS_CERTAINTY = "cmas_certainty";
+
+        /**
+         * The default sort order for this table
+         */
+        public static final String DEFAULT_SORT_ORDER = DELIVERY_TIME + " DESC";
+
+        /**
+         * Query columns for instantiating {@link android.telephony.CellBroadcastMessage} objects.
+         */
+        public static final String[] QUERY_COLUMNS = {
+                _ID,
+                GEOGRAPHICAL_SCOPE,
+                PLMN,
+                LAC,
+                CID,
+                SERIAL_NUMBER,
+                SERVICE_CATEGORY,
+                LANGUAGE_CODE,
+                MESSAGE_BODY,
+                DELIVERY_TIME,
+                MESSAGE_READ,
+                MESSAGE_FORMAT,
+                MESSAGE_PRIORITY,
+                ETWS_WARNING_TYPE,
+                CMAS_MESSAGE_CLASS,
+                CMAS_CATEGORY,
+                CMAS_RESPONSE_TYPE,
+                CMAS_SEVERITY,
+                CMAS_URGENCY,
+                CMAS_CERTAINTY
+        };
+    }
+
     public static final class Intents {
         private Intents() {
             // Not instantiable
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 7ce96c0..6917fb2 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -140,6 +140,7 @@
         boolean mIsCreating;
         boolean mDrawingAllowed;
         boolean mOffsetsChanged;
+        boolean mFixedSizeAllowed;
         int mWidth;
         int mHeight;
         int mFormat;
@@ -211,7 +212,7 @@
 
             @Override
             public void setFixedSize(int width, int height) {
-                if (Process.myUid() != Process.SYSTEM_UID) {
+                if (!mFixedSizeAllowed) {
                     // Regular apps can't do this.  It can only work for
                     // certain designs of window animations, so you can't
                     // rely on it.
@@ -385,7 +386,12 @@
                 updateSurface(false, false, false);
             }
         }
-        
+
+        /** {@hide} */
+        public void setFixedSizeAllowed(boolean allowed) {
+            mFixedSizeAllowed = allowed;
+        }
+
         /**
          * Called once to initialize the engine.  After returning, the
          * engine's surface will be created by the framework.
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 54c62ee..e3f5b96 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -58,9 +58,14 @@
 
     private final AccessibilityNodePrefetcher mPrefetcher;
 
+    private final long mMyLooperThreadId;
+
+    private final int mMyProcessId;
+
     public AccessibilityInteractionController(ViewRootImpl viewRootImpl) {
-        // mView is never null - the caller has already checked.
-        Looper looper = viewRootImpl.mView.mContext.getMainLooper();
+        Looper looper =  viewRootImpl.mHandler.getLooper();
+        mMyLooperThreadId = looper.getThread().getId();
+        mMyProcessId = Process.myPid();
         mHandler = new PrivateHandler(looper);
         mViewRootImpl = viewRootImpl;
         mPrefetcher = new AccessibilityNodePrefetcher();
@@ -137,8 +142,7 @@
         // thread in this process, set the message as a static reference so
         // after this call completes the same thread but in the interrogating
         // client can handle the message to generate the result.
-        if (interrogatingPid == Process.myPid()
-                && interrogatingTid == Looper.getMainLooper().getThread().getId()) {
+        if (interrogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) {
             AccessibilityInteractionClient.getInstanceForThread(
                     interrogatingTid).setSameThreadMessage(message);
         } else {
@@ -169,7 +173,7 @@
             } else {
                 root = findViewByAccessibilityId(accessibilityViewId);
             }
-            if (root != null && isDisplayedOnScreen(root)) {
+            if (root != null && root.isDisplayedOnScreen()) {
                 mPrefetcher.prefetchAccessibilityNodeInfos(root, virtualDescendantId, flags, infos);
             }
         } finally {
@@ -199,8 +203,7 @@
         // thread in this process, set the message as a static reference so
         // after this call completes the same thread but in the interrogating
         // client can handle the message to generate the result.
-        if (interrogatingPid == Process.myPid()
-                && interrogatingTid == Looper.getMainLooper().getThread().getId()) {
+        if (interrogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) {
             AccessibilityInteractionClient.getInstanceForThread(
                     interrogatingTid).setSameThreadMessage(message);
         } else {
@@ -232,7 +235,7 @@
             }
             if (root != null) {
                 View target = root.findViewById(viewId);
-                if (target != null && isDisplayedOnScreen(target)) {
+                if (target != null && target.isDisplayedOnScreen()) {
                     info = target.createAccessibilityNodeInfo();
                 }
             }
@@ -263,8 +266,7 @@
         // thread in this process, set the message as a static reference so
         // after this call completes the same thread but in the interrogating
         // client can handle the message to generate the result.
-        if (interrogatingPid == Process.myPid()
-                && interrogatingTid == Looper.getMainLooper().getThread().getId()) {
+        if (interrogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) {
             AccessibilityInteractionClient.getInstanceForThread(
                     interrogatingTid).setSameThreadMessage(message);
         } else {
@@ -295,7 +297,7 @@
             } else {
                 root = mViewRootImpl.mView;
             }
-            if (root != null && isDisplayedOnScreen(root)) {
+            if (root != null && root.isDisplayedOnScreen()) {
                 AccessibilityNodeProvider provider = root.getAccessibilityNodeProvider();
                 if (provider != null) {
                     infos = provider.findAccessibilityNodeInfosByText(text,
@@ -312,7 +314,7 @@
                         final int viewCount = foundViews.size();
                         for (int i = 0; i < viewCount; i++) {
                             View foundView = foundViews.get(i);
-                            if (isDisplayedOnScreen(foundView)) {
+                            if (foundView.isDisplayedOnScreen()) {
                                 provider = foundView.getAccessibilityNodeProvider();
                                 if (provider != null) {
                                     List<AccessibilityNodeInfo> infosFromProvider =
@@ -356,8 +358,7 @@
         // thread in this process, set the message as a static reference so
         // after this call completes the same thread but in the interrogating
         // client can handle the message to generate the result.
-        if (interogatingPid == Process.myPid()
-                && interrogatingTid == Looper.getMainLooper().getThread().getId()) {
+        if (interogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) {
             AccessibilityInteractionClient.getInstanceForThread(
                     interrogatingTid).setSameThreadMessage(message);
         } else {
@@ -388,7 +389,7 @@
             } else {
                 root = mViewRootImpl.mView;
             }
-            if (root != null && isDisplayedOnScreen(root)) {
+            if (root != null && root.isDisplayedOnScreen()) {
                 switch (focusType) {
                     case AccessibilityNodeInfo.FOCUS_ACCESSIBILITY: {
                         View host = mViewRootImpl.mAccessibilityFocusedHost;
@@ -409,7 +410,7 @@
                     case AccessibilityNodeInfo.FOCUS_INPUT: {
                         // Input focus cannot go to virtual views.
                         View target = root.findFocus();
-                        if (target != null && isDisplayedOnScreen(target)) {
+                        if (target != null && target.isDisplayedOnScreen()) {
                             focused = target.createAccessibilityNodeInfo();
                         }
                     } break;
@@ -444,8 +445,7 @@
         // thread in this process, set the message as a static reference so
         // after this call completes the same thread but in the interrogating
         // client can handle the message to generate the result.
-        if (interogatingPid == Process.myPid()
-                && interrogatingTid == Looper.getMainLooper().getThread().getId()) {
+        if (interogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) {
             AccessibilityInteractionClient.getInstanceForThread(
                     interrogatingTid).setSameThreadMessage(message);
         } else {
@@ -476,7 +476,7 @@
             } else {
                 root = mViewRootImpl.mView;
             }
-            if (root != null && isDisplayedOnScreen(root)) {
+            if (root != null && root.isDisplayedOnScreen()) {
                 if ((direction & View.FOCUS_ACCESSIBILITY) ==  View.FOCUS_ACCESSIBILITY) {
                     AccessibilityNodeProvider provider = root.getAccessibilityNodeProvider();
                     if (provider != null) {
@@ -530,8 +530,7 @@
         // thread in this process, set the message as a static reference so
         // after this call completes the same thread but in the interrogating
         // client can handle the message to generate the result.
-        if (interogatingPid == Process.myPid()
-                && interrogatingTid == Looper.getMainLooper().getThread().getId()) {
+        if (interogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) {
             AccessibilityInteractionClient.getInstanceForThread(
                     interrogatingTid).setSameThreadMessage(message);
         } else {
@@ -562,7 +561,7 @@
             } else {
                 target = mViewRootImpl.mView;
             }
-            if (target != null && isDisplayedOnScreen(target)) {
+            if (target != null && target.isDisplayedOnScreen()) {
                 AccessibilityNodeProvider provider = target.getAccessibilityNodeProvider();
                 if (provider != null) {
                     succeeded = provider.performAccessibilityAction(action, virtualDescendantId);
@@ -586,31 +585,13 @@
             return null;
         }
         View foundView = root.findViewByAccessibilityId(accessibilityId);
-        if (foundView != null && !isDisplayedOnScreen(foundView)) {
+        if (foundView != null && !foundView.isDisplayedOnScreen()) {
             return null;
         }
         return foundView;
     }
 
     /**
-     * Computes whether a view is visible on the screen.
-     *
-     * @param view The view to check.
-     * @return Whether the view is visible on the screen.
-     */
-    private boolean isDisplayedOnScreen(View view) {
-        // The first two checks are made also made by isShown() which
-        // however traverses the tree up to the parent to catch that.
-        // Therefore, we do some fail fast check to minimize the up
-        // tree traversal.
-        return (view.mAttachInfo != null
-                && view.mAttachInfo.mWindowVisibility == View.VISIBLE
-                && view.getAlpha() > 0
-                && view.isShown()
-                && view.getGlobalVisibleRect(mViewRootImpl.mTempRect));
-    }
-
-    /**
      * This class encapsulates a prefetching strategy for the accessibility APIs for
      * querying window content. It is responsible to prefetch a batch of
      * AccessibilityNodeInfos in addition to the one for a requested node.
@@ -684,7 +665,7 @@
                     }
                     View child = children.getChildAt(i);
                     if (child.getAccessibilityViewId() != current.getAccessibilityViewId()
-                            &&  isDisplayedOnScreen(child)) {
+                            &&  child.isDisplayedOnScreen()) {
                         AccessibilityNodeInfo info = null;
                         AccessibilityNodeProvider provider = child.getAccessibilityNodeProvider();
                         if (provider == null) {
@@ -718,7 +699,7 @@
                     return;
                 }
                 View child = children.getChildAt(i);
-                if ( isDisplayedOnScreen(child)) {
+                if (child.isDisplayedOnScreen()) {
                     AccessibilityNodeProvider provider = child.getAccessibilityNodeProvider();
                     if (provider == null) {
                         AccessibilityNodeInfo info = child.createAccessibilityNodeInfo();
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index ad2283e..bda8016 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -143,6 +143,49 @@
     }
 
     /**
+     * Return the range of display sizes an application can expect to encounter
+     * under normal operation, as long as there is no physical change in screen
+     * size.  This is basically the sizes you will see as the orientation
+     * changes, taking into account whatever screen decoration there is in
+     * each rotation.  For example, the status bar is always at the top of the
+     * screen, so it will reduce the height both in landscape and portrait, and
+     * the smallest height returned here will be the smaller of the two.
+     *
+     * This is intended for applications to get an idea of the range of sizes
+     * they will encounter while going through device rotations, to provide a
+     * stable UI through rotation.  The sizes here take into account all standard
+     * system decorations that reduce the size actually available to the
+     * application: the status bar, navigation bar, system bar, etc.  It does
+     * <em>not</em> take into account more transient elements like an IME
+     * soft keyboard.
+     *
+     * @param outSmallestSize Filled in with the smallest width and height
+     * that the application will encounter, in pixels (not dp units).  The x
+     * (width) dimension here directly corresponds to
+     * {@link android.content.res.Configuration#smallestScreenWidthDp
+     * Configuration.smallestScreenWidthDp}, except the value here is in raw
+     * screen pixels rather than dp units.  Your application may of course
+     * still get smaller space yet if, for example, a soft keyboard is
+     * being displayed.
+     * @param outLargestSize Filled in with the largest width and height
+     * that the application will encounter, in pixels (not dp units).  Your
+     * application may of course still get larger space than this if,
+     * for example, screen decorations like the status bar are being hidden.
+     */
+    public void getCurrentSizeRange(Point outSmallestSize, Point outLargestSize) {
+        try {
+            IWindowManager wm = getWindowManager();
+            wm.getCurrentSizeRange(outSmallestSize, outLargestSize);
+        } catch (RemoteException e) {
+            Slog.w("Display", "Unable to get display size range", e);
+            outSmallestSize.x = 0;
+            outSmallestSize.y = 0;
+            outLargestSize.x = 0;
+            outLargestSize.y = 0;
+        }
+    }
+
+    /**
      * Return the maximum screen size dimension that will happen.  This is
      * mostly for wallpapers.
      * @hide
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index b70d7b5..e1f01db 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -58,6 +58,7 @@
     void getDisplaySize(out Point size);
     void getRealDisplaySize(out Point size);
     int getMaximumSizeDimension();
+    void getCurrentSizeRange(out Point smallestSize, out Point largestSize);
 
     void setForcedDisplaySize(int longDimen, int shortDimen);
     void clearForcedDisplaySize();
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index 4848a7a..85f435c 100755
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -167,6 +167,19 @@
 
     /**
      * The input source is a stylus pointing device.
+     * <p>
+     * Note that this bit merely indicates that an input device is capable of obtaining
+     * input from a stylus.  To determine whether a given touch event was produced
+     * by a stylus, examine the tool type returned by {@link MotionEvent#getToolType(int)}
+     * for each individual pointer.
+     * </p><p>
+     * A single touch event may multiple pointers with different tool types,
+     * such as an event that has one pointer with tool type
+     * {@link MotionEvent#TOOL_TYPE_FINGER} and another pointer with tool type
+     * {@link MotionEvent#TOOL_TYPE_STYLUS}.  So it is important to examine
+     * the tool type of each pointer, regardless of the source reported
+     * by {@link MotionEvent#getSource()}.
+     * </p>
      *
      * @see #SOURCE_CLASS_POINTER
      */
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 537c474..ce02113 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4680,6 +4680,23 @@
     }
 
     /**
+     * Computes whether this view is visible on the screen.
+     *
+     * @return Whether the view is visible on the screen.
+     */
+    boolean isDisplayedOnScreen() {
+        // The first two checks are made also made by isShown() which
+        // however traverses the tree up to the parent to catch that.
+        // Therefore, we do some fail fast check to minimize the up
+        // tree traversal.
+        return (mAttachInfo != null
+                && mAttachInfo.mWindowVisibility == View.VISIBLE
+                && getAlpha() > 0
+                && isShown()
+                && getGlobalVisibleRect(mAttachInfo.mTmpInvalRect));
+    }
+
+    /**
      * Sets a delegate for implementing accessibility support via compositon as
      * opposed to inheritance. The delegate's primary use is for implementing
      * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
@@ -6301,9 +6318,9 @@
     boolean includeForAccessibility() {
         if (mAttachInfo != null) {
             if (!mAttachInfo.mIncludeNotImportantViews) {
-                return isImportantForAccessibility();
+                return isImportantForAccessibility() && isDisplayedOnScreen();
             } else {
-                return true;
+                return isDisplayedOnScreen();
             }
         }
         return false;
@@ -7338,7 +7355,7 @@
                 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
                 // If the window does not have input focus we take away accessibility
                 // focus as soon as the user stop hovering over the view.
-                if (!mAttachInfo.mHasWindowFocus) {
+                if (mAttachInfo != null && !mAttachInfo.mHasWindowFocus) {
                     getViewRootImpl().setAccessibilityFocusedHost(null);
                 }
             }
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 91e945b..1641d4c 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1569,6 +1569,43 @@
         return handled;
     }
 
+    private void exitHoverTargets() {
+        if (mHoveredSelf || mFirstHoverTarget != null) {
+            final long now = SystemClock.uptimeMillis();
+            MotionEvent event = MotionEvent.obtain(now, now,
+                    MotionEvent.ACTION_HOVER_EXIT, 0.0f, 0.0f, 0);
+            event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+            dispatchHoverEvent(event);
+            event.recycle();
+        }
+    }
+
+    private void cancelHoverTarget(View view) {
+        HoverTarget predecessor = null;
+        HoverTarget target = mFirstHoverTarget;
+        while (target != null) {
+            final HoverTarget next = target.next;
+            if (target.child == view) {
+                if (predecessor == null) {
+                    mFirstHoverTarget = next;
+                } else {
+                    predecessor.next = next;
+                }
+                target.recycle();
+
+                final long now = SystemClock.uptimeMillis();
+                MotionEvent event = MotionEvent.obtain(now, now,
+                        MotionEvent.ACTION_HOVER_EXIT, 0.0f, 0.0f, 0);
+                event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+                view.dispatchHoverEvent(event);
+                event.recycle();
+                return;
+            }
+            predecessor = target;
+            target = next;
+        }
+    }
+
     /** @hide */
     @Override
     protected boolean hasHoveredChild() {
@@ -1997,6 +2034,32 @@
         }
     }
 
+    private void cancelTouchTarget(View view) {
+        TouchTarget predecessor = null;
+        TouchTarget target = mFirstTouchTarget;
+        while (target != null) {
+            final TouchTarget next = target.next;
+            if (target.child == view) {
+                if (predecessor == null) {
+                    mFirstTouchTarget = next;
+                } else {
+                    predecessor.next = next;
+                }
+                target.recycle();
+
+                final long now = SystemClock.uptimeMillis();
+                MotionEvent event = MotionEvent.obtain(now, now,
+                        MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
+                event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+                view.dispatchTouchEvent(event);
+                event.recycle();
+                return;
+            }
+            predecessor = target;
+            target = next;
+        }
+    }
+
     /**
      * Returns true if a child view can receive pointer events.
      * @hide
@@ -2416,6 +2479,9 @@
         // first send it an ACTION_CANCEL motion event.
         cancelAndClearTouchTargets(null);
 
+        // Similarly, set ACTION_EXIT to all hover targets and clear them.
+        exitHoverTargets();
+
         // In case view is detached while transition is running
         mLayoutSuppressed = false;
 
@@ -3453,6 +3519,9 @@
             clearChildFocus = true;
         }
 
+        cancelTouchTarget(view);
+        cancelHoverTarget(view);
+
         if (view.getAnimation() != null ||
                 (mTransitioningViews != null && mTransitioningViews.contains(view))) {
             addDisappearingView(view);
@@ -3533,6 +3602,9 @@
                 clearChildFocus = view;
             }
 
+            cancelTouchTarget(view);
+            cancelHoverTarget(view);
+
             if (view.getAnimation() != null ||
                 (mTransitioningViews != null && mTransitioningViews.contains(view))) {
                 addDisappearingView(view);
@@ -3603,6 +3675,9 @@
                 clearChildFocus = view;
             }
 
+            cancelTouchTarget(view);
+            cancelHoverTarget(view);
+
             if (view.getAnimation() != null ||
                     (mTransitioningViews != null && mTransitioningViews.contains(view))) {
                 addDisappearingView(view);
@@ -3648,6 +3723,9 @@
             child.clearFocus();
         }
 
+        cancelTouchTarget(child);
+        cancelHoverTarget(child);
+
         if ((animate && child.getAnimation() != null) ||
                 (mTransitioningViews != null && mTransitioningViews.contains(child))) {
             addDisappearingView(child);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 3d40b2f..247f673 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1199,13 +1199,13 @@
             }
         }
 
+        // Execute enqueued actions on every traversal in case a detached view enqueued an action
+        getRunQueue().executeActions(attachInfo.mHandler);
+
         boolean insetsChanged = false;
 
         boolean layoutRequested = mLayoutRequested && !mStopped;
         if (layoutRequested) {
-            // Execute enqueued actions on every layout in case a view that was detached
-            // enqueued an action after being detached
-            getRunQueue().executeActions(attachInfo.mHandler);
 
             final Resources res = mView.getContext().getResources();
 
diff --git a/core/java/android/webkit/ViewStateSerializer.java b/core/java/android/webkit/ViewStateSerializer.java
index e672b62..35168cf 100644
--- a/core/java/android/webkit/ViewStateSerializer.java
+++ b/core/java/android/webkit/ViewStateSerializer.java
@@ -34,21 +34,21 @@
 
     static final int VERSION = 1;
 
-    static boolean serializeViewState(OutputStream stream, WebViewClassic web)
+    static boolean serializeViewState(OutputStream stream, DrawData draw)
             throws IOException {
-        int baseLayer = web.getBaseLayer();
+        int baseLayer = draw.mBaseLayer;
         if (baseLayer == 0) {
             return false;
         }
         DataOutputStream dos = new DataOutputStream(stream);
         dos.writeInt(VERSION);
-        dos.writeInt(web.getContentWidth());
-        dos.writeInt(web.getContentHeight());
+        dos.writeInt(draw.mContentSize.x);
+        dos.writeInt(draw.mContentSize.y);
         return nativeSerializeViewState(baseLayer, dos,
                 new byte[WORKING_STREAM_STORAGE]);
     }
 
-    static DrawData deserializeViewState(InputStream stream, WebViewClassic web)
+    static DrawData deserializeViewState(InputStream stream)
             throws IOException {
         DataInputStream dis = new DataInputStream(stream);
         int version = dis.readInt();
@@ -62,13 +62,10 @@
 
         final WebViewCore.DrawData draw = new WebViewCore.DrawData();
         draw.mViewState = new WebViewCore.ViewState();
-        int viewWidth = web.getViewWidth();
-        int viewHeight = web.getViewHeightWithTitle() - web.getTitleHeight();
-        draw.mViewSize = new Point(viewWidth, viewHeight);
         draw.mContentSize = new Point(contentWidth, contentHeight);
-        draw.mViewState.mDefaultScale = web.getDefaultZoomScale();
         draw.mBaseLayer = baseLayer;
         draw.mInvalRegion = new Region(0, 0, contentWidth, contentHeight);
+        stream.close();
         return draw;
     }
 
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index ba48da1..4cd828e 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -17,6 +17,7 @@
 package android.webkit;
 
 import android.os.Message;
+import android.os.Build;
 
 /**
  * Manages settings state for a WebView. When a WebView is first created, it
@@ -29,7 +30,7 @@
 // This is (effectively) an abstract base class; concrete WebViewProviders must
 // create a class derived from this, and return an instance of it in the
 // WebViewProvider.getWebSettingsProvider() method implementation.
-public class WebSettings {
+public abstract class WebSettings {
     // TODO: Remove MustOverrideException and make all methods throwing it abstract instead;
     // needs API file update.
     private static class MustOverrideException extends RuntimeException {
@@ -771,6 +772,29 @@
     }
 
     /**
+     * Configure scripting (such as XmlHttpRequest) access from file scheme URLs
+     * to any origin. Note, calling this method with a true argument value also
+     * implies calling setAllowFileAccessFromFileURLs with a true. The default
+     * value is false for API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN}
+     * and higher and true otherwise.
+     *
+   . * @param flag True if the WebView should allow scripting access from file
+     *                  scheme URLs to any origin
+     */
+    public abstract void setAllowUniversalAccessFromFileURLs(boolean flag);
+
+    /**
+     * Configure scripting (such as XmlHttpRequest) access from file scheme URLs
+     * to file origin. The default value is false for API level
+     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} and higher and true
+     * otherwise.
+     *
+     * @param flag True if the WebView should allow scripting access from file
+     *                  scheme URLs to file origin
+     */
+    public abstract void setAllowFileAccessFromFileURLs(boolean flag);
+
+    /**
      * Tell the WebView to enable plugins.
      * @param flag True if the WebView should load plugins.
      * @deprecated This method has been deprecated in favor of
@@ -912,6 +936,26 @@
     }
 
     /**
+     * Return true if scripting access {see @setAllowUniversalAccessFromFileURLs} from
+     * file URLs to any origin is enabled. The default value is false for API level
+     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} and higher and true otherwise.
+     *
+     * @return True if the WebView allows scripting access from file scheme requests
+     *              to any origin
+     */
+    public abstract boolean getAllowUniversalAccessFromFileURLs();
+
+    /**
+     * Return true if scripting access {see @setAllowFileAccessFromFileURLs} from file
+     * URLs to file origin is enabled. The default value is false for API level
+     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} and higher, and true otherwise.
+     *
+     * @return True if the WebView allows scripting access from file scheme requests
+     *              to file origin
+     */
+    public abstract boolean getAllowFileAccessFromFileURLs();
+
+    /**
      * Return true if plugins are enabled.
      * @return True if plugins are enabled.
      * @deprecated This method has been replaced by {@link #getPluginState}
diff --git a/core/java/android/webkit/WebSettingsClassic.java b/core/java/android/webkit/WebSettingsClassic.java
index aa3d8d3..354bb5a 100644
--- a/core/java/android/webkit/WebSettingsClassic.java
+++ b/core/java/android/webkit/WebSettingsClassic.java
@@ -72,6 +72,8 @@
     private boolean         mBlockNetworkImage = false;
     private boolean         mBlockNetworkLoads;
     private boolean         mJavaScriptEnabled = false;
+    private boolean         mAllowUniversalAccessFromFileURLs = false;
+    private boolean         mAllowFileAccessFromFileURLs = false;
     private boolean         mHardwareAccelSkia = false;
     private boolean         mShowVisualIndicator = false;
     private PluginState     mPluginState = PluginState.OFF;
@@ -286,6 +288,13 @@
         mBlockNetworkLoads = mContext.checkPermission(
                 "android.permission.INTERNET", android.os.Process.myPid(),
                 android.os.Process.myUid()) != PackageManager.PERMISSION_GRANTED;
+
+        // SDK specific settings. See issue 6212665
+        if (mContext.getApplicationInfo().targetSdkVersion <
+                Build.VERSION_CODES.JELLY_BEAN) {
+            mAllowUniversalAccessFromFileURLs = true;
+            mAllowFileAccessFromFileURLs = true;
+        }
     }
 
     private static final String ACCEPT_LANG_FOR_US_LOCALE = "en-US";
@@ -1101,6 +1110,28 @@
     }
 
     /**
+     * @see android.webkit.WebSettings#setAllowUniversalAccessFromFileURLs
+     */
+    @Override
+    public synchronized void setAllowUniversalAccessFromFileURLs(boolean flag) {
+        if (mAllowUniversalAccessFromFileURLs != flag) {
+            mAllowUniversalAccessFromFileURLs = flag;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setAllowFileAccessFromFileURLs
+     */
+    @Override
+    public synchronized void setAllowFileAccessFromFileURLs(boolean flag) {
+        if (mAllowFileAccessFromFileURLs != flag) {
+            mAllowFileAccessFromFileURLs = flag;
+            postSync();
+        }
+    }
+
+    /**
      * Tell the WebView to use Skia's hardware accelerated rendering path
      * @param flag True if the WebView should use Skia's hw-accel path
      */
@@ -1324,6 +1355,22 @@
     }
 
     /**
+     * @see android.webkit.WebSettings#getAllowUniversalFileAccessFromFileURLs
+     */
+    @Override
+    public synchronized boolean getAllowUniversalAccessFromFileURLs() {
+        return mAllowUniversalAccessFromFileURLs;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getAllowFileAccessFromFileURLs
+     */
+    @Override
+    public synchronized boolean getAllowFileAccessFromFileURLs() {
+        return mAllowFileAccessFromFileURLs;
+    }
+
+    /**
      * @see android.webkit.WebSettings#getPluginsEnabled()
      */
     @Override
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index f1eacff..f429e09 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -1074,7 +1074,6 @@
     private static final int STD_SPEED = 480;  // pixels per second
     // time for the longest scroll animation
     private static final int MAX_DURATION = 750;   // milliseconds
-    private static final int SLIDE_TITLE_DURATION = 500;   // milliseconds
 
     // Used by OverScrollGlow
     OverScroller mScroller;
@@ -2438,34 +2437,51 @@
      * version specific, and may not be able to be loaded by newer versions
      * of WebView.
      * @param stream The {@link OutputStream} to save to
-     * @return True if saved successfully
+     * @param callback The {@link ValueCallback} to call with the result
      */
-    public boolean saveViewState(OutputStream stream) {
-        try {
-            return ViewStateSerializer.serializeViewState(stream, this);
-        } catch (IOException e) {
-            Log.w(LOGTAG, "Failed to saveViewState", e);
+    public void saveViewState(OutputStream stream, ValueCallback<Boolean> callback) {
+        if (mWebViewCore == null) {
+            callback.onReceiveValue(false);
+            return;
         }
-        return false;
+        mWebViewCore.sendMessageAtFrontOfQueue(EventHub.SAVE_VIEW_STATE,
+                new WebViewCore.SaveViewStateRequest(stream, callback));
     }
 
     /**
      * Loads the view data from the input stream. See
      * {@link #saveViewState(OutputStream)} for more information.
      * @param stream The {@link InputStream} to load from
-     * @return True if loaded successfully
      */
-    public boolean loadViewState(InputStream stream) {
-        try {
-            mLoadedPicture = ViewStateSerializer.deserializeViewState(stream, this);
-            mBlockWebkitViewMessages = true;
-            setNewPicture(mLoadedPicture, true);
-            mLoadedPicture.mViewState = null;
-            return true;
-        } catch (IOException e) {
-            Log.w(LOGTAG, "Failed to loadViewState", e);
-        }
-        return false;
+    public void loadViewState(InputStream stream) {
+        mBlockWebkitViewMessages = true;
+        new AsyncTask<InputStream, Void, DrawData>() {
+
+            @Override
+            protected DrawData doInBackground(InputStream... params) {
+                try {
+                    return ViewStateSerializer.deserializeViewState(params[0]);
+                } catch (IOException e) {
+                    return null;
+                }
+            }
+
+            @Override
+            protected void onPostExecute(DrawData draw) {
+                if (draw == null) {
+                    Log.e(LOGTAG, "Failed to load view state!");
+                    return;
+                }
+                int viewWidth = getViewWidth();
+                int viewHeight = getViewHeightWithTitle() - getTitleHeight();
+                draw.mViewSize = new Point(viewWidth, viewHeight);
+                draw.mViewState.mDefaultScale = getDefaultZoomScale();
+                mLoadedPicture = draw;
+                setNewPicture(mLoadedPicture, true);
+                mLoadedPicture.mViewState = null;
+            }
+
+        }.execute(stream);
     }
 
     /**
@@ -4012,17 +4028,6 @@
      * @param url The URL of the page which has finished loading.
      */
     /* package */ void onPageFinished(String url) {
-        if (mPageThatNeedsToSlideTitleBarOffScreen != null) {
-            // If the user is now on a different page, or has scrolled the page
-            // past the point where the title bar is offscreen, ignore the
-            // scroll request.
-            if (mPageThatNeedsToSlideTitleBarOffScreen.equals(url)
-                    && getScrollX() == 0 && getScrollY() == 0) {
-                pinScrollTo(0, mYDistanceToSlideTitleOffScreen, true,
-                        SLIDE_TITLE_DURATION);
-            }
-            mPageThatNeedsToSlideTitleBarOffScreen = null;
-        }
         mZoomManager.onPageFinished(url);
         injectAccessibilityForUrl(url);
     }
@@ -4134,93 +4139,16 @@
         return -1;
     }
 
-    /**
-     * The URL of a page that sent a message to scroll the title bar off screen.
-     *
-     * Many mobile sites tell the page to scroll to (0,1) in order to scroll the
-     * title bar off the screen.  Sometimes, the scroll position is set before
-     * the page finishes loading.  Rather than scrolling while the page is still
-     * loading, keep track of the URL and new scroll position so we can perform
-     * the scroll once the page finishes loading.
-     */
-    private String mPageThatNeedsToSlideTitleBarOffScreen;
-
-    /**
-     * The destination Y scroll position to be used when the page finishes
-     * loading.  See mPageThatNeedsToSlideTitleBarOffScreen.
-     */
-    private int mYDistanceToSlideTitleOffScreen;
-
     // scale from content to view coordinates, and pin
-    // return true if pin caused the final x/y different than the request cx/cy,
-    // and a future scroll may reach the request cx/cy after our size has
-    // changed
-    // return false if the view scroll to the exact position as it is requested,
-    // where negative numbers are taken to mean 0
-    private boolean setContentScrollTo(int cx, int cy) {
-        if (mDrawHistory) {
-            // disallow WebView to change the scroll position as History Picture
-            // is used in the view system.
-            // One known case where this is called is that WebCore tries to
-            // restore the scroll position. As history Picture already uses the
-            // saved scroll position, it is ok to skip this.
-            return false;
-        }
-        int vx;
-        int vy;
-        if ((cx | cy) == 0) {
-            // If the page is being scrolled to (0,0), do not add in the title
-            // bar's height, and simply scroll to (0,0). (The only other work
-            // in contentToView_ is to multiply, so this would not change 0.)
-            vx = 0;
-            vy = 0;
-        } else {
-            vx = contentToViewX(cx);
-            vy = contentToViewY(cy);
-        }
-//        Log.d(LOGTAG, "content scrollTo [" + cx + " " + cy + "] view=[" +
-//                      vx + " " + vy + "]");
-        // Some mobile sites attempt to scroll the title bar off the page by
-        // scrolling to (0,1).  If we are at the top left corner of the
-        // page, assume this is an attempt to scroll off the title bar, and
-        // animate the title bar off screen slowly enough that the user can see
-        // it.
-        if (cx == 0 && cy == 1 && getScrollX() == 0 && getScrollY() == 0
-                && getTitleHeight() > 0) {
-            // FIXME: 100 should be defined somewhere as our max progress.
-            if (getProgress() < 100) {
-                // Wait to scroll the title bar off screen until the page has
-                // finished loading.  Keep track of the URL and the destination
-                // Y position
-                mPageThatNeedsToSlideTitleBarOffScreen = getUrl();
-                mYDistanceToSlideTitleOffScreen = vy;
-            } else {
-                pinScrollTo(vx, vy, true, SLIDE_TITLE_DURATION);
-            }
-            // Since we are animating, we have not yet reached the desired
-            // scroll position.  Do not return true to request another attempt
-            return false;
-        }
-        pinScrollTo(vx, vy, false, 0);
-        // If the request was to scroll to a negative coordinate, treat it as if
-        // it was a request to scroll to 0
-        if ((getScrollX() != vx && cx >= 0) || (getScrollY() != vy && cy >= 0)) {
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    // scale from content to view coordinates, and pin
-    private void spawnContentScrollTo(int cx, int cy) {
+    private void contentScrollTo(int cx, int cy, boolean animate) {
         if (mDrawHistory) {
             // disallow WebView to change the scroll position as History Picture
             // is used in the view system.
             return;
         }
-        int vx = contentToViewDimension(cx - mScrollOffset.x);
-        int vy = contentToViewDimension(cy - mScrollOffset.y);
-        pinScrollBy(vx, vy, true, 0);
+        int vx = contentToViewX(cx);
+        int vy = contentToViewY(cy);
+        pinScrollTo(vx, vy, animate, 0);
     }
 
     /**
@@ -7427,11 +7355,7 @@
                         }
                     }
                     final Point p = (Point) msg.obj;
-                    if (msg.arg1 == 1) {
-                        spawnContentScrollTo(p.x, p.y);
-                    } else {
-                        setContentScrollTo(p.x, p.y);
-                    }
+                    contentScrollTo(p.x, p.y, msg.arg1 == 1);
                     break;
                 }
                 case UPDATE_ZOOM_RANGE: {
@@ -8072,7 +7996,7 @@
             int scrollX = viewState.mShouldStartScrolledRight
                     ? getContentWidth() : viewState.mScrollX;
             int scrollY = viewState.mScrollY;
-            setContentScrollTo(scrollX, scrollY);
+            contentScrollTo(scrollX, scrollY, false);
             if (!mDrawHistory) {
                 // As we are on a new page, hide the keyboard
                 hideSoftKeyboard();
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index f86262e..0565ed7 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -44,6 +44,7 @@
 
 import junit.framework.Assert;
 
+import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Iterator;
@@ -1048,6 +1049,15 @@
         public int mMatchIndex;
     }
 
+    static class SaveViewStateRequest {
+        SaveViewStateRequest(OutputStream s, ValueCallback<Boolean> cb) {
+            mStream = s;
+            mCallback = cb;
+        }
+        public OutputStream mStream;
+        public ValueCallback<Boolean> mCallback;
+    }
+
     /**
      * @hide
      */
@@ -1180,6 +1190,8 @@
         static final int KEY_PRESS = 223;
         static final int SET_INITIAL_FOCUS = 224;
 
+        static final int SAVE_VIEW_STATE = 225;
+
         // Private handler for WebCore messages.
         private Handler mHandler;
         // Message queue for containing messages before the WebCore thread is
@@ -1754,8 +1766,13 @@
                         case SET_INITIAL_FOCUS:
                             nativeSetInitialFocus(mNativeClass, msg.arg1);
                             break;
+                        case SAVE_VIEW_STATE:
+                            SaveViewStateRequest request = (SaveViewStateRequest) msg.obj;
+                            saveViewState(request.mStream, request.mCallback);
+                            break;
                     }
                 }
+
             };
             // Take all queued messages and resend them to the new handler.
             synchronized (this) {
@@ -2254,6 +2271,31 @@
         }
     }
 
+    private void saveViewState(OutputStream stream,
+            ValueCallback<Boolean> callback) {
+        // TODO: Create a native method to do this better without overloading
+        // the draw path (and fix saving <canvas>)
+        DrawData draw = new DrawData();
+        if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "saveViewState start");
+        draw.mBaseLayer = nativeRecordContent(mNativeClass, draw.mInvalRegion,
+                draw.mContentSize);
+        boolean result = false;
+        try {
+            result = ViewStateSerializer.serializeViewState(stream, draw);
+        } catch (Throwable t) {
+            Log.w(LOGTAG, "Failed to save view state", t);
+        }
+        callback.onReceiveValue(result);
+        if (draw.mBaseLayer != 0) {
+            if (mDrawIsScheduled) {
+                mDrawIsScheduled = false;
+                mEventHub.removeMessages(EventHub.WEBKIT_DRAW);
+            }
+            mLastDrawData = draw;
+            webkitDraw(draw);
+        }
+    }
+
     static void reducePriority() {
         // remove the pending REDUCE_PRIORITY and RESUME_PRIORITY messages
         sWebCoreHandler.removeMessages(WebCoreThread.REDUCE_PRIORITY);
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index e68049c..53d5e0b 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -403,7 +403,7 @@
     /**
      * Handles scrolling between positions within the list.
      */
-    private PositionScroller mPositionScroller;
+    PositionScroller mPositionScroller;
 
     /**
      * The offset in pixels form the top of the AdapterView to the top
@@ -3080,6 +3080,10 @@
             return isClickable() || isLongClickable();
         }
 
+        if (mPositionScroller != null) {
+            mPositionScroller.stop();
+        }
+
         if (mFastScroller != null) {
             boolean intercepted = mFastScroller.onTouchEvent(ev);
             if (intercepted) {
@@ -3564,6 +3568,10 @@
         int action = ev.getAction();
         View v;
 
+        if (mPositionScroller != null) {
+            mPositionScroller.stop();
+        }
+
         if (mFastScroller != null) {
             boolean intercepted = mFastScroller.onInterceptTouchEvent(ev);
             if (intercepted) {
@@ -3748,7 +3756,7 @@
             mScroller.fling(0, initialY, 0, initialVelocity,
                     0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE);
             mTouchMode = TOUCH_MODE_FLING;
-            post(this);
+            postOnAnimation(this);
 
             if (PROFILE_FLINGING) {
                 if (!mFlingProfilingStarted) {
@@ -3766,7 +3774,7 @@
             if (mScroller.springBack(0, mScrollY, 0, 0, 0, 0)) {
                 mTouchMode = TOUCH_MODE_OVERFLING;
                 invalidate();
-                post(this);
+                postOnAnimation(this);
             } else {
                 mTouchMode = TOUCH_MODE_REST;
                 reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
@@ -3778,7 +3786,7 @@
                     Integer.MIN_VALUE, Integer.MAX_VALUE, 0, getHeight());
             mTouchMode = TOUCH_MODE_OVERFLING;
             invalidate();
-            post(this);
+            postOnAnimation(this);
         }
 
         void edgeReached(int delta) {
@@ -3800,7 +3808,7 @@
                 }
             }
             invalidate();
-            post(this);
+            postOnAnimation(this);
         }
 
         void startScroll(int distance, int duration) {
@@ -3808,7 +3816,7 @@
             mLastFlingY = initialY;
             mScroller.startScroll(0, initialY, 0, distance, duration);
             mTouchMode = TOUCH_MODE_FLING;
-            post(this);
+            postOnAnimation(this);
         }
 
         void endFling() {
@@ -3907,7 +3915,7 @@
                 if (more && !atEnd) {
                     if (atEdge) invalidate();
                     mLastFlingY = y;
-                    post(this);
+                    postOnAnimation(this);
                 } else {
                     endFling();
 
@@ -3948,7 +3956,7 @@
                         }
                     } else {
                         invalidate();
-                        post(this);
+                        postOnAnimation(this);
                     }
                 } else {
                     endFling();
@@ -3959,7 +3967,6 @@
         }
     }
 
-
     class PositionScroller implements Runnable {
         private static final int SCROLL_DURATION = 400;
 
@@ -4009,7 +4016,7 @@
             mBoundPos = INVALID_POSITION;
             mLastSeenPos = INVALID_POSITION;
 
-            post(this);
+            postOnAnimation(this);
         }
 
         void start(int position, int boundPosition) {
@@ -4070,7 +4077,7 @@
             mBoundPos = boundPosition;
             mLastSeenPos = INVALID_POSITION;
 
-            post(this);
+            postOnAnimation(this);
         }
 
         void startWithOffset(int position, int offset) {
@@ -4080,6 +4087,8 @@
         void startWithOffset(int position, int offset, int duration) {
             stop();
 
+            offset += getPaddingTop();
+
             mTargetPos = position;
             mOffsetFromTop = offset;
             mBoundPos = INVALID_POSITION;
@@ -4108,7 +4117,7 @@
                     (int) (duration / screenTravelCount);
             mLastSeenPos = INVALID_POSITION;
 
-            post(this);
+            postOnAnimation(this);
         }
 
         void stop() {
@@ -4116,10 +4125,6 @@
         }
 
         public void run() {
-            if (mTouchMode != TOUCH_MODE_FLING && mLastSeenPos != INVALID_POSITION) {
-                return;
-            }
-
             final int listHeight = getHeight();
             final int firstPos = mFirstPosition;
 
@@ -4134,7 +4139,7 @@
 
                 if (lastPos == mLastSeenPos) {
                     // No new views, let things keep going.
-                    post(this);
+                    postOnAnimation(this);
                     return;
                 }
 
@@ -4142,14 +4147,15 @@
                 final int lastViewHeight = lastView.getHeight();
                 final int lastViewTop = lastView.getTop();
                 final int lastViewPixelsShowing = listHeight - lastViewTop;
-                final int extraScroll = lastPos < mItemCount - 1 ? mExtraScroll : mListPadding.bottom;
+                final int extraScroll = lastPos < mItemCount - 1 ?
+                        Math.max(mListPadding.bottom, mExtraScroll) : mListPadding.bottom;
 
-                smoothScrollBy(lastViewHeight - lastViewPixelsShowing + extraScroll,
-                        mScrollDuration);
+                final int scrollBy = lastViewHeight - lastViewPixelsShowing + extraScroll;
+                smoothScrollBy(scrollBy, mScrollDuration);
 
                 mLastSeenPos = lastPos;
                 if (lastPos < mTargetPos) {
-                    post(this);
+                    postOnAnimation(this);
                 }
                 break;
             }
@@ -4166,21 +4172,21 @@
 
                 if (nextPos == mLastSeenPos) {
                     // No new views, let things keep going.
-                    post(this);
+                    postOnAnimation(this);
                     return;
                 }
 
                 final View nextView = getChildAt(nextViewIndex);
                 final int nextViewHeight = nextView.getHeight();
                 final int nextViewTop = nextView.getTop();
-                final int extraScroll = mExtraScroll;
+                final int extraScroll = Math.max(mListPadding.bottom, mExtraScroll);
                 if (nextPos < mBoundPos) {
                     smoothScrollBy(Math.max(0, nextViewHeight + nextViewTop - extraScroll),
                             mScrollDuration);
 
                     mLastSeenPos = nextPos;
 
-                    post(this);
+                    postOnAnimation(this);
                 } else  {
                     if (nextViewTop > extraScroll) {
                         smoothScrollBy(nextViewTop - extraScroll, mScrollDuration);
@@ -4192,7 +4198,7 @@
             case MOVE_UP_POS: {
                 if (firstPos == mLastSeenPos) {
                     // No new views, let things keep going.
-                    post(this);
+                    postOnAnimation(this);
                     return;
                 }
 
@@ -4201,14 +4207,15 @@
                     return;
                 }
                 final int firstViewTop = firstView.getTop();
-                final int extraScroll = firstPos > 0 ? mExtraScroll : mListPadding.top;
+                final int extraScroll = firstPos > 0 ?
+                        Math.max(mExtraScroll, mListPadding.top) : mListPadding.top;
 
                 smoothScrollBy(firstViewTop - extraScroll, mScrollDuration);
 
                 mLastSeenPos = firstPos;
 
                 if (firstPos > mTargetPos) {
-                    post(this);
+                    postOnAnimation(this);
                 }
                 break;
             }
@@ -4230,12 +4237,13 @@
                 final int lastViewHeight = lastView.getHeight();
                 final int lastViewTop = lastView.getTop();
                 final int lastViewPixelsShowing = listHeight - lastViewTop;
+                final int extraScroll = Math.max(mListPadding.top, mExtraScroll);
                 mLastSeenPos = lastPos;
                 if (lastPos > mBoundPos) {
-                    smoothScrollBy(-(lastViewPixelsShowing - mExtraScroll), mScrollDuration);
-                    post(this);
+                    smoothScrollBy(-(lastViewPixelsShowing - extraScroll), mScrollDuration);
+                    postOnAnimation(this);
                 } else {
-                    final int bottom = listHeight - mExtraScroll;
+                    final int bottom = listHeight - extraScroll;
                     final int lastViewBottom = lastViewTop + lastViewHeight;
                     if (bottom > lastViewBottom) {
                         smoothScrollBy(-(bottom - lastViewBottom), mScrollDuration);
@@ -4270,10 +4278,10 @@
                 final float modifier = Math.min(Math.abs(screenTravelCount), 1.f);
                 if (position < firstPos) {
                     smoothScrollBy((int) (-getHeight() * modifier), mScrollDuration);
-                    post(this);
+                    postOnAnimation(this);
                 } else if (position > lastPos) {
                     smoothScrollBy((int) (getHeight() * modifier), mScrollDuration);
-                    post(this);
+                    postOnAnimation(this);
                 } else {
                     // On-screen, just scroll.
                     final int targetTop = getChildAt(position - firstPos).getTop();
@@ -4620,7 +4628,7 @@
         // invalidate before moving the children to avoid unnecessary invalidate
         // calls to bubble up from the children all the way to the top
         if (!awakenScrollBars()) {
-            invalidate();
+           invalidate();
         }
 
         offsetChildrenTopAndBottom(incrementalDeltaY);
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index 0f1dab5..0a40d5e 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -1463,6 +1463,9 @@
             mResurrectToPosition = position;
         }
         mLayoutMode = LAYOUT_SET_SELECTION;
+        if (mPositionScroller != null) {
+            mPositionScroller.stop();
+        }
         requestLayout();
     }
 
@@ -1475,6 +1478,10 @@
     void setSelectionInt(int position) {
         int previousSelectedPosition = mNextSelectedPosition;
 
+        if (mPositionScroller != null) {
+            mPositionScroller.stop();
+        }
+
         setNextSelectedPositionInt(position);
         layoutChildren();
         
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 71700b3..5098523 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -1926,6 +1926,9 @@
                 mSyncRowId = mAdapter.getItemId(position);
             }
 
+            if (mPositionScroller != null) {
+                mPositionScroller.stop();
+            }
             requestLayout();
         }
     }
@@ -1950,6 +1953,10 @@
             }
         }
 
+        if (mPositionScroller != null) {
+            mPositionScroller.stop();
+        }
+
         layoutChildren();
 
         if (awakeScrollbars) {
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index 1ba6d43..d0071e3 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.app;
 
+import com.android.internal.view.ActionBarPolicy;
 import com.android.internal.view.menu.MenuBuilder;
 import com.android.internal.view.menu.MenuPopupHelper;
 import com.android.internal.view.menu.SubMenuBuilder;
@@ -183,18 +184,13 @@
         mContextDisplayMode = mActionView.isSplitActionBar() ?
                 CONTEXT_DISPLAY_SPLIT : CONTEXT_DISPLAY_NORMAL;
 
-        // Older apps get the home button interaction enabled by default.
-        // Newer apps need to enable it explicitly.
-        setHomeButtonEnabled(mContext.getApplicationInfo().targetSdkVersion <
-                Build.VERSION_CODES.ICE_CREAM_SANDWICH);
-
-        setHasEmbeddedTabs(mContext.getResources().getBoolean(
-                com.android.internal.R.bool.action_bar_embed_tabs));
+        ActionBarPolicy abp = ActionBarPolicy.get(mContext);
+        setHomeButtonEnabled(abp.enableHomeButtonByDefault());
+        setHasEmbeddedTabs(abp.hasEmbeddedTabs());
     }
 
     public void onConfigurationChanged(Configuration newConfig) {
-        setHasEmbeddedTabs(mContext.getResources().getBoolean(
-                com.android.internal.R.bool.action_bar_embed_tabs));
+        setHasEmbeddedTabs(ActionBarPolicy.get(mContext).hasEmbeddedTabs());
     }
 
     private void setHasEmbeddedTabs(boolean hasEmbeddedTabs) {
diff --git a/core/java/com/android/internal/view/ActionBarPolicy.java b/core/java/com/android/internal/view/ActionBarPolicy.java
new file mode 100644
index 0000000..0c6b780
--- /dev/null
+++ b/core/java/com/android/internal/view/ActionBarPolicy.java
@@ -0,0 +1,90 @@
+/*
+ * 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.internal.view;
+
+import com.android.internal.R;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.os.Build;
+import android.view.ViewConfiguration;
+
+/**
+ * Allows components to query for various configuration policy decisions
+ * about how the action bar should lay out and behave on the current device.
+ */
+public class ActionBarPolicy {
+    private Context mContext;
+
+    public static ActionBarPolicy get(Context context) {
+        return new ActionBarPolicy(context);
+    }
+
+    private ActionBarPolicy(Context context) {
+        mContext = context;
+    }
+
+    public int getMaxActionButtons() {
+        return mContext.getResources().getInteger(R.integer.max_action_buttons);
+    }
+
+    public boolean showsOverflowMenuButton() {
+        return !ViewConfiguration.get(mContext).hasPermanentMenuKey();
+    }
+
+    public int getEmbeddedMenuWidthLimit() {
+        return mContext.getResources().getDisplayMetrics().widthPixels / 2;
+    }
+
+    public boolean hasEmbeddedTabs() {
+        final int targetSdk = mContext.getApplicationInfo().targetSdkVersion;
+        if (targetSdk >= Build.VERSION_CODES.JELLY_BEAN) {
+            return mContext.getResources().getBoolean(R.bool.action_bar_embed_tabs);
+        }
+
+        // The embedded tabs policy changed in Jellybean; give older apps the old policy
+        // so they get what they expect.
+        return mContext.getResources().getBoolean(R.bool.action_bar_embed_tabs_pre_jb);
+    }
+
+    public int getTabContainerHeight() {
+        TypedArray a = mContext.obtainStyledAttributes(null, R.styleable.ActionBar,
+                com.android.internal.R.attr.actionBarStyle, 0);
+        int height = a.getLayoutDimension(R.styleable.ActionBar_height, 0);
+        Resources r = mContext.getResources();
+        if (!hasEmbeddedTabs()) {
+            // Stacked tabs; limit the height
+            height = Math.min(height,
+                    r.getDimensionPixelSize(R.dimen.action_bar_stacked_max_height));
+        }
+        a.recycle();
+        return height;
+    }
+
+    public boolean enableHomeButtonByDefault() {
+        // Older apps get the home button interaction enabled by default.
+        // Newer apps need to enable it explicitly.
+        return mContext.getApplicationInfo().targetSdkVersion <
+                Build.VERSION_CODES.ICE_CREAM_SANDWICH;
+    }
+
+    public int getStackedTabMaxWidth() {
+        return mContext.getResources().getDimensionPixelSize(
+                R.dimen.action_bar_stacked_tab_max_width);
+    }
+}
diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
index dca45a9..73324c0 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.view.menu;
 
+import com.android.internal.view.ActionBarPolicy;
 import com.android.internal.view.menu.ActionMenuView.ActionMenuChildView;
 
 import android.content.Context;
@@ -29,7 +30,6 @@
 import android.view.SoundEffectConstants;
 import android.view.View;
 import android.view.View.MeasureSpec;
-import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.widget.ImageButton;
 
@@ -79,17 +79,18 @@
 
         final Resources res = context.getResources();
 
+        final ActionBarPolicy abp = ActionBarPolicy.get(context);
         if (!mReserveOverflowSet) {
-            mReserveOverflow = !ViewConfiguration.get(context).hasPermanentMenuKey();
+            mReserveOverflow = abp.showsOverflowMenuButton();
         }
 
         if (!mWidthLimitSet) {
-            mWidthLimit = res.getDisplayMetrics().widthPixels / 2;
+            mWidthLimit = abp.getEmbeddedMenuWidthLimit();
         }
 
         // Measure for initial configuration
         if (!mMaxItemsSet) {
-            mMaxItems = res.getInteger(com.android.internal.R.integer.max_action_buttons);
+            mMaxItems = abp.getMaxActionButtons();
         }
 
         int width = mWidthLimit;
diff --git a/core/java/com/android/internal/widget/AbsActionBarView.java b/core/java/com/android/internal/widget/AbsActionBarView.java
index 06f5158..25a9c54 100644
--- a/core/java/com/android/internal/widget/AbsActionBarView.java
+++ b/core/java/com/android/internal/widget/AbsActionBarView.java
@@ -161,10 +161,12 @@
 
     @Override
     public void setVisibility(int visibility) {
-        if (mVisibilityAnim != null) {
-            mVisibilityAnim.end();
+        if (visibility != getVisibility()) {
+            if (mVisibilityAnim != null) {
+                mVisibilityAnim.end();
+            }
+            super.setVisibility(visibility);
         }
-        super.setVisibility(visibility);
     }
 
     public boolean showOverflowMenu() {
diff --git a/core/java/com/android/internal/widget/ScrollingTabContainerView.java b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
index 1767d68..83ac896 100644
--- a/core/java/com/android/internal/widget/ScrollingTabContainerView.java
+++ b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
@@ -15,7 +15,7 @@
  */
 package com.android.internal.widget;
 
-import com.android.internal.R;
+import com.android.internal.view.ActionBarPolicy;
 
 import android.animation.Animator;
 import android.animation.ObjectAnimator;
@@ -23,7 +23,6 @@
 import android.app.ActionBar;
 import android.content.Context;
 import android.content.res.Configuration;
-import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
 import android.text.TextUtils.TruncateAt;
 import android.view.Gravity;
@@ -55,6 +54,7 @@
     private boolean mAllowCollapse;
 
     int mMaxTabWidth;
+    int mStackedTabMaxWidth;
     private int mContentHeight;
     private int mSelectedTabIndex;
 
@@ -69,10 +69,9 @@
         super(context);
         setHorizontalScrollBarEnabled(false);
 
-        TypedArray a = getContext().obtainStyledAttributes(null, R.styleable.ActionBar,
-                com.android.internal.R.attr.actionBarStyle, 0);
-        setContentHeight(a.getLayoutDimension(R.styleable.ActionBar_height, 0));
-        a.recycle();
+        ActionBarPolicy abp = ActionBarPolicy.get(context);
+        setContentHeight(abp.getTabContainerHeight());
+        mStackedTabMaxWidth = abp.getStackedTabMaxWidth();
 
         mTabLayout = createTabLayout();
         addView(mTabLayout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
@@ -93,6 +92,7 @@
             } else {
                 mMaxTabWidth = MeasureSpec.getSize(widthMeasureSpec) / 2;
             }
+            mMaxTabWidth = Math.min(mMaxTabWidth, mStackedTabMaxWidth);
         } else {
             mMaxTabWidth = -1;
         }
@@ -187,6 +187,7 @@
         final LinearLayout tabLayout = new LinearLayout(getContext(), null,
                 com.android.internal.R.attr.actionBarTabBarStyle);
         tabLayout.setMeasureWithLargestChildEnabled(true);
+        tabLayout.setGravity(Gravity.CENTER);
         tabLayout.setLayoutParams(new LinearLayout.LayoutParams(
                 LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT));
         return tabLayout;
@@ -205,12 +206,11 @@
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
 
+        ActionBarPolicy abp = ActionBarPolicy.get(getContext());
         // Action bar can change size on configuration changes.
         // Reread the desired height from the theme-specified style.
-        TypedArray a = getContext().obtainStyledAttributes(null, R.styleable.ActionBar,
-                com.android.internal.R.attr.actionBarStyle, 0);
-        setContentHeight(a.getLayoutDimension(R.styleable.ActionBar_height, 0));
-        a.recycle();
+        setContentHeight(abp.getTabContainerHeight());
+        mStackedTabMaxWidth = abp.getStackedTabMaxWidth();
     }
 
     public void animateToVisibility(int visibility) {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index f5c0f8f..4443bc8 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -202,6 +202,23 @@
         android:label="@string/permlab_receiveEmergencyBroadcast"
         android:description="@string/permdesc_receiveEmergencyBroadcast" />
 
+    <!-- Allows an application to read previously received cell broadcast
+         messages and to register a content observer to get notifications when
+         a cell broadcast has been received and added to the database. For
+         emergency alerts, the database is updated immediately after the
+         alert dialog and notification sound/vibration/speech are presented.
+         The "read" column is then updated after the user dismisses the alert.
+         This enables supplementary emergency assistance apps to start loading
+         additional emergency information (if Internet access is available)
+         when the alert is first received, and to delay presenting the info
+         to the user until after the initial alert dialog is dismissed.
+         @hide Pending API council approval -->
+    <permission android:name="android.permission.READ_CELL_BROADCASTS"
+        android:permissionGroup="android.permission-group.MESSAGES"
+        android:protectionLevel="dangerous"
+        android:label="@string/permlab_readCellBroadcasts"
+        android:description="@string/permdesc_readCellBroadcasts" />
+
     <!-- Allows an application to read SMS messages. -->
     <permission android:name="android.permission.READ_SMS"
         android:permissionGroup="android.permission-group.MESSAGES"
@@ -737,6 +754,14 @@
         android:label="@string/permlab_removeTasks"
         android:description="@string/permdesc_removeTasks" />
 
+    <!-- Allows an application to start any activity, regardless of permission
+         protection or exported state. @hide -->
+    <permission android:name="android.permission.START_ANY_ACTIVITY"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="signature"
+        android:label="@string/permlab_startAnyActivity"
+        android:description="@string/permdesc_startAnyActivity" />
+
     <!-- @hide Change the screen compatibility mode of applications -->
     <permission android:name="android.permission.SET_SCREEN_COMPATIBILITY"
         android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index b2714dd..15f56f3 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -70,7 +70,7 @@
     <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"የደዋይ  ID  ወደ አልተከለከለም ነባሪዎች።ቀጥሎ ጥሪ፡ ተከልክሏል"</string>
     <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"የደዋይ ID ነባሪዎች ወደአልተከለከለም። ቀጥሎ ጥሪ፡አልተከለከለም"</string>
     <string name="serviceNotProvisioned" msgid="8614830180508686666">"አገልግሎት አልቀረበም።"</string>
-    <string name="CLIRPermanent" msgid="3377371145926835671">"የደዋይ መታወቂያ ቅንጅቶች መለወጥ አትችልም፡፡"</string>
+    <string name="CLIRPermanent" msgid="3377371145926835671">"የደዋይ መታወቂያ ቅንብሮች  መለወጥ አትችልም፡፡"</string>
     <string name="RestrictedChangedTitle" msgid="5592189398956187498">"ክልክል ድረስተለውጧል"</string>
     <string name="RestrictedOnData" msgid="8653794784690065540">"የውሂብ አገልግሎት የታገደ ነው።"</string>
     <string name="RestrictedOnEmergency" msgid="6581163779072833665">"የአደጋ ጊዜአገልግሎት የታገደ ነው።"</string>
@@ -375,7 +375,7 @@
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"የንዑስ ክፈፍ ቋት አንብብ"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"የክፈፍ ቋት ይዘት ለማንበብ ለመተግበሪያው ይፈቅዳሉ።"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"የድምፅ ቅንብሮችን ለውጥ"</string>
-    <string name="permdesc_modifyAudioSettings" msgid="7343951185408396919">"የዓለም አቀፍ ኦዲዮ ቅንጅቶች እንደ ድምፅ እና ፈለግ ለመቀየር ለመተግበሪያው ይፈቅዳሉ ።"</string>
+    <string name="permdesc_modifyAudioSettings" msgid="7343951185408396919">"የዓለም አቀፍ ኦዲዮ ቅንብሮች  እንደ ድምፅ እና ፈለግ ለመቀየር ለመተግበሪያው ይፈቅዳሉ ።"</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ኦዲዮ ቅዳ"</string>
     <string name="permdesc_recordAudio" msgid="2387462233976248635">"መተግበሪያ የድምፅ መዝገብ ዱካን ለመድረስ ይፈቅዳል።"</string>
     <string name="permlab_camera" msgid="3616391919559751192">"ፎቶዎች እና ቪዲዮዎች አንሳ"</string>
@@ -445,7 +445,7 @@
     <string name="permlab_setWallpaperHints" msgid="3600721069353106851">"የልጣፍአዘጋጅ መጠን ፍንጮች"</string>
     <string name="permdesc_setWallpaperHints" msgid="8235784384223730091">"የስርዓቱን ልጥፍ መጠንለማዘጋጀት ለመተግበሪያው ይፈቅዳሉ፡፡"</string>
     <string name="permlab_masterClear" msgid="2315750423139697397">"ስርዓትን ወደ ፋብሪካ ነባሪዎች ዳግም አስጀምር"</string>
-    <string name="permdesc_masterClear" msgid="3665380492633910226">"ወደ ፋብሪካው ቅንጅቶች ሙሉ በሙሉ ስርዓቱን ዳግም ለማስጀመር ለመተግበሪያው ይፈቅዳሉ ፤ ሁሉንም ውሂብ፣ አወቃቀር፣ እና የተጫኑ መተግበሪያዎችን በማጥፈት፡፡"</string>
+    <string name="permdesc_masterClear" msgid="3665380492633910226">"ወደ ፋብሪካው ቅንብሮች  ሙሉ በሙሉ ስርዓቱን ዳግም ለማስጀመር ለመተግበሪያው ይፈቅዳሉ ፤ ሁሉንም ውሂብ፣ አወቃቀር፣ እና የተጫኑ መተግበሪያዎችን በማጥፈት፡፡"</string>
     <string name="permlab_setTime" msgid="2021614829591775646">"ሰዓት ሙላ"</string>
     <string name="permdesc_setTime" product="tablet" msgid="1896341438151152881">"መተግበሪያውን የጡባዊ ተኮን ሰዓት ለመለወጥ ይፈቅዳሉ።"</string>
     <string name="permdesc_setTime" product="default" msgid="1855702730738020">"መተግበሪያውን የስልኩን ሰዓት ለመለወጥ ይፈቅዳሉ።"</string>
@@ -474,7 +474,7 @@
     <string name="permlab_changeTetherState" msgid="5952584964373017960">"የተያያዘ ግንኙነት ለውጥ"</string>
     <string name="permdesc_changeTetherState" msgid="1524441344412319780">"መተግበሪያ የእውታረ መረቡን ግንኙነት ትይይዝ ሁኔታ ለመለወጥ ይፈቅዳል።"</string>
     <string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"የዳራ ውሂብ አጠቃቀም ቅንብር ለውጥ"</string>
-    <string name="permdesc_changeBackgroundDataSetting" msgid="5347729578468744379">"የዳራ ውሂብ አጠቃቀም ቅንጅቶች ለመለወጥ ለመተግበሪያው ይፈቅዳሉ፡፡"</string>
+    <string name="permdesc_changeBackgroundDataSetting" msgid="5347729578468744379">"የዳራ ውሂብ አጠቃቀም ቅንብሮች  ለመለወጥ ለመተግበሪያው ይፈቅዳሉ፡፡"</string>
     <string name="permlab_accessWifiState" msgid="8100926650211034400">"የWi-Fi ሁኔታ እይ"</string>
     <string name="permdesc_accessWifiState" msgid="7770452658226256831">"ስለWi-Fi ሁኔታ መረጃን ለማየት ለመተግበሪያው ይፈቅዳሉ፡፡"</string>
     <string name="permlab_changeWifiState" msgid="7280632711057112137">"የWi-Fi  ሁኔታን ለውጥ"</string>
@@ -924,7 +924,7 @@
     <string name="capital_off" msgid="6815870386972805832">"ውጪ"</string>
     <string name="whichApplication" msgid="4533185947064773386">"... በመጠቀም ድርጊቱን አጠናቅ"</string>
     <string name="alwaysUse" msgid="4583018368000610438">"ለዕርምጃ ነባሪ ተጠቀም።"</string>
-    <string name="clearDefaultHintMsg" msgid="3252584689512077257">"ነባሪ አጽዳ በስርዓት ቅንጅቶች ውስጥ  &gt; Apps &amp;gt፤ወርዷል፡፡"</string>
+    <string name="clearDefaultHintMsg" msgid="3252584689512077257">"ነባሪ አጽዳ በስርዓት ቅንብሮች  ውስጥ  &gt; Apps &amp;gt፤ወርዷል፡፡"</string>
     <string name="chooseActivity" msgid="7486876147751803333">"ድርጊት ምረጥ"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"ለUSB መሳሪያ መተግበሪያ ምረጥ"</string>
     <string name="noApplications" msgid="2991814273936504689">"ምንም ትግበራዎች ይህን ድርጊት ማከናወን አይችሉም።"</string>
@@ -945,7 +945,7 @@
     <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> በዋናነት የተነሳው።"</string>
     <string name="screen_compat_mode_scale" msgid="3202955667675944499">"የልኬት ለውጥ"</string>
     <string name="screen_compat_mode_show" msgid="4013878876486655892">"ሁልጊዜ አሳይ"</string>
-    <string name="screen_compat_mode_hint" msgid="1064524084543304459">"በስርዓት ቅንጅቶች ውስጥ ይሄንን ዳግም አንቃ&gt; Apps &amp;gt፤ወርዷል፡፡"</string>
+    <string name="screen_compat_mode_hint" msgid="1064524084543304459">"በስርዓት ቅንብሮች  ውስጥ ይሄንን ዳግም አንቃ&gt; Apps &amp;gt፤ወርዷል፡፡"</string>
     <string name="smv_application" msgid="3307209192155442829">"መተግበሪያው <xliff:g id="APPLICATION">%1$s</xliff:g>( ሂደት<xliff:g id="PROCESS">%2$s</xliff:g>) በራስ ተነሳሺ StrictMode ደንብን ይተላለፋል።"</string>
     <string name="smv_process" msgid="5120397012047462446">"ሂደቱ <xliff:g id="PROCESS">%1$s</xliff:g> በራስ ተነሳሺ StrictMode ፖሊሲን ይተላለፋል።"</string>
     <string name="android_upgrading_title" msgid="1584192285441405746">"Android እያሻሻለ ነው..."</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index e57c157..bdd802d7 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1012,9 +1012,9 @@
     <string name="sms_control_yes" msgid="3663725993855816807">"Engedélyezés"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Elutasítás"</string>
     <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"SMS küldése a rövid kódra?"</string>
-    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Elküldi a prémium SMS-t?"</string>
-    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"A(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; szöveges üzenetet szeretne küldeni a(z) &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; címre, ami egy SMS rövid kódja.&lt;p&gt;Az egyes rövid kódokra küldött üzenetek miatt mobilszámláján prémiumszolgáltatások lesznek kiszámlázva.&lt;/b&gt;&lt;p&gt;Engedélyezi, hogy az alkalmazás elküldje az üzenetet?"</string>
-    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"A(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; szöveges üzenetet szeretne küldeni a(z) &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; címre, ami egy prémium SMS rövid kódja.&lt;p&gt;Az ide küldött üzenet miatt mobilszámláján prémiumszolgáltatások lesznek kiszámlázva.&lt;/b&gt;&lt;p&gt;Engedélyezi, hogy az alkalmazás elküldje az üzenetet?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Elküldi az emelt díjas SMS-t?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"A(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; szöveges üzenetet szeretne küldeni a(z) &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; címre, ami egy SMS rövid kódja.&lt;p&gt;Az egyes rövid kódokra küldött üzenetek miatt mobilszámláján emelt díjas szolgáltatások lesznek kiszámlázva.&lt;/b&gt;&lt;p&gt;Engedélyezi, hogy az alkalmazás elküldje az üzenetet?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"A(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; szöveges üzenetet szeretne küldeni a(z) &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; címre, ami egy emelt díjas SMS rövid kódja.&lt;p&gt;Az ide küldött üzenet miatt mobilszámláján emelt díjas szolgáltatások lesznek kiszámlázva.&lt;/b&gt;&lt;p&gt;Engedélyezi, hogy az alkalmazás elküldje az üzenetet?"</string>
     <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Üzenet küldése"</string>
     <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Nincs küldés"</string>
     <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Rosszindulatú alk. bejelentése"</string>
diff --git a/core/res/res/values-port/bools.xml b/core/res/res/values-port/bools.xml
new file mode 100644
index 0000000..fc62b69
--- /dev/null
+++ b/core/res/res/values-port/bools.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+    <bool name="action_bar_embed_tabs">false</bool>
+</resources>
diff --git a/core/res/res/values-sw600dp/bools.xml b/core/res/res/values-sw600dp/bools.xml
index 2097049..e74379c 100644
--- a/core/res/res/values-sw600dp/bools.xml
+++ b/core/res/res/values-sw600dp/bools.xml
@@ -17,6 +17,5 @@
 <resources>
     <bool name="preferences_prefer_dual_pane">true</bool>
     <bool name="show_ongoing_ime_switcher">false</bool>
-    <bool name="action_bar_expanded_action_views_exclusive">false</bool>
     <bool name="target_honeycomb_needs_options_menu">false</bool>
 </resources>
diff --git a/core/res/res/values-w480dp/bools.xml b/core/res/res/values-w480dp/bools.xml
index 57a2939..3a463a6 100644
--- a/core/res/res/values-w480dp/bools.xml
+++ b/core/res/res/values-w480dp/bools.xml
@@ -17,6 +17,6 @@
 */
 -->
 <resources>
-    <bool name="action_bar_embed_tabs">true</bool>
+    <bool name="action_bar_embed_tabs_pre_jb">true</bool>
     <bool name="split_action_bar_is_narrow">false</bool>
 </resources>
diff --git a/core/res/res/values-w720dp/bools.xml b/core/res/res/values-w720dp/bools.xml
new file mode 100644
index 0000000..352c319
--- /dev/null
+++ b/core/res/res/values-w720dp/bools.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+    <bool name="action_bar_expanded_action_views_exclusive">false</bool>
+</resources>
diff --git a/core/res/res/values/bools.xml b/core/res/res/values/bools.xml
index 87a98e2..f9762b1 100644
--- a/core/res/res/values/bools.xml
+++ b/core/res/res/values/bools.xml
@@ -15,7 +15,8 @@
 -->
 
 <resources>
-    <bool name="action_bar_embed_tabs">false</bool>
+    <bool name="action_bar_embed_tabs">true</bool>
+    <bool name="action_bar_embed_tabs_pre_jb">false</bool>
     <bool name="split_action_bar_is_narrow">true</bool>
     <bool name="preferences_prefer_dual_pane">false</bool>
     <bool name="show_ongoing_ime_switcher">true</bool>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 0442be8..ef80160 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -213,4 +213,13 @@
 
     <!-- Minimum width for an action button in the menu area of an action bar -->
     <dimen name="action_button_min_width">56dip</dimen>
+
+    <!-- Maximum height for a stacked tab bar as part of an action bar -->
+    <dimen name="action_bar_stacked_max_height">48dp</dimen>
+
+    <!-- Maximum width for a stacked action bar tab. This prevents
+         action bar tabs from becoming too wide on a wide screen when only
+         a few are present. -->
+    <dimen name="action_bar_stacked_tab_max_width">180dp</dimen>
+
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index b564b97..03ba08c 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -234,6 +234,7 @@
   <java-symbol type="attr" name="accessibilityFocusedDrawable"/>
 
   <java-symbol type="bool" name="action_bar_embed_tabs" />
+  <java-symbol type="bool" name="action_bar_embed_tabs_pre_jb" />
   <java-symbol type="bool" name="action_bar_expanded_action_views_exclusive" />
   <java-symbol type="bool" name="config_allowActionMenuItemTextWithIcon" />
   <java-symbol type="bool" name="config_bluetooth_adapter_quick_switch" />
@@ -292,6 +293,8 @@
   <java-symbol type="dimen" name="textview_error_popup_default_width" />
   <java-symbol type="dimen" name="toast_y_offset" />
   <java-symbol type="dimen" name="volume_panel_top" />
+  <java-symbol type="dimen" name="action_bar_stacked_max_height" />
+  <java-symbol type="dimen" name="action_bar_stacked_tab_max_width" />
 
   <java-symbol type="string" name="addToDictionary" />
   <java-symbol type="string" name="action_bar_home_description" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index e00986c..149a78c 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -474,6 +474,15 @@
       and process emergency broadcast messages. This permission is only available
       to system apps.</string>
 
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_readCellBroadcasts">read cell broadcast messages</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_readCellBroadcasts">Allows the app to read
+      cell broadcast messages received by your device. Cell broadcast alerts
+      are delivered in some locations to warn you of emergency situations.
+      Malicious apps may interfere with the performance or operation of your
+      device when an emergency cell broadcast is received.</string>
+
      <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_sendSms">send SMS messages</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
@@ -538,6 +547,11 @@
         tasks and kill their apps. Malicious apps may disrupt
         the behavior of other apps.</string>
 
+    <!-- Title of an application permission, allowing an application to start any activity, regardless of permission protection or exported state. -->
+    <string name="permlab_startAnyActivity">start any activity</string>
+    <!-- Description of an application permission, allowing an application to start any activity, regardless of permission protection or exported state. -->
+    <string name="permdesc_startAnyActivity">Allows the app to start any activity, regardless of permission protection or exported state.</string>
+
     <!-- Title of an application permission, allowing control of app screen compatibility mode -->
     <string name="permlab_setScreenCompatibility">set screen compatibility</string>
     <!-- Description of an application permission, allowing control of app screen compatibility mode -->
diff --git a/docs/html/live/index.jd b/docs/html/live/index.jd
index 70559e7..3885725 100644
--- a/docs/html/live/index.jd
+++ b/docs/html/live/index.jd
@@ -9,7 +9,7 @@
 livecasts on YouTube and videos of past sessions or follow us on 
 <a href="https://plus.google.com/108967384991768947849/posts">+Android Developers</a> for updates.</p>
   
-  <div id="interviewBlock" style="border-top:1px solid #ddd;margin-top:2em;padding-top:1em;clear:both;">
+  <div id="interviewBlock" id="pocketgems" style="border-top:1px solid #ddd;margin-top:2em;padding-top:1em;clear:both;">
 
     <div id="mainBodyLeft" class="videoPlayer">
 
@@ -26,7 +26,7 @@
           developers joining on air via the moderator queue. </p>
           
           <div id="objectWrapper">
-            <img width="560" height="315" src="{@docRoot}images/LivePocketGemsTitleCard.png" frameborder="0" allowfullscreen></iframe>
+            <iframe width="560" height="315" src="http://www.youtube.com/embed/-wkXan-xNqA" frameborder="0" allowfullscreen></iframe>
           </div>
 
     </div><!-- end mainBodyLeft -->
@@ -50,7 +50,7 @@
 
         <h3 style="color:#000;font-size:12px;">Join</h3>
           <p style="line-height:1.5em;">
-            <a style="text-decoration:none" href="http://www.youtube.com/user/androiddevelopers">Watch live on YouTube</a><br />
+            <a style="text-decoration:none" href="http://youtu.be/-wkXan-xNqA">Watch on YouTube</a><br />
             <a style="text-decoration:none" href="http://www.google.com/moderator/#15/e=1fd27e&t=1fd27e.40">Submit a question</a><br />
             <a style="text-decoration:none" href="https://www.google.com/calendar/ical/g2ilcr0iki4olp10aluid7gl70%40group.calendar.google.com/public/basic.ics">Add to calendar</a> (iCal)
           </p>
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 2efacd8..258760f 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -280,6 +280,19 @@
     */
     public native final void flush();
 
+    public final static class CryptoException extends RuntimeException {
+        public CryptoException(int errorCode, String detailMessage) {
+            super(detailMessage);
+            mErrorCode = errorCode;
+        }
+
+        public int getErrorCode() {
+            return mErrorCode;
+        }
+
+        private int mErrorCode;
+    }
+
     /** After filling a range of the input buffer at the specified index
      *  submit it to the component.
      *
@@ -304,10 +317,13 @@
      *  @param presentationTimeUs The time at which this buffer should be rendered.
      *  @param flags A bitmask of flags {@link #FLAG_SYNCFRAME},
      *               {@link #FLAG_CODECCONFIG} or {@link #FLAG_EOS}.
+     *  @throws CryptoException if a crypto object has been specified in
+     *          {@link #configure}
     */
     public native final void queueInputBuffer(
             int index,
-            int offset, int size, long presentationTimeUs, int flags);
+            int offset, int size, long presentationTimeUs, int flags)
+        throws CryptoException;
 
     /** Metadata describing the structure of a (at least partially) encrypted
      *  input sample.
@@ -361,7 +377,7 @@
             int offset,
             CryptoInfo info,
             long presentationTimeUs,
-            int flags);
+            int flags) throws CryptoException;
 
     /** Returns the index of an input buffer to be filled with valid data
      *  or -1 if no such buffer is currently available.
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 545752c..fae7d0b 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1577,26 +1577,39 @@
 
     /**
      * Returns an array of track information.
+     * If it is called in an invalid state, IllegalStateException will be thrown.
      *
-     * @return Array of track info. null if an error occured.
+     * @return Array of track info. The total number of tracks is the array length.
+     * Must be called again if an external source has been added after any of the
+     * addExternalSource methods are called.
      * {@hide}
      */
-    // FIXME: It returns timed text tracks' information for now. Other types of tracks will be
-    // supported in future.
     public TrackInfo[] getTrackInfo() {
         Parcel request = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         request.writeInterfaceToken(IMEDIA_PLAYER);
         request.writeInt(INVOKE_ID_GET_TRACK_INFO);
-        invoke(request, reply);
+        int status = invoke(request, reply);
+        if (status != 0) {
+            throw new IllegalStateException();
+        }
         TrackInfo trackInfo[] = reply.createTypedArray(TrackInfo.CREATOR);
         return trackInfo;
     }
 
+    /* Do not change these values without updating their counterparts
+     * in include/media/stagefright/MediaDefs.h and media/libstagefright/MediaDefs.cpp!
+     */
+    /**
+     * MIME type for SubRip (SRT) container. Used in addExternalSource APIs.
+     * {@hide}
+     */
+    public static final String MEDIA_MIMETYPE_TEXT_SUBRIP = "application/x-subrip";
+
     /*
      * A helper function to check if the mime type is supported by media framework.
      */
-    private boolean availableMimeTypeForExternalSource(String mimeType) {
+    private static boolean availableMimeTypeForExternalSource(String mimeType) {
         if (mimeType == MEDIA_MIMETYPE_TEXT_SUBRIP) {
             return true;
         }
@@ -1614,10 +1627,11 @@
      * additional tracks become available after this method call.
      *
      * @param path The file path of external source file.
+     * @param mimeType The mime type of the file. Must be one of the mime types listed above.
+     * @throws IOException if the file cannot be accessed or is corrupted.
+     * @throws IllegalArgumentException if the mimeType is not supported.
      * {@hide}
      */
-    // FIXME: define error codes and throws exceptions according to the error codes.
-    // (IllegalStateException, IOException).
     public void addExternalSource(String path, String mimeType)
             throws IOException, IllegalArgumentException {
         if (!availableMimeTypeForExternalSource(mimeType)) {
@@ -1647,10 +1661,11 @@
      *
      * @param context the Context to use when resolving the Uri
      * @param uri the Content URI of the data you want to play
+     * @param mimeType The mime type of the file. Must be one of the mime types listed above.
+     * @throws IOException if the file cannot be accessed or is corrupted.
+     * @throws IllegalArgumentException if the mimeType is not supported.
      * {@hide}
      */
-    // FIXME: define error codes and throws exceptions according to the error codes.
-    // (IllegalStateException, IOException).
     public void addExternalSource(Context context, Uri uri, String mimeType)
             throws IOException, IllegalArgumentException {
         String scheme = uri.getScheme();
@@ -1677,15 +1692,6 @@
         }
     }
 
-    /* Do not change these values without updating their counterparts
-     * in include/media/stagefright/MediaDefs.h and media/libstagefright/MediaDefs.cpp!
-     */
-    /**
-     * MIME type for SubRip (SRT) container. Used in {@link #addExternalSource()} APIs.
-     * {@hide}
-     */
-    public static final String MEDIA_MIMETYPE_TEXT_SUBRIP = "application/x-subrip";
-
     /**
      * Adds an external source file (FileDescriptor).
      * It is the caller's responsibility to close the file descriptor.
@@ -1697,14 +1703,10 @@
      * additional tracks become available after this method call.
      *
      * @param fd the FileDescriptor for the file you want to play
-     * @param mimeType A MIME type for the content. It can be null.
-     * <ul>
-     * <li>{@link #MEDIA_MIMETYPE_TEXT_SUBRIP}
-     * </ul>
+     * @param mimeType The mime type of the file. Must be one of the mime types listed above.
+     * @throws IllegalArgumentException if the mimeType is not supported.
      * {@hide}
      */
-    // FIXME: define error codes and throws exceptions according to the error codes.
-    // (IllegalStateException, IOException).
     public void addExternalSource(FileDescriptor fd, String mimeType)
             throws IllegalArgumentException {
         // intentionally less than LONG_MAX
@@ -1724,11 +1726,10 @@
      * @param fd the FileDescriptor for the file you want to play
      * @param offset the offset into the file where the data to be played starts, in bytes
      * @param length the length in bytes of the data to be played
-     * @param mimeType A MIME type for the content. It can be null.
+     * @param mimeType The mime type of the file. Must be one of the mime types listed above.
+     * @throws IllegalArgumentException if the mimeType is not supported.
      * {@hide}
      */
-    // FIXME: define error codes and throws exceptions according to the error codes.
-    // (IllegalStateException, IOException).
     public void addExternalSource(FileDescriptor fd, long offset, long length, String mimeType)
             throws IllegalArgumentException {
         if (!availableMimeTypeForExternalSource(mimeType)) {
@@ -1749,8 +1750,8 @@
     /**
      * Selects a track.
      * <p>
-     * If a MediaPlayer is in invalid state, it throws exception.
-     * If a MediaPlayer is in Started state, the selected track will be presented immediately.
+     * If a MediaPlayer is in invalid state, it throws an IllegalStateException exception.
+     * If a MediaPlayer is in <em>Started</em> state, the selected track is presented immediately.
      * If a MediaPlayer is not in Started state, it just marks the track to be played.
      * </p>
      * <p>
@@ -1758,38 +1759,58 @@
      * Audio, Timed Text), the most recent one will be chosen.
      * </p>
      * <p>
-     * The first audio and video tracks will be selected by default, even though this function is not
-     * called. However, no timed text track will be selected until this function is called.
+     * The first audio and video tracks are selected by default if available, even though
+     * this method is not called. However, no timed text track will be selected until
+     * this function is called.
      * </p>
+     * <p>
+     * Currently, only timed text tracks or audio tracks can be selected via this method.
+     * In addition, the support for selecting an audio track at runtime is pretty limited
+     * in that an audio track can only be selected in the <em>Prepared</em> state.
+     * </p>
+     * @param index the index of the track to be selected. The valid range of the index
+     * is 0..total number of track - 1. The total number of tracks as well as the type of
+     * each individual track can be found by calling {@link #getTrackInfo()} method.
+     * @see android.media.MediaPlayer.getTrackInfo
      * {@hide}
      */
-    // FIXME: define error codes and throws exceptions according to the error codes.
-    // (IllegalStateException, IOException, IllegalArgumentException).
     public void selectTrack(int index) {
-        Parcel request = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        request.writeInterfaceToken(IMEDIA_PLAYER);
-        request.writeInt(INVOKE_ID_SELECT_TRACK);
-        request.writeInt(index);
-        invoke(request, reply);
+        selectOrUnselectTrack(index, true /* select */);
     }
 
     /**
      * Unselect a track.
-     * If the track identified by index has not been selected before, it throws an exception.
+     * <p>
+     * Currently, the track must be a timed text track and no audio or video tracks can be
+     * unselected. If the timed text track identified by index has not been
+     * selected before, it throws an exception.
+     * </p>
+     * @param index the index of the track to be unselected. The valid range of the index
+     * is 0..total number of tracks - 1. The total number of tracks as well as the type of
+     * each individual track can be found by calling {@link #getTrackInfo()} method.
+     *
+     * @see android.media.MediaPlayer.getTrackInfo
      * {@hide}
      */
-    // FIXME: define error codes and throws exceptions according to the error codes.
-    // (IllegalStateException, IOException, IllegalArgumentException).
     public void unselectTrack(int index) {
+        selectOrUnselectTrack(index, false /* select */);
+    }
+
+    private void selectOrUnselectTrack(int index, boolean select) {
         Parcel request = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         request.writeInterfaceToken(IMEDIA_PLAYER);
-        request.writeInt(INVOKE_ID_UNSELECT_TRACK);
+        request.writeInt(select? INVOKE_ID_SELECT_TRACK: INVOKE_ID_UNSELECT_TRACK);
         request.writeInt(index);
-        invoke(request, reply);
+        int status = invoke(request, reply);
+        if (status != 0) {
+            String msg = select? "selectTrack ": "unselectTrack ";
+            msg += "failed for track index: " + index;
+            throw new RuntimeException(msg);
+        }
     }
 
+
     /**
      * @param reply Parcel with audio/video duration info for battery
                     tracking usage
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index a120a2f..8009fb5 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -36,6 +36,7 @@
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
 #include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/AString.h>
 #include <media/stagefright/MediaErrors.h>
 
 namespace android {
@@ -129,8 +130,10 @@
 
 status_t JMediaCodec::queueInputBuffer(
         size_t index,
-        size_t offset, size_t size, int64_t timeUs, uint32_t flags) {
-    return mCodec->queueInputBuffer(index, offset, size, timeUs, flags);
+        size_t offset, size_t size, int64_t timeUs, uint32_t flags,
+        AString *errorDetailMsg) {
+    return mCodec->queueInputBuffer(
+            index, offset, size, timeUs, flags, errorDetailMsg);
 }
 
 status_t JMediaCodec::queueSecureInputBuffer(
@@ -142,10 +145,11 @@
         const uint8_t iv[16],
         CryptoPlugin::Mode mode,
         int64_t presentationTimeUs,
-        uint32_t flags) {
+        uint32_t flags,
+        AString *errorDetailMsg) {
     return mCodec->queueSecureInputBuffer(
             index, offset, subSamples, numSubSamples, key, iv, mode,
-            presentationTimeUs, flags);
+            presentationTimeUs, flags, errorDetailMsg);
 }
 
 status_t JMediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
@@ -251,7 +255,31 @@
     setMediaCodec(env, thiz, NULL);
 }
 
-static jint throwExceptionAsNecessary(JNIEnv *env, status_t err) {
+static void throwCryptoException(JNIEnv *env, status_t err, const char *msg) {
+    jclass clazz = env->FindClass("android/media/MediaCodec$CryptoException");
+    CHECK(clazz != NULL);
+
+    jmethodID constructID =
+        env->GetMethodID(clazz, "<init>", "(ILjava/lang/String;)V");
+    CHECK(constructID != NULL);
+
+    jstring msgObj = env->NewStringUTF(msg != NULL ? msg : "Unknown Error");
+
+    jthrowable exception =
+        (jthrowable)env->NewObject(clazz, constructID, err, msgObj);
+
+    env->Throw(exception);
+}
+
+static jint throwExceptionAsNecessary(
+        JNIEnv *env, status_t err, const char *msg = NULL) {
+    if (err >= ERROR_DRM_WV_VENDOR_MIN && err <= ERROR_DRM_WV_VENDOR_MAX) {
+        // We'll throw our custom MediaCodec.CryptoException
+
+        throwCryptoException(env, err, msg);
+        return 0;
+    }
+
     switch (err) {
         case OK:
             return 0;
@@ -383,10 +411,13 @@
         return;
     }
 
-    status_t err = codec->queueInputBuffer(
-            index, offset, size, timestampUs, flags);
+    AString errorDetailMsg;
 
-    throwExceptionAsNecessary(env, err);
+    status_t err = codec->queueInputBuffer(
+            index, offset, size, timestampUs, flags, &errorDetailMsg);
+
+    throwExceptionAsNecessary(
+            env, err, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str());
 }
 
 static void android_media_MediaCodec_queueSecureInputBuffer(
@@ -497,13 +528,17 @@
         }
     }
 
+    AString errorDetailMsg;
+
     if (err == OK) {
         err = codec->queueSecureInputBuffer(
                 index, offset,
                 subSamples, numSubSamples,
                 (const uint8_t *)key, (const uint8_t *)iv,
                 (CryptoPlugin::Mode)mode,
-                timestampUs, flags);
+                timestampUs,
+                flags,
+                &errorDetailMsg);
     }
 
     if (iv != NULL) {
@@ -519,7 +554,8 @@
     delete[] subSamples;
     subSamples = NULL;
 
-    throwExceptionAsNecessary(env, err);
+    throwExceptionAsNecessary(
+            env, err, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str());
 }
 
 static jint android_media_MediaCodec_dequeueInputBuffer(
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index 570c33b..e2688be 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -28,6 +28,7 @@
 
 struct ALooper;
 struct AMessage;
+struct AString;
 struct ICrypto;
 struct ISurfaceTexture;
 struct MediaCodec;
@@ -52,7 +53,8 @@
 
     status_t queueInputBuffer(
             size_t index,
-            size_t offset, size_t size, int64_t timeUs, uint32_t flags);
+            size_t offset, size_t size, int64_t timeUs, uint32_t flags,
+            AString *errorDetailMsg);
 
     status_t queueSecureInputBuffer(
             size_t index,
@@ -63,7 +65,8 @@
             const uint8_t iv[16],
             CryptoPlugin::Mode mode,
             int64_t presentationTimeUs,
-            uint32_t flags);
+            uint32_t flags,
+            AString *errorDetailMsg);
 
     status_t dequeueInputBuffer(size_t *index, int64_t timeoutUs);
 
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index e937587..39fb2b4 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -1,15 +1,44 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.android.systemui"
-        coreApp="true"
-        android:sharedUserId="android.uid.system"
-        android:process="system"
-        >
+        coreApp="true">
+
+    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
+
+    <uses-permission android:name="android.permission.INJECT_EVENTS" />
+    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
 
     <uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />
+    <uses-permission android:name="android.permission.STATUS_BAR" />
+    <uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
+
+    <!-- Networking and telephony -->
     <uses-permission android:name="android.permission.BLUETOOTH" />
     <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
-    <uses-permission android:name="android.permission.GET_TASKS" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+
+    <!-- Physical hardware -->
     <uses-permission android:name="android.permission.MANAGE_USB" />
+    <uses-permission android:name="android.permission.DEVICE_POWER" />
+    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
+    <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" />
+
+    <!-- ActivityManager -->
+    <uses-permission android:name="android.permission.GET_TASKS" />
+    <uses-permission android:name="android.permission.REORDER_TASKS" />
+    <uses-permission android:name="android.permission.REMOVE_TASKS" />
+    <uses-permission android:name="android.permission.STOP_APP_SWITCHES" />
+    <uses-permission android:name="android.permission.SET_SCREEN_COMPATIBILITY" />
+    <uses-permission android:name="android.permission.START_ANY_ACTIVITY" />
+
+    <!-- WindowManager -->
+    <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" />
+    <uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
+    <uses-permission android:name="android.permission.MANAGE_APP_TOKENS" />
+    <uses-permission android:name="android.permission.SET_ORIENTATION" />
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
 
     <application
         android:persistent="true"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 1654eca..d54439e 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Ligging deur GPS gestel"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Verwyder alle kennisgewings."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktiveer sluimerskerm"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 42eef13..0540052 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -118,7 +118,7 @@
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"ብሉቱዝ ማያያዝ።"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"የአውሮፕላን ሁነታ።"</string>
     <string name="accessibility_battery_level" msgid="7451474187113371965">"የባትሪ <xliff:g id="NUMBER">%d</xliff:g> መቶኛ።"</string>
-    <string name="accessibility_settings_button" msgid="799583911231893380">"የስርዓት ቅንጅቶች"</string>
+    <string name="accessibility_settings_button" msgid="799583911231893380">"የስርዓት ቅንብሮች"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"ማሳወቂያዎች"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"ማሳወቂያ አጥራ"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS ነቅቷል።"</string>
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"በ GPS የተዘጋጀ ሥፍራ"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"ሁሉንም ማሳወቂያዎች አጽዳ"</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">" ገፁማያ ማቆያ አንቃ"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 9d6051e..7f1b816 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"تم تعيين الموقع بواسطة GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"محو جميع الإشعارات."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"تنشيط شاشة التوقف"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 433c124..8ce52db 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -141,4 +141,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Месца задана праз GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Выдалiць усе апавяшчэннi."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Актывацыя экраннай застаўкі"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 429f246..b78dbc9 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Местоположението е зададено от GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Изчистване на всички известия."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Активиране на скрийнсейвъра"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 427abce..e5f8776 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -141,4 +141,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"S\'ha establert la ubicació per GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Esborra totes les notificacions."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Activa el protector de pantalla"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 9c9674a..f5a12e4 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -141,4 +141,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Poloha nastavena pomocí systému GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Vymazat všechna oznámení."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktivovat spořič obrazovky"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 6c614cd..62f69ff 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Placeringen er angivet ved hjælp af GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Ryd alle meddelelser."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktiver pauseskærm"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index e3d82b1..3b06f06 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -141,4 +141,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Standort durch GPS festgelegt"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Alle Benachrichtigungen löschen"</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Bildschirmschoner aktivieren"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 5511b1a..1850182 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -141,4 +141,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Ρύθμιση τοποθεσίας με GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Εκκαθάριση όλων των ειδοποιήσεων."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Ενεργοποίηση προφύλαξης οθόνης"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index b20a5f3..7061148 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Location set by GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Clear all notifications."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Activate screen saver"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 96c8c23..7e1fe16 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -141,4 +141,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"La ubicación se estableció por GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Eliminar todas las notificaciones"</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Activar el protector de pantalla"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 0b3e4e4..10dbf0d 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Ubicación definida por GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Borrar todas las notificaciones"</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Activar salvapantallas"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 055e3ee..8ebd2a5 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"GPS-i määratud asukoht"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Kustuta kõik teatised."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktiveeri ekraanisäästja"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index df25d5e..736d164 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"مکان تنظیم شده توسط GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"پاک کردن تمام اعلان‌ها"</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"فعال کردن محافظ صفحه نمایش"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 370d234..698e59c 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Sijainti määritetty GPS:n avulla"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Tyhjennä kaikki ilmoitukset."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Ota näytönsäästäjä käyttöön"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index c7f307c..5c5658d 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -141,4 +141,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Position définie par GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Supprimer toutes les notifications"</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Activer l\'économiseur d\'écran"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 9805f90..2b927d7 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"GPS द्वारा सेट किया गया स्‍थान"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"सभी सूचनाएं साफ़ करें."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"स्‍क्रीन सेवर सक्रिय करें"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 2226aa8..5cd66d3 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Lokaciju utvrdio GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Brisanje svih obavijesti."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktivirajte čuvar zaslona"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 87a9d45..65a04b8 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"A GPS beállította a helyet"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Minden értesítés törlése"</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Képernyővédő aktiválása"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index f246132..3611da25 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Lokasi yang disetel oleh GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Menghapus semua pemberitahuan."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktifkan tirai layar"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index a725377..c2c7856 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -141,4 +141,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Posizione stabilita dal GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Cancella tutte le notifiche."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Attiva screensaver"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 03fba7e..17f5a36 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"מיקום מוגדר על ידי GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"נקה את כל ההתראות."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"הפעלת שומר מסך"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 4818ca9..203fe9c 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -141,4 +141,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"GPSにより現在地が設定されました"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"通知をすべて消去。"</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"スクリーンセーバーを有効にする"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 3321912..5350cd1 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"GPS에서 위치 설정"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"모든 알림 지우기"</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"스크린 세이버 활성화"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 831fa41..a30dd5a 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"GPS nustatyta vieta"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Išvalyti visus pranešimus."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktyvinti ekrano užsklandą"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 158c850..0461ccd 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"GPS iestatītā atrašanās vieta"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Notīrīt visus paziņojumus"</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktivizēt ekrānsaudzētāju"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 899a204..dc5128a 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Lokasi ditetapkan oleh GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Padamkan semua pemberitahuan."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktifkan gambar skrin"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index c7b272a..39b622e 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Posisjon angitt av GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Fjern alle varslinger."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktiver skjermbeskytter"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index e05e2c9..444b05b 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Locatie bepaald met GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Alle meldingen wissen."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Schermbeveiliging inschakelen"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 0618eb5..d44efbe 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Lokalizacja ustawiona według GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Usuń wszystkie powiadomienia."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Włącz wygaszacz ekranu."</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 6a278ba..876eb799 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Localização definida por GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Limpar todas as notificações."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Ativar proteção de ecrã"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 23a2ba5..500ee2b 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -141,4 +141,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Local definido por GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Limpar todas as notificações."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Ativar proteção de tela"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml
index 3062d48..917306a 100644
--- a/packages/SystemUI/res/values-rm/strings.xml
+++ b/packages/SystemUI/res/values-rm/strings.xml
@@ -248,4 +248,6 @@
     <skip />
     <!-- no translation found for dreams_dock_launcher (3541196417659166245) -->
     <skip />
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index b778e4d..0e7509c 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Locaţie setată prin GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Ştergeţi toate notificările."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Activaţi screensaverul"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 3753309..23eb1d2 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -141,4 +141,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Местоположение установлено с помощью GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Удалить все уведомления"</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Активация заставки экрана"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 599f99c..a729cce 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -141,4 +141,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Poloha nastavená pomocou GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Vymazať všetky upozornenia."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktivovať šetrič obrazovky"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index fb229e2..6da01c7 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Lokacija nastavljena z GPS-om"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Izbriši vsa obvestila."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Vklop ohranjevalnika zaslona"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index fb7c21a..3586b84 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Локацију је подесио GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Обриши сва обавештења."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Активирање чувара екрана"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 8eaa126..ed73106 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Platsen har identifierats av GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Ta bort alla meddelanden."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktivera skärmsläckare"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 19bd4ab..16ccca3 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -137,4 +137,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Mahali pamewekwa na GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Futa arifa zote."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Amilisha hifadhi ya skrini"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 82c5dd7..0e3344e 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"ตำแหน่งที่กำหนดโดย GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"ล้างการแจ้งเตือนทั้งหมด"</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"เปิดโปรแกรมรักษาหน้าจอ"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 2054121..7b294ac 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Lokasyong itinatakda ng GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"I-clear ang lahat ng notification."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"I-activate ang screen saver"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index ca422f7..f0da20e 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Konum GPS ile belirlendi"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Tüm bildirimleri temizle"</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Ekran koruyucuyu etkinleştir"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 8a13400..c76798c 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Місцезнаходження встановлено за допомогою GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Очистити всі сповіщення."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Активувати заставку"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 05ab87c..35ac681 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Vị trí đặt bởi GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Xóa tất cả thông báo."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Kích hoạt trình bảo vệ màn hình"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index c862d74..996119c 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -141,4 +141,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"已通过 GPS 确定位置"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"清除所有通知。"</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"激活屏幕保护程序"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 399890b..d075352 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -141,4 +141,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"GPS 已定位"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"清除所有通知。"</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"啟用螢幕保護程式"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 91f6566..9c02a27 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -139,4 +139,6 @@
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Indawo ihlelwe i-GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Susa zonke izaziso."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Yenza ukuthi iskrini seyiva sisebenze"</string>
+    <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 724679f..c60c806 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -155,6 +155,11 @@
             }
         }
 
+        public DrawableEngine() {
+            super();
+            setFixedSizeAllowed(true);
+        }
+
         @Override
         public void onCreate(SurfaceHolder surfaceHolder) {
             if (DEBUG) {
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
index 10c3381..679158d 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -667,20 +667,21 @@
 
     InfoCallbackImpl mInfoCallback = new InfoCallbackImpl() {
 
-        /**
-         * When somebody plugs in or unplugs the device, we don't want to display the biometric
-         * unlock.
-         */
         @Override
         public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn,
                 int batteryLevel) {
-            mSupressBiometricUnlock |= mPluggedIn != pluggedIn;
-            mPluggedIn = pluggedIn;
-            // If it's already running, don't close it down: the unplug didn't start it
-            if (!mBiometricUnlock.isRunning()) {
+            // When someone plugs in or unplugs the device, we hide the biometric sensor area and
+            // suppress its startup for the next onScreenTurnedOn().  Since plugging/unplugging
+            // causes the screen to turn on, the biometric unlock would start if it wasn't
+            // suppressed.
+            //
+            // However, if the biometric unlock is already running, we do not want to interrupt it.
+            if (mPluggedIn != pluggedIn && !mBiometricUnlock.isRunning()) {
                 mBiometricUnlock.stop();
                 mBiometricUnlock.hide();
+                mSupressBiometricUnlock = true;
             }
+            mPluggedIn = pluggedIn;
         }
 
         @Override
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index 4cc3d44..3a48b16 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -1292,12 +1292,17 @@
 // --- TouchButtonAccumulator ---
 
 TouchButtonAccumulator::TouchButtonAccumulator() :
-        mHaveBtnTouch(false) {
+        mHaveBtnTouch(false), mHaveStylus(false) {
     clearButtons();
 }
 
 void TouchButtonAccumulator::configure(InputDevice* device) {
     mHaveBtnTouch = device->hasKey(BTN_TOUCH);
+    mHaveStylus = device->hasKey(BTN_TOOL_PEN)
+            || device->hasKey(BTN_TOOL_RUBBER)
+            || device->hasKey(BTN_TOOL_BRUSH)
+            || device->hasKey(BTN_TOOL_PENCIL)
+            || device->hasKey(BTN_TOOL_AIRBRUSH);
 }
 
 void TouchButtonAccumulator::reset(InputDevice* device) {
@@ -1421,6 +1426,10 @@
     return mHaveBtnTouch && !mBtnTouch;
 }
 
+bool TouchButtonAccumulator::hasStylus() const {
+    return mHaveStylus;
+}
+
 
 // --- RawPointerAxes ---
 
@@ -1572,16 +1581,19 @@
 // --- MultiTouchMotionAccumulator ---
 
 MultiTouchMotionAccumulator::MultiTouchMotionAccumulator() :
-        mCurrentSlot(-1), mSlots(NULL), mSlotCount(0), mUsingSlotsProtocol(false) {
+        mCurrentSlot(-1), mSlots(NULL), mSlotCount(0), mUsingSlotsProtocol(false),
+        mHaveStylus(false) {
 }
 
 MultiTouchMotionAccumulator::~MultiTouchMotionAccumulator() {
     delete[] mSlots;
 }
 
-void MultiTouchMotionAccumulator::configure(size_t slotCount, bool usingSlotsProtocol) {
+void MultiTouchMotionAccumulator::configure(InputDevice* device,
+        size_t slotCount, bool usingSlotsProtocol) {
     mSlotCount = slotCount;
     mUsingSlotsProtocol = usingSlotsProtocol;
+    mHaveStylus = device->hasAbsoluteAxis(ABS_MT_TOOL_TYPE);
 
     delete[] mSlots;
     mSlots = new Slot[slotCount];
@@ -1713,6 +1725,10 @@
     }
 }
 
+bool MultiTouchMotionAccumulator::hasStylus() const {
+    return mHaveStylus;
+}
+
 
 // --- MultiTouchMotionAccumulator::Slot ---
 
@@ -2872,10 +2888,16 @@
             && mConfig.pointerGesturesEnabled) {
         mSource = AINPUT_SOURCE_MOUSE;
         mDeviceMode = DEVICE_MODE_POINTER;
+        if (hasStylus()) {
+            mSource |= AINPUT_SOURCE_STYLUS;
+        }
     } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
             && mParameters.associatedDisplayId >= 0) {
         mSource = AINPUT_SOURCE_TOUCHSCREEN;
         mDeviceMode = DEVICE_MODE_DIRECT;
+        if (hasStylus()) {
+            mSource |= AINPUT_SOURCE_STYLUS;
+        }
     } else {
         mSource = AINPUT_SOURCE_TOUCHPAD;
         mDeviceMode = DEVICE_MODE_UNSCALED;
@@ -5786,6 +5808,10 @@
     getAbsoluteAxisInfo(ABS_TILT_Y, &mRawPointerAxes.tiltY);
 }
 
+bool SingleTouchInputMapper::hasStylus() const {
+    return mTouchButtonAccumulator.hasStylus();
+}
+
 
 // --- MultiTouchInputMapper ---
 
@@ -5920,12 +5946,19 @@
                     getDeviceName().string(), slotCount, MAX_SLOTS);
             slotCount = MAX_SLOTS;
         }
-        mMultiTouchMotionAccumulator.configure(slotCount, true /*usingSlotsProtocol*/);
+        mMultiTouchMotionAccumulator.configure(getDevice(),
+                slotCount, true /*usingSlotsProtocol*/);
     } else {
-        mMultiTouchMotionAccumulator.configure(MAX_POINTERS, false /*usingSlotsProtocol*/);
+        mMultiTouchMotionAccumulator.configure(getDevice(),
+                MAX_POINTERS, false /*usingSlotsProtocol*/);
     }
 }
 
+bool MultiTouchInputMapper::hasStylus() const {
+    return mMultiTouchMotionAccumulator.hasStylus()
+            || mTouchButtonAccumulator.hasStylus();
+}
+
 
 // --- JoystickInputMapper ---
 
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index e5897e7..acdec85 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -507,6 +507,12 @@
         return getEventHub()->hasScanCode(mId, code);
     }
 
+    bool hasAbsoluteAxis(int32_t code) {
+        RawAbsoluteAxisInfo info;
+        getEventHub()->getAbsoluteAxisInfo(mId, code, &info);
+        return info.valid;
+    }
+
     bool isKeyPressed(int32_t code) {
         return getEventHub()->getScanCodeState(mId, code) == AKEY_STATE_DOWN;
     }
@@ -627,9 +633,11 @@
     int32_t getToolType() const;
     bool isToolActive() const;
     bool isHovering() const;
+    bool hasStylus() const;
 
 private:
     bool mHaveBtnTouch;
+    bool mHaveStylus;
 
     bool mBtnTouch;
     bool mBtnStylus;
@@ -817,10 +825,11 @@
     MultiTouchMotionAccumulator();
     ~MultiTouchMotionAccumulator();
 
-    void configure(size_t slotCount, bool usingSlotsProtocol);
+    void configure(InputDevice* device, size_t slotCount, bool usingSlotsProtocol);
     void reset(InputDevice* device);
     void process(const RawEvent* rawEvent);
     void finishSync();
+    bool hasStylus() const;
 
     inline size_t getSlotCount() const { return mSlotCount; }
     inline const Slot* getSlot(size_t index) const { return &mSlots[index]; }
@@ -830,6 +839,7 @@
     Slot* mSlots;
     size_t mSlotCount;
     bool mUsingSlotsProtocol;
+    bool mHaveStylus;
 
     void clearSlots(int32_t initialSlot);
 };
@@ -1257,6 +1267,7 @@
     virtual void parseCalibration();
     virtual void resolveCalibration();
     virtual void dumpCalibration(String8& dump);
+    virtual bool hasStylus() const = 0;
 
     virtual void syncTouch(nsecs_t when, bool* outHavePointerIds) = 0;
 
@@ -1605,6 +1616,7 @@
 protected:
     virtual void syncTouch(nsecs_t when, bool* outHavePointerIds);
     virtual void configureRawPointerAxes();
+    virtual bool hasStylus() const;
 
 private:
     SingleTouchMotionAccumulator mSingleTouchMotionAccumulator;
@@ -1622,6 +1634,7 @@
 protected:
     virtual void syncTouch(nsecs_t when, bool* outHavePointerIds);
     virtual void configureRawPointerAxes();
+    virtual bool hasStylus() const;
 
 private:
     MultiTouchMotionAccumulator mMultiTouchMotionAccumulator;
diff --git a/services/java/com/android/server/DeviceStorageMonitorService.java b/services/java/com/android/server/DeviceStorageMonitorService.java
index b943c09..0ed5189 100644
--- a/services/java/com/android/server/DeviceStorageMonitorService.java
+++ b/services/java/com/android/server/DeviceStorageMonitorService.java
@@ -26,6 +26,7 @@
 import android.content.pm.IPackageManager;
 import android.os.Binder;
 import android.os.Environment;
+import android.os.FileObserver;
 import android.os.Handler;
 import android.os.Message;
 import android.os.Process;
@@ -91,6 +92,7 @@
     private Intent mStorageFullIntent;
     private Intent mStorageNotFullIntent;
     private CachePackageDataObserver mClearCacheObserver;
+    private final CacheFileDeletedObserver mCacheFileDeletedObserver;
     private static final int _TRUE = 1;
     private static final int _FALSE = 0;
     private long mMemLowThreshold;
@@ -324,6 +326,9 @@
         mMemLowThreshold = getMemThreshold();
         mMemFullThreshold = getMemFullThreshold();
         checkMemory(true);
+
+        mCacheFileDeletedObserver = new CacheFileDeletedObserver();
+        mCacheFileDeletedObserver.startWatching();
     }
 
 
@@ -419,4 +424,15 @@
     public boolean isMemoryLow() {
         return mLowMemFlag;
     }
+
+    public static class CacheFileDeletedObserver extends FileObserver {
+        public CacheFileDeletedObserver() {
+            super(Environment.getDownloadCacheDirectory().getAbsolutePath(), FileObserver.DELETE);
+        }
+
+        @Override
+        public void onEvent(int event, String path) {
+            EventLogTags.writeCacheFileDeleted(path);
+        }
+    }
 }
diff --git a/services/java/com/android/server/EventLogTags.logtags b/services/java/com/android/server/EventLogTags.logtags
index 0bcec2e..249513f 100644
--- a/services/java/com/android/server/EventLogTags.logtags
+++ b/services/java/com/android/server/EventLogTags.logtags
@@ -36,7 +36,7 @@
 
 
 # ---------------------------
-# DeviceStorageMonitoryService.java
+# DeviceStorageMonitorService.java
 # ---------------------------
 # The disk space free on the /data partition, in bytes
 2744 free_storage_changed (data|2|2)
@@ -44,6 +44,8 @@
 2745 low_storage (data|2|2)
 # disk space free on the /data, /system, and /cache partitions in bytes
 2746 free_storage_left (data|2|2),(system|2|2),(cache|2|2)
+# file on cache partition was deleted
+2748 cache_file_deleted (path|3)
 
 
 # ---------------------------
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index ad13c41..24bab99 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -16,6 +16,9 @@
 
 package com.android.server.am;
 
+import static android.Manifest.permission.START_ANY_ACTIVITY;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
 import com.android.internal.app.HeavyWeightSwitcherActivity;
 import com.android.internal.os.BatteryStatsImpl;
 import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
@@ -2407,9 +2410,11 @@
             return err;
         }
 
-        final int perm = mService.checkComponentPermission(aInfo.permission, callingPid,
+        final int startAnyPerm = mService.checkPermission(
+                START_ANY_ACTIVITY, callingPid, callingUid);
+        final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
                 callingUid, aInfo.applicationInfo.uid, aInfo.exported);
-        if (perm != PackageManager.PERMISSION_GRANTED) {
+        if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
             if (resultRecord != null) {
                 sendActivityResultLocked(-1,
                     resultRecord, resultWho, requestCode,
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index b4a458f..f698fbc 100755
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -461,6 +461,10 @@
     int mCurDisplayHeight = 0;
     int mAppDisplayWidth = 0;
     int mAppDisplayHeight = 0;
+    int mSmallestDisplayWidth = 0;
+    int mSmallestDisplayHeight = 0;
+    int mLargestDisplayWidth = 0;
+    int mLargestDisplayHeight = 0;
 
     int mRotation = 0;
     int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@@ -6068,12 +6072,21 @@
         return config;
     }
 
-    private int reduceConfigWidthSize(int curSize, int rotation, float density, int dw, int dh) {
-        int size = (int)(mPolicy.getConfigDisplayWidth(dw, dh, rotation) / density);
-        if (size < curSize) {
-            curSize = size;
+    private void adjustDisplaySizeRanges(int rotation, int dw, int dh) {
+        final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation);
+        if (width < mSmallestDisplayWidth) {
+            mSmallestDisplayWidth = width;
         }
-        return curSize;
+        if (width > mLargestDisplayWidth) {
+            mLargestDisplayWidth = width;
+        }
+        final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation);
+        if (height < mSmallestDisplayHeight) {
+            mSmallestDisplayHeight = height;
+        }
+        if (height > mLargestDisplayHeight) {
+            mLargestDisplayHeight = height;
+        }
     }
 
     private int reduceConfigLayout(int curLayout, int rotation, float density,
@@ -6155,7 +6168,7 @@
         return curLayout;
     }
 
-    private void computeSmallestWidthAndScreenLayout(boolean rotated, int dw, int dh,
+    private void computeSizeRangesAndScreenLayout(boolean rotated, int dw, int dh,
             float density, Configuration outConfig) {
         // We need to determine the smallest width that will occur under normal
         // operation.  To this, start with the base screen size and compute the
@@ -6169,17 +6182,21 @@
             unrotDw = dw;
             unrotDh = dh;
         }
-        int sw = reduceConfigWidthSize(unrotDw, Surface.ROTATION_0, density, unrotDw, unrotDh);
-        sw = reduceConfigWidthSize(sw, Surface.ROTATION_90, density, unrotDh, unrotDw);
-        sw = reduceConfigWidthSize(sw, Surface.ROTATION_180, density, unrotDw, unrotDh);
-        sw = reduceConfigWidthSize(sw, Surface.ROTATION_270, density, unrotDh, unrotDw);
+        mSmallestDisplayWidth = 1<<30;
+        mSmallestDisplayHeight = 1<<30;
+        mLargestDisplayWidth = 0;
+        mLargestDisplayHeight = 0;
+        adjustDisplaySizeRanges(Surface.ROTATION_0, unrotDw, unrotDh);
+        adjustDisplaySizeRanges(Surface.ROTATION_90, unrotDh, unrotDw);
+        adjustDisplaySizeRanges(Surface.ROTATION_180, unrotDw, unrotDh);
+        adjustDisplaySizeRanges(Surface.ROTATION_270, unrotDh, unrotDw);
         int sl = Configuration.SCREENLAYOUT_SIZE_XLARGE
                 | Configuration.SCREENLAYOUT_LONG_YES;
         sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh);
         sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw);
         sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh);
         sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw);
-        outConfig.smallestScreenWidthDp = sw;
+        outConfig.smallestScreenWidthDp = (int)(mSmallestDisplayWidth / density);
         outConfig.screenLayout = sl;
     }
 
@@ -6289,7 +6306,7 @@
                     / dm.density);
             config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation)
                     / dm.density);
-            computeSmallestWidthAndScreenLayout(rotated, dw, dh, dm.density, config);
+            computeSizeRangesAndScreenLayout(rotated, dw, dh, dm.density, config);
 
             config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
             config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
@@ -7199,6 +7216,15 @@
         }
     }
 
+    public void getCurrentSizeRange(Point smallestSize, Point largestSize) {
+        synchronized(mDisplaySizeLock) {
+            smallestSize.x = mSmallestDisplayWidth;
+            smallestSize.y = mSmallestDisplayHeight;
+            largestSize.x = mLargestDisplayWidth;
+            largestSize.y = mLargestDisplayHeight;
+        }
+    }
+
     public void setForcedDisplaySize(int longDimen, int shortDimen) {
         synchronized(mWindowMap) {
             int width, height;
@@ -9391,14 +9417,25 @@
         pw.println();
         if (mDisplay != null) {
             pw.print("  Display: init="); pw.print(mInitialDisplayWidth); pw.print("x");
-                    pw.print(mInitialDisplayHeight); pw.print(" base=");
-                    pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight);
+                    pw.print(mInitialDisplayHeight);
+                    if (mInitialDisplayWidth != mBaseDisplayWidth
+                            || mInitialDisplayHeight != mBaseDisplayHeight) {
+                        pw.print(" base=");
+                        pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight);
+                    }
+                    final int rawWidth = mDisplay.getRawWidth();
+                    final int rawHeight = mDisplay.getRawHeight();
+                    if (rawWidth != mCurDisplayWidth || rawHeight != mCurDisplayHeight) {
+                        pw.print(" raw="); pw.print(rawWidth); pw.print("x"); pw.print(rawHeight);
+                    }
                     pw.print(" cur=");
                     pw.print(mCurDisplayWidth); pw.print("x"); pw.print(mCurDisplayHeight);
                     pw.print(" app=");
                     pw.print(mAppDisplayWidth); pw.print("x"); pw.print(mAppDisplayHeight);
-                    pw.print(" raw="); pw.print(mDisplay.getRawWidth());
-                    pw.print("x"); pw.println(mDisplay.getRawHeight());
+                    pw.print(" rng="); pw.print(mSmallestDisplayWidth);
+                    pw.print("x"); pw.print(mSmallestDisplayHeight);
+                    pw.print("-"); pw.print(mLargestDisplayWidth);
+                    pw.print("x"); pw.println(mLargestDisplayHeight);
         } else {
             pw.println("  NO DISPLAY");
         }
diff --git a/telephony/java/android/telephony/CellBroadcastMessage.java b/telephony/java/android/telephony/CellBroadcastMessage.java
new file mode 100644
index 0000000..36c238d
--- /dev/null
+++ b/telephony/java/android/telephony/CellBroadcastMessage.java
@@ -0,0 +1,422 @@
+/*
+ * Copyright (C) 2011 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 android.telephony;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.graphics.Typeface;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.provider.Telephony;
+import android.telephony.SmsCbCmasInfo;
+import android.telephony.SmsCbEtwsInfo;
+import android.telephony.SmsCbLocation;
+import android.telephony.SmsCbMessage;
+import android.text.Spannable;
+import android.text.SpannableStringBuilder;
+import android.text.format.DateUtils;
+import android.text.style.StyleSpan;
+
+/**
+ * Application wrapper for {@link SmsCbMessage}. This is Parcelable so that
+ * decoded broadcast message objects can be passed between running Services.
+ * New broadcasts are received by the CellBroadcastReceiver app, which exports
+ * the database of previously received broadcasts at "content://cellbroadcasts/".
+ * The "android.permission.READ_CELL_BROADCASTS" permission is required to read
+ * from the ContentProvider, and writes to the database are not allowed.<p>
+ *
+ * Use {@link #createFromCursor} to create CellBroadcastMessage objects from rows
+ * in the database cursor returned by the ContentProvider.
+ *
+ * {@hide}
+ */
+public class CellBroadcastMessage implements Parcelable {
+
+    /** Identifier for getExtra() when adding this object to an Intent. */
+    public static final String SMS_CB_MESSAGE_EXTRA =
+            "com.android.cellbroadcastreceiver.SMS_CB_MESSAGE";
+
+    /** SmsCbMessage. */
+    private final SmsCbMessage mSmsCbMessage;
+
+    private final long mDeliveryTime;
+    private boolean mIsRead;
+
+    public CellBroadcastMessage(SmsCbMessage message) {
+        mSmsCbMessage = message;
+        mDeliveryTime = System.currentTimeMillis();
+        mIsRead = false;
+    }
+
+    private CellBroadcastMessage(SmsCbMessage message, long deliveryTime, boolean isRead) {
+        mSmsCbMessage = message;
+        mDeliveryTime = deliveryTime;
+        mIsRead = isRead;
+    }
+
+    private CellBroadcastMessage(Parcel in) {
+        mSmsCbMessage = new SmsCbMessage(in);
+        mDeliveryTime = in.readLong();
+        mIsRead = (in.readInt() != 0);
+    }
+
+    /** Parcelable: no special flags. */
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel out, int flags) {
+        mSmsCbMessage.writeToParcel(out, flags);
+        out.writeLong(mDeliveryTime);
+        out.writeInt(mIsRead ? 1 : 0);
+    }
+
+    public static final Parcelable.Creator<CellBroadcastMessage> CREATOR
+            = new Parcelable.Creator<CellBroadcastMessage>() {
+        public CellBroadcastMessage createFromParcel(Parcel in) {
+            return new CellBroadcastMessage(in);
+        }
+
+        public CellBroadcastMessage[] newArray(int size) {
+            return new CellBroadcastMessage[size];
+        }
+    };
+
+    /**
+     * Create a CellBroadcastMessage from a row in the database.
+     * @param cursor an open SQLite cursor pointing to the row to read
+     * @return the new CellBroadcastMessage
+     * @throws IllegalArgumentException if one of the required columns is missing
+     */
+    public static CellBroadcastMessage createFromCursor(Cursor cursor) {
+        int geoScope = cursor.getInt(
+                cursor.getColumnIndexOrThrow(Telephony.CellBroadcasts.GEOGRAPHICAL_SCOPE));
+        int serialNum = cursor.getInt(
+                cursor.getColumnIndexOrThrow(Telephony.CellBroadcasts.SERIAL_NUMBER));
+        int category = cursor.getInt(
+                cursor.getColumnIndexOrThrow(Telephony.CellBroadcasts.SERVICE_CATEGORY));
+        String language = cursor.getString(
+                cursor.getColumnIndexOrThrow(Telephony.CellBroadcasts.LANGUAGE_CODE));
+        String body = cursor.getString(
+                cursor.getColumnIndexOrThrow(Telephony.CellBroadcasts.MESSAGE_BODY));
+        int format = cursor.getInt(
+                cursor.getColumnIndexOrThrow(Telephony.CellBroadcasts.MESSAGE_FORMAT));
+        int priority = cursor.getInt(
+                cursor.getColumnIndexOrThrow(Telephony.CellBroadcasts.MESSAGE_PRIORITY));
+
+        String plmn;
+        int plmnColumn = cursor.getColumnIndex(Telephony.CellBroadcasts.PLMN);
+        if (plmnColumn != -1 && !cursor.isNull(plmnColumn)) {
+            plmn = cursor.getString(plmnColumn);
+        } else {
+            plmn = null;
+        }
+
+        int lac;
+        int lacColumn = cursor.getColumnIndex(Telephony.CellBroadcasts.LAC);
+        if (lacColumn != -1 && !cursor.isNull(lacColumn)) {
+            lac = cursor.getInt(lacColumn);
+        } else {
+            lac = -1;
+        }
+
+        int cid;
+        int cidColumn = cursor.getColumnIndex(Telephony.CellBroadcasts.CID);
+        if (cidColumn != -1 && !cursor.isNull(cidColumn)) {
+            cid = cursor.getInt(cidColumn);
+        } else {
+            cid = -1;
+        }
+
+        SmsCbLocation location = new SmsCbLocation(plmn, lac, cid);
+
+        SmsCbEtwsInfo etwsInfo;
+        int etwsWarningTypeColumn = cursor.getColumnIndex(
+                Telephony.CellBroadcasts.ETWS_WARNING_TYPE);
+        if (etwsWarningTypeColumn != -1 && !cursor.isNull(etwsWarningTypeColumn)) {
+            int warningType = cursor.getInt(etwsWarningTypeColumn);
+            etwsInfo = new SmsCbEtwsInfo(warningType, false, false, null);
+        } else {
+            etwsInfo = null;
+        }
+
+        SmsCbCmasInfo cmasInfo;
+        int cmasMessageClassColumn = cursor.getColumnIndex(
+                Telephony.CellBroadcasts.CMAS_MESSAGE_CLASS);
+        if (cmasMessageClassColumn != -1 && !cursor.isNull(cmasMessageClassColumn)) {
+            int messageClass = cursor.getInt(cmasMessageClassColumn);
+
+            int cmasCategory;
+            int cmasCategoryColumn = cursor.getColumnIndex(
+                    Telephony.CellBroadcasts.CMAS_CATEGORY);
+            if (cmasCategoryColumn != -1 && !cursor.isNull(cmasCategoryColumn)) {
+                cmasCategory = cursor.getInt(cmasCategoryColumn);
+            } else {
+                cmasCategory = SmsCbCmasInfo.CMAS_CATEGORY_UNKNOWN;
+            }
+
+            int responseType;
+            int cmasResponseTypeColumn = cursor.getColumnIndex(
+                    Telephony.CellBroadcasts.CMAS_RESPONSE_TYPE);
+            if (cmasResponseTypeColumn != -1 && !cursor.isNull(cmasResponseTypeColumn)) {
+                responseType = cursor.getInt(cmasResponseTypeColumn);
+            } else {
+                responseType = SmsCbCmasInfo.CMAS_RESPONSE_TYPE_UNKNOWN;
+            }
+
+            int severity;
+            int cmasSeverityColumn = cursor.getColumnIndex(
+                    Telephony.CellBroadcasts.CMAS_SEVERITY);
+            if (cmasSeverityColumn != -1 && !cursor.isNull(cmasSeverityColumn)) {
+                severity = cursor.getInt(cmasSeverityColumn);
+            } else {
+                severity = SmsCbCmasInfo.CMAS_SEVERITY_UNKNOWN;
+            }
+
+            int urgency;
+            int cmasUrgencyColumn = cursor.getColumnIndex(
+                    Telephony.CellBroadcasts.CMAS_URGENCY);
+            if (cmasUrgencyColumn != -1 && !cursor.isNull(cmasUrgencyColumn)) {
+                urgency = cursor.getInt(cmasUrgencyColumn);
+            } else {
+                urgency = SmsCbCmasInfo.CMAS_URGENCY_UNKNOWN;
+            }
+
+            int certainty;
+            int cmasCertaintyColumn = cursor.getColumnIndex(
+                    Telephony.CellBroadcasts.CMAS_CERTAINTY);
+            if (cmasCertaintyColumn != -1 && !cursor.isNull(cmasCertaintyColumn)) {
+                certainty = cursor.getInt(cmasCertaintyColumn);
+            } else {
+                certainty = SmsCbCmasInfo.CMAS_CERTAINTY_UNKNOWN;
+            }
+
+            cmasInfo = new SmsCbCmasInfo(messageClass, cmasCategory, responseType, severity,
+                    urgency, certainty);
+        } else {
+            cmasInfo = null;
+        }
+
+        SmsCbMessage msg = new SmsCbMessage(format, geoScope, serialNum, location, category,
+                language, body, priority, etwsInfo, cmasInfo);
+
+        long deliveryTime = cursor.getLong(cursor.getColumnIndexOrThrow(
+                Telephony.CellBroadcasts.DELIVERY_TIME));
+        boolean isRead = (cursor.getInt(cursor.getColumnIndexOrThrow(
+                Telephony.CellBroadcasts.MESSAGE_READ)) != 0);
+
+        return new CellBroadcastMessage(msg, deliveryTime, isRead);
+    }
+
+    /**
+     * Return a ContentValues object for insertion into the database.
+     * @return a new ContentValues object containing this object's data
+     */
+    public ContentValues getContentValues() {
+        ContentValues cv = new ContentValues(16);
+        SmsCbMessage msg = mSmsCbMessage;
+        cv.put(Telephony.CellBroadcasts.GEOGRAPHICAL_SCOPE, msg.getGeographicalScope());
+        SmsCbLocation location = msg.getLocation();
+        if (location.getPlmn() != null) {
+            cv.put(Telephony.CellBroadcasts.PLMN, location.getPlmn());
+        }
+        if (location.getLac() != -1) {
+            cv.put(Telephony.CellBroadcasts.LAC, location.getLac());
+        }
+        if (location.getCid() != -1) {
+            cv.put(Telephony.CellBroadcasts.CID, location.getCid());
+        }
+        cv.put(Telephony.CellBroadcasts.SERIAL_NUMBER, msg.getSerialNumber());
+        cv.put(Telephony.CellBroadcasts.SERVICE_CATEGORY, msg.getServiceCategory());
+        cv.put(Telephony.CellBroadcasts.LANGUAGE_CODE, msg.getLanguageCode());
+        cv.put(Telephony.CellBroadcasts.MESSAGE_BODY, msg.getMessageBody());
+        cv.put(Telephony.CellBroadcasts.DELIVERY_TIME, mDeliveryTime);
+        cv.put(Telephony.CellBroadcasts.MESSAGE_READ, mIsRead);
+        cv.put(Telephony.CellBroadcasts.MESSAGE_FORMAT, msg.getMessageFormat());
+        cv.put(Telephony.CellBroadcasts.MESSAGE_PRIORITY, msg.getMessagePriority());
+
+        SmsCbEtwsInfo etwsInfo = mSmsCbMessage.getEtwsWarningInfo();
+        if (etwsInfo != null) {
+            cv.put(Telephony.CellBroadcasts.ETWS_WARNING_TYPE, etwsInfo.getWarningType());
+        }
+
+        SmsCbCmasInfo cmasInfo = mSmsCbMessage.getCmasWarningInfo();
+        if (cmasInfo != null) {
+            cv.put(Telephony.CellBroadcasts.CMAS_MESSAGE_CLASS, cmasInfo.getMessageClass());
+            cv.put(Telephony.CellBroadcasts.CMAS_CATEGORY, cmasInfo.getCategory());
+            cv.put(Telephony.CellBroadcasts.CMAS_RESPONSE_TYPE, cmasInfo.getResponseType());
+            cv.put(Telephony.CellBroadcasts.CMAS_SEVERITY, cmasInfo.getSeverity());
+            cv.put(Telephony.CellBroadcasts.CMAS_URGENCY, cmasInfo.getUrgency());
+            cv.put(Telephony.CellBroadcasts.CMAS_CERTAINTY, cmasInfo.getCertainty());
+        }
+
+        return cv;
+    }
+
+    /**
+     * Set or clear the "read message" flag.
+     * @param isRead true if the message has been read; false if not
+     */
+    public void setIsRead(boolean isRead) {
+        mIsRead = isRead;
+    }
+
+    public String getLanguageCode() {
+        return mSmsCbMessage.getLanguageCode();
+    }
+
+    public int getServiceCategory() {
+        return mSmsCbMessage.getServiceCategory();
+    }
+
+    public long getDeliveryTime() {
+        return mDeliveryTime;
+    }
+
+    public String getMessageBody() {
+        return mSmsCbMessage.getMessageBody();
+    }
+
+    public boolean isRead() {
+        return mIsRead;
+    }
+
+    public int getSerialNumber() {
+        return mSmsCbMessage.getSerialNumber();
+    }
+
+    public SmsCbCmasInfo getCmasWarningInfo() {
+        return mSmsCbMessage.getCmasWarningInfo();
+    }
+
+    public SmsCbEtwsInfo getEtwsWarningInfo() {
+        return mSmsCbMessage.getEtwsWarningInfo();
+    }
+
+    /**
+     * Return whether the broadcast is an emergency (PWS) message type.
+     * This includes lower priority test messages and Amber alerts.
+     *
+     * All public alerts show the flashing warning icon in the dialog,
+     * but only emergency alerts play the alert sound and speak the message.
+     *
+     * @return true if the message is PWS type; false otherwise
+     */
+    public boolean isPublicAlertMessage() {
+        return mSmsCbMessage.isEmergencyMessage();
+    }
+
+    /**
+     * Returns whether the broadcast is an emergency (PWS) message type,
+     * including test messages, but excluding lower priority Amber alert broadcasts.
+     *
+     * @return true if the message is PWS type, excluding Amber alerts
+     */
+    public boolean isEmergencyAlertMessage() {
+        if (!mSmsCbMessage.isEmergencyMessage()) {
+            return false;
+        }
+        SmsCbCmasInfo cmasInfo = mSmsCbMessage.getCmasWarningInfo();
+        if (cmasInfo != null &&
+                cmasInfo.getMessageClass() == SmsCbCmasInfo.CMAS_CLASS_CHILD_ABDUCTION_EMERGENCY) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Return whether the broadcast is an ETWS emergency message type.
+     * @return true if the message is ETWS emergency type; false otherwise
+     */
+    public boolean isEtwsMessage() {
+        return mSmsCbMessage.isEtwsMessage();
+    }
+
+    /**
+     * Return whether the broadcast is a CMAS emergency message type.
+     * @return true if the message is CMAS emergency type; false otherwise
+     */
+    public boolean isCmasMessage() {
+        return mSmsCbMessage.isCmasMessage();
+    }
+
+    /**
+     * Return the CMAS message class.
+     * @return the CMAS message class, e.g. {@link SmsCbCmasInfo#CMAS_CLASS_SEVERE_THREAT}, or
+     *  {@link SmsCbCmasInfo#CMAS_CLASS_UNKNOWN} if this is not a CMAS alert
+     */
+    public int getCmasMessageClass() {
+        if (mSmsCbMessage.isCmasMessage()) {
+            return mSmsCbMessage.getCmasWarningInfo().getMessageClass();
+        } else {
+            return SmsCbCmasInfo.CMAS_CLASS_UNKNOWN;
+        }
+    }
+
+    /**
+     * Return whether the broadcast is an ETWS popup alert.
+     * This method checks the message ID and the message code.
+     * @return true if the message indicates an ETWS popup alert
+     */
+    public boolean isEtwsPopupAlert() {
+        SmsCbEtwsInfo etwsInfo = mSmsCbMessage.getEtwsWarningInfo();
+        return etwsInfo != null && etwsInfo.isPopupAlert();
+    }
+
+    /**
+     * Return whether the broadcast is an ETWS emergency user alert.
+     * This method checks the message ID and the message code.
+     * @return true if the message indicates an ETWS emergency user alert
+     */
+    public boolean isEtwsEmergencyUserAlert() {
+        SmsCbEtwsInfo etwsInfo = mSmsCbMessage.getEtwsWarningInfo();
+        return etwsInfo != null && etwsInfo.isEmergencyUserAlert();
+    }
+
+    /**
+     * Return whether the broadcast is an ETWS test message.
+     * @return true if the message is an ETWS test message; false otherwise
+     */
+    public boolean isEtwsTestMessage() {
+        SmsCbEtwsInfo etwsInfo = mSmsCbMessage.getEtwsWarningInfo();
+        return etwsInfo != null &&
+                etwsInfo.getWarningType() == SmsCbEtwsInfo.ETWS_WARNING_TYPE_TEST_MESSAGE;
+    }
+
+    /**
+     * Return the abbreviated date string for the message delivery time.
+     * @param context the context object
+     * @return a String to use in the broadcast list UI
+     */
+    public String getDateString(Context context) {
+        int flags = DateUtils.FORMAT_NO_NOON_MIDNIGHT | DateUtils.FORMAT_SHOW_TIME |
+                DateUtils.FORMAT_ABBREV_ALL | DateUtils.FORMAT_SHOW_DATE |
+                DateUtils.FORMAT_CAP_AMPM;
+        return DateUtils.formatDateTime(context, mDeliveryTime, flags);
+    }
+
+    /**
+     * Return the date string for the message delivery time, suitable for text-to-speech.
+     * @param context the context object
+     * @return a String for populating the list item AccessibilityEvent for TTS
+     */
+    public String getSpokenDateString(Context context) {
+        int flags = DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE;
+        return DateUtils.formatDateTime(context, mDeliveryTime, flags);
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
index 44d28fa..85b67d5 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
@@ -78,6 +78,10 @@
     }
 
     @Override
+    public void getCurrentSizeRange(Point smallestSize, Point largestSize) {
+    }
+
+    @Override
     public void getDisplaySize(Point arg0) throws RemoteException {
     }
 
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index df14bb9..018e0a8 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -415,8 +415,8 @@
     /**
      * Passed with {@link ActionListener#onFailure}.
      * Indicates that the {@link #discoverServices} failed because no service
-     * requests are set.
-     * @hide
+     * requests are added. Use {@link #addServiceRequest} to add a service
+     * request.
      */
     public static final int NO_SERVICE_REQUESTS = 3;