Merge "Allow related users to show activities on primary user"
diff --git a/api/current.txt b/api/current.txt
index e15c1d7..62154b8 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -345,7 +345,7 @@
     field public static final int canRetrieveWindowContent = 16843653; // 0x1010385
     field public static final int candidatesTextStyleSpans = 16843312; // 0x1010230
     field public static final deprecated int capitalize = 16843113; // 0x1010169
-    field public static final int castsShadow = 16843775; // 0x10103ff
+    field public static final int castsShadow = 16843774; // 0x10103fe
     field public static final int category = 16843752; // 0x10103e8
     field public static final int centerBright = 16842956; // 0x10100cc
     field public static final int centerColor = 16843275; // 0x101020b
@@ -399,10 +399,10 @@
     field public static final int content = 16843355; // 0x101025b
     field public static final int contentAuthority = 16843408; // 0x1010290
     field public static final int contentDescription = 16843379; // 0x1010273
-    field public static final int controlX1 = 16843769; // 0x10103f9
-    field public static final int controlX2 = 16843771; // 0x10103fb
-    field public static final int controlY1 = 16843770; // 0x10103fa
-    field public static final int controlY2 = 16843772; // 0x10103fc
+    field public static final int controlX1 = 16843768; // 0x10103f8
+    field public static final int controlX2 = 16843770; // 0x10103fa
+    field public static final int controlY1 = 16843769; // 0x10103f9
+    field public static final int controlY2 = 16843771; // 0x10103fb
     field public static final int cropToPadding = 16843043; // 0x1010123
     field public static final int cursorVisible = 16843090; // 0x1010152
     field public static final int customNavigationLayout = 16843474; // 0x10102d2
@@ -636,7 +636,6 @@
     field public static final int isScrollContainer = 16843342; // 0x101024e
     field public static final int isSticky = 16843335; // 0x1010247
     field public static final int isolatedProcess = 16843689; // 0x10103a9
-    field public static final int isolatedZVolume = 16843768; // 0x10103f8
     field public static final int itemBackground = 16843056; // 0x1010130
     field public static final int itemIconDisabledAlpha = 16843057; // 0x1010131
     field public static final int itemPadding = 16843565; // 0x101032d
@@ -889,7 +888,7 @@
     field public static final int required = 16843406; // 0x101028e
     field public static final int requiredAccountType = 16843734; // 0x10103d6
     field public static final int requiredForAllUsers = 16843728; // 0x10103d0
-    field public static final int requiredForProfile = 16843776; // 0x1010400
+    field public static final int requiredForProfile = 16843775; // 0x10103ff
     field public static final int requiresFadingEdge = 16843685; // 0x10103a5
     field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364
     field public static final int resizeMode = 16843619; // 0x1010363
@@ -960,7 +959,7 @@
     field public static final int shadowRadius = 16843108; // 0x1010164
     field public static final int shape = 16843162; // 0x101019a
     field public static final int shareInterpolator = 16843195; // 0x10101bb
-    field public static final int sharedElementName = 16843773; // 0x10103fd
+    field public static final int sharedElementName = 16843772; // 0x10103fc
     field public static final int sharedUserId = 16842763; // 0x101000b
     field public static final int sharedUserLabel = 16843361; // 0x1010261
     field public static final int shouldDisableView = 16843246; // 0x10101ee
@@ -1159,7 +1158,7 @@
     field public static final int transformPivotX = 16843552; // 0x1010320
     field public static final int transformPivotY = 16843553; // 0x1010321
     field public static final int transition = 16843743; // 0x10103df
-    field public static final int transitionGroup = 16843774; // 0x10103fe
+    field public static final int transitionGroup = 16843773; // 0x10103fd
     field public static final int transitionOrdering = 16843744; // 0x10103e0
     field public static final int translationX = 16843554; // 0x1010322
     field public static final int translationY = 16843555; // 0x1010323
@@ -4728,6 +4727,7 @@
     method public void onPasswordExpiring(android.content.Context, android.content.Intent);
     method public void onPasswordFailed(android.content.Context, android.content.Intent);
     method public void onPasswordSucceeded(android.content.Context, android.content.Intent);
+    method public void onProfileProvisioningComplete(android.content.Context, android.content.Intent);
     method public void onReceive(android.content.Context, android.content.Intent);
     field public static final java.lang.String ACTION_DEVICE_ADMIN_DISABLED = "android.app.action.DEVICE_ADMIN_DISABLED";
     field public static final java.lang.String ACTION_DEVICE_ADMIN_DISABLE_REQUESTED = "android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED";
@@ -4736,6 +4736,7 @@
     field public static final java.lang.String ACTION_PASSWORD_EXPIRING = "android.app.action.ACTION_PASSWORD_EXPIRING";
     field public static final java.lang.String ACTION_PASSWORD_FAILED = "android.app.action.ACTION_PASSWORD_FAILED";
     field public static final java.lang.String ACTION_PASSWORD_SUCCEEDED = "android.app.action.ACTION_PASSWORD_SUCCEEDED";
+    field public static final java.lang.String ACTION_PROFILE_PROVISIONING_COMPLETE = "android.managedprovisioning.ACTION_PROVISIONING_COMPLETE";
     field public static final java.lang.String DEVICE_ADMIN_META_DATA = "android.app.device_admin";
     field public static final java.lang.String EXTRA_DISABLE_WARNING = "android.app.extra.DISABLE_WARNING";
   }
@@ -13421,6 +13422,7 @@
 
   public static final class MediaMuxer.OutputFormat {
     field public static final int MUXER_OUTPUT_MPEG_4 = 0; // 0x0
+    field public static final int MUXER_OUTPUT_WEBM = 1; // 0x1
   }
 
   public class MediaPlayer {
@@ -19381,6 +19383,10 @@
     method public boolean isObbMounted(java.lang.String);
     method public boolean mountObb(java.lang.String, java.lang.String, android.os.storage.OnObbStateChangeListener);
     method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener);
+    field public static final int CRYPT_TYPE_DEFAULT = 1; // 0x1
+    field public static final int CRYPT_TYPE_PASSWORD = 0; // 0x0
+    field public static final int CRYPT_TYPE_PATTERN = 2; // 0x2
+    field public static final int CRYPT_TYPE_PIN = 3; // 0x3
   }
 
 }
@@ -28123,6 +28129,7 @@
     field public static final int KEYCODE_SHIFT_LEFT = 59; // 0x3b
     field public static final int KEYCODE_SHIFT_RIGHT = 60; // 0x3c
     field public static final int KEYCODE_SLASH = 76; // 0x4c
+    field public static final int KEYCODE_SLEEP = 223; // 0xdf
     field public static final int KEYCODE_SOFT_LEFT = 1; // 0x1
     field public static final int KEYCODE_SOFT_RIGHT = 2; // 0x2
     field public static final int KEYCODE_SPACE = 62; // 0x3e
@@ -28144,6 +28151,7 @@
     field public static final int KEYCODE_VOLUME_MUTE = 164; // 0xa4
     field public static final int KEYCODE_VOLUME_UP = 24; // 0x18
     field public static final int KEYCODE_W = 51; // 0x33
+    field public static final int KEYCODE_WAKEUP = 224; // 0xe0
     field public static final int KEYCODE_WINDOW = 171; // 0xab
     field public static final int KEYCODE_X = 52; // 0x34
     field public static final int KEYCODE_Y = 53; // 0x35
@@ -29530,7 +29538,6 @@
     method public int getLayoutMode();
     method public android.animation.LayoutTransition getLayoutTransition();
     method public int getPersistentDrawingCache();
-    method public boolean hasIsolatedZVolume();
     method public int indexOfChild(android.view.View);
     method public final void invalidateChild(android.view.View, android.graphics.Rect);
     method public android.view.ViewParent invalidateChildInParent(int[], android.graphics.Rect);
@@ -29576,7 +29583,6 @@
     method public void setClipChildren(boolean);
     method public void setClipToPadding(boolean);
     method public void setDescendantFocusability(int);
-    method public void setIsolatedZVolume(boolean);
     method public void setLayoutAnimation(android.view.animation.LayoutAnimationController);
     method public void setLayoutAnimationListener(android.view.animation.Animation.AnimationListener);
     method public void setLayoutMode(int);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index af4a362..287c463 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -21,6 +21,7 @@
 import android.transition.Transition;
 import android.transition.TransitionManager;
 import android.util.ArrayMap;
+import android.util.Pair;
 import android.util.SuperNotCalledException;
 import com.android.internal.app.ActionBarImpl;
 import com.android.internal.policy.PolicyManager;
@@ -3456,7 +3457,8 @@
     public void startActivityForResult(Intent intent, int requestCode) {
         Bundle options = null;
         if (mWindow.hasFeature(Window.FEATURE_CONTENT_TRANSITIONS)) {
-            options = ActivityOptions.makeSceneTransitionAnimation(null).toBundle();
+            final Pair<View, String>[] noSharedElements = null;
+            options = ActivityOptions.makeSceneTransitionAnimation(noSharedElements).toBundle();
         }
         startActivityForResult(intent, requestCode, options);
     }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 3258585..138eea2 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -71,6 +71,7 @@
 import android.os.UserHandle;
 import android.transition.Scene;
 import android.transition.TransitionManager;
+import android.provider.Settings;
 import android.util.AndroidRuntimeException;
 import android.util.ArrayMap;
 import android.util.DisplayMetrics;
@@ -110,6 +111,7 @@
 import java.lang.ref.WeakReference;
 import java.net.InetAddress;
 import java.security.Security;
+import java.text.DateFormat;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
@@ -750,8 +752,42 @@
 
             setCoreSettings(coreSettings);
 
-            // Tell the VMRuntime about the application.
-            VMRuntime.registerAppInfo(appInfo.dataDir, appInfo.processName);
+            /*
+             * Two possible indications that this package could be
+             * sharing its runtime with other packages:
+             *
+             * 1.) the sharedUserId attribute is set in the manifest,
+             *     indicating a request to share a VM with other
+             *     packages with the same sharedUserId.
+             *
+             * 2.) the application element of the manifest has an
+             *     attribute specifying a non-default process name,
+             *     indicating the desire to run in another packages VM.
+             *
+             * If sharing is enabled we do not have a unique application
+             * in a process and therefore cannot rely on the package
+             * name inside the runtime.
+             */
+            IPackageManager pm = getPackageManager();
+            android.content.pm.PackageInfo pi = null;
+            try {
+                pi = pm.getPackageInfo(appInfo.packageName, 0, UserHandle.myUserId());
+            } catch (RemoteException e) {
+            }
+            if (pi != null) {
+                boolean sharedUserIdSet = (pi.sharedUserId != null);
+                boolean processNameNotDefault =
+                (pi.applicationInfo != null &&
+                 !appInfo.packageName.equals(pi.applicationInfo.processName));
+                boolean sharable = (sharedUserIdSet || processNameNotDefault);
+
+                // Tell the VMRuntime about the application, unless it is shared
+                // inside a process.
+                if (!sharable) {
+                    VMRuntime.registerAppInfo(appInfo.packageName, appInfo.dataDir,
+                                            appInfo.processName);
+                }
+            }
 
             AppBindData data = new AppBindData();
             data.processName = processName;
@@ -1103,6 +1139,11 @@
         public void scheduleInstallProvider(ProviderInfo provider) {
             sendMessage(H.INSTALL_PROVIDER, provider);
         }
+
+        @Override
+        public final void updateTimePrefs(boolean is24Hour) {
+            DateFormat.set24HourTimePref(is24Hour);
+        }
     }
 
     private class H extends Handler {
@@ -1152,6 +1193,7 @@
         public static final int REQUEST_ASSIST_CONTEXT_EXTRAS = 143;
         public static final int TRANSLUCENT_CONVERSION_COMPLETE = 144;
         public static final int INSTALL_PROVIDER        = 145;
+
         String codeToString(int code) {
             if (DEBUG_MESSAGES) {
                 switch (code) {
@@ -4215,6 +4257,11 @@
                 Log.e(TAG, "Unable to setupGraphicsSupport due to missing cache directory");
             }
         }
+
+
+        final boolean is24Hr = "24".equals(mCoreSettings.getString(Settings.System.TIME_12_24));
+        DateFormat.set24HourTimePref(is24Hr);
+
         /**
          * For system applications on userdebug/eng builds, log stack
          * traces of disk and network access to dropbox for analysis.
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 20198f9..f1c632e 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -630,6 +630,15 @@
             reply.writeNoException();
             return true;
         }
+
+        case UPDATE_TIME_PREFS_TRANSACTION:
+        {
+            data.enforceInterface(IApplicationThread.descriptor);
+            byte is24Hour = data.readByte();
+            updateTimePrefs(is24Hour == (byte) 1);
+            reply.writeNoException();
+            return true;
+        }
         }
 
         return super.onTransact(code, data, reply, flags);
@@ -1273,4 +1282,13 @@
         mRemote.transact(SCHEDULE_INSTALL_PROVIDER_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
         data.recycle();
     }
+
+    @Override
+    public void updateTimePrefs(boolean is24Hour) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        data.writeInterfaceToken(IApplicationThread.descriptor);
+        data.writeByte(is24Hour ? (byte) 1 : (byte) 0);
+        mRemote.transact(UPDATE_TIME_PREFS_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
+        data.recycle();
+    }
 }
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 1ea9d87..ac8ac8f 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -139,6 +139,7 @@
             throws RemoteException;
     void setProcessState(int state) throws RemoteException;
     void scheduleInstallProvider(ProviderInfo provider) throws RemoteException;
+    void updateTimePrefs(boolean is24Hour) throws RemoteException;
 
     String descriptor = "android.app.IApplicationThread";
 
@@ -192,4 +193,5 @@
     int SCHEDULE_TRANSLUCENT_CONVERSION_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+48;
     int SET_PROCESS_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+49;
     int SCHEDULE_INSTALL_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+50;
+    int UPDATE_TIME_PREFS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+51;
 }
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index cd1fbf6f..12a8ff6 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -612,6 +612,13 @@
     public static final String EXTRA_AS_HEADS_UP = "headsup";
 
     /**
+     * Extra added from {@link Notification.Builder} to indicate that the remote views were inflated
+     * from the builder, as opposed to being created directly from the application.
+     * @hide
+     */
+    public static final String EXTRA_BUILDER_REMOTE_VIEWS = "android.builderRemoteViews";
+
+    /**
      * Value for {@link #EXTRA_AS_HEADS_UP}.
      * @hide
      */
@@ -1273,6 +1280,7 @@
         private boolean mShowWhen = true;
         private int mVisibility = VISIBILITY_PRIVATE;
         private Notification mPublicVersion = null;
+        private boolean mQuantumTheme;
 
         /**
          * Constructs a new Builder with the defaults:
@@ -1300,6 +1308,9 @@
             mWhen = System.currentTimeMillis();
             mAudioStreamType = STREAM_DEFAULT;
             mPriority = PRIORITY_DEFAULT;
+
+            // TODO: Decide on targetSdk from calling app whether to use quantum theme.
+            mQuantumTheme = true;
         }
 
         /**
@@ -1807,7 +1818,7 @@
                 contentView.setImageViewBitmap(R.id.icon, mLargeIcon);
                 smallIconImageViewId = R.id.right_icon;
             }
-            if (mPriority < PRIORITY_LOW) {
+            if (!mQuantumTheme && mPriority < PRIORITY_LOW) {
                 contentView.setInt(R.id.icon,
                         "setBackgroundResource", R.drawable.notification_template_icon_low_bg);
                 contentView.setInt(R.id.status_bar_latest_event_content,
@@ -1921,7 +1932,7 @@
             if (mContentView != null) {
                 return mContentView;
             } else {
-                return applyStandardTemplate(R.layout.notification_template_base, true); // no more special large_icon flavor
+                return applyStandardTemplate(getBaseLayoutResource(), true); // no more special large_icon flavor
             }
         }
 
@@ -1942,21 +1953,21 @@
         private RemoteViews makeBigContentView() {
             if (mActions.size() == 0) return null;
 
-            return applyStandardTemplateWithActions(R.layout.notification_template_big_base);
+            return applyStandardTemplateWithActions(getBigBaseLayoutResource());
         }
 
-        private RemoteViews makeHEadsUpContentView() {
+        private RemoteViews makeHeadsUpContentView() {
             if (mActions.size() == 0) return null;
 
-            return applyStandardTemplateWithActions(R.layout.notification_template_big_base);
+            return applyStandardTemplateWithActions(getBigBaseLayoutResource());
         }
 
 
         private RemoteViews generateActionButton(Action action) {
             final boolean tombstone = (action.actionIntent == null);
             RemoteViews button = new RemoteViews(mContext.getPackageName(),
-                    tombstone ? R.layout.notification_action_tombstone
-                              : R.layout.notification_action);
+                    tombstone ? getActionTombstoneLayoutResource()
+                              : getActionLayoutResource());
             button.setTextViewCompoundDrawablesRelative(R.id.action0, action.icon, 0, 0, 0);
             button.setTextViewText(R.id.action0, action.title);
             if (!tombstone) {
@@ -1992,7 +2003,7 @@
             n.defaults = mDefaults;
             n.flags = mFlags;
             n.bigContentView = makeBigContentView();
-            n.headsUpContentView = makeHEadsUpContentView();
+            n.headsUpContentView = makeHeadsUpContentView();
             if (mLedOnMs != 0 || mLedOffMs != 0) {
                 n.flags |= FLAG_SHOW_LIGHTS;
             }
@@ -2037,6 +2048,7 @@
             extras.putBoolean(EXTRA_PROGRESS_INDETERMINATE, mProgressIndeterminate);
             extras.putBoolean(EXTRA_SHOW_CHRONOMETER, mUseChronometer);
             extras.putBoolean(EXTRA_SHOW_WHEN, mShowWhen);
+            extras.putBoolean(EXTRA_BUILDER_REMOTE_VIEWS, mContentView == null);
             if (mLargeIcon != null) {
                 extras.putParcelable(EXTRA_LARGE_ICON, mLargeIcon);
             }
@@ -2080,6 +2092,49 @@
             build().cloneInto(n, true);
             return n;
         }
+
+
+        private int getBaseLayoutResource() {
+            return mQuantumTheme
+                    ? R.layout.notification_template_quantum_base
+                    : R.layout.notification_template_base;
+        }
+
+        private int getBigBaseLayoutResource() {
+            return mQuantumTheme
+                    ? R.layout.notification_template_quantum_big_base
+                    : R.layout.notification_template_big_base;
+        }
+
+        private int getBigPictureLayoutResource() {
+            return mQuantumTheme
+                    ? R.layout.notification_template_quantum_big_picture
+                    : R.layout.notification_template_big_picture;
+        }
+
+        private int getBigTextLayoutResource() {
+            return mQuantumTheme
+                    ? R.layout.notification_template_quantum_big_text
+                    : R.layout.notification_template_big_text;
+        }
+
+        private int getInboxLayoutResource() {
+            return mQuantumTheme
+                    ? R.layout.notification_template_quantum_inbox
+                    : R.layout.notification_template_inbox;
+        }
+
+        private int getActionLayoutResource() {
+            return mQuantumTheme
+                    ? R.layout.notification_quantum_action
+                    : R.layout.notification_action;
+        }
+
+        private int getActionTombstoneLayoutResource() {
+            return mQuantumTheme
+                    ? R.layout.notification_quantum_action_tombstone
+                    : R.layout.notification_action_tombstone;
+        }
     }
 
     /**
@@ -2249,7 +2304,7 @@
         }
 
         private RemoteViews makeBigContentView() {
-            RemoteViews contentView = getStandardView(R.layout.notification_template_big_picture);
+            RemoteViews contentView = getStandardView(mBuilder.getBigPictureLayoutResource());
 
             contentView.setImageViewBitmap(R.id.big_picture, mPicture);
 
@@ -2348,7 +2403,7 @@
             final boolean hadThreeLines = (mBuilder.mContentText != null && mBuilder.mSubText != null);
             mBuilder.mContentText = null;
 
-            RemoteViews contentView = getStandardView(R.layout.notification_template_big_text);
+            RemoteViews contentView = getStandardView(mBuilder.getBigTextLayoutResource());
 
             if (hadThreeLines) {
                 // vertical centering
@@ -2442,7 +2497,7 @@
         private RemoteViews makeBigContentView() {
             // Remove the content text so line3 disappears unless you have a summary
             mBuilder.mContentText = null;
-            RemoteViews contentView = getStandardView(R.layout.notification_template_inbox);
+            RemoteViews contentView = getStandardView(mBuilder.getInboxLayoutResource());
 
             contentView.setViewVisibility(R.id.text2, View.GONE);
 
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index 30b65de..00e7da4 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -29,25 +29,25 @@
  * Base class for implementing a device administration component.  This
  * class provides a convenience for interpreting the raw intent actions
  * that are sent by the system.
- * 
+ *
  * <p>The callback methods, like the base
  * {@link BroadcastReceiver#onReceive(Context, Intent) BroadcastReceiver.onReceive()}
  * method, happen on the main thread of the process.  Thus long running
  * operations must be done on another thread.  Note that because a receiver
  * is done once returning from its receive function, such long-running operations
  * should probably be done in a {@link Service}.
- * 
+ *
  * <p>When publishing your DeviceAdmin subclass as a receiver, it must
  * handle {@link #ACTION_DEVICE_ADMIN_ENABLED} and require the
  * {@link android.Manifest.permission#BIND_DEVICE_ADMIN} permission.  A typical
  * manifest entry would look like:</p>
- * 
+ *
  * {@sample development/samples/ApiDemos/AndroidManifest.xml device_admin_declaration}
- *   
+ *
  * <p>The meta-data referenced here provides addition information specific
  * to the device administrator, as parsed by the {@link DeviceAdminInfo} class.
  * A typical file would be:</p>
- * 
+ *
  * {@sample development/samples/ApiDemos/res/xml/device_admin_sample.xml meta_data}
  *
  * <div class="special reference">
@@ -86,7 +86,7 @@
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_DEVICE_ADMIN_DISABLE_REQUESTED
             = "android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED";
-    
+
     /**
      * A CharSequence that can be shown to the user informing them of the
      * impact of disabling your admin.
@@ -94,7 +94,7 @@
      * @see #ACTION_DEVICE_ADMIN_DISABLE_REQUESTED
      */
     public static final String EXTRA_DISABLE_WARNING = "android.app.extra.DISABLE_WARNING";
-    
+
     /**
      * Action sent to a device administrator when the user has disabled
      * it.  Upon return, the application no longer has access to the
@@ -107,7 +107,7 @@
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_DEVICE_ADMIN_DISABLED
             = "android.app.action.DEVICE_ADMIN_DISABLED";
-    
+
     /**
      * Action sent to a device administrator when the user has changed the
      * password of their device.  You can at this point check the characteristics
@@ -115,7 +115,7 @@
      * DevicePolicyManager.isActivePasswordSufficient()}.
      * You will generally
      * handle this in {@link DeviceAdminReceiver#onPasswordChanged}.
-     * 
+     *
      * <p>The calling device admin must have requested
      * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to receive
      * this broadcast.
@@ -123,7 +123,7 @@
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_PASSWORD_CHANGED
             = "android.app.action.ACTION_PASSWORD_CHANGED";
-    
+
     /**
      * Action sent to a device administrator when the user has failed at
      * attempted to enter the password.  You can at this point check the
@@ -131,7 +131,7 @@
      * {@link DevicePolicyManager#getCurrentFailedPasswordAttempts
      * DevicePolicyManager.getCurrentFailedPasswordAttempts()}.  You will generally
      * handle this in {@link DeviceAdminReceiver#onPasswordFailed}.
-     * 
+     *
      * <p>The calling device admin must have requested
      * {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} to receive
      * this broadcast.
@@ -139,11 +139,11 @@
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_PASSWORD_FAILED
             = "android.app.action.ACTION_PASSWORD_FAILED";
-    
+
     /**
      * Action sent to a device administrator when the user has successfully
      * entered their password, after failing one or more times.
-     * 
+     *
      * <p>The calling device admin must have requested
      * {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} to receive
      * this broadcast.
@@ -164,16 +164,24 @@
     public static final String ACTION_PASSWORD_EXPIRING
             = "android.app.action.ACTION_PASSWORD_EXPIRING";
 
+
+    /**
+     * Action broadcasted when provisioning of a managed profile has completed.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_PROFILE_PROVISIONING_COMPLETE
+            = "android.managedprovisioning.ACTION_PROVISIONING_COMPLETE";
+
     /**
      * Name under which a DevicePolicy component publishes information
      * about itself.  This meta-data must reference an XML resource containing
      * a device-admin tag.  XXX TO DO: describe syntax.
      */
     public static final String DEVICE_ADMIN_META_DATA = "android.app.device_admin";
-    
+
     private DevicePolicyManager mManager;
     private ComponentName mWho;
-    
+
     /**
      * Retrieve the DevicePolicyManager interface for this administrator to work
      * with the system.
@@ -186,7 +194,7 @@
                 Context.DEVICE_POLICY_SERVICE);
         return mManager;
     }
-    
+
     /**
      * Retrieve the ComponentName describing who this device administrator is, for
      * use in {@link DevicePolicyManager} APIs that require the administrator to
@@ -199,7 +207,7 @@
         mWho = new ComponentName(context, getClass());
         return mWho;
     }
-    
+
     /**
      * Called after the administrator is first enabled, as a result of
      * receiving {@link #ACTION_DEVICE_ADMIN_ENABLED}.  At this point you
@@ -209,7 +217,7 @@
      */
     public void onEnabled(Context context, Intent intent) {
     }
-    
+
     /**
      * Called when the user has asked to disable the administrator, as a result of
      * receiving {@link #ACTION_DEVICE_ADMIN_DISABLE_REQUESTED}, giving you
@@ -224,7 +232,7 @@
     public CharSequence onDisableRequested(Context context, Intent intent) {
         return null;
     }
-    
+
     /**
      * Called prior to the administrator being disabled, as a result of
      * receiving {@link #ACTION_DEVICE_ADMIN_DISABLED}.  Upon return, you
@@ -235,7 +243,7 @@
      */
     public void onDisabled(Context context, Intent intent) {
     }
-    
+
     /**
      * Called after the user has changed their password, as a result of
      * receiving {@link #ACTION_PASSWORD_CHANGED}.  At this point you
@@ -247,7 +255,7 @@
      */
     public void onPasswordChanged(Context context, Intent intent) {
     }
-    
+
     /**
      * Called after the user has failed at entering their current password, as a result of
      * receiving {@link #ACTION_PASSWORD_FAILED}.  At this point you
@@ -258,7 +266,7 @@
      */
     public void onPasswordFailed(Context context, Intent intent) {
     }
-    
+
     /**
      * Called after the user has succeeded at entering their current password,
      * as a result of receiving {@link #ACTION_PASSWORD_SUCCEEDED}.  This will
@@ -292,6 +300,26 @@
     }
 
     /**
+     * Called on the new profile when managed profile provisioning has completed.
+     * Managed profile provisioning is the process of setting up the device so that it has a
+     * separate profile which is managed by the mobile device management(mdm) application that
+     * triggered the provisioning.
+     *
+     * <p>As part of provisioning a new profile is created, the mdm is moved to the new profile and
+     * set as the owner of the profile so that it has full control over it.
+     * This intent is only received by the mdm package that is set as profile owner during
+     * provisioning.
+     *
+     * <p>Provisioning can be triggered via an intent with the action
+     * android.managedprovisioning.ACTION_PROVISION_MANAGED_PROFILE.
+     *
+     * @param context The running context as per {@link #onReceive}.
+     * @param intent The received intent as per {@link #onReceive}.
+     */
+    public void onProfileProvisioningComplete(Context context, Intent intent) {
+    }
+
+    /**
      * Intercept standard device administrator broadcasts.  Implementations
      * should not override this method; it is better to implement the
      * convenience callbacks for each action.
@@ -299,6 +327,7 @@
     @Override
     public void onReceive(Context context, Intent intent) {
         String action = intent.getAction();
+
         if (ACTION_PASSWORD_CHANGED.equals(action)) {
             onPasswordChanged(context, intent);
         } else if (ACTION_PASSWORD_FAILED.equals(action)) {
@@ -317,6 +346,8 @@
             onDisabled(context, intent);
         } else if (ACTION_PASSWORD_EXPIRING.equals(action)) {
             onPasswordExpiring(context, intent);
+        } else if (ACTION_PROFILE_PROVISIONING_COMPLETE.equals(action)) {
+            onProfileProvisioningComplete(context, intent);
         }
     }
 }
diff --git a/core/java/android/bluetooth/BluetoothInputDevice.java b/core/java/android/bluetooth/BluetoothInputDevice.java
index b8b8f5f..333f825 100644
--- a/core/java/android/bluetooth/BluetoothInputDevice.java
+++ b/core/java/android/bluetooth/BluetoothInputDevice.java
@@ -79,6 +79,13 @@
      * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_HANDSHAKE =
+        "android.bluetooth.input.profile.action.HANDSHAKE";
+
+    /**
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_REPORT =
         "android.bluetooth.input.profile.action.REPORT";
 
@@ -185,6 +192,11 @@
     /**
      * @hide
      */
+    public static final String EXTRA_STATUS = "android.bluetooth.BluetoothInputDevice.extra.STATUS";
+
+    /**
+     * @hide
+     */
     public static final String EXTRA_VIRTUAL_UNPLUG_STATUS = "android.bluetooth.BluetoothInputDevice.extra.VIRTUAL_UNPLUG_STATUS";
 
     private Context mContext;
@@ -608,7 +620,7 @@
      * @hide
      */
     public boolean setReport(BluetoothDevice device, byte reportType, String report) {
-        if (DBG) log("setReport(" + device + "), reportType=" + reportType + " report=" + report);
+        if (VDBG) log("setReport(" + device + "), reportType=" + reportType + " report=" + report);
         if (mService != null && isEnabled() && isValidDevice(device)) {
             try {
                 return mService.setReport(device, reportType, report);
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 3fdb6e7..f0b7ca8 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3334,6 +3334,15 @@
     public static final String EXTRA_SHUTDOWN_USERSPACE_ONLY
             = "android.intent.extra.SHUTDOWN_USERSPACE_ONLY";
 
+    /**
+     * Optional boolean extra for {@link #ACTION_TIME_CHANGED} that indicates the
+     * user has set their time format preferences to the 24 hour format.
+     *
+     * @hide for internal use only.
+     */
+    public static final String EXTRA_TIME_PREF_24_HOUR_FORMAT =
+            "android.intent.extra.TIME_PREF_24_HOUR_FORMAT";
+
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     // Intent flags (see mFlags variable).
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index 2893522..419abf2 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -315,6 +315,24 @@
         return mDefaultColor;
     }
 
+    /**
+     * Return the states in this {@link ColorStateList}.
+     * @return the states in this {@link ColorStateList}
+     * @hide
+     */
+    public int[][] getStates() {
+        return mStateSpecs;
+    }
+
+    /**
+     * Return the colors in this {@link ColorStateList}.
+     * @return the colors in this {@link ColorStateList}
+     * @hide
+     */
+    public int[] getColors() {
+        return mColors;
+    }
+
     @Override
     public String toString() {
         return "ColorStateList{" +
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index da6ae56..5c27072 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1625,7 +1625,7 @@
 
             String locale = null;
             if (mConfiguration.locale != null) {
-                locale = localeToLanguageTag(mConfiguration.locale);
+                locale = adjustLanguageTag(localeToLanguageTag(mConfiguration.locale));
             }
             int width, height;
             if (mMetrics.widthPixels >= mMetrics.heightPixels) {
@@ -1713,6 +1713,41 @@
     }
 
     /**
+     * {@code Locale.toLanguageTag} will transform the obsolete (and deprecated)
+     * language codes "in", "ji" and "iw" to "id", "yi" and "he" respectively.
+     *
+     * All released versions of android prior to "L" used the deprecated language
+     * tags, so we will need to support them for backwards compatibility.
+     *
+     * Note that this conversion needs to take place *after* the call to
+     * {@code toLanguageTag} because that will convert all the deprecated codes to
+     * the new ones, even if they're set manually.
+     */
+    private static String adjustLanguageTag(String languageTag) {
+        final int separator = languageTag.indexOf('-');
+        final String language;
+        final String remainder;
+
+        if (separator == -1) {
+            language = languageTag;
+            remainder = "";
+        } else {
+            language = languageTag.substring(0, separator);
+            remainder = languageTag.substring(separator);
+        }
+
+        if ("id".equals(language)) {
+            return "in" + remainder;
+        } else if ("yi".equals(language)) {
+            return "ji" + remainder;
+        } else if ("he".equals(language)) {
+            return "iw" + remainder;
+        } else {
+            return languageTag;
+        }
+    }
+
+    /**
      * Update the system resources configuration if they have previously
      * been initialized.
      *
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index cc4bb51..0da77ea 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -578,6 +578,9 @@
         // The wake lock that was acquired at this point.
         public HistoryTag wakelockTag;
 
+        // Kernel wakeup reason at this point.
+        public HistoryTag wakeReasonTag;
+
         public static final int EVENT_FLAG_START = 0x8000;
         public static final int EVENT_FLAG_FINISH = 0x4000;
 
@@ -612,6 +615,7 @@
 
         // Pre-allocated objects.
         public final HistoryTag localWakelockTag = new HistoryTag();
+        public final HistoryTag localWakeReasonTag = new HistoryTag();
         public final HistoryTag localEventTag = new HistoryTag();
 
         public HistoryItem() {
@@ -645,6 +649,12 @@
             } else {
                 dest.writeInt(0);
             }
+            if (wakeReasonTag != null) {
+                dest.writeInt(1);
+                wakeReasonTag.writeToParcel(dest, flags);
+            } else {
+                dest.writeInt(0);
+            }
             dest.writeInt(eventCode);
             if (eventCode != EVENT_NONE) {
                 dest.writeInt(eventCode);
@@ -670,6 +680,12 @@
             } else {
                 wakelockTag = null;
             }
+            if (src.readInt() != 0) {
+                wakeReasonTag = localWakeReasonTag;
+                wakeReasonTag.readFromParcel(src);
+            } else {
+                wakeReasonTag = null;
+            }
             eventCode = src.readInt();
             if (eventCode != EVENT_NONE) {
                 eventTag = localEventTag;
@@ -689,6 +705,7 @@
             batteryVoltage = 0;
             states = 0;
             wakelockTag = null;
+            wakeReasonTag = null;
             eventCode = EVENT_NONE;
             eventTag = null;
         }
@@ -719,6 +736,12 @@
             } else {
                 wakelockTag = null;
             }
+            if (o.wakeReasonTag != null) {
+                wakeReasonTag = localWakeReasonTag;
+                wakeReasonTag.setTo(o.wakeReasonTag);
+            } else {
+                wakeReasonTag = null;
+            }
             eventCode = o.eventCode;
             if (o.eventTag != null) {
                 eventTag = localEventTag;
@@ -750,6 +773,14 @@
                     return false;
                 }
             }
+            if (wakeReasonTag != o.wakeReasonTag) {
+                if (wakeReasonTag == null || o.wakeReasonTag == null) {
+                    return false;
+                }
+                if (!wakeReasonTag.equals(o.wakeReasonTag)) {
+                    return false;
+                }
+            }
             if (eventTag != o.eventTag) {
                 if (eventTag == null || o.eventTag == null) {
                     return false;
@@ -1916,51 +1947,6 @@
         long fullWakeLockTimeTotalMicros = 0;
         long partialWakeLockTimeTotalMicros = 0;
 
-        final Comparator<TimerEntry> timerComparator = new Comparator<TimerEntry>() {
-            @Override
-            public int compare(TimerEntry lhs, TimerEntry rhs) {
-                long lhsTime = lhs.mTime;
-                long rhsTime = rhs.mTime;
-                if (lhsTime < rhsTime) {
-                    return 1;
-                }
-                if (lhsTime > rhsTime) {
-                    return -1;
-                }
-                return 0;
-            }
-        };
-
-        if (reqUid < 0) {
-            Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
-            if (kernelWakelocks.size() > 0) {
-                final ArrayList<TimerEntry> timers = new ArrayList<TimerEntry>();
-                for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
-                    BatteryStats.Timer timer = ent.getValue();
-                    long totalTimeMillis = computeWakeLock(timer, rawRealtime, which);
-                    if (totalTimeMillis > 0) {
-                        timers.add(new TimerEntry(ent.getKey(), 0, timer, totalTimeMillis));
-                    }
-                }
-                Collections.sort(timers, timerComparator);
-                for (int i=0; i<timers.size(); i++) {
-                    TimerEntry timer = timers.get(i);
-                    String linePrefix = ": ";
-                    sb.setLength(0);
-                    sb.append(prefix);
-                    sb.append("  Kernel Wake lock ");
-                    sb.append(timer.mName);
-                    linePrefix = printWakeLock(sb, timer.mTimer, rawRealtime, null,
-                            which, linePrefix);
-                    if (!linePrefix.equals(": ")) {
-                        sb.append(" realtime");
-                        // Only print out wake locks that were held
-                        pw.println(sb.toString());
-                    }
-                }
-            }
-        }
-
         final ArrayList<TimerEntry> timers = new ArrayList<TimerEntry>();
 
         for (int iu = 0; iu < NU; iu++) {
@@ -2292,6 +2278,55 @@
             pw.println();
         }
 
+        final Comparator<TimerEntry> timerComparator = new Comparator<TimerEntry>() {
+            @Override
+            public int compare(TimerEntry lhs, TimerEntry rhs) {
+                long lhsTime = lhs.mTime;
+                long rhsTime = rhs.mTime;
+                if (lhsTime < rhsTime) {
+                    return 1;
+                }
+                if (lhsTime > rhsTime) {
+                    return -1;
+                }
+                return 0;
+            }
+        };
+
+        if (reqUid < 0) {
+            Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
+            if (kernelWakelocks.size() > 0) {
+                final ArrayList<TimerEntry> ktimers = new ArrayList<TimerEntry>();
+                for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
+                    BatteryStats.Timer timer = ent.getValue();
+                    long totalTimeMillis = computeWakeLock(timer, rawRealtime, which);
+                    if (totalTimeMillis > 0) {
+                        ktimers.add(new TimerEntry(ent.getKey(), 0, timer, totalTimeMillis));
+                    }
+                }
+                if (ktimers.size() > 0) {
+                    Collections.sort(ktimers, timerComparator);
+                    pw.print(prefix); pw.println("  All kernel wake locks:");
+                    for (int i=0; i<ktimers.size(); i++) {
+                        TimerEntry timer = ktimers.get(i);
+                        String linePrefix = ": ";
+                        sb.setLength(0);
+                        sb.append(prefix);
+                        sb.append("  Kernel Wake lock ");
+                        sb.append(timer.mName);
+                        linePrefix = printWakeLock(sb, timer.mTimer, rawRealtime, null,
+                                which, linePrefix);
+                        if (!linePrefix.equals(": ")) {
+                            sb.append(" realtime");
+                            // Only print out wake locks that were held
+                            pw.println(sb.toString());
+                        }
+                    }
+                    pw.println();
+                }
+            }
+        }
+
         if (timers.size() > 0) {
             Collections.sort(timers, timerComparator);
             pw.print(prefix); pw.println("  All partial wake locks:");
@@ -2727,14 +2762,22 @@
         public void printNextItem(PrintWriter pw, HistoryItem rec, long now, boolean checkin) {
             if (!checkin) {
                 pw.print("  ");
-                TimeUtils.formatDuration(rec.time-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
+                if (now >= 0) {
+                    TimeUtils.formatDuration(rec.time-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
+                } else {
+                    TimeUtils.formatDuration(rec.time, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
+                }
                 pw.print(" (");
                 pw.print(rec.numReadInts);
                 pw.print(") ");
             } else {
                 if (lastTime < 0) {
-                    pw.print("@");
-                    pw.print(rec.time-now);
+                    if (now >= 0) {
+                        pw.print("@");
+                        pw.print(rec.time-now);
+                    } else {
+                        pw.print(rec.time);
+                    }
                 } else {
                     pw.print(rec.time-lastTime);
                 }
@@ -2858,6 +2901,18 @@
                 }
                 printBitDescriptions(pw, oldState, rec.states, rec.wakelockTag,
                         HISTORY_STATE_DESCRIPTIONS, !checkin);
+                if (rec.wakeReasonTag != null) {
+                    if (checkin) {
+                        pw.print(",Wr=");
+                        pw.print(rec.wakeReasonTag.poolIdx);
+                    } else {
+                        pw.print(" wake_reason=");
+                        pw.print(rec.wakeReasonTag.uid);
+                        pw.print(":\"");
+                        pw.print(rec.wakeReasonTag.string);
+                        pw.print("\"");
+                    }
+                }
                 if (rec.eventCode != HistoryItem.EVENT_NONE) {
                     pw.print(checkin ? "," : " ");
                     if ((rec.eventCode&HistoryItem.EVENT_FLAG_START) != 0) {
@@ -2918,108 +2973,130 @@
         pw.print(suffix);
     }
 
+    public static final int DUMP_UNPLUGGED_ONLY = 1<<0;
+    public static final int DUMP_CHARGED_ONLY = 1<<1;
+    public static final int DUMP_HISTORY_ONLY = 1<<2;
+    public static final int DUMP_INCLUDE_HISTORY = 1<<3;
+
     /**
      * Dumps a human-readable summary of the battery statistics to the given PrintWriter.
      *
      * @param pw a Printer to receive the dump output.
      */
     @SuppressWarnings("unused")
-    public void dumpLocked(Context context, PrintWriter pw, boolean isUnpluggedOnly, int reqUid,
-            boolean historyOnly) {
+    public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
         prepareForDumpLocked();
 
-        long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
+        final boolean filtering =
+                (flags&(DUMP_HISTORY_ONLY|DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY)) != 0;
 
-        final HistoryItem rec = new HistoryItem();
-        final long historyTotalSize = getHistoryTotalSize();
-        final long historyUsedSize = getHistoryUsedSize();
-        if (startIteratingHistoryLocked()) {
-            try {
-                pw.print("Battery History (");
-                pw.print((100*historyUsedSize)/historyTotalSize);
-                pw.print("% used, ");
-                printSizeValue(pw, historyUsedSize);
-                pw.print(" used of ");
-                printSizeValue(pw, historyTotalSize);
-                pw.print(", ");
-                pw.print(getHistoryStringPoolSize());
-                pw.print(" strings using ");
-                printSizeValue(pw, getHistoryStringPoolBytes());
-                pw.println("):");
-                HistoryPrinter hprinter = new HistoryPrinter();
-                while (getNextHistoryLocked(rec)) {
-                    hprinter.printNextItem(pw, rec, now, false);
+        if ((flags&DUMP_HISTORY_ONLY) != 0 || !filtering) {
+            long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
+
+            final HistoryItem rec = new HistoryItem();
+            final long historyTotalSize = getHistoryTotalSize();
+            final long historyUsedSize = getHistoryUsedSize();
+            if (startIteratingHistoryLocked()) {
+                try {
+                    pw.print("Battery History (");
+                    pw.print((100*historyUsedSize)/historyTotalSize);
+                    pw.print("% used, ");
+                    printSizeValue(pw, historyUsedSize);
+                    pw.print(" used of ");
+                    printSizeValue(pw, historyTotalSize);
+                    pw.print(", ");
+                    pw.print(getHistoryStringPoolSize());
+                    pw.print(" strings using ");
+                    printSizeValue(pw, getHistoryStringPoolBytes());
+                    pw.println("):");
+                    HistoryPrinter hprinter = new HistoryPrinter();
+                    long lastTime = -1;
+                    while (getNextHistoryLocked(rec)) {
+                        lastTime = rec.time;
+                        if (rec.time >= histStart) {
+                            hprinter.printNextItem(pw, rec, histStart >= 0 ? -1 : now, false);
+                        }
+                    }
+                    if (histStart >= 0) {
+                        pw.print("  NEXT: "); pw.println(lastTime+1);
+                    }
+                    pw.println();
+                } finally {
+                    finishIteratingHistoryLocked();
                 }
-                pw.println();
-            } finally {
-                finishIteratingHistoryLocked();
+            }
+
+            if (startIteratingOldHistoryLocked()) {
+                try {
+                    pw.println("Old battery History:");
+                    HistoryPrinter hprinter = new HistoryPrinter();
+                    while (getNextOldHistoryLocked(rec)) {
+                        hprinter.printNextItem(pw, rec, now, false);
+                    }
+                    pw.println();
+                } finally {
+                    finishIteratingOldHistoryLocked();
+                }
             }
         }
 
-        if (startIteratingOldHistoryLocked()) {
-            try {
-                pw.println("Old battery History:");
-                HistoryPrinter hprinter = new HistoryPrinter();
-                while (getNextOldHistoryLocked(rec)) {
-                    hprinter.printNextItem(pw, rec, now, false);
-                }
-                pw.println();
-            } finally {
-                finishIteratingOldHistoryLocked();
-            }
-        }
-
-        if (historyOnly) {
+        if (filtering && (flags&(DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY)) == 0) {
             return;
         }
 
-        SparseArray<? extends Uid> uidStats = getUidStats();
-        final int NU = uidStats.size();
-        boolean didPid = false;
-        long nowRealtime = SystemClock.elapsedRealtime();
-        for (int i=0; i<NU; i++) {
-            Uid uid = uidStats.valueAt(i);
-            SparseArray<? extends Uid.Pid> pids = uid.getPidStats();
-            if (pids != null) {
-                for (int j=0; j<pids.size(); j++) {
-                    Uid.Pid pid = pids.valueAt(j);
-                    if (!didPid) {
-                        pw.println("Per-PID Stats:");
-                        didPid = true;
+        if (!filtering) {
+            SparseArray<? extends Uid> uidStats = getUidStats();
+            final int NU = uidStats.size();
+            boolean didPid = false;
+            long nowRealtime = SystemClock.elapsedRealtime();
+            for (int i=0; i<NU; i++) {
+                Uid uid = uidStats.valueAt(i);
+                SparseArray<? extends Uid.Pid> pids = uid.getPidStats();
+                if (pids != null) {
+                    for (int j=0; j<pids.size(); j++) {
+                        Uid.Pid pid = pids.valueAt(j);
+                        if (!didPid) {
+                            pw.println("Per-PID Stats:");
+                            didPid = true;
+                        }
+                        long time = pid.mWakeSum + (pid.mWakeStart != 0
+                                ? (nowRealtime - pid.mWakeStart) : 0);
+                        pw.print("  PID "); pw.print(pids.keyAt(j));
+                                pw.print(" wake time: ");
+                                TimeUtils.formatDuration(time, pw);
+                                pw.println("");
                     }
-                    long time = pid.mWakeSum + (pid.mWakeStart != 0
-                            ? (nowRealtime - pid.mWakeStart) : 0);
-                    pw.print("  PID "); pw.print(pids.keyAt(j));
-                            pw.print(" wake time: ");
-                            TimeUtils.formatDuration(time, pw);
-                            pw.println("");
                 }
             }
-        }
-        if (didPid) {
-            pw.println("");
+            if (didPid) {
+                pw.println("");
+            }
         }
 
-        if (!isUnpluggedOnly) {
+        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
             pw.println("Statistics since last charge:");
             pw.println("  System starts: " + getStartCount()
                     + ", currently on battery: " + getIsOnBattery());
             dumpLocked(context, pw, "", STATS_SINCE_CHARGED, reqUid);
             pw.println("");
         }
-        pw.println("Statistics since last unplugged:");
-        dumpLocked(context, pw, "", STATS_SINCE_UNPLUGGED, reqUid);
+        if (!filtering || (flags&DUMP_UNPLUGGED_ONLY) != 0) {
+            pw.println("Statistics since last unplugged:");
+            dumpLocked(context, pw, "", STATS_SINCE_UNPLUGGED, reqUid);
+        }
     }
     
     @SuppressWarnings("unused")
-    public void dumpCheckinLocked(Context context,
-            PrintWriter pw, List<ApplicationInfo> apps, boolean isUnpluggedOnly,
-            boolean includeHistory, boolean historyOnly) {
+    public void dumpCheckinLocked(Context context, PrintWriter pw,
+            List<ApplicationInfo> apps, int flags, long histStart) {
         prepareForDumpLocked();
         
         long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
 
-        if (includeHistory || historyOnly) {
+        final boolean filtering =
+                (flags&(DUMP_HISTORY_ONLY|DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY)) != 0;
+
+        if ((flags&DUMP_INCLUDE_HISTORY) != 0 || (flags&DUMP_HISTORY_ONLY) != 0) {
             final HistoryItem rec = new HistoryItem();
             if (startIteratingHistoryLocked()) {
                 try {
@@ -3034,10 +3111,17 @@
                         pw.println();
                     }
                     HistoryPrinter hprinter = new HistoryPrinter();
+                    long lastTime = -1;
                     while (getNextHistoryLocked(rec)) {
-                        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
-                        pw.print(HISTORY_DATA); pw.print(',');
-                        hprinter.printNextItem(pw, rec, now, true);
+                        lastTime = rec.time;
+                        if (rec.time >= histStart) {
+                            pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
+                            pw.print(HISTORY_DATA); pw.print(',');
+                            hprinter.printNextItem(pw, rec, histStart >= 0 ? -1 : now, true);
+                        }
+                    }
+                    if (histStart >= 0) {
+                        pw.print("NEXT: "); pw.println(lastTime+1);
                     }
                 } finally {
                     finishIteratingHistoryLocked();
@@ -3045,7 +3129,7 @@
             }
         }
 
-        if (historyOnly) {
+        if (filtering && (flags&(DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY)) == 0) {
             return;
         }
 
@@ -3076,11 +3160,10 @@
                 }
             }
         }
-        if (isUnpluggedOnly) {
-            dumpCheckinLocked(context, pw, STATS_SINCE_UNPLUGGED, -1);
-        }
-        else {
+        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
             dumpCheckinLocked(context, pw, STATS_SINCE_CHARGED, -1);
+        }
+        if (!filtering || (flags&DUMP_UNPLUGGED_ONLY) != 0) {
             dumpCheckinLocked(context, pw, STATS_SINCE_UNPLUGGED, -1);
         }
     }
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 68b91cb..4963991 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -58,6 +58,24 @@
  * argument of {@link android.content.Context#STORAGE_SERVICE}.
  */
 public class StorageManager {
+
+    /// Consts to match the password types in cryptfs.h
+    /** Master key is encrypted with a password.
+     */
+    public static final int CRYPT_TYPE_PASSWORD = 0;
+
+    /** Master key is encrypted with the default password.
+     */
+    public static final int CRYPT_TYPE_DEFAULT = 1;
+
+    /** Master key is encrypted with a pattern.
+     */
+    public static final int CRYPT_TYPE_PATTERN = 2;
+
+    /** Master key is encrypted with a pin.
+     */
+    public static final int CRYPT_TYPE_PIN = 3;
+
     private static final String TAG = "StorageManager";
 
     private final ContentResolver mResolver;
@@ -645,14 +663,4 @@
         return Settings.Global.getLong(mResolver, Settings.Global.SYS_STORAGE_FULL_THRESHOLD_BYTES,
                 DEFAULT_FULL_THRESHOLD_BYTES);
     }
-
-    /// Consts to match the password types in cryptfs.h
-    /** @hide */
-    public static final int CRYPT_TYPE_PASSWORD = 0;
-    /** @hide */
-    public static final int CRYPT_TYPE_DEFAULT = 1;
-    /** @hide */
-    public static final int CRYPT_TYPE_PATTERN = 2;
-    /** @hide */
-    public static final int CRYPT_TYPE_PIN = 3;
 }
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index 9f1e72d..c88b4c0 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -28,6 +28,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewOverlay;
+import android.view.WindowId;
 import android.widget.ListView;
 import android.widget.Spinner;
 
@@ -496,7 +497,8 @@
                             view = (start != null) ? start.view : null;
                         }
                         if (animator != null) {
-                            AnimationInfo info = new AnimationInfo(view, getName(), infoValues);
+                            AnimationInfo info = new AnimationInfo(view, getName(),
+                                    sceneRoot.getWindowId(), infoValues);
                             runningAnimators.put(animator, info);
                             mAnimators.add(animator);
                         }
@@ -1199,13 +1201,17 @@
      *
      * @hide
      */
-    public void pause() {
+    public void pause(View sceneRoot) {
         if (!mEnded) {
             ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
             int numOldAnims = runningAnimators.size();
+            WindowId windowId = sceneRoot.getWindowId();
             for (int i = numOldAnims - 1; i >= 0; i--) {
-                Animator anim = runningAnimators.keyAt(i);
-                anim.pause();
+                AnimationInfo info = runningAnimators.valueAt(i);
+                if (info.view != null && windowId.equals(info.windowId)) {
+                    Animator anim = runningAnimators.keyAt(i);
+                    anim.pause();
+                }
             }
             if (mListeners != null && mListeners.size() > 0) {
                 ArrayList<TransitionListener> tmpListeners =
@@ -1226,14 +1232,18 @@
      *
      * @hide
      */
-    public void resume() {
+    public void resume(View sceneRoot) {
         if (mPaused) {
             if (!mEnded) {
                 ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
                 int numOldAnims = runningAnimators.size();
+                WindowId windowId = sceneRoot.getWindowId();
                 for (int i = numOldAnims - 1; i >= 0; i--) {
-                    Animator anim = runningAnimators.keyAt(i);
-                    anim.resume();
+                    AnimationInfo info = runningAnimators.valueAt(i);
+                    if (info.view != null && windowId.equals(info.windowId)) {
+                        Animator anim = runningAnimators.keyAt(i);
+                        anim.resume();
+                    }
                 }
                 if (mListeners != null && mListeners.size() > 0) {
                     ArrayList<TransitionListener> tmpListeners =
@@ -1644,11 +1654,13 @@
         public View view;
         String name;
         TransitionValues values;
+        WindowId windowId;
 
-        AnimationInfo(View view, String name, TransitionValues values) {
+        AnimationInfo(View view, String name, WindowId windowId, TransitionValues values) {
             this.view = view;
             this.name = name;
             this.values = values;
+            this.windowId = windowId;
         }
     }
 
diff --git a/core/java/android/transition/TransitionManager.java b/core/java/android/transition/TransitionManager.java
index f3abfb0..1614d34 100644
--- a/core/java/android/transition/TransitionManager.java
+++ b/core/java/android/transition/TransitionManager.java
@@ -302,7 +302,7 @@
             ArrayList<Transition> runningTransitions = getRunningTransitions().get(mSceneRoot);
             if (runningTransitions != null && runningTransitions.size() > 0) {
                 for (Transition runningTransition : runningTransitions) {
-                    runningTransition.resume();
+                    runningTransition.resume(mSceneRoot);
                 }
             }
             mTransition.clearValues(true);
@@ -335,7 +335,7 @@
             mTransition.captureValues(mSceneRoot, false);
             if (previousRunningTransitions != null) {
                 for (Transition runningTransition : previousRunningTransitions) {
-                    runningTransition.resume();
+                    runningTransition.resume(mSceneRoot);
                 }
             }
             mTransition.playTransition(mSceneRoot);
@@ -351,7 +351,7 @@
 
         if (runningTransitions != null && runningTransitions.size() > 0) {
             for (Transition runningTransition : runningTransitions) {
-                runningTransition.pause();
+                runningTransition.pause(sceneRoot);
             }
         }
 
diff --git a/core/java/android/transition/TransitionSet.java b/core/java/android/transition/TransitionSet.java
index 4545e3b..19d6b3d 100644
--- a/core/java/android/transition/TransitionSet.java
+++ b/core/java/android/transition/TransitionSet.java
@@ -317,21 +317,21 @@
 
     /** @hide */
     @Override
-    public void pause() {
-        super.pause();
+    public void pause(View sceneRoot) {
+        super.pause(sceneRoot);
         int numTransitions = mTransitions.size();
         for (int i = 0; i < numTransitions; ++i) {
-            mTransitions.get(i).pause();
+            mTransitions.get(i).pause(sceneRoot);
         }
     }
 
     /** @hide */
     @Override
-    public void resume() {
-        super.resume();
+    public void resume(View sceneRoot) {
+        super.resume(sceneRoot);
         int numTransitions = mTransitions.size();
         for (int i = 0; i < numTransitions; ++i) {
-            mTransitions.get(i).resume();
+            mTransitions.get(i).resume(sceneRoot);
         }
     }
 
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java
index 0ae36c1..be6f401 100644
--- a/core/java/android/view/DisplayList.java
+++ b/core/java/android/view/DisplayList.java
@@ -122,9 +122,6 @@
  * @hide
  */
 public class DisplayList {
-    private boolean mValid;
-    private final long mNativeDisplayList;
-
     /**
      * Flag used when calling
      * {@link HardwareCanvas#drawDisplayList(DisplayList, android.graphics.Rect, int)}
@@ -175,6 +172,10 @@
      */
     public static final int STATUS_DREW = 0x4;
 
+    private boolean mValid;
+    private final long mNativeDisplayList;
+    private HardwareRenderer mRenderer;
+
     private DisplayList(String name) {
         mNativeDisplayList = nCreate();
         nSetDisplayListName(mNativeDisplayList, name);
@@ -233,7 +234,13 @@
         GLES20RecordingCanvas canvas = (GLES20RecordingCanvas) endCanvas;
         canvas.onPostDraw();
         long displayListData = canvas.finishRecording();
-        renderer.swapDisplayListData(mNativeDisplayList, displayListData);
+        if (renderer != mRenderer) {
+            // If we are changing renderers first destroy with the old
+            // renderer, then set with the new one
+            destroyDisplayListData();
+        }
+        mRenderer = renderer;
+        setDisplayListData(displayListData);
         canvas.recycle();
         mValid = true;
     }
@@ -245,14 +252,22 @@
      *
      * @hide
      */
-    public void destroyDisplayListData(HardwareRenderer renderer) {
-        if (renderer == null) {
-            throw new IllegalArgumentException("Cannot destroyDisplayListData with a null renderer");
-        }
-        renderer.swapDisplayListData(mNativeDisplayList, 0);
+    public void destroyDisplayListData() {
+        if (!mValid) return;
+
+        setDisplayListData(0);
+        mRenderer = null;
         mValid = false;
     }
 
+    private void setDisplayListData(long newData) {
+        if (mRenderer != null) {
+            mRenderer.setDisplayListData(mNativeDisplayList, newData);
+        } else {
+            throw new IllegalStateException("Trying to set data without a renderer! data=" + newData);
+        }
+    }
+
     /**
      * Returns whether the display list is currently usable. If this returns false,
      * the display list should be re-recorded prior to replaying it.
@@ -907,6 +922,7 @@
     @Override
     protected void finalize() throws Throwable {
         try {
+            destroyDisplayListData();
             nDestroyDisplayList(mNativeDisplayList);
         } finally {
             super.finalize();
diff --git a/core/java/android/view/GLRenderer.java b/core/java/android/view/GLRenderer.java
index c90e4b0..81f778d 100644
--- a/core/java/android/view/GLRenderer.java
+++ b/core/java/android/view/GLRenderer.java
@@ -1196,10 +1196,10 @@
         }
     }
 
-    void swapDisplayListData(long displayList, long newData) {
-        nSwapDisplayListData(displayList, newData);
+    void setDisplayListData(long displayList, long newData) {
+        nSetDisplayListData(displayList, newData);
     }
-    private static native void nSwapDisplayListData(long displayList, long newData);
+    private static native void nSetDisplayListData(long displayList, long newData);
 
     private DisplayList buildDisplayList(View view, HardwareCanvas canvas) {
         if (mDrawDelta <= 0) {
diff --git a/core/java/android/view/HardwareLayer.java b/core/java/android/view/HardwareLayer.java
index c526dd2..46e2690 100644
--- a/core/java/android/view/HardwareLayer.java
+++ b/core/java/android/view/HardwareLayer.java
@@ -88,7 +88,7 @@
         }
 
         if (mDisplayList != null) {
-            mDisplayList.destroyDisplayListData(mRenderer);
+            mDisplayList.destroyDisplayListData();
             mDisplayList = null;
         }
         if (mRenderer != null) {
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index bcc28e3..34efcf5 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -562,7 +562,7 @@
         mRequested = requested;
     }
 
-    abstract void swapDisplayListData(long displayList, long newData);
+    abstract void setDisplayListData(long displayList, long newData);
 
     /**
      * Describes a series of frames that should be drawn on screen as a graph.
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 7e745d8..c183f08 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -628,11 +628,19 @@
     /** Key code constant: Brightness Up key.
      * Adjusts the screen brightness up. */
     public static final int KEYCODE_BRIGHTNESS_UP   = 221;
-    /** Key code constant: Audio Track key
+    /** Key code constant: Audio Track key.
      * Switches the audio tracks. */
     public static final int KEYCODE_MEDIA_AUDIO_TRACK = 222;
+    /** Key code constant: Sleep key.
+     * Puts the device to sleep.  Behaves somewhat like {@link #KEYCODE_POWER} but it
+     * has no effect if the device is already asleep. */
+    public static final int KEYCODE_SLEEP           = 223;
+    /** Key code constant: Wakeup key.
+     * Wakes up the device.  Behaves somewhat like {@link #KEYCODE_POWER} but it
+     * has no effect if the device is already awake. */
+    public static final int KEYCODE_WAKEUP          = 224;
 
-    private static final int LAST_KEYCODE           = KEYCODE_MEDIA_AUDIO_TRACK;
+    private static final int LAST_KEYCODE = KEYCODE_WAKEUP;
 
     // NOTE: If you add a new keycode here you must also add it to:
     //  isSystem()
@@ -877,6 +885,8 @@
         names.append(KEYCODE_BRIGHTNESS_DOWN, "KEYCODE_BRIGHTNESS_DOWN");
         names.append(KEYCODE_BRIGHTNESS_UP, "KEYCODE_BRIGHTNESS_UP");
         names.append(KEYCODE_MEDIA_AUDIO_TRACK, "KEYCODE_MEDIA_AUDIO_TRACK");
+        names.append(KEYCODE_SLEEP, "KEYCODE_SLEEP");
+        names.append(KEYCODE_WAKEUP, "KEYCODE_WAKEUP");
     };
 
     // Symbolic names of all metakeys in bit order from least significant to most significant.
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 9b23b35..1f211c2 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -255,8 +255,9 @@
         updateWindow(false, false);
     }
 
+    /** @hide */
     @Override
-    protected void onDetachedFromWindow() {
+    protected void onDetachedFromWindowInternal() {
         if (mGlobalListenersAdded) {
             ViewTreeObserver observer = getViewTreeObserver();
             observer.removeOnScrollChangedListener(mScrollChangedListener);
@@ -278,7 +279,7 @@
         mSession = null;
         mLayout.token = null;
 
-        super.onDetachedFromWindow();
+        super.onDetachedFromWindowInternal();
     }
 
     @Override
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index ef0d80d..3cfe5e9 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -228,10 +228,11 @@
         }
     }
 
+    /** @hide */
     @Override
-    protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
+    protected void onDetachedFromWindowInternal() {
         destroySurface();
+        super.onDetachedFromWindowInternal();
     }
 
     private void destroySurface() {
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 3dcfbb3..a1fb123 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -148,8 +148,8 @@
     }
 
     @Override
-    void swapDisplayListData(long displayList, long newData) {
-        nSwapDisplayListData(mNativeProxy, displayList, newData);
+    void setDisplayListData(long displayList, long newData) {
+        nSetDisplayListData(mNativeProxy, displayList, newData);
     }
 
     @Override
@@ -257,7 +257,7 @@
     private static native boolean nInitialize(long nativeProxy, Surface window);
     private static native void nUpdateSurface(long nativeProxy, Surface window);
     private static native void nSetup(long nativeProxy, int width, int height);
-    private static native void nSwapDisplayListData(long nativeProxy, long displayList,
+    private static native void nSetDisplayListData(long nativeProxy, long displayList,
             long newData);
     private static native void nDrawDisplayList(long nativeProxy, long displayList,
             int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index afa63a2..904ec44 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -8705,7 +8705,14 @@
      *
      * <p>When implementing this, you probably also want to implement
      * {@link #onCheckIsTextEditor()} to indicate you will return a
-     * non-null InputConnection.
+     * non-null InputConnection.</p>
+     *
+     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
+     * object correctly and in its entirety, so that the connected IME can rely
+     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
+     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
+     * must be filled in with the correct cursor position for IMEs to work correctly
+     * with your application.</p>
      *
      * @param outAttrs Fill in with attribute information about the connection.
      */
@@ -10927,9 +10934,8 @@
      * Set to true to enable this View to cast shadows.
      * <p>
      * If enabled, and the View has a z translation greater than 0, or is
-     * rotated in 3D, the shadow will be cast onto the current
-     * {@link ViewGroup#setIsolatedZVolume(boolean) isolated Z volume},
-     * at the z = 0 plane.
+     * rotated in 3D, the shadow will be cast onto its parent at the z = 0
+     * plane.
      * <p>
      * The shape of the shadow being cast is defined by the
      * {@link #setOutline(Path) outline} of the view, or the rectangular bounds
@@ -13116,6 +13122,19 @@
      * @see #onAttachedToWindow()
      */
     protected void onDetachedFromWindow() {
+    }
+
+    /**
+     * This is a framework-internal mirror of onDetachedFromWindow() that's called
+     * after onDetachedFromWindow().
+     *
+     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
+     * The super method should be called at the end of the overriden method to ensure
+     * subclasses are destroyed first
+     *
+     * @hide
+     */
+    protected void onDetachedFromWindowInternal() {
         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
 
@@ -13303,6 +13322,7 @@
         }
 
         onDetachedFromWindow();
+        onDetachedFromWindowInternal();
 
         ListenerInfo li = mListenerInfo;
         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
@@ -14042,13 +14062,12 @@
     }
 
     private void resetDisplayList() {
-        HardwareRenderer renderer = getHardwareRenderer();
         if (mDisplayList != null && mDisplayList.isValid()) {
-            mDisplayList.destroyDisplayListData(renderer);
+            mDisplayList.destroyDisplayListData();
         }
 
         if (mBackgroundDisplayList != null && mBackgroundDisplayList.isValid()) {
-            mBackgroundDisplayList.destroyDisplayListData(renderer);
+            mBackgroundDisplayList.destroyDisplayListData();
         }
     }
 
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 9c50323..f9b9401 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3166,6 +3166,8 @@
      * @see #setIsolatedZVolume(boolean)
      *
      * @return True if the ViewGroup has an isolated Z volume.
+     *
+     * @hide
      */
     public boolean hasIsolatedZVolume() {
         return ((mGroupFlags & FLAG_ISOLATED_Z_VOLUME) != 0);
@@ -3180,6 +3182,8 @@
      *         ordering space, false if its decendents should inhabit the
      *         inherited Z ordering volume.
      * @attr ref android.R.styleable#ViewGroup_isolatedZVolume
+     *
+     * @hide
      */
     public void setIsolatedZVolume(boolean isolateZVolume) {
         boolean previousValue = (mGroupFlags & FLAG_ISOLATED_Z_VOLUME) != 0;
diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java
index d4e005b..c0395cf 100644
--- a/core/java/android/view/inputmethod/EditorInfo.java
+++ b/core/java/android/view/inputmethod/EditorInfo.java
@@ -26,13 +26,13 @@
 /**
  * An EditorInfo describes several attributes of a text editing object
  * that an input method is communicating with (typically an EditText), most
- * importantly the type of text content it contains.
+ * importantly the type of text content it contains and the current cursor position.
  */
 public class EditorInfo implements InputType, Parcelable {
     /**
      * The content type of the text box, whose bits are defined by
      * {@link InputType}.
-     * 
+     *
      * @see InputType
      * @see #TYPE_MASK_CLASS
      * @see #TYPE_MASK_VARIATION
@@ -47,55 +47,55 @@
      * to provide alternative mechanisms for providing that command.
      */
     public static final int IME_MASK_ACTION = 0x000000ff;
-    
+
     /**
      * Bits of {@link #IME_MASK_ACTION}: no specific action has been
      * associated with this editor, let the editor come up with its own if
      * it can.
      */
     public static final int IME_ACTION_UNSPECIFIED = 0x00000000;
-    
+
     /**
      * Bits of {@link #IME_MASK_ACTION}: there is no available action.
      */
     public static final int IME_ACTION_NONE = 0x00000001;
-    
+
     /**
      * Bits of {@link #IME_MASK_ACTION}: the action key performs a "go"
      * operation to take the user to the target of the text they typed.
      * Typically used, for example, when entering a URL.
      */
     public static final int IME_ACTION_GO = 0x00000002;
-    
+
     /**
      * Bits of {@link #IME_MASK_ACTION}: the action key performs a "search"
      * operation, taking the user to the results of searching for the text
      * they have typed (in whatever context is appropriate).
      */
     public static final int IME_ACTION_SEARCH = 0x00000003;
-    
+
     /**
      * Bits of {@link #IME_MASK_ACTION}: the action key performs a "send"
      * operation, delivering the text to its target.  This is typically used
      * when composing a message in IM or SMS where sending is immediate.
      */
     public static final int IME_ACTION_SEND = 0x00000004;
-    
+
     /**
      * Bits of {@link #IME_MASK_ACTION}: the action key performs a "next"
      * operation, taking the user to the next field that will accept text.
      */
     public static final int IME_ACTION_NEXT = 0x00000005;
-    
+
     /**
      * Bits of {@link #IME_MASK_ACTION}: the action key performs a "done"
      * operation, typically meaning there is nothing more to input and the
      * IME will be closed.
      */
     public static final int IME_ACTION_DONE = 0x00000006;
-    
+
     /**
-     * Bits of {@link #IME_MASK_ACTION}: Like {@link #IME_ACTION_NEXT}, but
+     * Bits of {@link #IME_MASK_ACTION}: like {@link #IME_ACTION_NEXT}, but
      * for moving to the previous field.  This will normally not be used to
      * specify an action (since it precludes {@link #IME_ACTION_NEXT}), but
      * can be returned to the app if it sets {@link #IME_FLAG_NAVIGATE_PREVIOUS}.
@@ -154,7 +154,7 @@
      * on older versions of the platform.
      */
     public static final int IME_FLAG_NO_EXTRACT_UI = 0x10000000;
-    
+
     /**
      * Flag of {@link #imeOptions}: used in conjunction with one of the actions
      * masked by {@link #IME_MASK_ACTION}, this indicates that the action
@@ -167,7 +167,7 @@
      * to show more text.
      */
     public static final int IME_FLAG_NO_ACCESSORY_ACTION = 0x20000000;
-    
+
     /**
      * Flag of {@link #imeOptions}: used in conjunction with one of the actions
      * masked by {@link #IME_MASK_ACTION}. If this flag is not set, IMEs will
@@ -202,13 +202,13 @@
      * Generic unspecified type for {@link #imeOptions}.
      */
     public static final int IME_NULL = 0x00000000;
-    
+
     /**
      * Extended type information for the editor, to help the IME better
      * integrate with it.
      */
     public int imeOptions = IME_NULL;
-    
+
     /**
      * A string supplying additional information options that are
      * private to a particular IME implementation.  The string must be
@@ -221,7 +221,7 @@
      * attribute of a TextView.
      */
     public String privateImeOptions = null;
-    
+
     /**
      * In some cases an IME may be able to display an arbitrary label for
      * a command the user can perform, which you can specify here. This is
@@ -233,7 +233,7 @@
      * ignore this.
      */
     public CharSequence actionLabel = null;
-    
+
     /**
      * If {@link #actionLabel} has been given, this is the id for that command
      * when the user presses its button that is delivered back with
@@ -241,50 +241,66 @@
      * InputConnection.performEditorAction()}.
      */
     public int actionId = 0;
-    
+
     /**
      * The text offset of the start of the selection at the time editing
-     * began; -1 if not known. Keep in mind some IMEs may not be able
-     * to give their full feature set without knowing the cursor position;
-     * avoid passing -1 here if you can.
+     * begins; -1 if not known. Keep in mind that, without knowing the cursor
+     * position, many IMEs will not be able to offer their full feature set and
+     * may even behave in unpredictable ways: pass the actual cursor position
+     * here if possible at all.
+     *
+     * <p>Also, this needs to be the cursor position <strong>right now</strong>,
+     * not at some point in the past, even if input is starting in the same text field
+     * as before. When the app is filling this object, input is about to start by
+     * definition, and this value will override any value the app may have passed to
+     * {@link InputMethodManager#updateSelection(android.view.View, int, int, int, int)}
+     * before.</p>
      */
     public int initialSelStart = -1;
-    
+
     /**
-     * The text offset of the end of the selection at the time editing
-     * began; -1 if not known. Keep in mind some IMEs may not be able
-     * to give their full feature set without knowing the cursor position;
-     * avoid passing -1 here if you can.
+     * <p>The text offset of the end of the selection at the time editing
+     * begins; -1 if not known. Keep in mind that, without knowing the cursor
+     * position, many IMEs will not be able to offer their full feature set and
+     * may behave in unpredictable ways: pass the actual cursor position
+     * here if possible at all.</p>
+     *
+     * <p>Also, this needs to be the cursor position <strong>right now</strong>,
+     * not at some point in the past, even if input is starting in the same text field
+     * as before. When the app is filling this object, input is about to start by
+     * definition, and this value will override any value the app may have passed to
+     * {@link InputMethodManager#updateSelection(android.view.View, int, int, int, int)}
+     * before.</p>
      */
     public int initialSelEnd = -1;
-    
+
     /**
      * The capitalization mode of the first character being edited in the
      * text.  Values may be any combination of
      * {@link TextUtils#CAP_MODE_CHARACTERS TextUtils.CAP_MODE_CHARACTERS},
      * {@link TextUtils#CAP_MODE_WORDS TextUtils.CAP_MODE_WORDS}, and
      * {@link TextUtils#CAP_MODE_SENTENCES TextUtils.CAP_MODE_SENTENCES}, though
-     * you should generally just take a non-zero value to mean start out in
-     * caps mode.
+     * you should generally just take a non-zero value to mean "start out in
+     * caps mode".
      */
     public int initialCapsMode = 0;
-    
+
     /**
      * The "hint" text of the text view, typically shown in-line when the
      * text is empty to tell the user what to enter.
      */
     public CharSequence hintText;
-    
+
     /**
      * A label to show to the user describing the text they are writing.
      */
     public CharSequence label;
-    
+
     /**
      * Name of the package that owns this editor.
      */
     public String packageName;
-    
+
     /**
      * Identifier for the editor's field.  This is optional, and may be
      * 0.  By default it is filled in with the result of
@@ -292,14 +308,14 @@
      * is being edited.
      */
     public int fieldId;
-    
+
     /**
      * Additional name for the editor's field.  This can supply additional
      * name information for the field.  By default it is null.  The actual
      * contents have no meaning.
      */
     public String fieldName;
-    
+
     /**
      * Any extra data to supply to the input method.  This is for extended
      * communication with specific input methods; the name fields in the
@@ -309,7 +325,7 @@
      * attribute of a TextView.
      */
     public Bundle extras;
-    
+
     /**
      * Ensure that the data in this EditorInfo is compatible with an application
      * that was developed against the given target API version.  This can
@@ -365,10 +381,10 @@
                 + " fieldName=" + fieldName);
         pw.println(prefix + "extras=" + extras);
     }
-    
+
     /**
      * Used to package this object into a {@link Parcel}.
-     * 
+     *
      * @param dest The {@link Parcel} to be written.
      * @param flags The flags used for parceling.
      */
@@ -392,30 +408,31 @@
     /**
      * Used to make this class parcelable.
      */
-    public static final Parcelable.Creator<EditorInfo> CREATOR = new Parcelable.Creator<EditorInfo>() {
-        public EditorInfo createFromParcel(Parcel source) {
-            EditorInfo res = new EditorInfo();
-            res.inputType = source.readInt();
-            res.imeOptions = source.readInt();
-            res.privateImeOptions = source.readString();
-            res.actionLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
-            res.actionId = source.readInt();
-            res.initialSelStart = source.readInt();
-            res.initialSelEnd = source.readInt();
-            res.initialCapsMode = source.readInt();
-            res.hintText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
-            res.label = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
-            res.packageName = source.readString();
-            res.fieldId = source.readInt();
-            res.fieldName = source.readString();
-            res.extras = source.readBundle();
-            return res;
-        }
+    public static final Parcelable.Creator<EditorInfo> CREATOR =
+            new Parcelable.Creator<EditorInfo>() {
+                public EditorInfo createFromParcel(Parcel source) {
+                    EditorInfo res = new EditorInfo();
+                    res.inputType = source.readInt();
+                    res.imeOptions = source.readInt();
+                    res.privateImeOptions = source.readString();
+                    res.actionLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
+                    res.actionId = source.readInt();
+                    res.initialSelStart = source.readInt();
+                    res.initialSelEnd = source.readInt();
+                    res.initialCapsMode = source.readInt();
+                    res.hintText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
+                    res.label = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
+                    res.packageName = source.readString();
+                    res.fieldId = source.readInt();
+                    res.fieldName = source.readString();
+                    res.extras = source.readBundle();
+                    return res;
+                }
 
-        public EditorInfo[] newArray(int size) {
-            return new EditorInfo[size];
-        }
-    };
+                public EditorInfo[] newArray(int size) {
+                    return new EditorInfo[size];
+                }
+            };
 
     public int describeContents() {
         return 0;
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index 9f2bf33..f8160c8 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -37,6 +37,7 @@
 import android.util.Slog;
 import android.util.Xml;
 import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
+import android.view.inputmethod.InputMethodSubtypeArray;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -86,9 +87,9 @@
     final int mIsDefaultResId;
 
     /**
-     * The array of the subtypes.
+     * An array-like container of the subtypes.
      */
-    private final ArrayList<InputMethodSubtype> mSubtypes = new ArrayList<InputMethodSubtype>();
+    private final InputMethodSubtypeArray mSubtypes;
 
     private final boolean mIsAuxIme;
 
@@ -138,6 +139,7 @@
         int isDefaultResId = 0;
 
         XmlResourceParser parser = null;
+        final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
         try {
             parser = si.loadXmlMetaData(pm, InputMethod.SERVICE_META_DATA);
             if (parser == null) {
@@ -206,7 +208,7 @@
                     if (!subtype.isAuxiliary()) {
                         isAuxIme = false;
                     }
-                    mSubtypes.add(subtype);
+                    subtypes.add(subtype);
                 }
             }
         } catch (NameNotFoundException e) {
@@ -216,7 +218,7 @@
             if (parser != null) parser.close();
         }
 
-        if (mSubtypes.size() == 0) {
+        if (subtypes.size() == 0) {
             isAuxIme = false;
         }
 
@@ -225,14 +227,15 @@
             final int N = additionalSubtypes.size();
             for (int i = 0; i < N; ++i) {
                 final InputMethodSubtype subtype = additionalSubtypes.get(i);
-                if (!mSubtypes.contains(subtype)) {
-                    mSubtypes.add(subtype);
+                if (!subtypes.contains(subtype)) {
+                    subtypes.add(subtype);
                 } else {
                     Slog.w(TAG, "Duplicated subtype definition found: "
                             + subtype.getLocale() + ", " + subtype.getMode());
                 }
             }
         }
+        mSubtypes = new InputMethodSubtypeArray(subtypes);
         mSettingsActivityName = settingsActivityComponent;
         mIsDefaultResId = isDefaultResId;
         mIsAuxIme = isAuxIme;
@@ -246,7 +249,7 @@
         mIsAuxIme = source.readInt() == 1;
         mSupportsSwitchingToNextInputMethod = source.readInt() == 1;
         mService = ResolveInfo.CREATOR.createFromParcel(source);
-        source.readTypedList(mSubtypes, InputMethodSubtype.CREATOR);
+        mSubtypes = new InputMethodSubtypeArray(source);
         mForceDefault = false;
     }
 
@@ -272,9 +275,7 @@
         mSettingsActivityName = settingsActivity;
         mIsDefaultResId = isDefaultResId;
         mIsAuxIme = isAuxIme;
-        if (subtypes != null) {
-            mSubtypes.addAll(subtypes);
-        }
+        mSubtypes = new InputMethodSubtypeArray(subtypes);
         mForceDefault = forceDefault;
         mSupportsSwitchingToNextInputMethod = true;
     }
@@ -364,7 +365,7 @@
      * composed of {@link #getPackageName} and the class name returned here.
      *
      * <p>A null will be returned if there is no settings activity associated
-     * with the input method.
+     * with the input method.</p>
      */
     public String getSettingsActivity() {
         return mSettingsActivityName;
@@ -374,7 +375,7 @@
      * Return the count of the subtypes of Input Method.
      */
     public int getSubtypeCount() {
-        return mSubtypes.size();
+        return mSubtypes.getCount();
     }
 
     /**
@@ -479,7 +480,7 @@
         dest.writeInt(mIsAuxIme ? 1 : 0);
         dest.writeInt(mSupportsSwitchingToNextInputMethod ? 1 : 0);
         mService.writeToParcel(dest, flags);
-        dest.writeTypedList(mSubtypes);
+        mSubtypes.writeToParcel(dest);
     }
 
     /**
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 70c53d2..e812edd 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1394,6 +1394,14 @@
     
     /**
      * Report the current selection range.
+     *
+     * <p><strong>Editor authors</strong>, you need to call this method whenever
+     * the cursor moves in your editor. Remember that in addition to doing this, your
+     * editor needs to always supply current cursor values in
+     * {@link EditorInfo#initialSelStart} and {@link EditorInfo#initialSelEnd} every
+     * time {@link android.view.View#onCreateInputConnection(EditorInfo)} is
+     * called, which happens whenever the keyboard shows up or the focus changes
+     * to a text field, among other cases.</p>
      */
     public void updateSelection(View view, int selStart, int selEnd,
             int candidatesStart, int candidatesEnd) {
diff --git a/core/java/android/view/inputmethod/InputMethodSubtypeArray.java b/core/java/android/view/inputmethod/InputMethodSubtypeArray.java
new file mode 100644
index 0000000..5bef71f
--- /dev/null
+++ b/core/java/android/view/inputmethod/InputMethodSubtypeArray.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2007-2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package android.view.inputmethod;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.AndroidRuntimeException;
+import android.util.Slog;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+/**
+ * An array-like container that stores multiple instances of {@link InputMethodSubtype}.
+ *
+ * <p>This container is designed to reduce the risk of {@link TransactionTooLargeException}
+ * when one or more instancess of {@link InputMethodInfo} are transferred through IPC.
+ * Basically this class does following three tasks.</p>
+ * <ul>
+ * <li>Applying compression for the marshalled data</li>
+ * <li>Lazily unmarshalling objects</li>
+ * <li>Caching the marshalled data when appropriate</li>
+ * </ul>
+ *
+ * @hide
+ */
+public class InputMethodSubtypeArray {
+    private final static String TAG = "InputMethodSubtypeArray";
+
+    /**
+     * Create a new instance of {@link InputMethodSubtypeArray} from an existing list of
+     * {@link InputMethodSubtype}.
+     *
+     * @param subtypes A list of {@link InputMethodSubtype} from which
+     * {@link InputMethodSubtypeArray} will be created.
+     */
+    public InputMethodSubtypeArray(final List<InputMethodSubtype> subtypes) {
+        if (subtypes == null) {
+            mCount = 0;
+            return;
+        }
+        mCount = subtypes.size();
+        mInstance = subtypes.toArray(new InputMethodSubtype[mCount]);
+    }
+
+    /**
+     * Unmarshall an instance of {@link InputMethodSubtypeArray} from a given {@link Parcel}
+     * object.
+     *
+     * @param source A {@link Parcel} object from which {@link InputMethodSubtypeArray} will be
+     * unmarshalled.
+     */
+    public InputMethodSubtypeArray(final Parcel source) {
+        mCount = source.readInt();
+        if (mCount > 0) {
+            mDecompressedSize = source.readInt();
+            mCompressedData = source.createByteArray();
+        }
+    }
+
+    /**
+     * Marshall the instance into a given {@link Parcel} object.
+     *
+     * <p>This methods may take a bit additional time to compress data lazily when called
+     * first time.</p>
+     *
+     * @param source A {@link Parcel} object to which {@link InputMethodSubtypeArray} will be
+     * marshalled.
+     */
+    public void writeToParcel(final Parcel dest) {
+        if (mCount == 0) {
+            dest.writeInt(mCount);
+            return;
+        }
+
+        byte[] compressedData = mCompressedData;
+        int decompressedSize = mDecompressedSize;
+        if (compressedData == null && decompressedSize == 0) {
+            synchronized (mLockObject) {
+                compressedData = mCompressedData;
+                decompressedSize = mDecompressedSize;
+                if (compressedData == null && decompressedSize == 0) {
+                    final byte[] decompressedData = marshall(mInstance);
+                    compressedData = compress(decompressedData);
+                    if (compressedData == null) {
+                        decompressedSize = -1;
+                        Slog.i(TAG, "Failed to compress data.");
+                    } else {
+                        decompressedSize = decompressedData.length;
+                    }
+                    mDecompressedSize = decompressedSize;
+                    mCompressedData = compressedData;
+                }
+            }
+        }
+
+        if (compressedData != null && decompressedSize > 0) {
+            dest.writeInt(mCount);
+            dest.writeInt(decompressedSize);
+            dest.writeByteArray(compressedData);
+        } else {
+            Slog.i(TAG, "Unexpected state. Behaving as an empty array.");
+            dest.writeInt(0);
+        }
+    }
+
+    /**
+     * Return {@link InputMethodSubtype} specified with the given index.
+     *
+     * <p>This methods may take a bit additional time to decompress data lazily when called
+     * first time.</p>
+     *
+     * @param index The index of {@link InputMethodSubtype}.
+     */
+    public InputMethodSubtype get(final int index) {
+        if (index < 0 || mCount <= index) {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+        InputMethodSubtype[] instance = mInstance;
+        if (instance == null) {
+            synchronized (mLockObject) {
+                instance = mInstance;
+                if (instance == null) {
+                    final byte[] decompressedData =
+                          decompress(mCompressedData, mDecompressedSize);
+                    // Clear the compressed data until {@link #getMarshalled()} is called.
+                    mCompressedData = null;
+                    mDecompressedSize = 0;
+                    if (decompressedData != null) {
+                        instance = unmarshall(decompressedData);
+                    } else {
+                        Slog.e(TAG, "Failed to decompress data. Returns null as fallback.");
+                        instance = new InputMethodSubtype[mCount];
+                    }
+                    mInstance = instance;
+                }
+            }
+        }
+        return instance[index];
+    }
+
+    /**
+     * Return the number of {@link InputMethodSubtype} objects.
+     */
+    public int getCount() {
+        return mCount;
+    }
+
+    private final Object mLockObject = new Object();
+    private final int mCount;
+
+    private volatile InputMethodSubtype[] mInstance;
+    private volatile byte[] mCompressedData;
+    private volatile int mDecompressedSize;
+
+    private static byte[] marshall(final InputMethodSubtype[] array) {
+        Parcel parcel = null;
+        try {
+            parcel = Parcel.obtain();
+            parcel.writeTypedArray(array, 0);
+            return parcel.marshall();
+        } finally {
+            if (parcel != null) {
+                parcel.recycle();
+                parcel = null;
+            }
+        }
+    }
+
+    private static InputMethodSubtype[] unmarshall(final byte[] data) {
+        Parcel parcel = null;
+        try {
+            parcel = Parcel.obtain();
+            parcel.unmarshall(data, 0, data.length);
+            parcel.setDataPosition(0);
+            return parcel.createTypedArray(InputMethodSubtype.CREATOR);
+        } finally {
+            if (parcel != null) {
+                parcel.recycle();
+                parcel = null;
+            }
+        }
+    }
+
+    private static byte[] compress(final byte[] data) {
+        ByteArrayOutputStream resultStream = null;
+        GZIPOutputStream zipper = null;
+        try {
+            resultStream = new ByteArrayOutputStream();
+            zipper = new GZIPOutputStream(resultStream);
+            zipper.write(data);
+        } catch(IOException e) {
+            return null;
+        } finally {
+            try {
+                if (zipper != null) {
+                    zipper.close();
+                }
+            } catch (IOException e) {
+                zipper = null;
+                Slog.e(TAG, "Failed to close the stream.", e);
+                // swallowed, not propagated back to the caller
+            }
+            try {
+                if (resultStream != null) {
+                    resultStream.close();
+                }
+            } catch (IOException e) {
+                resultStream = null;
+                Slog.e(TAG, "Failed to close the stream.", e);
+                // swallowed, not propagated back to the caller
+            }
+        }
+        return resultStream != null ? resultStream.toByteArray() : null;
+    }
+
+    private static byte[] decompress(final byte[] data, final int expectedSize) {
+        ByteArrayInputStream inputStream = null;
+        GZIPInputStream unzipper = null;
+        try {
+            inputStream = new ByteArrayInputStream(data);
+            unzipper = new GZIPInputStream(inputStream);
+            final byte [] result = new byte[expectedSize];
+            int totalReadBytes = 0;
+            while (totalReadBytes < result.length) {
+                final int restBytes = result.length - totalReadBytes;
+                final int readBytes = unzipper.read(result, totalReadBytes, restBytes);
+                if (readBytes < 0) {
+                    break;
+                }
+                totalReadBytes += readBytes;
+            }
+            if (expectedSize != totalReadBytes) {
+                return null;
+            }
+            return result;
+        } catch(IOException e) {
+            return null;
+        } finally {
+            try {
+                if (unzipper != null) {
+                    unzipper.close();
+                }
+            } catch (IOException e) {
+                Slog.e(TAG, "Failed to close the stream.", e);
+                // swallowed, not propagated back to the caller
+            }
+            try {
+                if (inputStream != null) {
+                  inputStream.close();
+                }
+            } catch (IOException e) {
+                Slog.e(TAG, "Failed to close the stream.", e);
+                // swallowed, not propagated back to the caller
+            }
+        }
+    }
+}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 826bcec..81d36a4 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2139,10 +2139,11 @@
         mProvider.getViewDelegate().onAttachedToWindow();
     }
 
+    /** @hide */
     @Override
-    protected void onDetachedFromWindow() {
+    protected void onDetachedFromWindowInternal() {
         mProvider.getViewDelegate().onDetachedFromWindow();
-        super.onDetachedFromWindow();
+        super.onDetachedFromWindowInternal();
     }
 
     @Override
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 47d42dc..96a2ab5 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -2135,15 +2135,15 @@
             mRecycler.markChildrenDirty();
         }
 
-        // TODO: Move somewhere sane. This doesn't belong in onLayout().
-        if (mFastScroll != null) {
-            mFastScroll.onItemCountChanged(childCount, mItemCount);
-        }
-
         layoutChildren();
         mInLayout = false;
 
         mOverscrollMax = (b - t) / OVERSCROLL_LIMIT_DIVISOR;
+
+        // TODO: Move somewhere sane. This doesn't belong in onLayout().
+        if (mFastScroll != null) {
+            mFastScroll.onItemCountChanged(getChildCount(), mItemCount);
+        }
     }
 
     /**
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 98b43b3..53d9e28 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -287,13 +287,12 @@
     }
 
     private void destroyDisplayListsData() {
-        HardwareRenderer renderer = mTextView.getHardwareRenderer();
         if (mTextDisplayLists != null) {
             for (int i = 0; i < mTextDisplayLists.length; i++) {
                 DisplayList displayList = mTextDisplayLists[i] != null
                         ? mTextDisplayLists[i].displayList : null;
                 if (displayList != null && displayList.isValid()) {
-                    displayList.destroyDisplayListData(renderer);
+                    displayList.destroyDisplayListData();
                 }
             }
         }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index e5cb16f..687036c 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -4729,10 +4729,9 @@
         if (mEditor != null) mEditor.onAttachedToWindow();
     }
 
+    /** @hide */
     @Override
-    protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-
+    protected void onDetachedFromWindowInternal() {
         if (mPreDrawRegistered) {
             getViewTreeObserver().removeOnPreDrawListener(this);
             mPreDrawRegistered = false;
@@ -4741,6 +4740,8 @@
         resetResolvedDrawables();
 
         if (mEditor != null) mEditor.onDetachedFromWindow();
+
+        super.onDetachedFromWindowInternal();
     }
 
     @Override
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index fd93604..db21906 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -87,7 +87,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 97 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 98 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS = 2000;
@@ -1712,7 +1712,7 @@
     static final int DELTA_STATE_FLAG           = 0x00100000;
     // Flag in delta int: a new full state2 int follows.
     static final int DELTA_STATE2_FLAG          = 0x00200000;
-    // Flag in delta int: contains a wakelock tag.
+    // Flag in delta int: contains a wakelock or wakeReason tag.
     static final int DELTA_WAKELOCK_FLAG        = 0x00400000;
     // Flag in delta int: contains an event description.
     static final int DELTA_EVENT_FLAG           = 0x00800000;
@@ -1759,7 +1759,7 @@
         if (stateIntChanged) {
             firstToken |= DELTA_STATE_FLAG;
         }
-        if (cur.wakelockTag != null) {
+        if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
             firstToken |= DELTA_WAKELOCK_FLAG;
         }
         if (cur.eventCode != HistoryItem.EVENT_NONE) {
@@ -1795,11 +1795,24 @@
                     + " batteryPlugType=" + cur.batteryPlugType
                     + " states=0x" + Integer.toHexString(cur.states));
         }
-        if (cur.wakelockTag != null) {
-            int index = writeHistoryTag(cur.wakelockTag);
-            dest.writeInt(index);
-            if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
-                + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
+        if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
+            int wakeLockIndex;
+            int wakeReasonIndex;
+            if (cur.wakelockTag != null) {
+                wakeLockIndex = writeHistoryTag(cur.wakelockTag);
+                if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
+                    + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
+            } else {
+                wakeLockIndex = 0xffff;
+            }
+            if (cur.wakeReasonTag != null) {
+                wakeReasonIndex = writeHistoryTag(cur.wakeReasonTag);
+                if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
+                    + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
+            } else {
+                wakeReasonIndex = 0xffff;
+            }
+            dest.writeInt((wakeReasonIndex<<16) | wakeLockIndex);
         }
         if (cur.eventCode != HistoryItem.EVENT_NONE) {
             int index = writeHistoryTag(cur.eventTag);
@@ -1905,14 +1918,29 @@
         }
 
         if ((firstToken&DELTA_WAKELOCK_FLAG) != 0) {
-            cur.wakelockTag = cur.localWakelockTag;
-            int index = src.readInt();
-            readHistoryTag(index, cur.wakelockTag);
+            int indexes = src.readInt();
+            int wakeLockIndex = indexes&0xffff;
+            int wakeReasonIndex = (indexes>>16)&0xffff;
+            if (wakeLockIndex != 0xffff) {
+                cur.wakelockTag = cur.localWakelockTag;
+                readHistoryTag(wakeLockIndex, cur.wakelockTag);
+                if (DEBUG) Slog.i(TAG, "READ DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
+                    + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
+            } else {
+                cur.wakelockTag = null;
+            }
+            if (wakeReasonIndex != 0xffff) {
+                cur.wakeReasonTag = cur.localWakeReasonTag;
+                readHistoryTag(wakeReasonIndex, cur.wakeReasonTag);
+                if (DEBUG) Slog.i(TAG, "READ DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
+                    + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
+            } else {
+                cur.wakeReasonTag = null;
+            }
             cur.numReadInts += 1;
-            if (DEBUG) Slog.i(TAG, "READ DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
-                + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
         } else {
             cur.wakelockTag = null;
+            cur.wakeReasonTag = null;
         }
 
         if ((firstToken&DELTA_EVENT_FLAG) != 0) {
@@ -1944,6 +1972,7 @@
         if (mHistoryBufferLastPos >= 0 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE
                 && timeDiff < 1000 && (diffStates&lastDiffStates) == 0
                 && (mHistoryLastWritten.wakelockTag == null || mHistoryCur.wakelockTag == null)
+                && (mHistoryLastWritten.wakeReasonTag == null || mHistoryCur.wakeReasonTag == null)
                 && (mHistoryLastWritten.eventCode == HistoryItem.EVENT_NONE
                         || mHistoryCur.eventCode == HistoryItem.EVENT_NONE)
                 && mHistoryLastWritten.batteryLevel == mHistoryCur.batteryLevel
@@ -1968,6 +1997,13 @@
                 mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
                 mHistoryCur.wakelockTag.setTo(mHistoryLastWritten.wakelockTag);
             }
+            // If the last written history had a wake reason tag, we need to retain it.
+            // Note that the condition above made sure that we aren't in a case where
+            // both it and the current history item have a wakelock tag.
+            if (mHistoryLastWritten.wakeReasonTag != null) {
+                mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
+                mHistoryCur.wakeReasonTag.setTo(mHistoryLastWritten.wakeReasonTag);
+            }
             // If the last written history had an event, we need to retain it.
             // Note that the condition above made sure that we aren't in a case where
             // both it and the current history item have an event.
@@ -2016,6 +2052,7 @@
         writeHistoryDelta(mHistoryBuffer, mHistoryLastWritten, mHistoryLastLastWritten);
         mLastHistoryTime = curTime;
         mHistoryCur.wakelockTag = null;
+        mHistoryCur.wakeReasonTag = null;
         mHistoryCur.eventCode = HistoryItem.EVENT_NONE;
         mHistoryCur.eventTag = null;
         if (DEBUG_HISTORY) Slog.i(TAG, "Writing history buffer: was " + mHistoryBufferLastPos
@@ -2304,6 +2341,16 @@
         }
     }
 
+    public void noteWakeupReasonLocked(int irq, String reason) {
+        final long elapsedRealtime = SystemClock.elapsedRealtime();
+        if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason irq #" + irq + "\"" + reason +"\": "
+                + Integer.toHexString(mHistoryCur.states));
+        mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
+        mHistoryCur.wakeReasonTag.string = reason;
+        mHistoryCur.wakeReasonTag.uid = irq;
+        addHistoryRecordLocked(elapsedRealtime);
+    }
+
     public int startAddingCpuLocked() {
         mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
 
@@ -7219,8 +7266,7 @@
         pullPendingStateUpdatesLocked();
     }
 
-    public void dumpLocked(Context context, PrintWriter pw, boolean isUnpluggedOnly, int reqUid,
-            boolean historyOnly) {
+    public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
         if (DEBUG) {
             pw.println("mOnBatteryTimeBase:");
             mOnBatteryTimeBase.dump(pw, "  ");
@@ -7264,6 +7310,6 @@
                 mBluetoothStateTimer[i].logState(pr, "  ");
             }
         }
-        super.dumpLocked(context, pw, isUnpluggedOnly, reqUid, historyOnly);
+        super.dumpLocked(context, pw, flags, reqUid, histStart);
     }
 }
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index 325a27d..e51345c 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -32,7 +32,9 @@
  * this file.
  */
 interface IInputMethodManager {
+    // TODO: Use ParceledListSlice instead
     List<InputMethodInfo> getInputMethodList();
+    // TODO: Use ParceledListSlice instead
     List<InputMethodInfo> getEnabledInputMethodList();
     List<InputMethodSubtype> getEnabledInputMethodSubtypeList(in String imiId,
             boolean allowsImplicitlySelectedSubtypes);
diff --git a/core/java/com/android/internal/view/RotationPolicy.java b/core/java/com/android/internal/view/RotationPolicy.java
index 9fefd00..b479cb1 100644
--- a/core/java/com/android/internal/view/RotationPolicy.java
+++ b/core/java/com/android/internal/view/RotationPolicy.java
@@ -58,7 +58,9 @@
         PackageManager pm = context.getPackageManager();
         return pm.hasSystemFeature(PackageManager.FEATURE_SENSOR_ACCELEROMETER)
                 && pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_PORTRAIT)
-                && pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_LANDSCAPE);
+                && pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_LANDSCAPE)
+                && context.getResources().getBoolean(
+                        com.android.internal.R.bool.config_supportAutoRotation);
     }
 
     /**
@@ -184,6 +186,7 @@
      */
     public static abstract class RotationPolicyListener {
         final ContentObserver mObserver = new ContentObserver(new Handler()) {
+            @Override
             public void onChange(boolean selfChange, Uri uri) {
                 RotationPolicyListener.this.onChange();
             }
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index f5c18f5..2d79491 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -35,7 +35,6 @@
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.Log;
-import android.util.Slog;
 import android.view.IWindowManager;
 import android.view.View;
 import android.widget.Button;
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index ee9c18d..e50c1d8 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -750,10 +750,11 @@
         mOptions.add(opt);
     }
 
-    // libart tolerates libdvm flags, but not vice versa, so only pass these if libart.
+    // libart tolerates libdvm flags, but not vice versa, so only pass some options if libart.
     property_get("persist.sys.dalvik.vm.lib.1", dalvikVmLibBuf, "libdvm.so");
-    if (strncmp(dalvikVmLibBuf, "libart", 6) == 0) {
+    bool libart = (strncmp(dalvikVmLibBuf, "libart", 6) == 0);
 
+    if (libart) {
         // Extra options for DexClassLoader.
         property_get("dalvik.vm.dex2oat-flags", dex2oatFlagsBuf, "");
         parseExtraOpts(dex2oatFlagsBuf, "-Xcompiler-option");
@@ -781,6 +782,49 @@
         mOptions.add(opt);
     }
 
+    /*
+     * Set profiler options
+     */
+    if (libart) {
+      char period[sizeof("-Xprofile-period:") + PROPERTY_VALUE_MAX];
+      char duration[sizeof("-Xprofile-duration:") + PROPERTY_VALUE_MAX];
+      char interval[sizeof("-Xprofile-interval:") + PROPERTY_VALUE_MAX];
+      char backoff[sizeof("-Xprofile-backoff:") + PROPERTY_VALUE_MAX];
+
+      // Number of seconds during profile runs.
+      strcpy(period, "-Xprofile-period:");
+      property_get("dalvik.vm.profile.period_secs", period+17, "10");
+      opt.optionString = period;
+      mOptions.add(opt);
+
+      // Length of each profile run (seconds).
+      strcpy(duration, "-Xprofile-duration:");
+      property_get("dalvik.vm.profile.duration_secs", duration+19, "30");
+      opt.optionString = duration;
+      mOptions.add(opt);
+
+
+      // Polling interval during profile run (microseconds).
+      strcpy(interval, "-Xprofile-interval:");
+      property_get("dalvik.vm.profile.interval_us", interval+19, "10000");
+      opt.optionString = interval;
+      mOptions.add(opt);
+
+      // Coefficient for period backoff.  The the period is multiplied
+      // by this value after each profile run.
+      strcpy(backoff, "-Xprofile-backoff:");
+      property_get("dalvik.vm.profile.backoff_coeff", backoff+18, "2.0");
+      opt.optionString = backoff;
+      mOptions.add(opt);
+    }
+
+    /*
+     * We don't have /tmp on the device, but we often have an SD card.  Apps
+     * shouldn't use this, but some test suites might want to exercise it.
+     */
+    opt.optionString = "-Djava.io.tmpdir=/sdcard";
+    mOptions.add(opt);
+
     initArgs.version = JNI_VERSION_1_4;
     initArgs.options = mOptions.editArray();
     initArgs.nOptions = mOptions.size();
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index e8feacb..fc587c0 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -107,17 +107,19 @@
     chunk->paddingRight = int(chunk->paddingRight * scale + 0.5f);
     chunk->paddingBottom = int(chunk->paddingBottom * scale + 0.5f);
 
+    int32_t* xDivs = chunk->getXDivs();
     for (int i = 0; i < chunk->numXDivs; i++) {
-        chunk->xDivs[i] = int(chunk->xDivs[i] * scale + 0.5f);
-        if (i > 0 && chunk->xDivs[i] == chunk->xDivs[i - 1]) {
-            chunk->xDivs[i]++;
+        xDivs[i] = int32_t(xDivs[i] * scale + 0.5f);
+        if (i > 0 && xDivs[i] == xDivs[i - 1]) {
+            xDivs[i]++;
         }
     }
 
+    int32_t* yDivs = chunk->getXDivs();
     for (int i = 0; i < chunk->numYDivs; i++) {
-        chunk->yDivs[i] = int(chunk->yDivs[i] * scale + 0.5f);
-        if (i > 0 && chunk->yDivs[i] == chunk->yDivs[i - 1]) {
-            chunk->yDivs[i]++;
+        yDivs[i] = int32_t(yDivs[i] * scale + 0.5f);
+        if (i > 0 && yDivs[i] == yDivs[i - 1]) {
+            yDivs[i]++;
         }
     }
 }
@@ -379,7 +381,7 @@
             return nullObjectReturn("primitive array == null");
         }
 
-        peeker.fPatch->serialize(array);
+        memcpy(array, peeker.fPatch, peeker.fPatchSize);
         env->ReleasePrimitiveArrayCritical(ninePatchChunk, array, 0);
     }
 
diff --git a/core/jni/android/graphics/NinePatchImpl.cpp b/core/jni/android/graphics/NinePatchImpl.cpp
index d43c1be..1793208 100644
--- a/core/jni/android/graphics/NinePatchImpl.cpp
+++ b/core/jni/android/graphics/NinePatchImpl.cpp
@@ -115,13 +115,15 @@
         defaultPaint.setDither(true);
         paint = &defaultPaint;
     }
-    
+   
+    const int32_t* xDivs = chunk.getXDivs();
+    const int32_t* yDivs = chunk.getYDivs();
     // if our SkCanvas were back by GL we should enable this and draw this as
     // a mesh, which will be faster in most cases.
     if (false) {
         SkNinePatch::DrawMesh(canvas, bounds, bitmap,
-                              chunk.xDivs, chunk.numXDivs,
-                              chunk.yDivs, chunk.numYDivs,
+                              xDivs, chunk.numXDivs,
+                              yDivs, chunk.numYDivs,
                               paint);
         return;
     }
@@ -145,8 +147,8 @@
     if (gTrace) {
         ALOGV("======== ninepatch bounds [%g %g]\n", SkScalarToFloat(bounds.width()), SkScalarToFloat(bounds.height()));
         ALOGV("======== ninepatch paint bm [%d,%d]\n", bitmap.width(), bitmap.height());
-        ALOGV("======== ninepatch xDivs [%d,%d]\n", chunk.xDivs[0], chunk.xDivs[1]);
-        ALOGV("======== ninepatch yDivs [%d,%d]\n", chunk.yDivs[0], chunk.yDivs[1]);
+        ALOGV("======== ninepatch xDivs [%d,%d]\n", xDivs[0], xDivs[1]);
+        ALOGV("======== ninepatch yDivs [%d,%d]\n", yDivs[0], yDivs[1]);
     }
 #endif
 
@@ -171,8 +173,8 @@
     SkRect      dst;
     SkIRect     src;
 
-    const int32_t x0 = chunk.xDivs[0];
-    const int32_t y0 = chunk.yDivs[0];
+    const int32_t x0 = xDivs[0];
+    const int32_t y0 = yDivs[0];
     const SkColor initColor = ((SkPaint*)paint)->getColor();
     const uint8_t numXDivs = chunk.numXDivs;
     const uint8_t numYDivs = chunk.numYDivs;
@@ -191,12 +193,12 @@
 
     int numStretchyXPixelsRemaining = 0;
     for (i = 0; i < numXDivs; i += 2) {
-        numStretchyXPixelsRemaining += chunk.xDivs[i + 1] - chunk.xDivs[i];
+        numStretchyXPixelsRemaining += xDivs[i + 1] - xDivs[i];
     }
     int numFixedXPixelsRemaining = bitmapWidth - numStretchyXPixelsRemaining;
     int numStretchyYPixelsRemaining = 0;
     for (i = 0; i < numYDivs; i += 2) {
-        numStretchyYPixelsRemaining += chunk.yDivs[i + 1] - chunk.yDivs[i];
+        numStretchyYPixelsRemaining += yDivs[i + 1] - yDivs[i];
     }
     int numFixedYPixelsRemaining = bitmapHeight - numStretchyYPixelsRemaining;
 
@@ -235,7 +237,7 @@
             src.fBottom = bitmapHeight;
             dst.fBottom = bounds.fBottom;
         } else {
-            src.fBottom = chunk.yDivs[j];
+            src.fBottom = yDivs[j];
             const int srcYSize = src.fBottom - src.fTop;
             if (yIsStretchable) {
                 dst.fBottom = dst.fTop + calculateStretch(bounds.fBottom, dst.fTop,
@@ -252,15 +254,16 @@
         xIsStretchable = initialXIsStretchable;
         // The initial xDiv and whether the first column is considered
         // stretchable or not depends on whether xDiv[0] was zero or not.
+        const uint32_t* colors = chunk.getColors();
         for (i = xIsStretchable ? 1 : 0;
               i <= numXDivs && src.fLeft < bitmapWidth;
               i++, xIsStretchable = !xIsStretchable) {
-            color = chunk.colors[colorIndex++];
+            color = colors[colorIndex++];
             if (i == numXDivs) {
                 src.fRight = bitmapWidth;
                 dst.fRight = bounds.fRight;
             } else {
-                src.fRight = chunk.xDivs[i];
+                src.fRight = xDivs[i];
                 if (dstRightsHaveBeenCached) {
                     dst.fRight = dstRights[i];
                 } else {
diff --git a/core/jni/android/graphics/NinePatchPeeker.cpp b/core/jni/android/graphics/NinePatchPeeker.cpp
index d3482da..5daa1ad 100644
--- a/core/jni/android/graphics/NinePatchPeeker.cpp
+++ b/core/jni/android/graphics/NinePatchPeeker.cpp
@@ -28,11 +28,11 @@
         // You have to copy the data because it is owned by the png reader
         Res_png_9patch* patchNew = (Res_png_9patch*) malloc(patchSize);
         memcpy(patchNew, patch, patchSize);
-        // this relies on deserialization being done in place
         Res_png_9patch::deserialize(patchNew);
         patchNew->fileToDevice();
         free(fPatch);
         fPatch = patchNew;
+        fPatchSize = patchSize;
         //printf("9patch: (%d,%d)-(%d,%d)\n",
         //       fPatch.sizeLeft, fPatch.sizeTop,
         //       fPatch.sizeRight, fPatch.sizeBottom);
diff --git a/core/jni/android/graphics/NinePatchPeeker.h b/core/jni/android/graphics/NinePatchPeeker.h
index 10d268a..2043862 100644
--- a/core/jni/android/graphics/NinePatchPeeker.h
+++ b/core/jni/android/graphics/NinePatchPeeker.h
@@ -29,6 +29,7 @@
         // the host lives longer than we do, so a raw ptr is safe
         fHost = host;
         fPatch = NULL;
+        fPatchSize = 0;
         fLayoutBounds = NULL;
     }
 
@@ -38,6 +39,7 @@
     }
 
     Res_png_9patch*  fPatch;
+    size_t fPatchSize;
     int    *fLayoutBounds;
 
     virtual bool peek(const char tag[], const void* data, size_t length);
diff --git a/core/jni/android_view_GLRenderer.cpp b/core/jni/android_view_GLRenderer.cpp
index 5ea8460..b7e795e 100644
--- a/core/jni/android_view_GLRenderer.cpp
+++ b/core/jni/android_view_GLRenderer.cpp
@@ -140,7 +140,7 @@
     LayerRenderer::destroyLayer(layer);
 }
 
-static void android_view_GLRenderer_swapDisplayListData(JNIEnv* env, jobject clazz,
+static void android_view_GLRenderer_setDisplayListData(JNIEnv* env, jobject clazz,
         jlong displayListPtr, jlong newDataPtr) {
     using namespace android::uirenderer;
     DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListPtr);
@@ -178,7 +178,7 @@
 
     { "getSystemTime",         "()J",   (void*) android_view_GLRenderer_getSystemTime },
     { "nDestroyLayer",         "(J)V",  (void*) android_view_GLRenderer_destroyLayer },
-    { "nSwapDisplayListData",  "(JJ)V", (void*) android_view_GLRenderer_swapDisplayListData },
+    { "nSetDisplayListData",  "(JJ)V", (void*) android_view_GLRenderer_setDisplayListData },
 #endif
 
     { "setupShadersDiskCache", "(Ljava/lang/String;)V",
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 444c8be..2b20758 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -103,12 +103,12 @@
     proxy->setup(width, height);
 }
 
-static void android_view_ThreadedRenderer_swapDisplayListData(JNIEnv* env, jobject clazz,
+static void android_view_ThreadedRenderer_setDisplayListData(JNIEnv* env, jobject clazz,
         jlong proxyPtr, jlong displayListPtr, jlong newDataPtr) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
     DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListPtr);
     DisplayListData* newData = reinterpret_cast<DisplayListData*>(newDataPtr);
-    proxy->swapDisplayListData(displayList, newData);
+    proxy->setDisplayListData(displayList, newData);
 }
 
 static void android_view_ThreadedRenderer_drawDisplayList(JNIEnv* env, jobject clazz,
@@ -191,7 +191,7 @@
     { "nInitialize", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_initialize },
     { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
     { "nSetup", "(JII)V", (void*) android_view_ThreadedRenderer_setup },
-    { "nSwapDisplayListData", "(JJJ)V", (void*) android_view_ThreadedRenderer_swapDisplayListData },
+    { "nSetDisplayListData", "(JJJ)V", (void*) android_view_ThreadedRenderer_setDisplayListData },
     { "nDrawDisplayList", "(JJIIII)V", (void*) android_view_ThreadedRenderer_drawDisplayList },
     { "nDestroyCanvas", "(J)V", (void*) android_view_ThreadedRenderer_destroyCanvas },
     { "nAttachFunctor", "(JJ)V", (void*) android_view_ThreadedRenderer_attachFunctor },
diff --git a/core/res/res/drawable/notification_quantum_background.xml b/core/res/res/drawable/notification_quantum_background.xml
new file mode 100644
index 0000000..f33e2e3
--- /dev/null
+++ b/core/res/res/drawable/notification_quantum_background.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="#ffffffff" />
+    <corners android:radius="2dp" />
+</shape>
\ No newline at end of file
diff --git a/core/res/res/drawable/notification_quantum_bg.xml b/core/res/res/drawable/notification_quantum_bg.xml
new file mode 100644
index 0000000..608115e
--- /dev/null
+++ b/core/res/res/drawable/notification_quantum_bg.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true"  android:drawable="@drawable/notification_quantum_press" />
+    <item android:state_pressed="false" android:drawable="@drawable/notification_quantum_background" />
+</selector>
\ No newline at end of file
diff --git a/core/res/res/drawable/notification_quantum_press.xml b/core/res/res/drawable/notification_quantum_press.xml
new file mode 100644
index 0000000..4999f55
--- /dev/null
+++ b/core/res/res/drawable/notification_quantum_press.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="#ffcccccc" />
+    <corners android:radius="2dp" />
+</shape>
\ No newline at end of file
diff --git a/core/res/res/layout/notification_quantum_action.xml b/core/res/res/layout/notification_quantum_action.xml
new file mode 100644
index 0000000..775182f
--- /dev/null
+++ b/core/res/res/layout/notification_quantum_action.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<Button xmlns:android="http://schemas.android.com/apk/res/android"
+    style="?android:attr/borderlessButtonStyle" 
+    android:id="@+id/action0"
+    android:layout_width="0dp"
+    android:layout_height="48dp"
+    android:layout_weight="1"
+    android:gravity="start|center_vertical"
+    android:drawablePadding="8dp"
+    android:paddingStart="8dp"
+    android:textColor="#555555"
+    android:textSize="14dp"
+    android:singleLine="true"
+    android:ellipsize="end"
+    />
diff --git a/core/res/res/layout/notification_quantum_action_list.xml b/core/res/res/layout/notification_quantum_action_list.xml
new file mode 100644
index 0000000..a8aef97
--- /dev/null
+++ b/core/res/res/layout/notification_quantum_action_list.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/actions"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal"
+    android:visibility="gone"
+    android:layout_marginBottom="8dp"
+    android:showDividers="middle"
+    android:divider="?android:attr/listDivider"
+    android:dividerPadding="12dp"
+    >
+    <!-- actions will be added here -->
+</LinearLayout>
diff --git a/core/res/res/layout/notification_quantum_action_tombstone.xml b/core/res/res/layout/notification_quantum_action_tombstone.xml
new file mode 100644
index 0000000..9104991
--- /dev/null
+++ b/core/res/res/layout/notification_quantum_action_tombstone.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<Button xmlns:android="http://schemas.android.com/apk/res/android"
+    style="?android:attr/borderlessButtonStyle" 
+    android:id="@+id/action0"
+    android:layout_width="0dp"
+    android:layout_height="48dp"
+    android:layout_weight="1"
+    android:gravity="start|center_vertical"
+    android:drawablePadding="8dp"
+    android:paddingStart="8dp"
+    android:textColor="#555555"
+    android:textSize="14dp"
+    android:singleLine="true"
+    android:ellipsize="end"
+    android:alpha="0.5"
+    android:enabled="false"
+    />
diff --git a/core/res/res/layout/notification_template_quantum_base.xml b/core/res/res/layout/notification_template_quantum_base.xml
new file mode 100644
index 0000000..3e97b2a
--- /dev/null
+++ b/core/res/res/layout/notification_template_quantum_base.xml
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
+    android:background="@android:drawable/notification_quantum_bg"
+    android:id="@+id/status_bar_latest_event_content"
+    android:layout_width="match_parent"
+    android:layout_height="64dp"
+    internal:layout_minHeight="64dp"
+    internal:layout_maxHeight="64dp"
+    >
+    <ImageView android:id="@+id/icon"
+        android:layout_width="@dimen/notification_large_icon_width"
+        android:layout_height="@dimen/notification_large_icon_height"
+        android:scaleType="center"
+        />
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+
+        android:layout_gravity="fill_vertical"
+        android:layout_marginStart="@dimen/notification_large_icon_width"
+        android:minHeight="@dimen/notification_large_icon_height"
+        android:orientation="vertical"
+        android:paddingEnd="8dp"
+        android:paddingTop="2dp"
+        android:paddingBottom="2dp"
+        android:gravity="top"
+        >
+        <LinearLayout
+            android:id="@+id/line1"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingTop="6dp"
+            android:layout_marginStart="8dp"
+            android:orientation="horizontal"
+            >
+            <TextView android:id="@+id/title"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Title"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:singleLine="true"
+                android:ellipsize="marquee"
+                android:fadingEdge="horizontal"
+                android:layout_weight="1"
+                />
+            <ViewStub android:id="@+id/time"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="0"
+                android:visibility="gone"
+                android:layout="@layout/notification_template_part_time"
+                />
+            <ViewStub android:id="@+id/chronometer"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="0"
+                android:visibility="gone"
+                android:layout="@layout/notification_template_part_chronometer"
+                />
+        </LinearLayout>
+        <TextView android:id="@+id/text2"
+            android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Line2"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="-2dp"
+            android:layout_marginBottom="-2dp"
+            android:layout_marginStart="8dp"
+            android:singleLine="true"
+            android:fadingEdge="horizontal"
+            android:ellipsize="marquee"
+            android:visibility="gone"
+            />
+        <ProgressBar
+            android:id="@android:id/progress"
+            android:layout_width="match_parent"
+            android:layout_height="12dp"
+            android:layout_marginStart="8dp"
+            android:visibility="gone"
+            style="?android:attr/progressBarStyleHorizontal"
+            />
+        <LinearLayout
+            android:id="@+id/line3"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            android:gravity="center_vertical"
+            android:layout_marginStart="8dp"
+            >
+            <TextView android:id="@+id/text"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:layout_gravity="center"
+                android:singleLine="true"
+                android:ellipsize="marquee"
+                android:fadingEdge="horizontal"
+                />
+            <TextView android:id="@+id/info"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Info"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:layout_weight="0"
+                android:singleLine="true"
+                android:gravity="center"
+                android:paddingStart="8dp"
+                />
+            <ImageView android:id="@+id/right_icon"
+                android:layout_width="16dp"
+                android:layout_height="16dp"
+                android:layout_gravity="center"
+                android:layout_weight="0"
+                android:layout_marginStart="8dp"
+                android:scaleType="centerInside"
+                android:visibility="gone"
+                android:drawableAlpha="153"
+                />
+        </LinearLayout>
+    </LinearLayout>
+</FrameLayout>
diff --git a/core/res/res/layout/notification_template_quantum_big_base.xml b/core/res/res/layout/notification_template_quantum_big_base.xml
new file mode 100644
index 0000000..d860045
--- /dev/null
+++ b/core/res/res/layout/notification_template_quantum_big_base.xml
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
+    android:background="@android:drawable/notification_quantum_bg"
+    android:id="@+id/status_bar_latest_event_content"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    internal:layout_minHeight="65dp"
+    internal:layout_maxHeight="unbounded"
+    >
+    <ImageView android:id="@+id/icon"
+        android:layout_width="@dimen/notification_large_icon_width"
+        android:layout_height="@dimen/notification_large_icon_height"
+        android:scaleType="center"
+        />
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="fill_vertical"
+        android:minHeight="@dimen/notification_large_icon_height"
+        android:orientation="vertical"
+        android:gravity="top"
+        >
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="@dimen/notification_large_icon_width"
+            android:minHeight="@dimen/notification_large_icon_height"
+            android:paddingTop="2dp"
+            android:orientation="vertical"
+            >
+            <LinearLayout
+                android:id="@+id/line1"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:paddingTop="6dp"
+                android:layout_marginEnd="8dp"
+                android:layout_marginStart="8dp"
+                android:orientation="horizontal"
+                >
+                <TextView android:id="@+id/title"
+                    android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Title"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:singleLine="true"
+                    android:ellipsize="marquee"
+                    android:fadingEdge="horizontal"
+                    android:layout_weight="1"
+                    />
+                <ViewStub android:id="@+id/time"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="0"
+                    android:visibility="gone"
+                    android:layout="@layout/notification_template_part_time"
+                    />
+                <ViewStub android:id="@+id/chronometer"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="0"
+                    android:visibility="gone"
+                    android:layout="@layout/notification_template_part_chronometer"
+                    />
+            </LinearLayout>
+            <TextView android:id="@+id/text2"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Line2"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="-2dp"
+                android:layout_marginBottom="-2dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:fadingEdge="horizontal"
+                android:ellipsize="marquee"
+                android:visibility="gone"
+                />
+            <TextView android:id="@+id/big_text"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="false"
+                android:visibility="gone"
+                />
+            <LinearLayout
+                android:id="@+id/line3"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:orientation="horizontal"
+                android:gravity="center_vertical"
+                >
+                <TextView android:id="@+id/text"
+                    android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1"
+                    android:layout_gravity="center"
+                    android:singleLine="true"
+                    android:ellipsize="marquee"
+                    android:fadingEdge="horizontal"
+                    />
+                <TextView android:id="@+id/info"
+                    android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Info"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center"
+                    android:layout_weight="0"
+                    android:singleLine="true"
+                    android:gravity="center"
+                    android:paddingStart="8dp"
+                    />
+                <ImageView android:id="@+id/right_icon"
+                    android:layout_width="16dp"
+                    android:layout_height="16dp"
+                    android:layout_gravity="center"
+                    android:layout_weight="0"
+                    android:layout_marginStart="8dp"
+                    android:scaleType="centerInside"
+                    android:visibility="gone"
+                    android:drawableAlpha="153"
+                    />
+            </LinearLayout>
+            <ProgressBar
+                android:id="@android:id/progress"
+                android:layout_width="match_parent"
+                android:layout_height="12dp"
+                android:layout_marginBottom="8dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:visibility="gone"
+                style="?android:attr/progressBarStyleHorizontal"
+                />
+        </LinearLayout>
+        <ImageView
+            android:layout_width="match_parent"
+            android:layout_height="1dp"
+            android:id="@+id/action_divider"
+            android:visibility="gone"
+            android:background="?android:attr/dividerHorizontal" />
+        <include
+            layout="@layout/notification_quantum_action_list"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="@dimen/notification_large_icon_width"
+            />
+    </LinearLayout>
+</FrameLayout>
diff --git a/core/res/res/layout/notification_template_quantum_big_picture.xml b/core/res/res/layout/notification_template_quantum_big_picture.xml
new file mode 100644
index 0000000..e49c3bd
--- /dev/null
+++ b/core/res/res/layout/notification_template_quantum_big_picture.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
+    android:background="@android:drawable/notification_quantum_bg"
+    android:id="@+id/status_bar_latest_event_content"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    internal:layout_minHeight="65dp"
+    internal:layout_maxHeight="unbounded"
+    >
+    <ImageView
+        android:id="@+id/big_picture"
+        android:layout_width="match_parent"
+        android:layout_height="192dp"
+        android:layout_marginTop="64dp"
+        android:layout_gravity="bottom"
+        android:scaleType="centerCrop"
+        />
+    <ImageView
+        android:layout_width="match_parent"
+        android:layout_height="6dp"
+        android:layout_marginTop="64dp"
+        android:scaleType="fitXY"
+        android:src="@drawable/title_bar_shadow"
+        />
+    <include layout="@layout/notification_template_quantum_base"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        />
+  <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="208dp"
+        android:paddingStart="64dp"
+        android:layout_gravity="bottom"
+        android:background="#CCEEEEEE"
+        >
+        <include
+            layout="@layout/notification_quantum_action_list"
+            android:id="@+id/actions"
+            android:layout_gravity="bottom"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            />
+    </FrameLayout>
+</FrameLayout>
diff --git a/core/res/res/layout/notification_template_quantum_big_text.xml b/core/res/res/layout/notification_template_quantum_big_text.xml
new file mode 100644
index 0000000..585be80
--- /dev/null
+++ b/core/res/res/layout/notification_template_quantum_big_text.xml
@@ -0,0 +1,182 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
+    android:background="@android:drawable/notification_quantum_bg"
+    android:id="@+id/status_bar_latest_event_content"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    internal:layout_minHeight="65dp"
+    internal:layout_maxHeight="unbounded"
+    >
+    <ImageView android:id="@+id/icon"
+        android:layout_width="@dimen/notification_large_icon_width"
+        android:layout_height="@dimen/notification_large_icon_height"
+        android:scaleType="center"
+        />
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="fill_vertical"
+        android:layout_marginStart="@dimen/notification_large_icon_width"
+        android:orientation="vertical"
+        android:paddingTop="0dp"
+        android:paddingBottom="2dp"
+        android:gravity="top"
+        >
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:minHeight="@dimen/notification_large_icon_height"
+            android:orientation="vertical"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
+            android:layout_weight="1"
+            >
+            <LinearLayout
+                android:id="@+id/line1"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:paddingTop="8dp"
+                android:orientation="horizontal"
+                android:layout_gravity="top"
+                android:layout_weight="0"
+                >
+                <TextView android:id="@+id/title"
+                    android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Title"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:singleLine="true"
+                    android:ellipsize="marquee"
+                    android:fadingEdge="horizontal"
+                    android:layout_weight="1"
+                    />
+                <ViewStub android:id="@+id/time"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="0"
+                    android:visibility="gone"
+                    android:layout="@layout/notification_template_part_time"
+                    />
+                <ViewStub android:id="@+id/chronometer"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="0"
+                    android:visibility="gone"
+                    android:layout="@layout/notification_template_part_chronometer"
+                    />
+            </LinearLayout>
+            <TextView android:id="@+id/text2"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Line2"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="-2dp"
+                android:layout_marginBottom="-2dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:fadingEdge="horizontal"
+                android:ellipsize="marquee"
+                android:layout_weight="0"
+                android:visibility="gone"
+                />
+            <ProgressBar
+                android:id="@android:id/progress"
+                android:layout_width="match_parent"
+                android:layout_height="12dp"
+                android:layout_marginBottom="8dp"
+                android:layout_marginEnd="8dp"
+                android:visibility="gone"
+                android:layout_weight="0"
+                style="?android:attr/progressBarStyleHorizontal"
+                />
+            <TextView android:id="@+id/big_text"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginBottom="10dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="false"
+                android:visibility="gone"
+                android:maxLines="8"
+                android:ellipsize="end"
+                android:layout_weight="1"
+                />
+        </LinearLayout>
+        <ImageView
+            android:layout_width="match_parent"
+            android:layout_height="1dip"
+            android:id="@+id/action_divider"
+            android:visibility="gone"
+            android:background="?android:attr/dividerHorizontal" />
+        <include
+            layout="@layout/notification_quantum_action_list"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:visibility="gone"
+            android:layout_weight="1"
+            />
+        <ImageView
+            android:layout_width="match_parent"
+            android:layout_height="1dp"
+            android:id="@+id/overflow_divider"
+            android:layout_marginBottom="8dp"
+            android:visibility="visible"
+            android:background="?android:attr/dividerHorizontal" />
+        <LinearLayout
+            android:id="@+id/line3"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="8dp"
+            android:layout_marginBottom="8dp"
+            android:layout_marginEnd="8dp"
+            android:orientation="horizontal"
+            android:layout_weight="0"
+            android:gravity="center_vertical"
+            >
+            <TextView android:id="@+id/text"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:layout_gravity="center"
+                android:singleLine="true"
+                android:ellipsize="marquee"
+                android:fadingEdge="horizontal"
+                />
+            <TextView android:id="@+id/info"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Info"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:layout_weight="0"
+                android:singleLine="true"
+                android:gravity="center"
+                android:paddingStart="8dp"
+                />
+            <ImageView android:id="@+id/right_icon"
+                android:layout_width="16dp"
+                android:layout_height="16dp"
+                android:layout_gravity="center"
+                android:layout_weight="0"
+                android:layout_marginStart="8dp"
+                android:scaleType="centerInside"
+                android:visibility="gone"
+                android:drawableAlpha="153"
+                />
+        </LinearLayout>
+    </LinearLayout>
+</FrameLayout>
diff --git a/core/res/res/layout/notification_template_quantum_inbox.xml b/core/res/res/layout/notification_template_quantum_inbox.xml
new file mode 100644
index 0000000..31ed508
--- /dev/null
+++ b/core/res/res/layout/notification_template_quantum_inbox.xml
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
+    android:id="@+id/status_bar_latest_event_content"
+    android:background="@android:drawable/notification_quantum_bg"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    internal:layout_minHeight="65dp"
+    internal:layout_maxHeight="unbounded"
+    >
+    <ImageView android:id="@+id/icon"
+        android:layout_width="@dimen/notification_large_icon_width"
+        android:layout_height="@dimen/notification_large_icon_height"
+        android:scaleType="center"
+        />
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="fill_vertical"
+        android:layout_marginStart="@dimen/notification_large_icon_width"
+        android:minHeight="@dimen/notification_large_icon_height"
+        android:orientation="vertical"
+        android:paddingTop="0dp"
+        android:paddingBottom="2dp"
+        android:gravity="top"
+        >
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:minHeight="@dimen/notification_large_icon_height"
+            android:paddingTop="2dp"
+            android:orientation="vertical"
+            >
+            <LinearLayout
+                android:id="@+id/line1"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:paddingTop="6dp"
+                android:orientation="horizontal"
+                android:layout_weight="0"
+                >
+                <TextView android:id="@+id/title"
+                    android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Title"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:singleLine="true"
+                    android:ellipsize="marquee"
+                    android:fadingEdge="horizontal"
+                    android:layout_weight="1"
+                    />
+                <ViewStub android:id="@+id/time"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="0"
+                    android:visibility="gone"
+                    android:layout="@layout/notification_template_part_time"
+                    />
+                <ViewStub android:id="@+id/chronometer"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="0"
+                    android:visibility="gone"
+                    android:layout="@layout/notification_template_part_chronometer"
+                    />
+            </LinearLayout>
+            <TextView android:id="@+id/text2"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Line2"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="-2dp"
+                android:layout_marginBottom="-2dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:fadingEdge="horizontal"
+                android:ellipsize="marquee"
+                android:visibility="gone"
+                android:layout_weight="0"
+                />
+            <ProgressBar
+                android:id="@android:id/progress"
+                android:layout_width="match_parent"
+                android:layout_height="12dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:visibility="gone"
+                android:layout_weight="0"
+                style="?android:attr/progressBarStyleHorizontal"
+                />
+            <TextView android:id="@+id/inbox_text0"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                />
+            <TextView android:id="@+id/inbox_text1"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                />
+            <TextView android:id="@+id/inbox_text2"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                />
+            <TextView android:id="@+id/inbox_text3"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                />
+            <TextView android:id="@+id/inbox_text4"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                />
+            <TextView android:id="@+id/inbox_text5"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                />
+            <TextView android:id="@+id/inbox_text6"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                />
+            <TextView android:id="@+id/inbox_more"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                android:text="@android:string/ellipsis"
+                />
+            <FrameLayout
+                android:id="@+id/inbox_end_pad"
+                android:layout_width="match_parent"
+                android:layout_height="8dip"
+                android:visibility="gone"
+                android:layout_weight="0"
+            />
+        </LinearLayout>
+        <ImageView
+            android:layout_width="match_parent"
+            android:layout_height="1dip"
+            android:id="@+id/action_divider"
+            android:visibility="gone"
+            android:background="?android:attr/dividerHorizontal" />
+        <include
+            layout="@layout/notification_quantum_action_list"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_weight="0"
+            />
+        <ImageView
+            android:layout_width="match_parent"
+            android:layout_height="1dip"
+            android:id="@+id/overflow_divider"
+            android:visibility="visible"
+            android:background="?android:attr/dividerHorizontal" />
+        <LinearLayout
+            android:id="@+id/line3"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="8dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginBottom="8dp"
+            android:layout_marginEnd="8dp"
+            android:orientation="horizontal"
+            android:layout_weight="0"
+            android:gravity="center_vertical"
+            >
+            <TextView android:id="@+id/text"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:layout_gravity="center"
+                android:singleLine="true"
+                android:ellipsize="marquee"
+                android:fadingEdge="horizontal"
+                />
+            <TextView android:id="@+id/info"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Info"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:layout_weight="0"
+                android:singleLine="true"
+                android:gravity="center"
+                android:paddingStart="8dp"
+                />
+            <ImageView android:id="@+id/right_icon"
+                android:layout_width="16dp"
+                android:layout_height="16dp"
+                android:layout_gravity="center"
+                android:layout_weight="0"
+                android:layout_marginStart="8dp"
+                android:scaleType="centerInside"
+                android:visibility="gone"
+                android:drawableAlpha="153"
+                />
+        </LinearLayout>
+    </LinearLayout>
+</FrameLayout>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index a78ce02..f85b193 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1596,6 +1596,8 @@
         <enum name="KEYCODE_BRIGHTNESS_DOWN" value="220" />
         <enum name="KEYCODE_BRIGHTNESS_UP" value="221" />
         <enum name="KEYCODE_MEDIA_AUDIO_TRACK" value="222" />
+        <enum name="KEYCODE_MEDIA_SLEEP" value="223" />
+        <enum name="KEYCODE_MEDIA_WAKEUP" value="224" />
     </attr>
 
     <!-- ***************************************************************** -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 8d68277..cfd4a63 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -370,6 +370,17 @@
     <!-- If this is true, key chords can be used to take a screenshot on the device. -->
     <bool name="config_enableScreenshotChord">true</bool>
 
+    <!-- Auto-rotation behavior -->
+
+    <!-- If true, enables auto-rotation features using the accelerometer.
+         Otherwise, auto-rotation is disabled.  Applications may still request
+         to use specific orientations but the sensor is ignored and sensor-based
+         orientations are not available.  Furthermore, all auto-rotation related
+         settings are omitted from the system UI.  In certain situations we may
+         still use the accelerometer to determine the orientation, such as when
+         docked if the dock is configured to enable the accelerometer. -->
+    <bool name="config_supportAutoRotation">true</bool>
+
     <!-- If true, the screen can be rotated via the accelerometer in all 4
          rotations as the default behavior. -->
     <bool name="config_allowAllRotations">false</bool>
@@ -382,57 +393,12 @@
          true here reverses that logic. -->
     <bool name="config_reverseDefaultRotation">false</bool>
 
+    <!-- Lid switch behavior -->
+
     <!-- The number of degrees to rotate the display when the keyboard is open.
          A value of -1 means no change in orientation by default. -->
     <integer name="config_lidOpenRotation">-1</integer>
 
-    <!-- The number of degrees to rotate the display when the device is in a desk dock.
-         A value of -1 means no change in orientation by default. -->
-    <integer name="config_deskDockRotation">-1</integer>
-
-    <!-- The number of degrees to rotate the display when the device is in a car dock.
-         A value of -1 means no change in orientation by default. -->
-    <integer name="config_carDockRotation">-1</integer>
-
-    <!-- The number of degrees to rotate the display when the device has HDMI connected
-         but is not in a dock.  A value of -1 means no change in orientation by default.
-         Use -1 except on older devices whose Hardware Composer HAL does not
-         provide full support for multiple displays.  -->
-    <integer name="config_undockedHdmiRotation">-1</integer>
-
-    <!-- Control the default UI mode type to use when there is no other type override
-         happening.  One of the following values (See Configuration.java):
-             1  UI_MODE_TYPE_NORMAL
-             4  UI_MODE_TYPE_TELEVISION
-             5  UI_MODE_TYPE_APPLIANCE
-         Any other values will have surprising consequences. -->
-    <integer name="config_defaultUiModeType">1</integer>
-
-    <!-- Control whether being in the desk dock (and powered) always
-         keeps the screen on.  By default it stays on when plugged in to
-         AC.  0 will not keep it on; or together 1 to stay on when plugged
-         in to AC and 2 to stay on when plugged in to USB.  (So 3 for both.) -->
-    <integer name="config_deskDockKeepsScreenOn">1</integer>
-
-    <!-- Control whether being in the car dock (and powered) always
-         keeps the screen on.  By default it stays on when plugged in to
-         AC.  0 will not keep it on; or together 1 to stay on when plugged
-         in to AC and 2 to stay on when plugged in to USB.  (So 3 for both.) -->
-    <integer name="config_carDockKeepsScreenOn">1</integer>
-
-    <!-- Control whether being in the desk dock should enable accelerometer
-         based screen orientation.  This defaults to true because it is
-         common for desk docks to be sold in a variety of form factors
-         with different orientations.  Since we cannot always tell these docks
-         apart and the docks cannot report their true orientation on their own,
-         we rely on gravity to determine the effective orientation. -->
-    <bool name="config_deskDockEnablesAccelerometer">true</bool>
-
-    <!-- Control whether being in the car dock should enable accelerometer based
-         screen orientation.  This defaults to true because putting a device in
-         a car dock make the accelerometer more a physical input (like a lid). -->
-    <bool name="config_carDockEnablesAccelerometer">true</bool>
-
     <!-- Indicate whether the lid state impacts the accessibility of
          the physical keyboard.  0 means it doesn't, 1 means it is accessible
          when the lid is open, 2 means it is accessible when the lid is
@@ -450,6 +416,60 @@
          The default is false. -->
     <bool name="config_lidControlsSleep">false</bool>
 
+    <!-- Desk dock behavior -->
+
+    <!-- The number of degrees to rotate the display when the device is in a desk dock.
+         A value of -1 means no change in orientation by default. -->
+    <integer name="config_deskDockRotation">-1</integer>
+
+    <!-- Control whether being in the desk dock (and powered) always
+         keeps the screen on.  By default it stays on when plugged in to
+         AC.  0 will not keep it on; or together 1 to stay on when plugged
+         in to AC and 2 to stay on when plugged in to USB.  (So 3 for both.) -->
+    <integer name="config_deskDockKeepsScreenOn">1</integer>
+
+    <!-- Control whether being in the desk dock should enable accelerometer
+         based screen orientation.  This defaults to true because it is
+         common for desk docks to be sold in a variety of form factors
+         with different orientations.  Since we cannot always tell these docks
+         apart and the docks cannot report their true orientation on their own,
+         we rely on gravity to determine the effective orientation. -->
+    <bool name="config_deskDockEnablesAccelerometer">true</bool>
+
+    <!-- Car dock behavior -->
+
+    <!-- The number of degrees to rotate the display when the device is in a car dock.
+         A value of -1 means no change in orientation by default. -->
+    <integer name="config_carDockRotation">-1</integer>
+
+    <!-- Control whether being in the car dock (and powered) always
+         keeps the screen on.  By default it stays on when plugged in to
+         AC.  0 will not keep it on; or together 1 to stay on when plugged
+         in to AC and 2 to stay on when plugged in to USB.  (So 3 for both.) -->
+    <integer name="config_carDockKeepsScreenOn">1</integer>
+
+    <!-- Control whether being in the car dock should enable accelerometer based
+         screen orientation.  This defaults to true because putting a device in
+         a car dock make the accelerometer more a physical input (like a lid). -->
+
+    <bool name="config_carDockEnablesAccelerometer">true</bool>
+
+    <!-- HDMI behavior -->
+
+    <!-- The number of degrees to rotate the display when the device has HDMI connected
+         but is not in a dock.  A value of -1 means no change in orientation by default.
+         Use -1 except on older devices whose Hardware Composer HAL does not
+         provide full support for multiple displays.  -->
+    <integer name="config_undockedHdmiRotation">-1</integer>
+
+    <!-- Control the default UI mode type to use when there is no other type override
+         happening.  One of the following values (See Configuration.java):
+             1  UI_MODE_TYPE_NORMAL
+             4  UI_MODE_TYPE_TELEVISION
+             5  UI_MODE_TYPE_APPLIANCE
+         Any other values will have surprising consequences. -->
+    <integer name="config_defaultUiModeType">1</integer>
+
     <!-- Indicate whether to allow the device to suspend when the screen is off
          due to the proximity sensor.  This resource should only be set to true
          if the sensor HAL correctly handles the proximity sensor as a wake-up source.
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 3106daa..3ab3e5d 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2098,7 +2098,6 @@
   <public type="attr" name="windowContentTransitionManager" />
   <public type="attr" name="translationZ" />
   <public type="attr" name="tintMode" />
-  <public type="attr" name="isolatedZVolume" />
   <public type="attr" name="controlX1" />
   <public type="attr" name="controlY1" />
   <public type="attr" name="controlX2" />
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index e525ef7..be875ff 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -271,6 +271,33 @@
         <item name="android:textColor">#CCCCCC</item>
     </style>
 
+    <style name="TextAppearance.StatusBar.Quantum">
+    </style>
+    <style name="TextAppearance.StatusBar.Quantum.EventContent">
+        <item name="android:textColor">#888888</item>
+        <item name="android:textSize">@dimen/notification_text_size</item>
+    </style>
+    <style name="TextAppearance.StatusBar.Quantum.EventContent.Title">
+        <item name="android:textColor">#000000</item>
+        <item name="android:fontFamily">sans-serif-light</item>
+        <item name="android:textSize">@dimen/notification_title_text_size</item>
+        <item name="android:textStyle">bold</item>
+    </style>
+    <style name="TextAppearance.StatusBar.Quantum.EventContent.Line2">
+        <item name="android:textSize">@dimen/notification_subtext_size</item>
+    </style>
+    <style name="TextAppearance.StatusBar.Quantum.EventContent.Info">
+        <item name="android:textSize">@dimen/notification_subtext_size</item>
+        <item name="android:textColor">#888888</item>
+    </style>
+    <style name="TextAppearance.StatusBar.Quantum.EventContent.Time">
+        <item name="android:textSize">@dimen/notification_subtext_size</item>
+        <item name="android:textColor">#888888</item>
+    </style>
+    <style name="TextAppearance.StatusBar.Quantum.EventContent.Emphasis">
+        <item name="android:textColor">#555555</item>
+    </style>
+
     <style name="TextAppearance.Small.CalendarViewWeekDayView">
         <item name="android:textStyle">bold</item>
     </style>
diff --git a/core/res/res/values/styles_micro.xml b/core/res/res/values/styles_micro.xml
index c35bd48..52d90bc 100644
--- a/core/res/res/values/styles_micro.xml
+++ b/core/res/res/values/styles_micro.xml
@@ -25,7 +25,7 @@
         <item name="android:solidColor">@android:color/transparent</item>
         <item name="android:selectionDivider">@android:drawable/numberpicker_selection_divider</item>
         <item name="android:selectionDividerHeight">0dip</item>
-        <item name="android:selectionDividersDistance">0dip</item>
+        <item name="android:selectionDividersDistance">104dip</item>
         <item name="android:internalMinWidth">64dip</item>
         <item name="android:internalMaxHeight">180dip</item>
         <item name="virtualButtonPressedDrawable">?android:attr/selectableItemBackground</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index a4f9762..6624da4 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1303,6 +1303,7 @@
   <java-symbol type="bool" name="config_lidControlsSleep" />
   <java-symbol type="bool" name="config_reverseDefaultRotation" />
   <java-symbol type="bool" name="config_showNavigationBar" />
+  <java-symbol type="bool" name="config_supportAutoRotation" />
   <java-symbol type="bool" name="target_honeycomb_needs_options_menu" />
   <java-symbol type="dimen" name="navigation_bar_height" />
   <java-symbol type="dimen" name="navigation_bar_height_landscape" />
@@ -1627,7 +1628,16 @@
   <java-symbol type="integer" name="config_maxResolverActivityColumns" />
   <java-symbol type="array" name="config_notificationScorers" />
 
-  <!-- From SystemUI -->
+  <java-symbol type="layout" name="notification_quantum_action" />
+  <java-symbol type="layout" name="notification_quantum_action_list" />
+  <java-symbol type="layout" name="notification_quantum_action_tombstone" />
+  <java-symbol type="layout" name="notification_template_quantum_base" />
+  <java-symbol type="layout" name="notification_template_quantum_big_base" />
+  <java-symbol type="layout" name="notification_template_quantum_big_picture" />
+  <java-symbol type="layout" name="notification_template_quantum_big_text" />
+  <java-symbol type="layout" name="notification_template_quantum_inbox" />
+
+    <!-- From SystemUI -->
   <java-symbol type="anim" name="push_down_in" />
   <java-symbol type="anim" name="push_down_out" />
   <java-symbol type="anim" name="push_up_in" />
diff --git a/core/res/res/values/themes_micro.xml b/core/res/res/values/themes_micro.xml
index e429f96..7c0b7bc 100644
--- a/core/res/res/values/themes_micro.xml
+++ b/core/res/res/values/themes_micro.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 <resources>
-    <style name="Theme.Micro" parent="Theme.Holo">
+    <style name="Theme.Micro" parent="Theme.Holo.NoActionBar">
+        <item name="textViewStyle">@android:style/Widget.Micro.TextView</item>
         <item name="numberPickerStyle">@android:style/Widget.Micro.NumberPicker</item>
         <item name="windowAnimationStyle">@android:style/Animation.SwipeDismiss</item>
         <item name="windowIsFloating">false</item>
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/NetworkState.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/NetworkState.java
index 5a4a2d0..9d97ac5 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/NetworkState.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/NetworkState.java
@@ -101,9 +101,10 @@
     }
 
     /*
-     * Transition from CONNECTED -> DISCONNECTED:
-     *    CONNECTED->DISCONNECTING->DISCONNECTED
-     * return false if any state transition is not valid and save a message in mReason
+     * Verifies state transition from CONNECTED->...-> DISCONNECTED.
+     *
+     * returns false if initial state or target state is not correct, or if there is
+     * any transition from DISCONNECTING/DISCONNECTED -> CONNECTED.
      */
     public boolean transitToDisconnection () {
         mReason = "states: " + printStates();
@@ -120,13 +121,13 @@
         for (int i = 1; i < mStateDepository.size() - 1; i++) {
             State preState = mStateDepository.get(i-1);
             State curState = mStateDepository.get(i);
-            if ((preState == State.CONNECTED) && ((curState == State.DISCONNECTING) ||
+            if (preState == curState) {
+                continue;
+            } else if ((preState == State.CONNECTED) && ((curState == State.DISCONNECTING) ||
                     (curState == State.DISCONNECTED))) {
                 continue;
             } else if ((preState == State.DISCONNECTING) && (curState == State.DISCONNECTED)) {
                 continue;
-            } else if ((preState == State.DISCONNECTED) && (curState == State.DISCONNECTED)) {
-                continue;
             } else {
                 mReason += " Transition state from " + preState.toString() + " to " +
                         curState.toString() + " is not valid.";
@@ -136,7 +137,12 @@
         return true;
     }
 
-    // DISCONNECTED->CONNECTING->CONNECTED
+    /*
+     * Verifies state transition from DISCONNECTED->...-> CONNECTED.
+     *
+     * returns false if initial state or target state is not correct, or if there is
+     * any transition from CONNECED -> DISCONNECTED.
+     */
     public boolean transitToConnection() {
         mReason = "states: " + printStates();
         if (mStateDepository.get(0) != State.DISCONNECTED) {
@@ -152,14 +158,15 @@
         for (int i = 1; i < mStateDepository.size(); i++) {
             State preState = mStateDepository.get(i-1);
             State curState = mStateDepository.get(i);
+            if (preState == curState) {
+                continue;
+            }
             if ((preState == State.DISCONNECTED) && ((curState == State.CONNECTING) ||
-                    (curState == State.CONNECTED) || (curState == State.DISCONNECTED))) {
+                    (curState == State.CONNECTED))) {
                 continue;
-            } else if ((preState == State.CONNECTING) && (curState == State.CONNECTED)) {
-                continue;
-            } else if ((preState == State.CONNECTED) && (curState == State.CONNECTED)) {
-                continue;
-            } else {
+             } else if ((preState == State.CONNECTING) && (curState == State.CONNECTED)) {
+                 continue;
+             } else {
                 mReason += " Transition state from " + preState.toString() + " to " +
                         curState.toString() + " is not valid.";
                 return false;
diff --git a/core/tests/inputmethodtests/run_core_inputmethod_test.sh b/core/tests/inputmethodtests/run_core_inputmethod_test.sh
index 5e123ec..b0b119b 100755
--- a/core/tests/inputmethodtests/run_core_inputmethod_test.sh
+++ b/core/tests/inputmethodtests/run_core_inputmethod_test.sh
@@ -21,4 +21,4 @@
   $COMMAND
 fi
 
-adb shell am instrument -w -e class android.os.InputMethodTest com.android.frameworks.coretests.inputmethod/android.test.InstrumentationTestRunner
+adb shell am instrument -w -e class android.os.InputMethodTest,android.os.InputMethodSubtypeArrayTest com.android.frameworks.coretests.inputmethod/android.test.InstrumentationTestRunner
diff --git a/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeArrayTest.java b/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeArrayTest.java
new file mode 100644
index 0000000..1e0a919
--- /dev/null
+++ b/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeArrayTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.inputmethod.InputMethodSubtype;
+import android.view.inputmethod.InputMethodSubtypeArray;
+import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
+
+import java.util.ArrayList;
+
+public class InputMethodSubtypeArrayTest extends InstrumentationTestCase {
+    @SmallTest
+    public void testInstanciate() throws Exception {
+        final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+        subtypes.add(createDummySubtype(0, "en_US"));
+        subtypes.add(createDummySubtype(1, "en_US"));
+        subtypes.add(createDummySubtype(2, "ja_JP"));
+
+        final InputMethodSubtypeArray array = new InputMethodSubtypeArray(subtypes);
+        assertEquals(subtypes.size(), array.getCount());
+        assertEquals(subtypes.get(0), array.get(0));
+        assertEquals(subtypes.get(1), array.get(1));
+        assertEquals(subtypes.get(2), array.get(2));
+
+        final InputMethodSubtypeArray clonedArray = cloneViaParcel(array);
+        assertEquals(subtypes.size(), clonedArray.getCount());
+        assertEquals(subtypes.get(0), clonedArray.get(0));
+        assertEquals(subtypes.get(1), clonedArray.get(1));
+        assertEquals(subtypes.get(2), clonedArray.get(2));
+
+        final InputMethodSubtypeArray clonedClonedArray = cloneViaParcel(clonedArray);
+        assertEquals(clonedArray.getCount(), clonedClonedArray.getCount());
+        assertEquals(clonedArray.get(0), clonedClonedArray.get(0));
+        assertEquals(clonedArray.get(1), clonedClonedArray.get(1));
+        assertEquals(clonedArray.get(2), clonedClonedArray.get(2));
+    }
+
+    InputMethodSubtypeArray cloneViaParcel(final InputMethodSubtypeArray original) {
+        Parcel parcel = null;
+        try {
+            parcel = Parcel.obtain();
+            original.writeToParcel(parcel);
+            parcel.setDataPosition(0);
+            return new InputMethodSubtypeArray(parcel);
+        } finally {
+            if (parcel != null) {
+                parcel.recycle();
+            }
+        }
+    }
+
+    private static InputMethodSubtype createDummySubtype(final int id, final String locale) {
+        final InputMethodSubtypeBuilder builder = new InputMethodSubtypeBuilder();
+        return builder.setSubtypeNameResId(0)
+                .setSubtypeIconResId(0)
+                .setSubtypeId(id)
+                .setSubtypeLocale(locale)
+                .setIsAsciiCapable(true)
+                .build();
+    }
+}
diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl
index 2042345..0cdcb1c 100644
--- a/data/keyboards/Generic.kl
+++ b/data/keyboards/Generic.kl
@@ -161,8 +161,8 @@
 key 139   MENU              WAKE_DROPPED
 key 140   CALCULATOR
 # key 141 "KEY_SETUP"
-key 142   POWER             WAKE
-key 143   POWER             WAKE
+key 142   SLEEP             WAKE
+key 143   WAKEUP            WAKE
 # key 144 "KEY_FILE"
 # key 145 "KEY_SENDFILE"
 # key 146 "KEY_DELETEFILE"
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index a0bae12..b334aab 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -79,7 +79,7 @@
  * two stretchable slices is exactly the ratio of their corresponding
  * segment lengths.
  *
- * xDivs and yDivs point to arrays of horizontal and vertical pixel
+ * xDivs and yDivs are arrays of horizontal and vertical pixel
  * indices.  The first pair of Divs (in either array) indicate the
  * starting and ending points of the first stretchable segment in that
  * axis. The next pair specifies the next stretchable segment, etc. So
@@ -92,32 +92,31 @@
  * go to xDiv[0] and slices 2, 6 and 10 start at xDiv[1] and end at
  * xDiv[2].
  *
- * The array pointed to by the colors field lists contains hints for
- * each of the regions.  They are ordered according left-to-right and
- * top-to-bottom as indicated above. For each segment that is a solid
- * color the array entry will contain that color value; otherwise it
- * will contain NO_COLOR.  Segments that are completely transparent
- * will always have the value TRANSPARENT_COLOR.
+ * The colors array contains hints for each of the regions. They are
+ * ordered according left-to-right and top-to-bottom as indicated above.
+ * For each segment that is a solid color the array entry will contain
+ * that color value; otherwise it will contain NO_COLOR. Segments that
+ * are completely transparent will always have the value TRANSPARENT_COLOR.
  *
  * The PNG chunk type is "npTc".
  */
 struct Res_png_9patch
 {
-    Res_png_9patch() : wasDeserialized(false), xDivs(NULL),
-                       yDivs(NULL), colors(NULL) { }
+    Res_png_9patch() : wasDeserialized(false), xDivsOffset(0),
+                       yDivsOffset(0), colorsOffset(0) { }
 
     int8_t wasDeserialized;
     int8_t numXDivs;
     int8_t numYDivs;
     int8_t numColors;
 
-    // These tell where the next section of a patch starts.
-    // For example, the first patch includes the pixels from
-    // 0 to xDivs[0]-1 and the second patch includes the pixels
-    // from xDivs[0] to xDivs[1]-1.
-    // Note: allocation/free of these pointers is left to the caller.
-    int32_t* xDivs;
-    int32_t* yDivs;
+    // The offset (from the start of this structure) to the xDivs & yDivs
+    // array for this 9patch. To get a pointer to this array, call
+    // getXDivs or getYDivs. Note that the serialized form for 9patches places
+    // the xDivs, yDivs and colors arrays immediately after the location
+    // of the Res_png_9patch struct.
+    uint32_t xDivsOffset;
+    uint32_t yDivsOffset;
 
     int32_t paddingLeft, paddingRight;
     int32_t paddingTop, paddingBottom;
@@ -129,22 +128,42 @@
         // The 9 patch segment is completely transparent.
         TRANSPARENT_COLOR = 0x00000000
     };
-    // Note: allocation/free of this pointer is left to the caller.
-    uint32_t* colors;
+
+    // The offset (from the start of this structure) to the colors array
+    // for this 9patch.
+    uint32_t colorsOffset;
 
     // Convert data from device representation to PNG file representation.
     void deviceToFile();
     // Convert data from PNG file representation to device representation.
     void fileToDevice();
-    // Serialize/Marshall the patch data into a newly malloc-ed block
-    void* serialize();
-    // Serialize/Marshall the patch data
-    void serialize(void* outData);
+
+    // Serialize/Marshall the patch data into a newly malloc-ed block.
+    static void* serialize(const Res_png_9patch& patchHeader, const int32_t* xDivs,
+                           const int32_t* yDivs, const uint32_t* colors);
+    // Serialize/Marshall the patch data into |outData|.
+    static void serialize(const Res_png_9patch& patchHeader, const int32_t* xDivs,
+                           const int32_t* yDivs, const uint32_t* colors, void* outData);
     // Deserialize/Unmarshall the patch data
-    static Res_png_9patch* deserialize(const void* data);
+    static Res_png_9patch* deserialize(void* data);
     // Compute the size of the serialized data structure
-    size_t serializedSize();
-};
+    size_t serializedSize() const;
+
+    // These tell where the next section of a patch starts.
+    // For example, the first patch includes the pixels from
+    // 0 to xDivs[0]-1 and the second patch includes the pixels
+    // from xDivs[0] to xDivs[1]-1.
+    inline int32_t* getXDivs() const {
+        return reinterpret_cast<int32_t*>(reinterpret_cast<uintptr_t>(this) + xDivsOffset);
+    }
+    inline int32_t* getYDivs() const {
+        return reinterpret_cast<int32_t*>(reinterpret_cast<uintptr_t>(this) + yDivsOffset);
+    }
+    inline uint32_t* getColors() const {
+        return reinterpret_cast<uint32_t*>(reinterpret_cast<uintptr_t>(this) + colorsOffset);
+    }
+
+} __attribute__((packed));
 
 /** ********************************************************************
  *  Base Types
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 51f59f6..98849e3 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -118,6 +118,12 @@
     return BAD_TYPE;
 }
 
+static void fill9patchOffsets(Res_png_9patch* patch) {
+    patch->xDivsOffset = sizeof(Res_png_9patch);
+    patch->yDivsOffset = patch->xDivsOffset + (patch->numXDivs * sizeof(int32_t));
+    patch->colorsOffset = patch->yDivsOffset + (patch->numYDivs * sizeof(int32_t));
+}
+
 inline void Res_value::copyFrom_dtoh(const Res_value& src)
 {
     size = dtohs(src.size);
@@ -128,9 +134,11 @@
 
 void Res_png_9patch::deviceToFile()
 {
+    int32_t* xDivs = getXDivs();
     for (int i = 0; i < numXDivs; i++) {
         xDivs[i] = htonl(xDivs[i]);
     }
+    int32_t* yDivs = getYDivs();
     for (int i = 0; i < numYDivs; i++) {
         yDivs[i] = htonl(yDivs[i]);
     }
@@ -138,6 +146,7 @@
     paddingRight = htonl(paddingRight);
     paddingTop = htonl(paddingTop);
     paddingBottom = htonl(paddingBottom);
+    uint32_t* colors = getColors();
     for (int i=0; i<numColors; i++) {
         colors[i] = htonl(colors[i]);
     }
@@ -145,9 +154,11 @@
 
 void Res_png_9patch::fileToDevice()
 {
+    int32_t* xDivs = getXDivs();
     for (int i = 0; i < numXDivs; i++) {
         xDivs[i] = ntohl(xDivs[i]);
     }
+    int32_t* yDivs = getYDivs();
     for (int i = 0; i < numYDivs; i++) {
         yDivs[i] = ntohl(yDivs[i]);
     }
@@ -155,60 +166,49 @@
     paddingRight = ntohl(paddingRight);
     paddingTop = ntohl(paddingTop);
     paddingBottom = ntohl(paddingBottom);
+    uint32_t* colors = getColors();
     for (int i=0; i<numColors; i++) {
         colors[i] = ntohl(colors[i]);
     }
 }
 
-size_t Res_png_9patch::serializedSize()
+size_t Res_png_9patch::serializedSize() const
 {
     // The size of this struct is 32 bytes on the 32-bit target system
     // 4 * int8_t
     // 4 * int32_t
-    // 3 * pointer
+    // 3 * uint32_t
     return 32
             + numXDivs * sizeof(int32_t)
             + numYDivs * sizeof(int32_t)
             + numColors * sizeof(uint32_t);
 }
 
-void* Res_png_9patch::serialize()
+void* Res_png_9patch::serialize(const Res_png_9patch& patch, const int32_t* xDivs,
+                                const int32_t* yDivs, const uint32_t* colors)
 {
     // Use calloc since we're going to leave a few holes in the data
     // and want this to run cleanly under valgrind
-    void* newData = calloc(1, serializedSize());
-    serialize(newData);
+    void* newData = calloc(1, patch.serializedSize());
+    serialize(patch, xDivs, yDivs, colors, newData);
     return newData;
 }
 
-void Res_png_9patch::serialize(void * outData)
+void Res_png_9patch::serialize(const Res_png_9patch& patch, const int32_t* xDivs,
+                               const int32_t* yDivs, const uint32_t* colors, void* outData)
 {
-    char* data = (char*) outData;
-    memmove(data, &wasDeserialized, 4);     // copy  wasDeserialized, numXDivs, numYDivs, numColors
-    memmove(data + 12, &paddingLeft, 16);   // copy paddingXXXX
+    uint8_t* data = (uint8_t*) outData;
+    memcpy(data, &patch.wasDeserialized, 4);     // copy  wasDeserialized, numXDivs, numYDivs, numColors
+    memcpy(data + 12, &patch.paddingLeft, 16);   // copy paddingXXXX
     data += 32;
 
-    memmove(data, this->xDivs, numXDivs * sizeof(int32_t));
-    data +=  numXDivs * sizeof(int32_t);
-    memmove(data, this->yDivs, numYDivs * sizeof(int32_t));
-    data +=  numYDivs * sizeof(int32_t);
-    memmove(data, this->colors, numColors * sizeof(uint32_t));
-}
+    memcpy(data, xDivs, patch.numXDivs * sizeof(int32_t));
+    data +=  patch.numXDivs * sizeof(int32_t);
+    memcpy(data, yDivs, patch.numYDivs * sizeof(int32_t));
+    data +=  patch.numYDivs * sizeof(int32_t);
+    memcpy(data, colors, patch.numColors * sizeof(uint32_t));
 
-static void deserializeInternal(const void* inData, Res_png_9patch* outData) {
-    char* patch = (char*) inData;
-    if (inData != outData) {
-        memmove(&outData->wasDeserialized, patch, 4);     // copy  wasDeserialized, numXDivs, numYDivs, numColors
-        memmove(&outData->paddingLeft, patch + 12, 4);     // copy  wasDeserialized, numXDivs, numYDivs, numColors
-    }
-    outData->wasDeserialized = true;
-    char* data = (char*)outData;
-    data +=  sizeof(Res_png_9patch);
-    outData->xDivs = (int32_t*) data;
-    data +=  outData->numXDivs * sizeof(int32_t);
-    outData->yDivs = (int32_t*) data;
-    data +=  outData->numYDivs * sizeof(int32_t);
-    outData->colors = (uint32_t*) data;
+    fill9patchOffsets(reinterpret_cast<Res_png_9patch*>(outData));
 }
 
 static bool assertIdmapHeader(const uint32_t* map, size_t sizeBytes)
@@ -312,14 +312,14 @@
     return NO_ERROR;
 }
 
-Res_png_9patch* Res_png_9patch::deserialize(const void* inData)
+Res_png_9patch* Res_png_9patch::deserialize(void* inData)
 {
-    if (sizeof(void*) != sizeof(int32_t)) {
-        ALOGE("Cannot deserialize on non 32-bit system\n");
-        return NULL;
-    }
-    deserializeInternal(inData, (Res_png_9patch*) inData);
-    return (Res_png_9patch*) inData;
+
+    Res_png_9patch* patch = reinterpret_cast<Res_png_9patch*>(inData);
+    patch->wasDeserialized = true;
+    fill9patchOffsets(patch);
+
+    return patch;
 }
 
 // --------------------------------------------------------------------
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index c3aa733..0f76486 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -109,6 +109,9 @@
 void DisplayList::setData(DisplayListData* data) {
     delete mDisplayListData;
     mDisplayListData = data;
+    if (mDisplayListData) {
+        Caches::getInstance().registerFunctors(mDisplayListData->functorCount);
+    }
 }
 
 /**
diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp
index 9b023f9..b2148b0 100644
--- a/libs/hwui/Patch.cpp
+++ b/libs/hwui/Patch.cpp
@@ -57,7 +57,7 @@
     if (vertices) return vertices;
 
     int8_t emptyQuads = 0;
-    mColors = patch->colors;
+    mColors = patch->getColors();
 
     const int8_t numColors = patch->numColors;
     if (uint8_t(numColors) < sizeof(uint32_t) * 4) {
@@ -79,8 +79,8 @@
     TextureVertex* tempVertices = new TextureVertex[maxVertices];
     TextureVertex* vertex = tempVertices;
 
-    const int32_t* xDivs = patch->xDivs;
-    const int32_t* yDivs = patch->yDivs;
+    const int32_t* xDivs = patch->getXDivs();
+    const int32_t* yDivs = patch->getYDivs();
 
     const uint32_t xStretchCount = (xCount + 1) >> 1;
     const uint32_t yStretchCount = (yCount + 1) >> 1;
diff --git a/libs/hwui/Patch.h b/libs/hwui/Patch.h
index 489064b..1ba045d 100644
--- a/libs/hwui/Patch.h
+++ b/libs/hwui/Patch.h
@@ -67,7 +67,7 @@
     void generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, float y2,
             float u1, float v1, float u2, float v2, uint32_t& quadCount);
 
-    uint32_t* mColors;
+    const uint32_t* mColors;
     UvMapper mUvMapper;
 }; // struct Patch
 
diff --git a/libs/hwui/PathTessellator.cpp b/libs/hwui/PathTessellator.cpp
index cc56333..4ef2158 100644
--- a/libs/hwui/PathTessellator.cpp
+++ b/libs/hwui/PathTessellator.cpp
@@ -16,7 +16,7 @@
 
 #define LOG_TAG "OpenGLRenderer"
 #define LOG_NDEBUG 1
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+#define ATRACE_TAG ATRACE_TAG_VIEW
 
 #define VERTEX_DEBUG 0
 
diff --git a/libs/hwui/ShadowTessellator.cpp b/libs/hwui/ShadowTessellator.cpp
index 526772b..5469aad 100644
--- a/libs/hwui/ShadowTessellator.cpp
+++ b/libs/hwui/ShadowTessellator.cpp
@@ -15,9 +15,11 @@
  */
 
 #define LOG_TAG "OpenGLRenderer"
+#define ATRACE_TAG ATRACE_TAG_VIEW
 
 #include <math.h>
 #include <utils/Log.h>
+#include <utils/Trace.h>
 
 #include "AmbientShadow.h"
 #include "ShadowTessellator.h"
@@ -34,6 +36,8 @@
 void ShadowTessellator::tessellateAmbientShadow(const Vector3* casterPolygon,
         int casterVertexCount, const Vector3& centroid3d,
         VertexBuffer& shadowVertexBuffer) {
+    ATRACE_CALL();
+
     // A bunch of parameters to tweak the shadow.
     // TODO: Allow some of these changable by debug settings or APIs.
     const float heightFactor = 128;
@@ -47,6 +51,8 @@
 void ShadowTessellator::tessellateSpotShadow(const Vector3* casterPolygon, int casterVertexCount,
         const Vector3& lightPosScale, const mat4& receiverTransform,
         int screenWidth, int screenHeight, VertexBuffer& shadowVertexBuffer) {
+    ATRACE_CALL();
+
     // A bunch of parameters to tweak the shadow.
     // TODO: Allow some of these changable by debug settings or APIs.
     int maximal = max(screenWidth, screenHeight);
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 0568851..ce66d8f 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -373,7 +373,7 @@
     mCanvas->setViewport(width, height);
 }
 
-void CanvasContext::swapDisplayListData(DisplayList* displayList, DisplayListData* newData) {
+void CanvasContext::setDisplayListData(DisplayList* displayList, DisplayListData* newData) {
     displayList->setData(newData);
 }
 
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 2c9348c..649ffb6 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -63,7 +63,7 @@
     bool initialize(EGLNativeWindowType window);
     void updateSurface(EGLNativeWindowType window);
     void setup(int width, int height);
-    void swapDisplayListData(DisplayList* displayList, DisplayListData* newData);
+    void setDisplayListData(DisplayList* displayList, DisplayListData* newData);
     void processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters);
     void drawDisplayList(DisplayList* displayList, Rect* dirty);
     void destroyCanvas();
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index c3bf404..200c21f 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -117,14 +117,14 @@
     post(task);
 }
 
-CREATE_BRIDGE3(swapDisplayListData, CanvasContext* context, DisplayList* displayList,
+CREATE_BRIDGE3(setDisplayListData, CanvasContext* context, DisplayList* displayList,
         DisplayListData* newData) {
-    args->context->swapDisplayListData(args->displayList, args->newData);
+    args->context->setDisplayListData(args->displayList, args->newData);
     return NULL;
 }
 
-void RenderProxy::swapDisplayListData(DisplayList* displayList, DisplayListData* newData) {
-    SETUP_TASK(swapDisplayListData);
+void RenderProxy::setDisplayListData(DisplayList* displayList, DisplayListData* newData) {
+    SETUP_TASK(setDisplayListData);
     args->context = mContext;
     args->displayList = displayList;
     args->newData = newData;
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 0934b98..83a8a8f 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -60,7 +60,7 @@
     ANDROID_API bool initialize(EGLNativeWindowType window);
     ANDROID_API void updateSurface(EGLNativeWindowType window);
     ANDROID_API void setup(int width, int height);
-    ANDROID_API void swapDisplayListData(DisplayList* displayList, DisplayListData* newData);
+    ANDROID_API void setDisplayListData(DisplayList* displayList, DisplayListData* newData);
     ANDROID_API void drawDisplayList(DisplayList* displayList,
             int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
     ANDROID_API void destroyCanvas();
diff --git a/media/java/android/media/MediaMuxer.java b/media/java/android/media/MediaMuxer.java
index e5c97e7..f518ab2 100644
--- a/media/java/android/media/MediaMuxer.java
+++ b/media/java/android/media/MediaMuxer.java
@@ -17,13 +17,11 @@
 package android.media;
 
 import android.media.MediaCodec.BufferInfo;
-
 import dalvik.system.CloseGuard;
 
-import java.io.File;
 import java.io.FileDescriptor;
-import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.RandomAccessFile;
 import java.nio.ByteBuffer;
 import java.util.Map;
 
@@ -79,6 +77,7 @@
         private OutputFormat() {}
         /** MPEG4 media file format*/
         public static final int MUXER_OUTPUT_MPEG_4 = 0;
+        public static final int MUXER_OUTPUT_WEBM   = 1;
     };
 
     // All the native functions are listed here.
@@ -120,20 +119,22 @@
         if (path == null) {
             throw new IllegalArgumentException("path must not be null");
         }
-        if (format != OutputFormat.MUXER_OUTPUT_MPEG_4) {
+        if (format != OutputFormat.MUXER_OUTPUT_MPEG_4 &&
+                format != OutputFormat.MUXER_OUTPUT_WEBM) {
             throw new IllegalArgumentException("format is invalid");
         }
-        FileOutputStream fos = null;
+        // Use RandomAccessFile so we can open the file with RW access;
+        // RW access allows the native writer to memory map the output file.
+        RandomAccessFile file = null;
         try {
-            File file = new File(path);
-            fos = new FileOutputStream(file);
-            FileDescriptor fd = fos.getFD();
+            file = new RandomAccessFile(path, "rws");
+            FileDescriptor fd = file.getFD();
             mNativeObject = nativeSetup(fd, format);
             mState = MUXER_STATE_INITIALIZED;
             mCloseGuard.open("release");
         } finally {
-            if (fos != null) {
-                fos.close();
+            if (file != null) {
+                file.close();
             }
         }
     }
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index 35327c0..ed98b96 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -38,6 +38,7 @@
     libcamera_client \
     libmtp \
     libusbhost \
+    libjhead \
     libexif \
     libstagefright_amrnb_common \
 
diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp
index d3a8b22..a78f16d 100644
--- a/media/jni/android_media_MediaExtractor.cpp
+++ b/media/jni/android_media_MediaExtractor.cpp
@@ -561,7 +561,7 @@
         return JNI_FALSE;
     }
 
-    size_t numSubSamples = size / sizeof(size_t);
+    size_t numSubSamples = size / sizeof(int32_t);
 
     if (numSubSamples == 0) {
         return JNI_FALSE;
@@ -571,7 +571,7 @@
     jboolean isCopy;
     jint *dst = env->GetIntArrayElements(numBytesOfEncryptedDataObj, &isCopy);
     for (size_t i = 0; i < numSubSamples; ++i) {
-        dst[i] = ((const size_t *)data)[i];
+        dst[i] = ((const int32_t *)data)[i];
     }
     env->ReleaseIntArrayElements(numBytesOfEncryptedDataObj, dst, 0);
     dst = NULL;
@@ -588,7 +588,7 @@
         jboolean isCopy;
         jint *dst = env->GetIntArrayElements(numBytesOfPlainDataObj, &isCopy);
         for (size_t i = 0; i < numSubSamples; ++i) {
-            dst[i] = ((const size_t *)data)[i];
+            dst[i] = ((const int32_t *)data)[i];
         }
         env->ReleaseIntArrayElements(numBytesOfPlainDataObj, dst, 0);
         dst = NULL;
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index f3a7ff7..4e42ae3 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -256,7 +256,7 @@
                         fields.createConfigMethod,
                         SkBitmap::kRGB_565_Config);
 
-    size_t width, height;
+    uint32_t width, height;
     bool swapWidthAndHeight = false;
     if (videoFrame->mRotationAngle == 90 || videoFrame->mRotationAngle == 270) {
         width = videoFrame->mHeight;
@@ -287,8 +287,8 @@
 
     if (videoFrame->mDisplayWidth  != videoFrame->mWidth ||
         videoFrame->mDisplayHeight != videoFrame->mHeight) {
-        size_t displayWidth = videoFrame->mDisplayWidth;
-        size_t displayHeight = videoFrame->mDisplayHeight;
+        uint32_t displayWidth = videoFrame->mDisplayWidth;
+        uint32_t displayHeight = videoFrame->mDisplayHeight;
         if (swapWidthAndHeight) {
             displayWidth = videoFrame->mDisplayHeight;
             displayHeight = videoFrame->mDisplayWidth;
diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java
index 5a2e261..a9322b9 100644
--- a/opengl/java/android/opengl/GLSurfaceView.java
+++ b/opengl/java/android/opengl/GLSurfaceView.java
@@ -595,13 +595,9 @@
         mDetached = false;
     }
 
-    /**
-     * This method is used as part of the View class and is not normally
-     * called or subclassed by clients of GLSurfaceView.
-     * Must not be called before a renderer has been set.
-     */
+    /** @hide */
     @Override
-    protected void onDetachedFromWindow() {
+    protected void onDetachedFromWindowInternal() {
         if (LOG_ATTACH_DETACH) {
             Log.d(TAG, "onDetachedFromWindow");
         }
@@ -609,7 +605,7 @@
             mGLThread.requestExitAndWait();
         }
         mDetached = true;
-        super.onDetachedFromWindow();
+        super.onDetachedFromWindowInternal();
     }
 
     // ----------------------------------------------------------------------
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
index 0fa27c1..14de6dd 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
@@ -58,8 +58,8 @@
     // how many cells the user has to cross before we poke the wakelock
     private static final int MIN_PATTERN_BEFORE_POKE_WAKELOCK = 2;
 
-    private int mFailedPatternAttemptsSinceLastTimeout = 0;
-    private int mTotalFailedPatternAttempts = 0;
+    private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+
     private CountDownTimer mCountdownTimer = null;
     private LockPatternUtils mLockPatternUtils;
     private LockPatternView mLockPatternView;
@@ -100,6 +100,7 @@
 
     public KeyguardPatternView(Context context, AttributeSet attrs) {
         super(context, attrs);
+        mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
     }
 
     public void setKeyguardCallback(KeyguardSecurityCallback callback) {
@@ -202,7 +203,8 @@
         if (mCallback.isVerifyUnlockOnly()) {
             updateFooter(FooterMode.VerifyUnlocked);
         } else if (mEnableFallback &&
-                (mTotalFailedPatternAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
+                (mKeyguardUpdateMonitor.getFailedUnlockAttempts()
+                        >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
             updateFooter(FooterMode.ForgotLockPattern);
         } else {
             updateFooter(FooterMode.Normal);
@@ -211,7 +213,7 @@
     }
 
     private void displayDefaultSecurityMessage() {
-        if (KeyguardUpdateMonitor.getInstance(mContext).getMaxBiometricUnlockAttemptsReached()) {
+        if (mKeyguardUpdateMonitor.getMaxBiometricUnlockAttemptsReached()) {
             mSecurityMessageDisplay.setMessage(R.string.faceunlock_multiple_failures, true);
         } else {
             mSecurityMessageDisplay.setMessage(R.string.kg_pattern_instructions, false);
@@ -262,20 +264,20 @@
             if (mLockPatternUtils.checkPattern(pattern)) {
                 mCallback.reportUnlockAttempt(true);
                 mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Correct);
-                mTotalFailedPatternAttempts = 0;
                 mCallback.dismiss(true);
             } else {
                 if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) {
                     mCallback.userActivity(UNLOCK_PATTERN_WAKE_INTERVAL_MS);
                 }
                 mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong);
-                if (pattern.size() >= LockPatternUtils.MIN_PATTERN_REGISTER_FAIL) {
-                    mTotalFailedPatternAttempts++;
-                    mFailedPatternAttemptsSinceLastTimeout++;
+                boolean registeredAttempt =
+                        pattern.size() >= LockPatternUtils.MIN_PATTERN_REGISTER_FAIL;
+                if (registeredAttempt) {
                     mCallback.reportUnlockAttempt(false);
                 }
-                if (mFailedPatternAttemptsSinceLastTimeout
-                        >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) {
+                int attempts = mKeyguardUpdateMonitor.getFailedUnlockAttempts();
+                if (registeredAttempt &&
+                        0 == (attempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
                     long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
                     handleAttemptLockout(deadline);
                 } else {
@@ -363,7 +365,6 @@
                 mLockPatternView.setEnabled(true);
                 displayDefaultSecurityMessage();
                 // TODO mUnlockIcon.setVisibility(View.VISIBLE);
-                mFailedPatternAttemptsSinceLastTimeout = 0;
                 if (mEnableFallback) {
                     updateFooter(FooterMode.ForgotLockPattern);
                 } else {
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_color_space_alpha.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_color_space_alpha.png
new file mode 100644
index 0000000..fe6dc52
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_color_space_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_contrast_alpha.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_contrast_alpha.png
new file mode 100644
index 0000000..0f9dfc7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_contrast_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_inversion_alpha.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_inversion_alpha.png
new file mode 100644
index 0000000..aea75c1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_inversion_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldpi/ic_qs_color_space_alpha.png b/packages/SystemUI/res/drawable-ldpi/ic_qs_color_space_alpha.png
new file mode 100644
index 0000000..46d2a16
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldpi/ic_qs_color_space_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldpi/ic_qs_contrast_alpha.png b/packages/SystemUI/res/drawable-ldpi/ic_qs_contrast_alpha.png
new file mode 100644
index 0000000..704b4ec
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldpi/ic_qs_contrast_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldpi/ic_qs_inversion_alpha.png b/packages/SystemUI/res/drawable-ldpi/ic_qs_inversion_alpha.png
new file mode 100644
index 0000000..d56efb5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldpi/ic_qs_inversion_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_color_space_alpha.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_color_space_alpha.png
new file mode 100644
index 0000000..18b6029
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_color_space_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_contrast_alpha.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_contrast_alpha.png
new file mode 100644
index 0000000..a4dd087
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_contrast_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_inversion_alpha.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_inversion_alpha.png
new file mode 100644
index 0000000..b6ea14e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_inversion_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_color_space_alpha.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_color_space_alpha.png
new file mode 100644
index 0000000..95cf67f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_color_space_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_contrast_alpha.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_contrast_alpha.png
new file mode 100644
index 0000000..9331e52
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_contrast_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_inversion_alpha.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_inversion_alpha.png
new file mode 100644
index 0000000..efd8b9e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_inversion_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_color_space_alpha.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_color_space_alpha.png
new file mode 100644
index 0000000..7f441c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_color_space_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_contrast_alpha.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_contrast_alpha.png
new file mode 100644
index 0000000..82c3842
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_contrast_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_inversion_alpha.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_inversion_alpha.png
new file mode 100644
index 0000000..ce9bae2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_inversion_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/ic_qs_color_space_off.xml b/packages/SystemUI/res/drawable/ic_qs_color_space_off.xml
new file mode 100644
index 0000000..cf34ba6
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_color_space_off.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_qs_color_space_alpha"
+    android:tint="@color/ic_qs_off" />
diff --git a/packages/SystemUI/res/drawable/ic_qs_color_space_on.xml b/packages/SystemUI/res/drawable/ic_qs_color_space_on.xml
new file mode 100644
index 0000000..1806688
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_color_space_on.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_qs_color_space_alpha"
+    android:tint="@color/ic_qs_on" />
diff --git a/packages/SystemUI/res/drawable/ic_qs_contrast_off.xml b/packages/SystemUI/res/drawable/ic_qs_contrast_off.xml
new file mode 100644
index 0000000..5f65d8a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_contrast_off.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_qs_contrast_alpha"
+    android:tint="@color/ic_qs_off" />
diff --git a/packages/SystemUI/res/drawable/ic_qs_contrast_on.xml b/packages/SystemUI/res/drawable/ic_qs_contrast_on.xml
new file mode 100644
index 0000000..a018929
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_contrast_on.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_qs_contrast_alpha"
+    android:tint="@color/ic_qs_on" />
diff --git a/packages/SystemUI/res/drawable/ic_qs_inversion_off.xml b/packages/SystemUI/res/drawable/ic_qs_inversion_off.xml
new file mode 100644
index 0000000..9018a90
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_inversion_off.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_qs_inversion_alpha"
+    android:tint="@color/ic_qs_off" />
diff --git a/packages/SystemUI/res/drawable/ic_qs_inversion_on.xml b/packages/SystemUI/res/drawable/ic_qs_inversion_on.xml
new file mode 100644
index 0000000..9110201
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_inversion_on.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_qs_inversion_alpha"
+    android:tint="@color/ic_qs_on" />
diff --git a/packages/SystemUI/res/drawable/notification_icon_legacy_bg.xml b/packages/SystemUI/res/drawable/notification_icon_legacy_bg.xml
new file mode 100644
index 0000000..4ac67c3
--- /dev/null
+++ b/packages/SystemUI/res/drawable/notification_icon_legacy_bg.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="oval">
+    <solid
+            android:color="@color/notification_icon_legacy_bg_color"/>
+</shape>
diff --git a/packages/SystemUI/res/drawable/notification_icon_legacy_bg_inset.xml b/packages/SystemUI/res/drawable/notification_icon_legacy_bg_inset.xml
new file mode 100644
index 0000000..96c5573
--- /dev/null
+++ b/packages/SystemUI/res/drawable/notification_icon_legacy_bg_inset.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+       android:drawable="@drawable/notification_icon_legacy_bg" android:insetBottom="8dp"
+       android:insetLeft="8dp" android:insetRight="8dp" android:insetTop="8dp"
+       android:visible="true"/>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index e525fbb..a59dc75 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -39,4 +39,12 @@
     <color name="status_bar_clock_color">#FFFFFFFF</color>
     <drawable name="notification_item_background_color">#ff111111</drawable>
     <drawable name="notification_item_background_color_pressed">#ff454545</drawable>
+    <color name="notification_icon_legacy_bg_color">#ff4285F4</color>
+    <color name="notification_action_legacy_color_filter">#ff555555</color>
+
+    <!-- Tint color for inactive Quick Settings icons. -->
+    <color name="ic_qs_off">#ff404040</color>
+
+    <!-- Tint color for active Quick Settings icons. -->
+    <color name="ic_qs_on">#ffffffff</color>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/ImageUtils.java b/packages/SystemUI/src/com/android/systemui/ImageUtils.java
new file mode 100644
index 0000000..540ba20
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ImageUtils.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui;
+
+import android.graphics.Bitmap;
+
+/**
+ * Utility class for image analysis and processing.
+ */
+public class ImageUtils {
+
+    // Amount (max is 255) that two channels can differ before the color is no longer "gray".
+    private static final int TOLERANCE = 20;
+
+    // Alpha amount for which values below are considered transparent.
+    private static final int ALPHA_TOLERANCE = 50;
+
+    private int[] mTempBuffer;
+
+    /**
+     * Checks whether a bitmap is grayscale. Grayscale here means "very close to a perfect
+     * gray".
+     */
+    public boolean isGrayscale(Bitmap bitmap) {
+        final int height = bitmap.getHeight();
+        final int width = bitmap.getWidth();
+        int size = height*width;
+
+        ensureBufferSize(size);
+        bitmap.getPixels(mTempBuffer, 0, width, 0, 0, width, height);
+        for (int i = 0; i < size; i++) {
+            if (!isGrayscale(mTempBuffer[i])) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Makes sure that {@code mTempBuffer} has at least length {@code size}.
+     */
+    private void ensureBufferSize(int size) {
+        if (mTempBuffer == null || mTempBuffer.length < size) {
+            mTempBuffer = new int[size];
+        }
+    }
+
+    /**
+     * Classifies a color as grayscale or not. Grayscale here means "very close to a perfect
+     * gray"; if all three channels are approximately equal, this will return true.
+     *
+     * Note that really transparent colors are always grayscale.
+     */
+    public boolean isGrayscale(int color) {
+        int alpha = 0xFF & (color >> 24);
+        if (alpha < ALPHA_TOLERANCE) {
+            return true;
+        }
+
+        int r = 0xFF & (color >> 16);
+        int g = 0xFF & (color >> 8);
+        int b = 0xFF & color;
+
+        return Math.abs(r - g) < TOLERANCE
+                && Math.abs(r - b) < TOLERANCE
+                && Math.abs(g - b) < TOLERANCE;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerDialogWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerDialogWarnings.java
new file mode 100644
index 0000000..feec87c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerDialogWarnings.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.power;
+
+import android.app.AlertDialog;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.media.AudioManager;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Slog;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+
+import java.io.PrintWriter;
+
+public class PowerDialogWarnings implements PowerUI.WarningsUI {
+    private static final String TAG = PowerUI.TAG + ".Dialog";
+    private static final boolean DEBUG = PowerUI.DEBUG;
+
+    private final Context mContext;
+
+    private int mBatteryLevel;
+    private int mBucket;
+    private long mScreenOffTime;
+
+    private AlertDialog mInvalidChargerDialog;
+    private AlertDialog mLowBatteryDialog;
+    private TextView mBatteryLevelTextView;
+
+    public PowerDialogWarnings(Context context) {
+        mContext = context;
+    }
+
+    @Override
+    public void dump(PrintWriter pw) {
+        pw.print("mInvalidChargerDialog=");
+        pw.println(mInvalidChargerDialog == null ? "null" : mInvalidChargerDialog.toString());
+        pw.print("mLowBatteryDialog=");
+        pw.println(mLowBatteryDialog == null ? "null" : mLowBatteryDialog.toString());
+    }
+
+    @Override
+    public void update(int batteryLevel, int bucket, long screenOffTime) {
+        mBatteryLevel = batteryLevel;
+        mBucket = bucket;
+        mScreenOffTime = screenOffTime;
+    }
+
+    @Override
+    public boolean isInvalidChargerWarningShowing() {
+        return mInvalidChargerDialog != null;
+    }
+
+    @Override
+    public void updateLowBatteryWarning() {
+        if (mBatteryLevelTextView != null) {
+            showLowBatteryWarning(false /*playSound*/);
+        }
+    }
+
+    @Override
+    public void dismissLowBatteryWarning() {
+        if (mLowBatteryDialog != null) {
+            Slog.i(TAG, "closing low battery warning: level=" + mBatteryLevel);
+            mLowBatteryDialog.dismiss();
+        }
+    }
+
+    @Override
+    public void showLowBatteryWarning(boolean playSound) {
+        Slog.i(TAG,
+                ((mBatteryLevelTextView == null) ? "showing" : "updating")
+                + " low battery warning: level=" + mBatteryLevel
+                + " [" + mBucket + "]");
+
+        CharSequence levelText = mContext.getString(
+                R.string.battery_low_percent_format, mBatteryLevel);
+
+        if (mBatteryLevelTextView != null) {
+            mBatteryLevelTextView.setText(levelText);
+        } else {
+            View v = View.inflate(mContext, R.layout.battery_low, null);
+            mBatteryLevelTextView = (TextView)v.findViewById(R.id.level_percent);
+
+            mBatteryLevelTextView.setText(levelText);
+
+            AlertDialog.Builder b = new AlertDialog.Builder(mContext);
+                b.setCancelable(true);
+                b.setTitle(R.string.battery_low_title);
+                b.setView(v);
+                b.setIconAttribute(android.R.attr.alertDialogIcon);
+                b.setPositiveButton(android.R.string.ok, null);
+
+            final Intent intent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                    | Intent.FLAG_ACTIVITY_MULTIPLE_TASK
+                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
+                    | Intent.FLAG_ACTIVITY_NO_HISTORY);
+            if (intent.resolveActivity(mContext.getPackageManager()) != null) {
+                b.setNegativeButton(R.string.battery_low_why,
+                        new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        mContext.startActivityAsUser(intent, UserHandle.CURRENT);
+                        dismissLowBatteryWarning();
+                    }
+                });
+            }
+
+            AlertDialog d = b.create();
+            d.setOnDismissListener(new DialogInterface.OnDismissListener() {
+                    @Override
+                    public void onDismiss(DialogInterface dialog) {
+                        mLowBatteryDialog = null;
+                        mBatteryLevelTextView = null;
+                    }
+                });
+            d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+            d.getWindow().getAttributes().privateFlags |=
+                    WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+            d.show();
+            mLowBatteryDialog = d;
+            if (playSound) {
+                playLowBatterySound();
+            }
+        }
+    }
+
+    private void playLowBatterySound() {
+        final ContentResolver cr = mContext.getContentResolver();
+
+        final int silenceAfter = Settings.Global.getInt(cr,
+                Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, 0);
+        final long offTime = SystemClock.elapsedRealtime() - mScreenOffTime;
+        if (silenceAfter > 0
+                && mScreenOffTime > 0
+                && offTime > silenceAfter) {
+            Slog.i(TAG, "screen off too long (" + offTime + "ms, limit " + silenceAfter
+                    + "ms): not waking up the user with low battery sound");
+            return;
+        }
+
+        if (DEBUG) {
+            Slog.d(TAG, "playing low battery sound. pick-a-doop!"); // WOMP-WOMP is deprecated
+        }
+
+        if (Settings.Global.getInt(cr, Settings.Global.POWER_SOUNDS_ENABLED, 1) == 1) {
+            final String soundPath = Settings.Global.getString(cr,
+                    Settings.Global.LOW_BATTERY_SOUND);
+            if (soundPath != null) {
+                final Uri soundUri = Uri.parse("file://" + soundPath);
+                if (soundUri != null) {
+                    final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
+                    if (sfx != null) {
+                        sfx.setStreamType(AudioManager.STREAM_SYSTEM);
+                        sfx.play();
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    public void dismissInvalidChargerWarning() {
+        if (mInvalidChargerDialog != null) {
+            mInvalidChargerDialog.dismiss();
+        }
+    }
+
+    @Override
+    public void showInvalidChargerWarning() {
+        Slog.d(TAG, "showing invalid charger dialog");
+
+        dismissLowBatteryWarning();
+
+        AlertDialog.Builder b = new AlertDialog.Builder(mContext);
+            b.setCancelable(true);
+            b.setMessage(R.string.invalid_charger);
+            b.setIconAttribute(android.R.attr.alertDialogIcon);
+            b.setPositiveButton(android.R.string.ok, null);
+
+        AlertDialog d = b.create();
+            d.setOnDismissListener(new DialogInterface.OnDismissListener() {
+                    public void onDismiss(DialogInterface dialog) {
+                        mInvalidChargerDialog = null;
+                        mBatteryLevelTextView = null;
+                    }
+                });
+
+        d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+        d.show();
+        mInvalidChargerDialog = d;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index 28c2772..0fb0f8b 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -16,29 +16,17 @@
 
 package com.android.systemui.power;
 
-import android.app.AlertDialog;
 import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
 import android.content.Context;
-import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.media.AudioManager;
-import android.media.Ringtone;
-import android.media.RingtoneManager;
-import android.net.Uri;
 import android.os.BatteryManager;
 import android.os.Handler;
 import android.os.PowerManager;
 import android.os.SystemClock;
-import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Slog;
-import android.view.View;
-import android.view.WindowManager;
-import android.widget.TextView;
 
-import com.android.systemui.R;
 import com.android.systemui.SystemUI;
 
 import java.io.FileDescriptor;
@@ -50,19 +38,17 @@
 
     static final boolean DEBUG = false;
 
-    Handler mHandler = new Handler();
+    private WarningsUI mWarnings;
 
-    int mBatteryLevel = 100;
-    int mBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN;
-    int mPlugType = 0;
-    int mInvalidCharger = 0;
+    private final Handler mHandler = new Handler();
 
-    int mLowBatteryAlertCloseLevel;
-    int[] mLowBatteryReminderLevels = new int[2];
+    private int mBatteryLevel = 100;
+    private int mBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN;
+    private int mPlugType = 0;
+    private int mInvalidCharger = 0;
 
-    AlertDialog mInvalidChargerDialog;
-    AlertDialog mLowBatteryDialog;
-    TextView mBatteryLevelTextView;
+    private int mLowBatteryAlertCloseLevel;
+    private final int[] mLowBatteryReminderLevels = new int[2];
 
     private long mScreenOffTime = -1;
 
@@ -77,6 +63,7 @@
 
         final PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mScreenOffTime = pm.isScreenOn() ? -1 : SystemClock.elapsedRealtime();
+        mWarnings = new PowerDialogWarnings(mContext);
 
         // Register for Intent broadcasts for...
         IntentFilter filter = new IntentFilter();
@@ -145,13 +132,14 @@
                     Slog.d(TAG, "plugged        " + oldPlugged + " --> " + plugged);
                 }
 
+                mWarnings.update(mBatteryLevel, bucket, mScreenOffTime);
                 if (oldInvalidCharger == 0 && mInvalidCharger != 0) {
                     Slog.d(TAG, "showing invalid charger warning");
-                    showInvalidChargerDialog();
+                    mWarnings.showInvalidChargerWarning();
                     return;
                 } else if (oldInvalidCharger != 0 && mInvalidCharger == 0) {
-                    dismissInvalidChargerDialog();
-                } else if (mInvalidChargerDialog != null) {
+                    mWarnings.dismissInvalidChargerWarning();
+                } else if (mWarnings.isInvalidChargerWarningShowing()) {
                     // if invalid charger is showing, don't show low battery
                     return;
                 }
@@ -160,16 +148,13 @@
                         && (bucket < oldBucket || oldPlugged)
                         && mBatteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
                         && bucket < 0) {
-                    showLowBatteryWarning();
-
                     // only play SFX when the dialog comes up or the bucket changes
-                    if (bucket != oldBucket || oldPlugged) {
-                        playLowBatterySound();
-                    }
+                    final boolean playSound = bucket != oldBucket || oldPlugged;
+                    mWarnings.showLowBatteryWarning(playSound);
                 } else if (plugged || (bucket > oldBucket && bucket > 0)) {
-                    dismissLowBatteryWarning();
-                } else if (mBatteryLevelTextView != null) {
-                    showLowBatteryWarning();
+                    mWarnings.dismissLowBatteryWarning();
+                } else {
+                    mWarnings.updateLowBatteryWarning();
                 }
             } else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
                 mScreenOffTime = SystemClock.elapsedRealtime();
@@ -181,142 +166,11 @@
         }
     };
 
-    void dismissLowBatteryWarning() {
-        if (mLowBatteryDialog != null) {
-            Slog.i(TAG, "closing low battery warning: level=" + mBatteryLevel);
-            mLowBatteryDialog.dismiss();
-        }
-    }
-
-    void showLowBatteryWarning() {
-        Slog.i(TAG,
-                ((mBatteryLevelTextView == null) ? "showing" : "updating")
-                + " low battery warning: level=" + mBatteryLevel
-                + " [" + findBatteryLevelBucket(mBatteryLevel) + "]");
-
-        CharSequence levelText = mContext.getString(
-                R.string.battery_low_percent_format, mBatteryLevel);
-
-        if (mBatteryLevelTextView != null) {
-            mBatteryLevelTextView.setText(levelText);
-        } else {
-            View v = View.inflate(mContext, R.layout.battery_low, null);
-            mBatteryLevelTextView = (TextView)v.findViewById(R.id.level_percent);
-
-            mBatteryLevelTextView.setText(levelText);
-
-            AlertDialog.Builder b = new AlertDialog.Builder(mContext);
-                b.setCancelable(true);
-                b.setTitle(R.string.battery_low_title);
-                b.setView(v);
-                b.setIconAttribute(android.R.attr.alertDialogIcon);
-                b.setPositiveButton(android.R.string.ok, null);
-
-            final Intent intent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
-                    | Intent.FLAG_ACTIVITY_MULTIPLE_TASK
-                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
-                    | Intent.FLAG_ACTIVITY_NO_HISTORY);
-            if (intent.resolveActivity(mContext.getPackageManager()) != null) {
-                b.setNegativeButton(R.string.battery_low_why,
-                        new DialogInterface.OnClickListener() {
-                    @Override
-                    public void onClick(DialogInterface dialog, int which) {
-                        mContext.startActivityAsUser(intent, UserHandle.CURRENT);
-                        dismissLowBatteryWarning();
-                    }
-                });
-            }
-
-            AlertDialog d = b.create();
-            d.setOnDismissListener(new DialogInterface.OnDismissListener() {
-                    @Override
-                    public void onDismiss(DialogInterface dialog) {
-                        mLowBatteryDialog = null;
-                        mBatteryLevelTextView = null;
-                    }
-                });
-            d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
-            d.getWindow().getAttributes().privateFlags |=
-                    WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
-            d.show();
-            mLowBatteryDialog = d;
-        }
-    }
-
-    void playLowBatterySound() {
-        final ContentResolver cr = mContext.getContentResolver();
-
-        final int silenceAfter = Settings.Global.getInt(cr,
-                Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, 0);
-        final long offTime = SystemClock.elapsedRealtime() - mScreenOffTime;
-        if (silenceAfter > 0
-                && mScreenOffTime > 0
-                && offTime > silenceAfter) {
-            Slog.i(TAG, "screen off too long (" + offTime + "ms, limit " + silenceAfter
-                    + "ms): not waking up the user with low battery sound");
-            return;
-        }
-
-        if (DEBUG) {
-            Slog.d(TAG, "playing low battery sound. pick-a-doop!"); // WOMP-WOMP is deprecated
-        }
-
-        if (Settings.Global.getInt(cr, Settings.Global.POWER_SOUNDS_ENABLED, 1) == 1) {
-            final String soundPath = Settings.Global.getString(cr,
-                    Settings.Global.LOW_BATTERY_SOUND);
-            if (soundPath != null) {
-                final Uri soundUri = Uri.parse("file://" + soundPath);
-                if (soundUri != null) {
-                    final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
-                    if (sfx != null) {
-                        sfx.setStreamType(AudioManager.STREAM_SYSTEM);
-                        sfx.play();
-                    }
-                }
-            }
-        }
-    }
-
-    void dismissInvalidChargerDialog() {
-        if (mInvalidChargerDialog != null) {
-            mInvalidChargerDialog.dismiss();
-        }
-    }
-
-    void showInvalidChargerDialog() {
-        Slog.d(TAG, "showing invalid charger dialog");
-
-        dismissLowBatteryWarning();
-
-        AlertDialog.Builder b = new AlertDialog.Builder(mContext);
-            b.setCancelable(true);
-            b.setMessage(R.string.invalid_charger);
-            b.setIconAttribute(android.R.attr.alertDialogIcon);
-            b.setPositiveButton(android.R.string.ok, null);
-
-        AlertDialog d = b.create();
-            d.setOnDismissListener(new DialogInterface.OnDismissListener() {
-                    public void onDismiss(DialogInterface dialog) {
-                        mInvalidChargerDialog = null;
-                        mBatteryLevelTextView = null;
-                    }
-                });
-
-        d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
-        d.show();
-        mInvalidChargerDialog = d;
-    }
-
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.print("mLowBatteryAlertCloseLevel=");
         pw.println(mLowBatteryAlertCloseLevel);
         pw.print("mLowBatteryReminderLevels=");
         pw.println(Arrays.toString(mLowBatteryReminderLevels));
-        pw.print("mInvalidChargerDialog=");
-        pw.println(mInvalidChargerDialog == null ? "null" : mInvalidChargerDialog.toString());
-        pw.print("mLowBatteryDialog=");
-        pw.println(mLowBatteryDialog == null ? "null" : mLowBatteryDialog.toString());
         pw.print("mBatteryLevel=");
         pw.println(Integer.toString(mBatteryLevel));
         pw.print("mBatteryStatus=");
@@ -338,6 +192,18 @@
                 Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, 0));
         pw.print("bucket: ");
         pw.println(Integer.toString(findBatteryLevelBucket(mBatteryLevel)));
+        mWarnings.dump(pw);
+    }
+
+    public interface WarningsUI {
+        void update(int batteryLevel, int bucket, long screenOffTime);
+        void dismissLowBatteryWarning();
+        void showLowBatteryWarning(boolean playSound);
+        void dismissInvalidChargerWarning();
+        void showInvalidChargerWarning();
+        void updateLowBatteryWarning();
+        boolean isInvalidChargerWarningShowing();
+        void dump(PrintWriter pw);
     }
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index fb11743..eb07d88 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -28,9 +28,15 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.ColorStateList;
 import android.content.res.Configuration;
 import android.database.ContentObserver;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
 import android.graphics.Rect;
+import android.graphics.drawable.AnimationDrawable;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Handler;
@@ -44,9 +50,13 @@
 import android.service.dreams.DreamService;
 import android.service.dreams.IDreamManager;
 import android.service.notification.StatusBarNotification;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
 import android.text.TextUtils;
+import android.text.style.TextAppearanceSpan;
 import android.util.Log;
 import android.util.SparseBooleanArray;
+import android.view.ContextThemeWrapper;
 import android.view.Display;
 import android.view.IWindowManager;
 import android.view.LayoutInflater;
@@ -57,6 +67,7 @@
 import android.view.ViewGroup.LayoutParams;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
+import android.widget.Button;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.PopupMenu;
@@ -67,6 +78,7 @@
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.statusbar.StatusBarIconList;
 import com.android.internal.widget.SizeAdaptiveLayout;
+import com.android.systemui.ImageUtils;
 import com.android.systemui.R;
 import com.android.systemui.RecentsComponent;
 import com.android.systemui.SearchPanelView;
@@ -76,6 +88,7 @@
 
 import java.util.ArrayList;
 import java.util.Locale;
+import java.util.Stack;
 
 public abstract class BaseStatusBar extends SystemUI implements
         CommandQueue.Callbacks {
@@ -140,6 +153,8 @@
     // public mode, private notifications, etc
     private boolean mLockscreenPublicMode = false;
     private final SparseBooleanArray mUsersAllowingPrivateNotifications = new SparseBooleanArray();
+    private Context mLightThemeContext;
+    private ImageUtils mImageUtils = new ImageUtils();
 
     // UI-specific methods
 
@@ -261,6 +276,8 @@
                 true,
                 mLockscreenSettingsObserver,
                 UserHandle.USER_ALL);
+        mLightThemeContext = new RemoteViewsThemeContextWrapper(mContext,
+                android.R.style.Theme_Holo_Light);
 
         mBarService = IStatusBarService.Stub.asInterface(
                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
@@ -412,6 +429,158 @@
         }
     }
 
+    private void processLegacyHoloNotification(StatusBarNotification sbn, View content) {
+
+        // TODO: Also skip processing if it is a holo-style notification.
+        // If the notification is custom, we can't process it.
+        if (!sbn.getNotification().extras.getBoolean(Notification.EXTRA_BUILDER_REMOTE_VIEWS)) {
+            return;
+        }
+
+        processLegacyHoloLargeIcon(content);
+        processLegacyHoloActions(content);
+        processLegacyNotificationIcon(content);
+        processLegacyTextViews(content);
+    }
+
+    /**
+     * @return the context to be used for the inflation of the specified {@code sbn}; this is
+     *      dependent whether the notification is quantum-style or holo-style
+     */
+    private Context getInflationContext(StatusBarNotification sbn) {
+
+        // TODO: Adjust this logic when we change the theme of the status bar windows.
+        if (sbn.getNotification().extras.getBoolean(Notification.EXTRA_BUILDER_REMOTE_VIEWS)) {
+            return mLightThemeContext;
+        } else {
+            return mContext;
+        }
+    }
+
+    private void processLegacyNotificationIcon(View content) {
+        View v = content.findViewById(com.android.internal.R.id.right_icon);
+        if (v != null & v instanceof ImageView) {
+            ImageView iv = (ImageView) v;
+            Drawable d = iv.getDrawable();
+            if (isMonochrome(d)) {
+                d.mutate();
+                d.setColorFilter(mLightThemeContext.getResources().getColor(
+                        R.color.notification_action_legacy_color_filter), PorterDuff.Mode.MULTIPLY);
+            }
+        }
+    }
+
+    private void processLegacyHoloLargeIcon(View content) {
+        View v = content.findViewById(com.android.internal.R.id.icon);
+        if (v != null & v instanceof ImageView) {
+            ImageView iv = (ImageView) v;
+            if (isMonochrome(iv.getDrawable())) {
+                iv.setBackground(mLightThemeContext.getResources().getDrawable(
+                        R.drawable.notification_icon_legacy_bg_inset));
+            }
+        }
+    }
+
+    private boolean isMonochrome(Drawable d) {
+        if (d == null) {
+            return false;
+        } else if (d instanceof BitmapDrawable) {
+            BitmapDrawable bd = (BitmapDrawable) d;
+            return bd.getBitmap() != null && mImageUtils.isGrayscale(bd.getBitmap());
+        } else if (d instanceof AnimationDrawable) {
+            AnimationDrawable ad = (AnimationDrawable) d;
+            int count = ad.getNumberOfFrames();
+            return count > 0 && isMonochrome(ad.getFrame(0));
+        } else {
+            return false;
+        }
+    }
+
+    private void processLegacyHoloActions(View content) {
+        View v = content.findViewById(com.android.internal.R.id.actions);
+        if (v != null & v instanceof ViewGroup) {
+            ViewGroup vg = (ViewGroup) v;
+            int childCount = vg.getChildCount();
+            for (int i = 0; i < childCount; i++) {
+                View child = vg.getChildAt(i);
+                if (child instanceof Button) {
+                    Button button = (Button) child;
+                    Drawable[] compoundDrawables = button.getCompoundDrawablesRelative();
+                    if (isMonochrome(compoundDrawables[0])) {
+                        Drawable d = compoundDrawables[0];
+                        d.mutate();
+                        d.setColorFilter(mLightThemeContext.getResources().getColor(
+                                R.color.notification_action_legacy_color_filter),
+                                PorterDuff.Mode.MULTIPLY);
+                    }
+                }
+            }
+        }
+    }
+
+    private void processLegacyTextViews(View content) {
+        Stack<View> viewStack = new Stack<View>();
+        viewStack.push(content);
+        while(!viewStack.isEmpty()) {
+            View current = viewStack.pop();
+            if(current instanceof ViewGroup){
+                ViewGroup currentGroup = (ViewGroup) current;
+                int numChildren = currentGroup.getChildCount();
+                for(int i=0;i<numChildren;i++){
+                    viewStack.push(currentGroup.getChildAt(i));
+                }
+            }
+            if (current instanceof TextView) {
+                processLegacyTextView((TextView) current);
+            }
+        }
+    }
+
+    private void processLegacyTextView(TextView textView) {
+        if (textView.getText() instanceof Spanned) {
+            Spanned ss = (Spanned) textView.getText();
+            Object[] spans = ss.getSpans(0, ss.length(), Object.class);
+            SpannableStringBuilder builder = new SpannableStringBuilder(ss.toString());
+            for (Object span : spans) {
+                Object resultSpan = span;
+                if (span instanceof TextAppearanceSpan) {
+                    resultSpan = processTextAppearanceSpan((TextAppearanceSpan) span);
+                }
+                builder.setSpan(resultSpan, ss.getSpanStart(span), ss.getSpanEnd(span),
+                        ss.getSpanFlags(span));
+            }
+            textView.setText(builder);
+        }
+    }
+
+    private TextAppearanceSpan processTextAppearanceSpan(TextAppearanceSpan span) {
+        ColorStateList colorStateList = span.getTextColor();
+        if (colorStateList != null) {
+            int[] colors = colorStateList.getColors();
+            boolean changed = false;
+            for (int i = 0; i < colors.length; i++) {
+                if (mImageUtils.isGrayscale(colors[i])) {
+                    colors[i] = processColor(colors[i]);
+                    changed = true;
+                }
+            }
+            if (changed) {
+                return new TextAppearanceSpan(
+                        span.getFamily(), span.getTextStyle(), span.getTextSize(),
+                        new ColorStateList(colorStateList.getStates(), colors),
+                        span.getLinkTextColor());
+            }
+        }
+        return span;
+    }
+
+    private int processColor(int color) {
+        return Color.argb(Color.alpha(color),
+                255 - Color.red(color),
+                255 - Color.green(color),
+                255 - Color.blue(color));
+    }
+
     private void startApplicationDetailsActivity(String packageName) {
         Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
                 Uri.fromParts("package", packageName, null));
@@ -748,9 +917,11 @@
         View contentViewLocal = null;
         View bigContentViewLocal = null;
         try {
-            contentViewLocal = contentView.apply(mContext, expanded, mOnClickHandler);
+            contentViewLocal = contentView.apply(getInflationContext(sbn), expanded,
+                    mOnClickHandler);
             if (bigContentView != null) {
-                bigContentViewLocal = bigContentView.apply(mContext, expanded, mOnClickHandler);
+                bigContentViewLocal = bigContentView.apply(getInflationContext(sbn), expanded,
+                        mOnClickHandler);
             }
         }
         catch (RuntimeException e) {
@@ -780,7 +951,7 @@
         View publicViewLocal = null;
         if (publicNotification != null) {
             try {
-                publicViewLocal = publicNotification.contentView.apply(mContext,
+                publicViewLocal = publicNotification.contentView.apply(getInflationContext(sbn),
                         expandedPublic, mOnClickHandler);
 
                 if (publicViewLocal != null) {
@@ -831,6 +1002,13 @@
         row.setDrawingCacheEnabled(true);
 
         applyLegacyRowBackground(sbn, content);
+        processLegacyHoloNotification(sbn, contentViewLocal);
+        if (bigContentViewLocal != null) {
+            processLegacyHoloNotification(sbn, bigContentViewLocal);
+        }
+        if (publicViewLocal != null) {
+            processLegacyHoloNotification(sbn, publicViewLocal);
+        }
 
         if (MULTIUSER_DEBUG) {
             TextView debug = (TextView) row.findViewById(R.id.debug_info);
@@ -1245,12 +1423,17 @@
                 : null;
 
         // Reapply the RemoteViews
-        contentView.reapply(mContext, entry.expanded, mOnClickHandler);
+        contentView.reapply(getInflationContext(notification), entry.expanded, mOnClickHandler);
+        processLegacyHoloNotification(notification, entry.expanded);
         if (bigContentView != null && entry.getBigContentView() != null) {
-            bigContentView.reapply(mContext, entry.getBigContentView(), mOnClickHandler);
+            bigContentView.reapply(getInflationContext(notification), entry.getBigContentView(),
+                    mOnClickHandler);
+            processLegacyHoloNotification(notification, entry.getBigContentView());
         }
         if (publicContentView != null && entry.getPublicContentView() != null) {
-            publicContentView.reapply(mContext, entry.getPublicContentView(), mOnClickHandler);
+            publicContentView.reapply(getInflationContext(notification),
+                    entry.getPublicContentView(), mOnClickHandler);
+            processLegacyHoloNotification(notification, entry.getPublicContentView());
         }
         // update the contentIntent
         final PendingIntent contentIntent = notification.getNotification().contentIntent;
@@ -1330,4 +1513,35 @@
         }
         mContext.unregisterReceiver(mBroadcastReceiver);
     }
+
+    /**
+     * A custom context theme wrapper that applies a platform theme to a created package context.
+     * This is useful if you want to inflate {@link RemoteViews} with a custom theme (normally, the
+     * theme used there is the default platform theme).
+     */
+    private static class RemoteViewsThemeContextWrapper extends ContextThemeWrapper {
+
+        private int mThemeRes;
+
+        private RemoteViewsThemeContextWrapper(Context base, int themeres) {
+            super(base, themeres);
+            mThemeRes = themeres;
+        }
+
+        @Override
+        public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
+                throws NameNotFoundException {
+            Context c = super.createPackageContextAsUser(packageName, flags, user);
+            c.setTheme(mThemeRes);
+            return c;
+        }
+
+        @Override
+        public Context createPackageContext(String packageName, int flags)
+                throws NameNotFoundException {
+            Context c = super.createPackageContext(packageName, flags);
+            c.setTheme(mThemeRes);
+            return c;
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
index 48ee1ce..174cad8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
@@ -996,8 +996,8 @@
         mInversionState.toggled = enabled;
         mInversionState.type = type;
         // TODO: Add real icon assets.
-        mInversionState.iconId = enabled ? R.drawable.ic_qs_bluetooth_on
-                : R.drawable.ic_qs_bluetooth_off;
+        mInversionState.iconId = enabled ? R.drawable.ic_qs_inversion_on
+                : R.drawable.ic_qs_inversion_off;
         mInversionState.label = res.getString(R.string.quick_settings_inversion_label);
         mInversionCallback.refreshView(mInversionTile, mInversionState);
     }
@@ -1026,8 +1026,8 @@
         mContrastState.contrast = contrast;
         mContrastState.brightness = brightness;
         // TODO: Add real icon assets.
-        mContrastState.iconId = enabled ? R.drawable.ic_qs_bluetooth_on
-                : R.drawable.ic_qs_bluetooth_off;
+        mContrastState.iconId = enabled ? R.drawable.ic_qs_contrast_on
+                : R.drawable.ic_qs_contrast_off;
         mContrastState.label = res.getString(R.string.quick_settings_contrast_label);
         mContrastCallback.refreshView(mContrastTile, mContrastState);
     }
@@ -1053,8 +1053,8 @@
         mColorSpaceState.toggled = enabled;
         mColorSpaceState.type = type;
         // TODO: Add real icon assets.
-        mColorSpaceState.iconId = enabled ? R.drawable.ic_qs_bluetooth_on
-                : R.drawable.ic_qs_bluetooth_off;
+        mColorSpaceState.iconId = enabled ? R.drawable.ic_qs_color_space_on
+                : R.drawable.ic_qs_color_space_off;
         mColorSpaceState.label = res.getString(R.string.quick_settings_color_space_label);
         mColorSpaceCallback.refreshView(mColorSpaceTile, mColorSpaceState);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java
index c4d2cce..fa7f96a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java
@@ -28,6 +28,8 @@
 import android.graphics.Typeface;
 import android.graphics.drawable.ShapeDrawable;
 import android.graphics.drawable.shapes.PathShape;
+import android.os.AsyncTask;
+import android.os.Vibrator;
 import android.text.Spannable;
 import android.text.SpannableStringBuilder;
 import android.text.TextPaint;
@@ -45,7 +47,6 @@
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.ListView;
-import android.widget.PopupWindow;
 import android.widget.RelativeLayout;
 import android.widget.Spinner;
 import android.widget.TextView;
@@ -79,6 +80,7 @@
     private final Rect mLayoutRect = new Rect();
     private final UntilPager mUntilPager;
     private final AlarmWarning mAlarmWarning;
+    private final int mPopDuration;
 
     private float mDownY;
     private int mDownBottom;
@@ -87,6 +89,7 @@
     private int mBottom;
     private int mWidthSpec;
     private Adapter mAdapter;
+    private boolean mPopped;
 
     public ZenModeView(Context context) {
         this(context, null);
@@ -144,7 +147,6 @@
         lp.addRule(RelativeLayout.CENTER_HORIZONTAL);
         addView(mModeSpinner, lp);
 
-
         mUntilPager = new UntilPager(mContext, mPathPaint, iconSize);
         mUntilPager.setId(android.R.id.tabhost);
         mUntilPager.setAlpha(0);
@@ -165,6 +167,8 @@
         mHintText.setGravity(Gravity.CENTER);
         mHintText.setTextColor(GRAY);
         addView(mHintText, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
+
+        mPopDuration = mContext.getResources().getInteger(R.integer.blinds_pop_duration_ms);
     }
 
     private boolean isApplicable() {
@@ -180,9 +184,11 @@
             public void onAnimationUpdate(ValueAnimator animation) {
                 final float f = animation.getAnimatedFraction();
                 final int hintBottom = mHintText.getBottom();
-                setPeeked(hintBottom + (int)((1-f) * (startBottom - hintBottom)), max);
-                if (f == 1) {
+                final boolean isDone = f == 1;
+                setPeeked(hintBottom + (int)((1-f) * (startBottom - hintBottom)), max, isDone);
+                if (isDone) {
                     mPeekable = true;
+                    mPopped = false;
                     mClosing = false;
                     mModeSpinner.updateState();
                     if (mAdapter != null) {
@@ -335,11 +341,15 @@
             return true;
         } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
             final float dy = event.getY() - mDownY;
-            setPeeked(mDownBottom + (int)dy, getExpandedBottom());
+            if (!mPopped) {
+                mPopped = true;
+                AsyncTask.execute(mPopVibration);
+            }
+            setPeeked(mDownBottom + (int)dy, getExpandedBottom(), false);
         } else if (event.getAction() == MotionEvent.ACTION_UP
                 || event.getAction() == MotionEvent.ACTION_CANCEL) {
             final float dy = event.getY() - mDownY;
-            setPeeked(mDownBottom + (int)dy, getExpandedBottom());
+            setPeeked(mDownBottom + (int)dy, getExpandedBottom(), true);
             if (mPeekable) {
                 close();
             }
@@ -347,14 +357,14 @@
         return rt;
     }
 
-    private void setPeeked(int peeked, int max) {
+    private void setPeeked(int peeked, int max, boolean isDone) {
         if (DEBUG) log("setPeeked=" + peeked);
         final int min = mHintText.getBottom();
         peeked = Math.max(min, Math.min(peeked, max));
-        if (mBottom == peeked) {
+        if (!isDone && mBottom == peeked) {
             return;
         }
-        if (peeked == max) {
+        if (peeked == max && isDone) {
             mPeekable = false;
             mModeSpinner.setEnabled(true);
             if (mAdapter != null) {
@@ -419,6 +429,14 @@
             }).start();
     }
 
+    private final Runnable mPopVibration = new Runnable() {
+        @Override
+        public void run() {
+            Vibrator v = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
+            v.vibrate(mPopDuration);
+        }
+    };
+
     private final class UntilPager extends RelativeLayout {
         private final ImageView mPrev;
         private final ImageView mNext;
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index abc3fb1..9ecb917 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -286,6 +286,7 @@
     int mUserRotation = Surface.ROTATION_0;
     boolean mAccelerometerDefault;
 
+    boolean mSupportAutoRotation;
     int mAllowAllRotations = -1;
     boolean mCarDockEnablesAccelerometer;
     boolean mDeskDockEnablesAccelerometer;
@@ -372,6 +373,7 @@
     static final Rect mTmpNavigationFrame = new Rect();
 
     WindowState mTopFullscreenOpaqueWindowState;
+    boolean mHideWindowBehindKeyguard;
     boolean mTopIsFullscreen;
     boolean mForceStatusBar;
     boolean mForceStatusBarFromKeyguard;
@@ -585,13 +587,15 @@
      * screen is switched off.
      */
     boolean needSensorRunningLp() {
-        if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
-                || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
-                || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
-                || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
-            // If the application has explicitly requested to follow the
-            // orientation, then we need to turn the sensor or.
-            return true;
+        if (mSupportAutoRotation) {
+            if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
+                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
+                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
+                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
+                // If the application has explicitly requested to follow the
+                // orientation, then we need to turn the sensor on.
+                return true;
+            }
         }
         if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) ||
                 (mDeskDockEnablesAccelerometer && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
@@ -612,7 +616,7 @@
             // still be turned off when the screen is off.)
             return false;
         }
-        return true;
+        return mSupportAutoRotation;
     }
 
     /*
@@ -877,6 +881,8 @@
         mBroadcastWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                 "PhoneWindowManager.mBroadcastWakeLock");
         mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
+        mSupportAutoRotation = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_supportAutoRotation);
         mLidOpenRotation = readRotation(
                 com.android.internal.R.integer.config_lidOpenRotation);
         mCarDockRotation = readRotation(
@@ -3355,6 +3361,7 @@
     @Override
     public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) {
         mTopFullscreenOpaqueWindowState = null;
+        mHideWindowBehindKeyguard = false;
         mForceStatusBar = false;
         mForceStatusBarFromKeyguard = false;
         mForcingShowNavBar = false;
@@ -3391,7 +3398,7 @@
             if (attrs.type == TYPE_KEYGUARD) {
                 mShowingLockscreen = true;
             }
-            boolean applyWindow = attrs.type >= FIRST_APPLICATION_WINDOW
+            boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
                     && attrs.type <= LAST_APPLICATION_WINDOW;
             if (attrs.type == TYPE_DREAM) {
                 // If the lockscreen was showing when the dream started then wait
@@ -3399,30 +3406,35 @@
                 if (!mDreamingLockscreen
                         || (win.isVisibleLw() && win.hasDrawnLw())) {
                     mShowingDream = true;
-                    applyWindow = true;
+                    appWindow = true;
                 }
             }
-            if (applyWindow
-                    && attrs.x == 0 && attrs.y == 0
-                    && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
-                    && attrs.height == WindowManager.LayoutParams.MATCH_PARENT) {
-                if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
-                mTopFullscreenOpaqueWindowState = win;
-                if ((fl & FLAG_SHOW_WHEN_LOCKED) != 0) {
-                    if (DEBUG_LAYOUT) Slog.v(TAG, "Setting mHideLockScreen to true by win " + win);
-                    mHideLockScreen = true;
-                    mForceStatusBarFromKeyguard = false;
-                }
-                if ((fl & FLAG_DISMISS_KEYGUARD) != 0
-                        && mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
-                    if (DEBUG_LAYOUT) Slog.v(TAG, "Setting mDismissKeyguard true by win " + win);
-                    mDismissKeyguard = mWinDismissingKeyguard == win ?
-                            DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START;
-                    mWinDismissingKeyguard = win;
-                    mForceStatusBarFromKeyguard = mShowingLockscreen && isKeyguardSecure();
-                }
-                if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
-                    mAllowLockscreenWhenOn = true;
+
+            final boolean showWhenLocked = (fl & FLAG_SHOW_WHEN_LOCKED) != 0;
+            if (appWindow) {
+                if (attrs.x == 0 && attrs.y == 0
+                        && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
+                        && attrs.height == WindowManager.LayoutParams.MATCH_PARENT) {
+                    if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
+                    mTopFullscreenOpaqueWindowState = win;
+                    if (showWhenLocked && !mHideWindowBehindKeyguard) {
+                        if (DEBUG_LAYOUT) Slog.v(TAG, "Setting mHideLockScreen to true by win " + win);
+                        mHideLockScreen = true;
+                        mForceStatusBarFromKeyguard = false;
+                    }
+                    if ((fl & FLAG_DISMISS_KEYGUARD) != 0
+                            && mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
+                        if (DEBUG_LAYOUT) Slog.v(TAG, "Setting mDismissKeyguard true by win " + win);
+                        mDismissKeyguard = mWinDismissingKeyguard == win ?
+                                DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START;
+                        mWinDismissingKeyguard = win;
+                        mForceStatusBarFromKeyguard = mShowingLockscreen && isKeyguardSecure();
+                    }
+                    if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
+                        mAllowLockscreenWhenOn = true;
+                    }
+                } else if (!showWhenLocked) {
+                    mHideWindowBehindKeyguard = true;
                 }
             }
         }
@@ -3509,7 +3521,7 @@
         if (mKeyguard != null) {
             if (localLOGV) Slog.v(TAG, "finishPostLayoutPolicyLw: mHideKeyguard="
                     + mHideLockScreen);
-            if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !mKeyguardDelegate.isSecure()) {
+            if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !isKeyguardSecure()) {
                 if (mKeyguard.hideLw(true)) {
                     changes |= FINISH_LAYOUT_REDO_LAYOUT
                             | FINISH_LAYOUT_REDO_CONFIG
@@ -3797,7 +3809,9 @@
                                                 mKeyguardDelegate.isShowingAndNotHidden() :
                                                 mKeyguardDelegate.isShowing()));
 
-        if (keyCode == KeyEvent.KEYCODE_POWER) {
+        if (keyCode == KeyEvent.KEYCODE_POWER
+                || keyCode == KeyEvent.KEYCODE_SLEEP
+                || keyCode == KeyEvent.KEYCODE_WAKEUP) {
             policyFlags |= WindowManagerPolicy.FLAG_WAKE;
         }
 
@@ -3997,6 +4011,18 @@
                 break;
             }
 
+            case KeyEvent.KEYCODE_SLEEP: {
+                result &= ~ACTION_PASS_TO_USER;
+                mPowerManager.goToSleep(event.getEventTime());
+                isWakeKey = false;
+                break;
+            }
+
+            case KeyEvent.KEYCODE_WAKEUP: {
+                result &= ~ACTION_PASS_TO_USER;
+                break;
+            }
+
             case KeyEvent.KEYCODE_MEDIA_PLAY:
             case KeyEvent.KEYCODE_MEDIA_PAUSE:
             case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
@@ -4481,6 +4507,10 @@
             } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
                 // Application just wants to remain locked in the last rotation.
                 preferredRotation = lastRotation;
+            } else if (!mSupportAutoRotation) {
+                // If we don't support auto-rotation then bail out here and ignore
+                // the sensor and any rotation lock settings.
+                preferredRotation = -1;
             } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
                             && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
                                     || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
@@ -5297,6 +5327,7 @@
             pw.print(prefix); pw.print("mLastFocusNeedsMenu=");
                     pw.println(mLastFocusNeedsMenu);
         }
+        pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation);
         pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
                 pw.print(" mDockMode="); pw.print(mDockMode);
                 pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index f03a8e0..bda0183 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -1283,7 +1283,10 @@
                                 setWakelockWorkSource(alarm.operation, alarm.workSource);
                                 mWakeLock.setUnimportantForLogging(
                                         alarm.operation == mTimeTickSender);
-                                mWakeLock.setHistoryTag(alarm.operation.getTag("*alarm*:"));
+                                mWakeLock.setHistoryTag(alarm.operation.getTag(
+                                        alarm.type == ELAPSED_REALTIME_WAKEUP
+                                                || alarm.type == RTC_WAKEUP
+                                                ? "*walarm*:" : "*alarm*:"));
                                 mWakeLock.acquire();
                             }
                             final InFlight inflight = new InFlight(AlarmManagerService.this,
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index a7ef424..cd74fed 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -80,7 +80,6 @@
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.PrintWriter;
-import java.io.UnsupportedEncodingException;
 import java.math.BigInteger;
 import java.nio.charset.StandardCharsets;
 import java.security.NoSuchAlgorithmException;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index f39e634..864211d 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1075,6 +1075,7 @@
     static final int PERSIST_URI_GRANTS_MSG = 38;
     static final int REQUEST_ALL_PSS_MSG = 39;
     static final int START_RELATED_USERS_MSG = 40;
+    static final int UPDATE_TIME = 41;
 
     static final int FIRST_ACTIVITY_STACK_MSG = 100;
     static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -1694,6 +1695,21 @@
                 }
                 break;
             }
+            case UPDATE_TIME: {
+                synchronized (ActivityManagerService.this) {
+                    for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
+                        ProcessRecord r = mLruProcesses.get(i);
+                        if (r.thread != null) {
+                            try {
+                                r.thread.updateTimePrefs(msg.arg1 == 0 ? false : true);
+                            } catch (RemoteException ex) {
+                                Slog.w(TAG, "Failed to update preferences for: " + r.info.processName);
+                            }
+                        }
+                    }
+                }
+                break;
+            }
             }
         }
     };
@@ -9213,8 +9229,13 @@
                         ActivityInfo ai = ris.get(i).activityInfo;
                         ComponentName comp = new ComponentName(ai.packageName, ai.name);
                         if (lastDoneReceivers.contains(comp)) {
+                            // We already did the pre boot receiver for this app with the current
+                            // platform version, so don't do it again...
                             ris.remove(i);
                             i--;
+                            // ...however, do keep it as one that has been done, so we don't
+                            // forget about it when rewriting the file of last done receivers.
+                            doneReceivers.add(comp);
                         }
                     }
 
@@ -13442,11 +13463,20 @@
          * of all currently running processes. This message will get queued up before the broadcast
          * happens.
          */
-        if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
+        if (Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
             mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
         }
 
-        if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
+        /*
+         * If the user set the time, let all running processes know.
+         */
+        if (Intent.ACTION_TIME_CHANGED.equals(intent.getAction())) {
+            final int is24Hour = intent.getBooleanExtra(
+                    Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT, false) ? 1 : 0;
+            mHandler.sendMessage(mHandler.obtainMessage(UPDATE_TIME, is24Hour, 0));
+        }
+
+        if (Intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
             mHandler.sendEmptyMessage(CLEAR_DNS_CACHE_MSG);
         }
 
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index fc7aac2..39bfc23 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -48,6 +48,8 @@
  * battery life.
  */
 public final class BatteryStatsService extends IBatteryStats.Stub {
+    static final String TAG = "BatteryStatsService";
+
     static IBatteryStats sService;
     
     final BatteryStatsImpl mStats;
@@ -66,7 +68,8 @@
         mStats.setRadioScanningTimeout(mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_radioScanningTimeout)
                 * 1000L);
-    }
+        (new WakeupReasonThread()).start();
+     }
     
     public void shutdown() {
         Slog.w("BatteryStats", "Writing battery stats before shutdown...");
@@ -538,14 +541,45 @@
         mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS,
                 Binder.getCallingPid(), Binder.getCallingUid(), null);
     }
-    
+
+    final class WakeupReasonThread extends Thread {
+        final int[] mIrqs = new int[32];
+        final String[] mReasons = new String[32];
+
+        WakeupReasonThread() {
+            super("BatteryStats_wakeupReason");
+        }
+
+        public void run() {
+            Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
+
+            try {
+                int num;
+                while ((num=nativeWaitWakeup(mIrqs, mReasons)) >= 0) {
+                    synchronized (mStats) {
+                        for (int i=0; i<num; i++) {
+                            //Slog.i(TAG, "Wakeup: irq #" + mIrqs[i] + " reason=" + mReasons[i]);
+                            mStats.noteWakeupReasonLocked(mIrqs[i], mReasons[i]);
+                        }
+                    }
+                }
+            } catch (RuntimeException e) {
+                Slog.e(TAG, "Failure reading wakeup reasons", e);
+            }
+        }
+    }
+
+    private static native int nativeWaitWakeup(int[] outIrqs, String[] outReasons);
+
     private void dumpHelp(PrintWriter pw) {
         pw.println("Battery stats (batterystats) dump options:");
-        pw.println("  [--checkin] [--history] [-c] [--unplugged] [--reset] [--write]");
-        pw.println("  [-h] [<package.name>]");
+        pw.println("  [--checkin] [--history] [--history-start] [--unplugged] [--charged] [-c]");
+        pw.println("  [--reset] [--write] [-h] [<package.name>]");
         pw.println("  --checkin: format output for a checkin report.");
         pw.println("  --history: show only history data.");
+        pw.println("  --history-start <num>: show only history data starting at given time offset.");
         pw.println("  --unplugged: only output data since last unplugged.");
+        pw.println("  --charged: only output data since last charged.");
         pw.println("  --reset: reset the stats, clearing all current data.");
         pw.println("  --write: force write current collected stats to disk.");
         pw.println("  -h: print this help text.");
@@ -562,23 +596,34 @@
             return;
         }
 
+        int flags = 0;
         boolean isCheckin = false;
-        boolean includeHistory = false;
-        boolean historyOnly = false;
-        boolean isUnpluggedOnly = false;
         boolean noOutput = false;
+        long historyStart = -1;
         int reqUid = -1;
         if (args != null) {
-            for (String arg : args) {
+            for (int i=0; i<args.length; i++) {
+                String arg = args[i];
                 if ("--checkin".equals(arg)) {
                     isCheckin = true;
                 } else if ("--history".equals(arg)) {
-                    historyOnly = true;
+                    flags |= BatteryStats.DUMP_HISTORY_ONLY;
+                } else if ("--history-start".equals(arg)) {
+                    flags |= BatteryStats.DUMP_HISTORY_ONLY;
+                    i++;
+                    if (i >= args.length) {
+                        pw.println("Missing time argument for --history-since");
+                        dumpHelp(pw);
+                        return;
+                    }
+                    historyStart = Long.parseLong(args[i]);
                 } else if ("-c".equals(arg)) {
                     isCheckin = true;
-                    includeHistory = true;
+                    flags |= BatteryStats.DUMP_INCLUDE_HISTORY;
                 } else if ("--unplugged".equals(arg)) {
-                    isUnpluggedOnly = true;
+                    flags |= BatteryStats.DUMP_UNPLUGGED_ONLY;
+                } else if ("--charged".equals(arg)) {
+                    flags |= BatteryStats.DUMP_CHARGED_ONLY;
                 } else if ("--reset".equals(arg)) {
                     synchronized (mStats) {
                         mStats.resetAllStatsCmdLocked();
@@ -619,12 +664,11 @@
         if (isCheckin) {
             List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(0);
             synchronized (mStats) {
-                mStats.dumpCheckinLocked(mContext, pw, apps, isUnpluggedOnly, includeHistory,
-                        historyOnly);
+                mStats.dumpCheckinLocked(mContext, pw, apps, flags, historyStart);
             }
         } else {
             synchronized (mStats) {
-                mStats.dumpLocked(mContext, pw, isUnpluggedOnly, reqUid, historyOnly);
+                mStats.dumpLocked(mContext, pw, flags, reqUid, historyStart);
             }
         }
     }
diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index 10ea67c..4c887dd 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -37,11 +37,16 @@
     private static final String LOG_TAG = CoreSettingsObserver.class.getSimpleName();
 
     // mapping form property name to its type
-    private static final Map<String, Class<?>> sCoreSettingToTypeMap = new HashMap<
+    private static final Map<String, Class<?>> sSecureSettingToTypeMap = new HashMap<
+            String, Class<?>>();
+    private static final Map<String, Class<?>> sSystemSettingToTypeMap = new HashMap<
             String, Class<?>>();
     static {
-        sCoreSettingToTypeMap.put(Settings.Secure.LONG_PRESS_TIMEOUT, int.class);
-        // add other core settings here...
+        sSecureSettingToTypeMap.put(Settings.Secure.LONG_PRESS_TIMEOUT, int.class);
+        // add other secure settings here...
+
+        sSystemSettingToTypeMap.put(Settings.System.TIME_12_24, String.class);
+        // add other system settings here...
     }
 
     private final Bundle mCoreSettings = new Bundle();
@@ -67,39 +72,62 @@
     }
 
     private void sendCoreSettings() {
-        populateCoreSettings(mCoreSettings);
+        populateSettings(mCoreSettings, sSecureSettingToTypeMap);
+        populateSettings(mCoreSettings, sSystemSettingToTypeMap);
         mActivityManagerService.onCoreSettingsChange(mCoreSettings);
     }
 
     private void beginObserveCoreSettings() {
-        for (String setting : sCoreSettingToTypeMap.keySet()) {
+        for (String setting : sSecureSettingToTypeMap.keySet()) {
             Uri uri = Settings.Secure.getUriFor(setting);
             mActivityManagerService.mContext.getContentResolver().registerContentObserver(
                     uri, false, this);
         }
+
+        for (String setting : sSystemSettingToTypeMap.keySet()) {
+            Uri uri = Settings.System.getUriFor(setting);
+            mActivityManagerService.mContext.getContentResolver().registerContentObserver(
+                    uri, false, this);
+        }
     }
 
-    private void populateCoreSettings(Bundle snapshot) {
+    private void populateSettings(Bundle snapshot, Map<String, Class<?>> map) {
         Context context = mActivityManagerService.mContext;
-        for (Map.Entry<String, Class<?>> entry : sCoreSettingToTypeMap.entrySet()) {
+        for (Map.Entry<String, Class<?>> entry : map.entrySet()) {
             String setting = entry.getKey();
             Class<?> type = entry.getValue();
             try {
                 if (type == String.class) {
-                    String value = Settings.Secure.getString(context.getContentResolver(),
-                            setting);
+                    final String value;
+                    if (map == sSecureSettingToTypeMap) {
+                        value = Settings.Secure.getString(context.getContentResolver(), setting);
+                    } else {
+                        value = Settings.System.getString(context.getContentResolver(), setting);
+                    }
                     snapshot.putString(setting, value);
                 } else if (type == int.class) {
-                    int value = Settings.Secure.getInt(context.getContentResolver(),
-                            setting);
+                    final int value;
+                    if (map == sSecureSettingToTypeMap) {
+                        value = Settings.Secure.getInt(context.getContentResolver(), setting);
+                    } else {
+                        value = Settings.System.getInt(context.getContentResolver(), setting);
+                    }
                     snapshot.putInt(setting, value);
                 } else if (type == float.class) {
-                    float value = Settings.Secure.getFloat(context.getContentResolver(),
-                            setting);
+                    final float value;
+                    if (map == sSecureSettingToTypeMap) {
+                        value = Settings.Secure.getFloat(context.getContentResolver(), setting);
+                    } else {
+                        value = Settings.System.getFloat(context.getContentResolver(), setting);
+                    }
                     snapshot.putFloat(setting, value);
                 } else if (type == long.class) {
-                    long value = Settings.Secure.getLong(context.getContentResolver(),
-                            setting);
+                    final long value;
+                    if (map == sSecureSettingToTypeMap) {
+                        value = Settings.Secure.getLong(context.getContentResolver(), setting);
+                    } else {
+                        value = Settings.System.getLong(context.getContentResolver(), setting);
+                    }
                     snapshot.putLong(setting, value);
                 }
             } catch (SettingNotFoundException snfe) {
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index ad6eabd..b7e367b 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -218,6 +218,19 @@
         builder.append(' ');
         builder.append(uid);
         builder.append(isPublic ? " 1" : " 0");
+        builder.append(" *");         // No pkgName arg present
+        return execute(builder.toString());
+    }
+
+    public int dexopt(String apkPath, int uid, boolean isPublic, String pkgName) {
+        StringBuilder builder = new StringBuilder("dexopt");
+        builder.append(' ');
+        builder.append(apkPath);
+        builder.append(' ');
+        builder.append(uid);
+        builder.append(isPublic ? " 1" : " 0");
+        builder.append(' ');
+        builder.append(pkgName);
         return execute(builder.toString());
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 7f00ce7..cbcf408 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1216,7 +1216,7 @@
                         continue;
                     }
                     try {
-                        if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
+                        if (dalvik.system.DexFile.isDexOptNeededInternal(lib, null, false)) {
                             alreadyDexOpted.add(lib);
                             mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
                             didDexOpt = true;
@@ -1260,7 +1260,7 @@
                         continue;
                     }
                     try {
-                        if (dalvik.system.DexFile.isDexOptNeeded(path)) {
+                        if (dalvik.system.DexFile.isDexOptNeededInternal(path, null, false)) {
                             mInstaller.dexopt(path, Process.SYSTEM_UID, true);
                             didDexOpt = true;
                         }
@@ -4088,7 +4088,8 @@
             String path = pkg.mScanPath;
             int ret = 0;
             try {
-                if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
+                if (forceDex || dalvik.system.DexFile.isDexOptNeededInternal(path, pkg.packageName,
+                                                                             defer)) {
                     if (!forceDex && defer) {
                         if (mDeferredDexOpt == null) {
                             mDeferredDexOpt = new HashSet<PackageParser.Package>();
@@ -4098,7 +4099,8 @@
                     } else {
                         Log.i(TAG, "Running dexopt on: " + pkg.applicationInfo.packageName);
                         final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
-                        ret = mInstaller.dexopt(path, sharedGid, !isForwardLocked(pkg));
+                        ret = mInstaller.dexopt(path, sharedGid, !isForwardLocked(pkg),
+                                                pkg.packageName);
                         pkg.mDidDexOpt = true;
                         performed = true;
                     }
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 97ea52c..87953fe 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -230,7 +230,6 @@
         public void onServiceConnected(ComponentName name, IBinder service) {
             synchronized (mLock) {
                 if (mWallpaper.connection == this) {
-                    mWallpaper.lastDiedTime = SystemClock.uptimeMillis();
                     mService = IWallpaperService.Stub.asInterface(service);
                     attachServiceLocked(this, mWallpaper);
                     // XXX should probably do saveSettingsLocked() later
@@ -250,11 +249,21 @@
                 if (mWallpaper.connection == this) {
                     Slog.w(TAG, "Wallpaper service gone: " + mWallpaper.wallpaperComponent);
                     if (!mWallpaper.wallpaperUpdating
-                            && (mWallpaper.lastDiedTime + MIN_WALLPAPER_CRASH_TIME)
-                                > SystemClock.uptimeMillis()
                             && mWallpaper.userId == mCurrentUserId) {
-                        Slog.w(TAG, "Reverting to built-in wallpaper!");
-                        clearWallpaperLocked(true, mWallpaper.userId, null);
+                        // There is a race condition which causes
+                        // {@link #mWallpaper.wallpaperUpdating} to be false even if it is
+                        // currently updating since the broadcast notifying us is async.
+                        // This race is overcome by the general rule that we only reset the
+                        // wallpaper if its service was shut down twice
+                        // during {@link #MIN_WALLPAPER_CRASH_TIME} millis.
+                        if (mWallpaper.lastDiedTime != 0
+                                && mWallpaper.lastDiedTime + MIN_WALLPAPER_CRASH_TIME
+                                    > SystemClock.uptimeMillis()) {
+                            Slog.w(TAG, "Reverting to built-in wallpaper!");
+                            clearWallpaperLocked(true, mWallpaper.userId, null);
+                        } else {
+                            mWallpaper.lastDiedTime = SystemClock.uptimeMillis();
+                        }
                     }
                 }
             }
@@ -938,7 +947,6 @@
             }
             wallpaper.wallpaperComponent = componentName;
             wallpaper.connection = newConn;
-            wallpaper.lastDiedTime = SystemClock.uptimeMillis();
             newConn.mReply = reply;
             try {
                 if (wallpaper.userId == mCurrentUserId) {
diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk
index 56144b0..0607925 100644
--- a/services/core/jni/Android.mk
+++ b/services/core/jni/Android.mk
@@ -6,6 +6,7 @@
 
 LOCAL_SRC_FILES += \
     $(LOCAL_REL_DIR)/com_android_server_AlarmManagerService.cpp \
+    $(LOCAL_REL_DIR)/com_android_server_am_BatteryStatsService.cpp \
     $(LOCAL_REL_DIR)/com_android_server_AssetAtlasService.cpp \
     $(LOCAL_REL_DIR)/com_android_server_ConsumerIrService.cpp \
     $(LOCAL_REL_DIR)/com_android_server_dreams_McuHal.cpp \
diff --git a/services/core/jni/com_android_server_am_BatteryStatsService.cpp b/services/core/jni/com_android_server_am_BatteryStatsService.cpp
new file mode 100644
index 0000000..22cc519
--- /dev/null
+++ b/services/core/jni/com_android_server_am_BatteryStatsService.cpp
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BatteryStatsService"
+//#define LOG_NDEBUG 0
+
+#include <android_runtime/AndroidRuntime.h>
+#include <jni.h>
+
+#include <ScopedLocalRef.h>
+#include <ScopedPrimitiveArray.h>
+
+#include <cutils/log.h>
+#include <utils/misc.h>
+#include <utils/Log.h>
+#include <hardware/hardware.h>
+#include <suspend/autosuspend.h>
+
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <semaphore.h>
+#include <stddef.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+namespace android
+{
+
+#define LAST_RESUME_REASON "/sys/kernel/wakeup_reasons/last_resume_reason"
+#define MAX_REASON_SIZE 512
+
+static bool wakeup_init = false;
+static sem_t wakeup_sem;
+
+static void wakeup_callback(void)
+{
+    ALOGV("In wakeup_callback");
+    int ret = sem_post(&wakeup_sem);
+    if (ret < 0) {
+        char buf[80];
+        strerror_r(errno, buf, sizeof(buf));
+        ALOGE("Error posting wakeup sem: %s\n", buf);
+    }
+}
+
+static jint nativeWaitWakeup(JNIEnv *env, jobject clazz, jintArray outIrqs,
+        jobjectArray outReasons)
+{
+    bool first_time = false;
+
+    if (outIrqs == NULL || outReasons == NULL) {
+        jniThrowException(env, "java/lang/NullPointerException", "null argument");
+        return -1;
+    }
+
+    // Register our wakeup callback if not yet done.
+    if (!wakeup_init) {
+        wakeup_init = true;
+        ALOGV("Creating semaphore...");
+        int ret = sem_init(&wakeup_sem, 0, 0);
+        if (ret < 0) {
+            char buf[80];
+            strerror_r(errno, buf, sizeof(buf));
+            ALOGE("Error creating semaphore: %s\n", buf);
+            jniThrowException(env, "java/lang/IllegalStateException", buf);
+            return -1;
+        }
+        ALOGV("Registering callback...");
+        set_wakeup_callback(&wakeup_callback);
+        // First time through, we will just drain the current wakeup reasons.
+        first_time = true;
+    } else {
+        // On following calls, we need to wait for wakeup.
+        ALOGV("Waiting for wakeup...");
+        int ret = sem_wait(&wakeup_sem);
+        if (ret < 0) {
+            char buf[80];
+            strerror_r(errno, buf, sizeof(buf));
+            ALOGE("Error waiting on semaphore: %s\n", buf);
+            // Return 0 here to let it continue looping but not return results.
+            return 0;
+        }
+    }
+
+    FILE *fp = fopen(LAST_RESUME_REASON, "r");
+    if (fp == NULL) {
+        ALOGE("Failed to open %s", LAST_RESUME_REASON);
+        return -1;
+    }
+
+    int numOut = env->GetArrayLength(outIrqs);
+    ScopedIntArrayRW irqs(env, outIrqs);
+
+    ALOGV("Reading up to %d wakeup reasons", numOut);
+
+    char mergedreason[MAX_REASON_SIZE];
+    char* mergedreasonpos = mergedreason;
+    int remainreasonlen = MAX_REASON_SIZE;
+    int firstirq = 0;
+    char reasonline[128];
+    int i = 0;
+    while (fgets(reasonline, sizeof(reasonline), fp) != NULL && i < numOut) {
+        char* pos = reasonline;
+        char* endPos;
+        // First field is the index.
+        int irq = (int)strtol(pos, &endPos, 10);
+        if (pos == endPos) {
+            // Ooops.
+            ALOGE("Bad reason line: %s", reasonline);
+            continue;
+        }
+        pos = endPos;
+        // Skip whitespace; rest of the buffer is the reason string.
+        while (*pos == ' ') {
+            pos++;
+        }
+        // Chop newline at end.
+        char* endpos = pos;
+        while (*endpos != 0) {
+            if (*endpos == '\n') {
+                *endpos = 0;
+                break;
+            }
+            endpos++;
+        }
+        if (i == 0) {
+            firstirq = irq;
+        } else {
+            int len = snprintf(mergedreasonpos, remainreasonlen, ":%d", irq);
+            if (len >= 0 && len < remainreasonlen) {
+                mergedreasonpos += len;
+                remainreasonlen -= len;
+            }
+        }
+        int len = snprintf(mergedreasonpos, remainreasonlen, i == 0 ? "%s" : ":%s", pos);
+        if (len >= 0 && len < remainreasonlen) {
+            mergedreasonpos += len;
+            remainreasonlen -= len;
+        }
+        // For now it is better to combine all of these in to one entry in the
+        // battery history.  In the future, it might be nice to figure out a way
+        // to efficiently store multiple lines as a single entry in the history.
+        //irqs[i] = irq;
+        //ScopedLocalRef<jstring> reasonString(env, env->NewStringUTF(pos));
+        //env->SetObjectArrayElement(outReasons, i, reasonString.get());
+        //ALOGV("Wakeup reason #%d: irw %d reason %s", i, irq, pos);
+        i++;
+    }
+
+    ALOGV("Got %d reasons", i);
+    if (first_time) {
+        i = 0;
+    }
+    if (i > 0) {
+        irqs[0] = firstirq;
+        *mergedreasonpos = 0;
+        ScopedLocalRef<jstring> reasonString(env, env->NewStringUTF(mergedreason));
+        env->SetObjectArrayElement(outReasons, 0, reasonString.get());
+        i = 1;
+    }
+
+    if (fclose(fp) != 0) {
+        ALOGE("Failed to close %s", LAST_RESUME_REASON);
+        return -1;
+    }
+
+    return first_time ? 0 : i;
+}
+
+static JNINativeMethod method_table[] = {
+    { "nativeWaitWakeup", "([I[Ljava/lang/String;)I", (void*)nativeWaitWakeup },
+};
+
+int register_android_server_BatteryStatsService(JNIEnv *env)
+{
+    return jniRegisterNativeMethods(env, "com/android/server/am/BatteryStatsService",
+            method_table, NELEM(method_table));
+}
+
+};
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index 00986d5..ac6585b 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -21,6 +21,7 @@
 
 namespace android {
 int register_android_server_AlarmManagerService(JNIEnv* env);
+int register_android_server_BatteryStatsService(JNIEnv* env);
 int register_android_server_ConsumerIrService(JNIEnv *env);
 int register_android_server_InputApplicationHandle(JNIEnv* env);
 int register_android_server_InputWindowHandle(JNIEnv* env);
@@ -69,6 +70,7 @@
     register_android_server_AssetAtlasService(env);
     register_android_server_ConsumerIrService(env);
     register_android_server_dreams_McuHal(env);
+    register_android_server_BatteryStatsService(env);
 
     return JNI_VERSION_1_4;
 }
diff --git a/tests/HwAccelerationTest/res/layout/isolation.xml b/tests/HwAccelerationTest/res/layout/isolation.xml
index 32eb628..e66db19 100644
--- a/tests/HwAccelerationTest/res/layout/isolation.xml
+++ b/tests/HwAccelerationTest/res/layout/isolation.xml
@@ -15,7 +15,6 @@
             android:layout_width="0dp"
             android:layout_height="200dp"
             android:layout_weight="1"
-            android:isolatedZVolume="false"
             android:orientation="vertical">
             <TextView style="@style/TopLeftReorderTextView"/>
             <TextView style="@style/BottomLeftReorderTextView"/>
@@ -25,7 +24,6 @@
             android:layout_height="200dp"
             android:layout_weight="1"
             android:translationY="50dp"
-            android:isolatedZVolume="false"
             android:orientation="vertical">
             <TextView style="@style/TopRightReorderTextView"/>
             <TextView style="@style/BottomRightReorderTextView"/>
diff --git a/tools/aapt/Android.mk b/tools/aapt/Android.mk
index 2949f8e..806f8ff 100644
--- a/tools/aapt/Android.mk
+++ b/tools/aapt/Android.mk
@@ -5,7 +5,7 @@
 #
 
 # This tool is prebuilt if we're doing an app-only build.
-ifeq ($(TARGET_BUILD_APPS),)
+ifeq ($(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)),)
 
 
 aapt_src_files := \
@@ -101,4 +101,4 @@
 include $(BUILD_EXECUTABLE)
 endif
 
-endif # TARGET_BUILD_APPS
+endif # No TARGET_BUILD_APPS or TARGET_BUILD_PDK
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 8e856b7..44b8340 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -435,6 +435,7 @@
     LARGEST_WIDTH_LIMIT_DP_ATTR = 0x01010366,
     PUBLIC_KEY_ATTR = 0x010103a6,
     CATEGORY_ATTR = 0x010103e8,
+    BANNER_ATTR = 0x10103f2,
 };
 
 String8 getComponentName(String8 &pkgName, String8 &componentName) {
@@ -762,6 +763,7 @@
             bool withinActivity = false;
             bool isMainActivity = false;
             bool isLauncherActivity = false;
+            bool isLeanbackLauncherActivity = false;
             bool isSearchable = false;
             bool withinApplication = false;
             bool withinSupportsInput = false;
@@ -872,6 +874,7 @@
             String8 activityName;
             String8 activityLabel;
             String8 activityIcon;
+            String8 activityBanner;
             String8 receiverName;
             String8 serviceName;
             Vector<String8> supportedInput;
@@ -896,16 +899,29 @@
                         withinApplication = false;
                         withinSupportsInput = false;
                     } else if (depth < 3) {
-                        if (withinActivity && isMainActivity && isLauncherActivity) {
+                        if (withinActivity && isMainActivity) {
                             String8 aName(getComponentName(pkg, activityName));
-                            printf("launchable-activity:");
-                            if (aName.length() > 0) {
-                                printf(" name='%s' ",
-                                        ResTable::normalizeForOutput(aName.string()).string());
+                            if (isLauncherActivity) {
+                                printf("launchable-activity:");
+                                if (aName.length() > 0) {
+                                    printf(" name='%s' ",
+                                            ResTable::normalizeForOutput(aName.string()).string());
+                                }
+                                printf(" label='%s' icon='%s'\n",
+                                        ResTable::normalizeForOutput(activityLabel.string()).string(),
+                                        ResTable::normalizeForOutput(activityIcon.string()).string());
                             }
-                            printf(" label='%s' icon='%s'\n",
-                                    ResTable::normalizeForOutput(activityLabel.string()).string(),
-                                    ResTable::normalizeForOutput(activityIcon.string()).string());
+                            if (isLeanbackLauncherActivity) {
+                                printf("leanback-launchable-activity:");
+                                if (aName.length() > 0) {
+                                    printf(" name='%s' ",
+                                            ResTable::normalizeForOutput(aName.string()).string());
+                                }
+                                printf(" label='%s' icon='%s' banner='%s'\n",
+                                        ResTable::normalizeForOutput(activityLabel.string()).string(),
+                                        ResTable::normalizeForOutput(activityIcon.string()).string(),
+                                        ResTable::normalizeForOutput(activityBanner.string()).string());
+                            }
                         }
                         if (!hasIntentFilter) {
                             hasOtherActivities |= withinActivity;
@@ -923,7 +939,7 @@
                         withinService = false;
                         withinReceiver = false;
                         hasIntentFilter = false;
-                        isMainActivity = isLauncherActivity = false;
+                        isMainActivity = isLauncherActivity = isLeanbackLauncherActivity = false;
                     } else if (depth < 4) {
                         if (withinIntentFilter) {
                             if (withinActivity) {
@@ -1329,6 +1345,13 @@
                                 goto bail;
                             }
 
+                            activityBanner = getResolvedAttribute(&res, tree, BANNER_ATTR, &error);
+                            if (error != "") {
+                                fprintf(stderr, "ERROR getting 'android:banner' attribute: %s\n",
+                                        error.string());
+                                goto bail;
+                            }
+
                             int32_t orien = getResolvedIntegerAttribute(&res, tree,
                                     SCREEN_ORIENTATION_ATTR, &error);
                             if (error == "") {
@@ -1538,6 +1561,8 @@
                         if (withinActivity) {
                             if (category == "android.intent.category.LAUNCHER") {
                                 isLauncherActivity = true;
+                            } else if (category == "android.intent.category.LEANBACK_LAUNCHER") {
+                                isLeanbackLauncherActivity = true;
                             }
                         }
                     }
diff --git a/tools/aapt/Images.cpp b/tools/aapt/Images.cpp
index b1a548e..12f5b92 100644
--- a/tools/aapt/Images.cpp
+++ b/tools/aapt/Images.cpp
@@ -35,7 +35,9 @@
 // This holds an image as 8bpp RGBA.
 struct image_info
 {
-    image_info() : rows(NULL), is9Patch(false), allocRows(NULL) { }
+    image_info() : rows(NULL), is9Patch(false),
+        xDivs(NULL), yDivs(NULL), colors(NULL), allocRows(NULL) { }
+
     ~image_info() {
         if (rows && rows != allocRows) {
             free(rows);
@@ -46,9 +48,15 @@
             }
             free(allocRows);
         }
-        free(info9Patch.xDivs);
-        free(info9Patch.yDivs);
-        free(info9Patch.colors);
+        free(xDivs);
+        free(yDivs);
+        free(colors);
+    }
+
+    void* serialize9patch() {
+        void* serialized = Res_png_9patch::serialize(info9Patch, xDivs, yDivs, colors);
+        reinterpret_cast<Res_png_9patch*>(serialized)->deviceToFile();
+        return serialized;
     }
 
     png_uint_32 width;
@@ -58,6 +66,9 @@
     // 9-patch info.
     bool is9Patch;
     Res_png_9patch info9Patch;
+    int32_t* xDivs;
+    int32_t* yDivs;
+    uint32_t* colors;
 
     // Layout padding, if relevant
     bool haveLayoutBounds;
@@ -440,10 +451,10 @@
 {
     int left, right, top, bottom;
     select_patch(
-        hpatch, image->info9Patch.xDivs[0], image->info9Patch.xDivs[1],
+        hpatch, image->xDivs[0], image->xDivs[1],
         image->width, &left, &right);
     select_patch(
-        vpatch, image->info9Patch.yDivs[0], image->info9Patch.yDivs[1],
+        vpatch, image->yDivs[0], image->yDivs[1],
         image->height, &top, &bottom);
     //printf("Selecting h=%d v=%d: (%d,%d)-(%d,%d)\n",
     //       hpatch, vpatch, left, top, right, bottom);
@@ -462,10 +473,11 @@
 
     int maxSizeXDivs = W * sizeof(int32_t);
     int maxSizeYDivs = H * sizeof(int32_t);
-    int32_t* xDivs = image->info9Patch.xDivs = (int32_t*) malloc(maxSizeXDivs);
-    int32_t* yDivs = image->info9Patch.yDivs = (int32_t*) malloc(maxSizeYDivs);
-    uint8_t  numXDivs = 0;
-    uint8_t  numYDivs = 0;
+    int32_t* xDivs = image->xDivs = (int32_t*) malloc(maxSizeXDivs);
+    int32_t* yDivs = image->yDivs = (int32_t*) malloc(maxSizeYDivs);
+    uint8_t numXDivs = 0;
+    uint8_t numYDivs = 0;
+
     int8_t numColors;
     int numRows;
     int numCols;
@@ -618,7 +630,7 @@
 
     numColors = numRows * numCols;
     image->info9Patch.numColors = numColors;
-    image->info9Patch.colors = (uint32_t*)malloc(numColors * sizeof(uint32_t));
+    image->colors = (uint32_t*)malloc(numColors * sizeof(uint32_t));
 
     // Fill in color information for each patch.
 
@@ -661,7 +673,7 @@
                 right = xDivs[i];
             }
             c = get_color(image->rows, left, top, right - 1, bottom - 1);
-            image->info9Patch.colors[colorIndex++] = c;
+            image->colors[colorIndex++] = c;
             NOISY(if (c != Res_png_9patch::NO_COLOR) hasColor = true);
             left = right;
         }
@@ -673,14 +685,10 @@
     for (i=0; i<numColors; i++) {
         if (hasColor) {
             if (i == 0) printf("Colors in %s:\n ", imageName);
-            printf(" #%08x", image->info9Patch.colors[i]);
+            printf(" #%08x", image->colors[i]);
             if (i == numColors - 1) printf("\n");
         }
     }
-
-    image->is9Patch = true;
-    image->info9Patch.deviceToFile();
-
 getout:
     if (errorMsg) {
         fprintf(stderr,
@@ -700,14 +708,10 @@
     return NO_ERROR;
 }
 
-static void checkNinePatchSerialization(Res_png_9patch* inPatch,  void * data)
+static void checkNinePatchSerialization(Res_png_9patch* inPatch,  void* data)
 {
-    if (sizeof(void*) != sizeof(int32_t)) {
-        // can't deserialize on a non-32 bit system
-        return;
-    }
     size_t patchSize = inPatch->serializedSize();
-    void * newData = malloc(patchSize);
+    void* newData = malloc(patchSize);
     memcpy(newData, data, patchSize);
     Res_png_9patch* outPatch = inPatch->deserialize(newData);
     // deserialization is done in place, so outPatch == newData
@@ -730,34 +734,6 @@
     free(newData);
 }
 
-static bool patch_equals(Res_png_9patch& patch1, Res_png_9patch& patch2) {
-    if (!(patch1.numXDivs == patch2.numXDivs &&
-          patch1.numYDivs == patch2.numYDivs &&
-          patch1.numColors == patch2.numColors &&
-          patch1.paddingLeft == patch2.paddingLeft &&
-          patch1.paddingRight == patch2.paddingRight &&
-          patch1.paddingTop == patch2.paddingTop &&
-          patch1.paddingBottom == patch2.paddingBottom)) {
-            return false;
-    }
-    for (int i = 0; i < patch1.numColors; i++) {
-        if (patch1.colors[i] != patch2.colors[i]) {
-            return false;
-        }
-    }
-    for (int i = 0; i < patch1.numXDivs; i++) {
-        if (patch1.xDivs[i] != patch2.xDivs[i]) {
-            return false;
-        }
-    }
-    for (int i = 0; i < patch1.numYDivs; i++) {
-        if (patch1.yDivs[i] != patch2.yDivs[i]) {
-            return false;
-        }
-    }
-    return true;
-}
-
 static void dump_image(int w, int h, png_bytepp rows, int color_type)
 {
     int i, j, rr, gg, bb, aa;
@@ -1070,7 +1046,7 @@
                 : (png_byte*)"npTc";
         NOISY(printf("Adding 9-patch info...\n"));
         strcpy((char*)unknowns[p_index].name, "npTc");
-        unknowns[p_index].data = (png_byte*)imageInfo.info9Patch.serialize();
+        unknowns[p_index].data = (png_byte*)imageInfo.serialize9patch();
         unknowns[p_index].size = imageInfo.info9Patch.serializedSize();
         // TODO: remove the check below when everything works
         checkNinePatchSerialization(&imageInfo.info9Patch, unknowns[p_index].data);
diff --git a/tools/aidl/Android.mk b/tools/aidl/Android.mk
index 77d46ab..efd60a2 100644
--- a/tools/aidl/Android.mk
+++ b/tools/aidl/Android.mk
@@ -3,7 +3,7 @@
 # Copies files into the directory structure described by a manifest
 
 # This tool is prebuilt if we're doing an app-only build.
-ifeq ($(TARGET_BUILD_APPS),)
+ifeq ($(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)),)
 
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
@@ -26,4 +26,4 @@
 
 include $(BUILD_HOST_EXECUTABLE)
 
-endif # TARGET_BUILD_APPS
+endif # No TARGET_BUILD_APPS or TARGET_BUILD_PDK