Merge "Volume: Hide zen options during setup." into lmp-dev
diff --git a/api/current.txt b/api/current.txt
index 07974ed..8467400 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -590,7 +590,6 @@
     field public static final int fillBefore = 16843196; // 0x10101bc
     field public static final int fillColor = 16843807; // 0x101041f
     field public static final int fillEnabled = 16843343; // 0x101024f
-    field public static final int fillOpacity = 16843806; // 0x101041e
     field public static final int fillViewport = 16843130; // 0x101017a
     field public static final int filter = 16843035; // 0x101011b
     field public static final int filterTouchesWhenObscured = 16843460; // 0x10102c4
@@ -603,6 +602,7 @@
     field public static final int focusableInTouchMode = 16842971; // 0x10100db
     field public static final int focusedMonthDateColor = 16843587; // 0x1010343
     field public static final int fontFamily = 16843692; // 0x10103ac
+    field public static final int fontFeatureSettings = 16843962; // 0x10104ba
     field public static final int footerDividersEnabled = 16843311; // 0x101022f
     field public static final int foreground = 16843017; // 0x1010109
     field public static final int foregroundGravity = 16843264; // 0x1010200
@@ -712,6 +712,7 @@
     field public static final int innerRadiusRatio = 16843163; // 0x101019b
     field public static final deprecated int inputMethod = 16843112; // 0x1010168
     field public static final int inputType = 16843296; // 0x1010220
+    field public static final int inset = 16843960; // 0x10104b8
     field public static final int insetBottom = 16843194; // 0x10101ba
     field public static final int insetLeft = 16843191; // 0x10101b7
     field public static final int insetRight = 16843192; // 0x10101b8
@@ -837,6 +838,7 @@
     field public static final int layout_x = 16843135; // 0x101017f
     field public static final int layout_y = 16843136; // 0x1010180
     field public static final int left = 16843181; // 0x10101ad
+    field public static final int letterSpacing = 16843961; // 0x10104b9
     field public static final int lineSpacingExtra = 16843287; // 0x1010217
     field public static final int lineSpacingMultiplier = 16843288; // 0x1010218
     field public static final int lines = 16843092; // 0x1010154
@@ -1190,7 +1192,6 @@
     field public static final int strokeLineCap = 16843815; // 0x1010427
     field public static final int strokeLineJoin = 16843816; // 0x1010428
     field public static final int strokeMiterLimit = 16843817; // 0x1010429
-    field public static final int strokeOpacity = 16843810; // 0x1010422
     field public static final int strokeWidth = 16843811; // 0x1010423
     field public static final int submitBackground = 16843914; // 0x101048a
     field public static final int subtitle = 16843473; // 0x10102d1
@@ -2056,6 +2057,13 @@
     field public static final int TextAppearance_StatusBar_EventContent = 16973927; // 0x1030067
     field public static final int TextAppearance_StatusBar_EventContent_Title = 16973928; // 0x1030068
     field public static final int TextAppearance_StatusBar_Icon = 16973926; // 0x1030066
+    field public static final int TextAppearance_StatusBar_Material = 16974559; // 0x10302df
+    field public static final int TextAppearance_StatusBar_Material_EventContent = 16974560; // 0x10302e0
+    field public static final int TextAppearance_StatusBar_Material_EventContent_Emphasis = 16974565; // 0x10302e5
+    field public static final int TextAppearance_StatusBar_Material_EventContent_Info = 16974563; // 0x10302e3
+    field public static final int TextAppearance_StatusBar_Material_EventContent_Line2 = 16974562; // 0x10302e2
+    field public static final int TextAppearance_StatusBar_Material_EventContent_Time = 16974564; // 0x10302e4
+    field public static final int TextAppearance_StatusBar_Material_EventContent_Title = 16974561; // 0x10302e1
     field public static final int TextAppearance_StatusBar_Title = 16973925; // 0x1030065
     field public static final int TextAppearance_SuggestionHighlight = 16974104; // 0x1030118
     field public static final int TextAppearance_Theme = 16973888; // 0x1030040
@@ -8677,6 +8685,7 @@
     method public abstract void onSuccess();
     method public abstract void onUserActionRequired(android.content.Intent);
     field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME";
+    field public static final int FAILURE_ABORTED = 5; // 0x5
     field public static final int FAILURE_CONFLICT = 2; // 0x2
     field public static final int FAILURE_INCOMPATIBLE = 4; // 0x4
     field public static final int FAILURE_INVALID = 1; // 0x1
@@ -8706,9 +8715,12 @@
 
   public static abstract class PackageInstaller.UninstallCallback {
     ctor public PackageInstaller.UninstallCallback();
-    method public abstract void onFailure(java.lang.String);
+    method public abstract void onFailure(int, java.lang.String, android.os.Bundle);
     method public abstract void onSuccess();
     method public abstract void onUserActionRequired(android.content.Intent);
+    field public static final int FAILURE_ABORTED = 2; // 0x2
+    field public static final int FAILURE_BLOCKED = 1; // 0x1
+    field public static final int FAILURE_UNKNOWN = 0; // 0x0
   }
 
   public class PackageItemInfo {
@@ -11028,12 +11040,14 @@
     method public android.graphics.ColorFilter getColorFilter();
     method public boolean getFillPath(android.graphics.Path, android.graphics.Path);
     method public int getFlags();
+    method public java.lang.String getFontFeatureSettings();
     method public float getFontMetrics(android.graphics.Paint.FontMetrics);
     method public android.graphics.Paint.FontMetrics getFontMetrics();
     method public int getFontMetricsInt(android.graphics.Paint.FontMetricsInt);
     method public android.graphics.Paint.FontMetricsInt getFontMetricsInt();
     method public float getFontSpacing();
     method public int getHinting();
+    method public float getLetterSpacing();
     method public android.graphics.MaskFilter getMaskFilter();
     method public android.graphics.PathEffect getPathEffect();
     method public deprecated android.graphics.Rasterizer getRasterizer();
@@ -11083,7 +11097,9 @@
     method public void setFakeBoldText(boolean);
     method public void setFilterBitmap(boolean);
     method public void setFlags(int);
+    method public void setFontFeatureSettings(java.lang.String);
     method public void setHinting(int);
+    method public void setLetterSpacing(float);
     method public void setLinearText(boolean);
     method public android.graphics.MaskFilter setMaskFilter(android.graphics.MaskFilter);
     method public android.graphics.PathEffect setPathEffect(android.graphics.PathEffect);
@@ -28600,6 +28616,7 @@
     method public void swapWithBackgroundCall();
     method public void unhold();
     field public static final int STATE_ACTIVE = 4; // 0x4
+    field public static final int STATE_CONNECTING = 9; // 0x9
     field public static final int STATE_DIALING = 1; // 0x1
     field public static final int STATE_DISCONNECTED = 7; // 0x7
     field public static final int STATE_HOLDING = 3; // 0x3
@@ -28692,6 +28709,7 @@
     method public static android.telecomm.CallState valueOf(java.lang.String);
     method public static final android.telecomm.CallState[] values();
     enum_constant public static final android.telecomm.CallState ACTIVE;
+    enum_constant public static final android.telecomm.CallState CONNECTING;
     enum_constant public static final android.telecomm.CallState DIALING;
     enum_constant public static final android.telecomm.CallState DISCONNECTED;
     enum_constant public static final android.telecomm.CallState NEW;
@@ -35536,6 +35554,7 @@
     method public int getSystemWindowInsetTop();
     method public boolean hasInsets();
     method public boolean hasSystemWindowInsets();
+    method public boolean isConsumed();
     method public boolean isRound();
     method public android.view.WindowInsets replaceSystemWindowInsets(int, int, int, int);
   }
@@ -39657,6 +39676,7 @@
     method public int getExtendedPaddingBottom();
     method public int getExtendedPaddingTop();
     method public android.text.InputFilter[] getFilters();
+    method public java.lang.String getFontFeatureSettings();
     method public boolean getFreezesText();
     method public int getGravity();
     method public int getHighlightColor();
@@ -39670,6 +39690,7 @@
     method public int getInputType();
     method public final android.text.method.KeyListener getKeyListener();
     method public final android.text.Layout getLayout();
+    method public float getLetterSpacing();
     method public int getLineBounds(int, android.graphics.Rect);
     method public int getLineCount();
     method public int getLineHeight();
@@ -39753,6 +39774,7 @@
     method public void setError(java.lang.CharSequence, android.graphics.drawable.Drawable);
     method public void setExtractedText(android.view.inputmethod.ExtractedText);
     method public void setFilters(android.text.InputFilter[]);
+    method public void setFontFeatureSettings(java.lang.String);
     method protected boolean setFrame(int, int, int, int);
     method public void setFreezesText(boolean);
     method public void setGravity(int);
@@ -39769,6 +39791,7 @@
     method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public void setInputType(int);
     method public void setKeyListener(android.text.method.KeyListener);
+    method public void setLetterSpacing(float);
     method public void setLineSpacing(float, float);
     method public void setLines(int);
     method public final void setLinkTextColor(int);
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 84b5516..a935dc0 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -28,7 +28,6 @@
 import android.content.pm.FeatureInfo;
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.IPackageDeleteObserver;
-import android.content.pm.IPackageDeleteObserver2;
 import android.content.pm.IPackageInstallObserver;
 import android.content.pm.IPackageManager;
 import android.content.pm.IPackageMoveObserver;
@@ -53,7 +52,6 @@
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
-import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Process;
 import android.os.RemoteException;
@@ -1655,39 +1653,6 @@
                 new UserHandle(mContext.getUserId()));
     }
 
-    private static class LegacyPackageInstallObserver extends PackageInstallObserver {
-        private final IPackageInstallObserver mLegacy;
-
-        public LegacyPackageInstallObserver(IPackageInstallObserver legacy) {
-            mLegacy = legacy;
-        }
-
-        @Override
-        public void onPackageInstalled(String basePackageName, int returnCode, String msg,
-                Bundle extras) {
-            try {
-                mLegacy.packageInstalled(basePackageName, returnCode);
-            } catch (RemoteException ignored) {
-            }
-        }
-    }
-
-    private static class LegacyPackageDeleteObserver extends PackageDeleteObserver {
-        private final IPackageDeleteObserver mLegacy;
-
-        public LegacyPackageDeleteObserver(IPackageDeleteObserver legacy) {
-            mLegacy = legacy;
-        }
-
-        @Override
-        public void onPackageDeleted(String basePackageName, int returnCode, String msg) {
-            try {
-                mLegacy.packageDeleted(basePackageName, returnCode);
-            } catch (RemoteException ignored) {
-            }
-        }
-    }
-
     private final ContextImpl mContext;
     private final IPackageManager mPM;
 
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index df0365e..e9297b9 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -161,11 +161,14 @@
         return result;
     }
 
+    // system APIs start here
+
     /**
      * Begin the process of restoring data from backup.  See the
      * {@link android.app.backup.RestoreSession} class for documentation on that process.
      * @hide
      */
+    @SystemApi
     public RestoreSession beginRestoreSession() {
         RestoreSession session = null;
         checkServiceBinder();
@@ -183,8 +186,6 @@
         return session;
     }
 
-    // system APIs start here
-
     /**
      * Enable/disable the backup service entirely.  When disabled, no backup
      * or restore operations will take place.  Data-changed notifications will
diff --git a/core/java/android/app/backup/BackupTransport.java b/core/java/android/app/backup/BackupTransport.java
index dc3bbc0..6adc2e0 100644
--- a/core/java/android/app/backup/BackupTransport.java
+++ b/core/java/android/app/backup/BackupTransport.java
@@ -405,6 +405,25 @@
         return BackupTransport.TRANSPORT_ERROR;
     }
 
+    /**
+     * Tells the transport to cancel the currently-ongoing full backup operation.  This
+     * will happen between {@link #performFullBackup()} and {@link #finishBackup()}
+     * if the OS needs to abort the backup operation for any reason, such as a crash in
+     * the application undergoing backup.
+     *
+     * <p>When it receives this call, the transport should discard any partial archive
+     * that it has stored so far.  If possible it should also roll back to the previous
+     * known-good archive in its datastore.
+     *
+     * <p>If the transport receives this callback, it will <em>not</em> receive a
+     * call to {@link #finishBackup()}.  It needs to tear down any ongoing backup state
+     * here.
+     */
+    public void cancelFullBackup() {
+        throw new UnsupportedOperationException(
+                "Transport cancelFullBackup() not implemented");
+    }
+
     // ------------------------------------------------------------------------------------
     // Full restore interfaces
 
diff --git a/core/java/android/app/backup/RestoreObserver.java b/core/java/android/app/backup/RestoreObserver.java
index dbddb78..b4a23d0 100644
--- a/core/java/android/app/backup/RestoreObserver.java
+++ b/core/java/android/app/backup/RestoreObserver.java
@@ -17,6 +17,8 @@
 package android.app.backup;
 
 import java.lang.String;
+
+import android.annotation.SystemApi;
 import android.app.backup.RestoreSet;
 
 /**
@@ -36,6 +38,7 @@
      *
      * @hide
      */
+    @SystemApi
     public void restoreSetsAvailable(RestoreSet[] result) {
     }
 
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index edf823e..7070bae 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -21,6 +21,7 @@
 import android.bluetooth.le.AdvertiseData;
 import android.bluetooth.le.ScanFilter;
 import android.bluetooth.le.ScanSettings;
+import android.bluetooth.le.ResultStorageDescriptor;
 import android.os.ParcelUuid;
 
 import android.bluetooth.IBluetoothGattCallback;
@@ -34,7 +35,8 @@
     List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
 
     void startScan(in int appIf, in boolean isServer, in ScanSettings settings,
-                   in List<ScanFilter> filters);
+                   in List<ScanFilter> filters,
+                   in List scanStorages);
     void stopScan(in int appIf, in boolean isServer);
     void flushPendingBatchResults(in int appIf, in boolean isServer);
     void startMultiAdvertising(in int appIf,
diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
index 6667cc4..7c3cbc6 100644
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java
@@ -16,20 +16,19 @@
 
 package android.bluetooth.le;
 
+import android.annotation.SystemApi;
 import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothGatt;
 import android.bluetooth.BluetoothGattCallbackWrapper;
 import android.bluetooth.IBluetoothGatt;
-import android.bluetooth.IBluetoothGattCallback;
 import android.bluetooth.IBluetoothManager;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.ParcelUuid;
 import android.os.RemoteException;
-import android.os.SystemClock;
 import android.util.Log;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -100,6 +99,11 @@
      */
     public void startScan(List<ScanFilter> filters, ScanSettings settings,
             final ScanCallback callback) {
+        startScan(filters, settings, callback, null);
+    }
+
+    private void startScan(List<ScanFilter> filters, ScanSettings settings,
+            final ScanCallback callback, List<List<ResultStorageDescriptor>> resultStorages) {
         checkAdapterState();
         if (settings == null || callback == null) {
             throw new IllegalArgumentException("settings or callback is null");
@@ -125,7 +129,7 @@
                 return;
             }
             BleScanCallbackWrapper wrapper = new BleScanCallbackWrapper(gatt, filters,
-                    settings, callback);
+                    settings, callback, resultStorages);
             try {
                 UUID uuid = UUID.randomUUID();
                 gatt.registerClient(new ParcelUuid(uuid), wrapper);
@@ -155,7 +159,8 @@
         synchronized (mLeScanClients) {
             BleScanCallbackWrapper wrapper = mLeScanClients.remove(callback);
             if (wrapper == null) {
-                if (DBG) Log.d(TAG, "could not find callback wrapper");
+                if (DBG)
+                    Log.d(TAG, "could not find callback wrapper");
                 return;
             }
             wrapper.stopLeScan();
@@ -185,6 +190,25 @@
     }
 
     /**
+     * Start truncated scan.
+     *
+     * @hide
+     */
+    @SystemApi
+    public void startTruncatedScan(List<TruncatedFilter> truncatedFilters, ScanSettings settings,
+            final ScanCallback callback) {
+        int filterSize = truncatedFilters.size();
+        List<ScanFilter> scanFilters = new ArrayList<ScanFilter>(filterSize);
+        List<List<ResultStorageDescriptor>> scanStorages =
+                new ArrayList<List<ResultStorageDescriptor>>(filterSize);
+        for (TruncatedFilter filter : truncatedFilters) {
+            scanFilters.add(filter.getFilter());
+            scanStorages.add(filter.getStorageDescriptors());
+        }
+        startScan(scanFilters, settings, callback, scanStorages);
+    }
+
+    /**
      * Bluetooth GATT interface callbacks
      */
     private static class BleScanCallbackWrapper extends BluetoothGattCallbackWrapper {
@@ -194,6 +218,7 @@
         private final List<ScanFilter> mFilters;
         private ScanSettings mSettings;
         private IBluetoothGatt mBluetoothGatt;
+        private List<List<ResultStorageDescriptor>> mResultStorages;
 
         // mLeHandle 0: not registered
         // -1: scan stopped
@@ -202,12 +227,13 @@
 
         public BleScanCallbackWrapper(IBluetoothGatt bluetoothGatt,
                 List<ScanFilter> filters, ScanSettings settings,
-                ScanCallback scanCallback) {
+                ScanCallback scanCallback, List<List<ResultStorageDescriptor>> resultStorages) {
             mBluetoothGatt = bluetoothGatt;
             mFilters = filters;
             mSettings = settings;
             mScanCallback = scanCallback;
             mClientIf = 0;
+            mResultStorages = resultStorages;
         }
 
         public boolean scanStarted() {
@@ -272,7 +298,8 @@
                 if (status == BluetoothGatt.GATT_SUCCESS) {
                     mClientIf = clientIf;
                     try {
-                        mBluetoothGatt.startScan(mClientIf, false, mSettings, mFilters);
+                        mBluetoothGatt.startScan(mClientIf, false, mSettings, mFilters,
+                                mResultStorages);
                     } catch (RemoteException e) {
                         Log.e(TAG, "fail to start le scan: " + e);
                         mClientIf = -1;
@@ -330,23 +357,26 @@
 
             // Check null in case the scan has been stopped
             synchronized (this) {
-                if (mClientIf <= 0) return;
+                if (mClientIf <= 0)
+                    return;
             }
             Handler handler = new Handler(Looper.getMainLooper());
             handler.post(new Runnable() {
                     @Override
                 public void run() {
                     if (onFound) {
-                        mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_FIRST_MATCH, scanResult);
+                        mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_FIRST_MATCH,
+                                scanResult);
                     } else {
-                        mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_MATCH_LOST, scanResult);
+                        mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_MATCH_LOST,
+                                scanResult);
                     }
                 }
             });
         }
     }
 
-    //TODO: move this api to a common util class.
+    // TODO: move this api to a common util class.
     private void checkAdapterState() {
         if (mBluetoothAdapter.getState() != mBluetoothAdapter.STATE_ON) {
             throw new IllegalStateException("BT Adapter is not turned ON");
diff --git a/core/java/android/bluetooth/le/ResultStorageDescriptor.aidl b/core/java/android/bluetooth/le/ResultStorageDescriptor.aidl
new file mode 100644
index 0000000..f218a01
--- /dev/null
+++ b/core/java/android/bluetooth/le/ResultStorageDescriptor.aidl
@@ -0,0 +1,23 @@
+/*
+ * 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.bluetooth.le;
+
+/**
+ * {@hide}
+ */
+
+parcelable ResultStorageDescriptor;
diff --git a/core/java/android/bluetooth/le/ResultStorageDescriptor.java b/core/java/android/bluetooth/le/ResultStorageDescriptor.java
new file mode 100644
index 0000000..748f97d
--- /dev/null
+++ b/core/java/android/bluetooth/le/ResultStorageDescriptor.java
@@ -0,0 +1,93 @@
+/*
+ * 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.bluetooth.le;
+
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Describes the way to store scan result.
+ *
+ * @hide
+ */
+@SystemApi
+public final class ResultStorageDescriptor implements Parcelable {
+    private int mType;
+    private int mOffset;
+    private int mLength;
+
+    public int getType() {
+        return mType;
+    }
+
+    public int getOffset() {
+        return mOffset;
+    }
+
+    public int getLength() {
+        return mLength;
+    }
+
+    /**
+     * Constructor of {@link ResultStorageDescriptor}
+     *
+     * @param type Type of the data.
+     * @param offset Offset from start of the advertise packet payload.
+     * @param length Byte length of the data
+     */
+    public ResultStorageDescriptor(int type, int offset, int length) {
+        mType = type;
+        mOffset = offset;
+        mLength = length;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mType);
+        dest.writeInt(mOffset);
+        dest.writeInt(mLength);
+    }
+
+    private ResultStorageDescriptor(Parcel in) {
+        ReadFromParcel(in);
+    }
+
+    private void ReadFromParcel(Parcel in) {
+        mType = in.readInt();
+        mOffset = in.readInt();
+        mLength = in.readInt();
+    }
+
+    public static final Parcelable.Creator<ResultStorageDescriptor>
+            CREATOR = new Creator<ResultStorageDescriptor>() {
+                    @Override
+                public ResultStorageDescriptor createFromParcel(Parcel source) {
+                    return new ResultStorageDescriptor(source);
+                }
+
+                    @Override
+                public ResultStorageDescriptor[] newArray(int size) {
+                    return new ResultStorageDescriptor[size];
+                }
+            };
+}
diff --git a/core/java/android/bluetooth/le/TruncatedFilter.java b/core/java/android/bluetooth/le/TruncatedFilter.java
new file mode 100644
index 0000000..6a6b3e3
--- /dev/null
+++ b/core/java/android/bluetooth/le/TruncatedFilter.java
@@ -0,0 +1,61 @@
+/*
+ * 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.bluetooth.le;
+
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.List;
+
+/**
+ * A special scan filter that lets the client decide how the scan record should be stored.
+ *
+ * @hide
+ */
+@SystemApi
+public final class TruncatedFilter {
+    private final ScanFilter mFilter;
+    private final List<ResultStorageDescriptor> mStorageDescriptors;
+
+    /**
+     * Constructor for {@link TruncatedFilter}.
+     *
+     * @param filter Scan filter of the truncated filter.
+     * @param storageDescriptors Describes how the scan should be stored.
+     */
+    public TruncatedFilter(ScanFilter filter, List<ResultStorageDescriptor> storageDescriptors) {
+        mFilter = filter;
+        mStorageDescriptors = storageDescriptors;
+    }
+
+    /**
+     * Returns the scan filter.
+     */
+    public ScanFilter getFilter() {
+        return mFilter;
+    }
+
+    /**
+     * Returns a list of descriptor for scan result storage.
+     */
+    public List<ResultStorageDescriptor> getStorageDescriptors() {
+        return mStorageDescriptors;
+    }
+
+
+}
diff --git a/core/java/android/content/pm/IPackageInstaller.aidl b/core/java/android/content/pm/IPackageInstaller.aidl
index cc0d569..5223476 100644
--- a/core/java/android/content/pm/IPackageInstaller.aidl
+++ b/core/java/android/content/pm/IPackageInstaller.aidl
@@ -36,4 +36,6 @@
 
     void uninstall(String packageName, int flags, in IPackageDeleteObserver2 observer, int userId);
     void uninstallSplit(String packageName, String splitName, int flags, in IPackageDeleteObserver2 observer, int userId);
+
+    void setPermissionsResult(int sessionId, boolean accepted);
 }
diff --git a/core/java/android/content/pm/InstallSessionInfo.java b/core/java/android/content/pm/InstallSessionInfo.java
index f263885..161bcde 100644
--- a/core/java/android/content/pm/InstallSessionInfo.java
+++ b/core/java/android/content/pm/InstallSessionInfo.java
@@ -16,7 +16,6 @@
 
 package android.content.pm;
 
-import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Intent;
 import android.graphics.Bitmap;
@@ -33,8 +32,12 @@
     /** {@hide} */
     public String installerPackageName;
     /** {@hide} */
+    public String resolvedBaseCodePath;
+    /** {@hide} */
     public float progress;
     /** {@hide} */
+    public boolean sealed;
+    /** {@hide} */
     public boolean open;
 
     /** {@hide} */
@@ -56,7 +59,9 @@
     public InstallSessionInfo(Parcel source) {
         sessionId = source.readInt();
         installerPackageName = source.readString();
+        resolvedBaseCodePath = source.readString();
         progress = source.readFloat();
+        sealed = source.readInt() != 0;
         open = source.readInt() != 0;
 
         mode = source.readInt();
@@ -149,7 +154,9 @@
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(sessionId);
         dest.writeString(installerPackageName);
+        dest.writeString(resolvedBaseCodePath);
         dest.writeFloat(progress);
+        dest.writeInt(sealed ? 1 : 0);
         dest.writeInt(open ? 1 : 0);
 
         dest.writeInt(mode);
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 01c080d..d70e22c 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -81,6 +81,10 @@
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_SESSION_DETAILS = "android.content.pm.action.SESSION_DETAILS";
 
+    /** {@hide} */
+    public static final String
+            ACTION_CONFIRM_PERMISSIONS = "android.content.pm.action.CONFIRM_PERMISSIONS";
+
     /**
      * An integer session ID.
      *
@@ -88,6 +92,9 @@
      */
     public static final String EXTRA_SESSION_ID = "android.content.pm.extra.SESSION_ID";
 
+    /** {@hide} */
+    public static final String EXTRA_CALLBACK = "android.content.pm.extra.CALLBACK";
+
     private final PackageManager mPm;
     private final IPackageInstaller mInstaller;
     private final int mUserId;
@@ -206,6 +213,15 @@
         }
     }
 
+    /** {@hide} */
+    public void setPermissionsResult(int sessionId, boolean accepted) {
+        try {
+            mInstaller.setPermissionsResult(sessionId, accepted);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
     /**
      * Events for observing session lifecycle.
      * <p>
@@ -541,6 +557,26 @@
      */
     public static abstract class UninstallCallback {
         /**
+         * Generic unknown failure. The system will always try to provide a more
+         * specific failure reason, but in some rare cases this may be
+         * delivered.
+         */
+        public static final int FAILURE_UNKNOWN = 0;
+
+        /**
+         * This uninstall was blocked. The package may be required for core
+         * system operation, or the user may be restricted. Attempting to
+         * uninstall again will have the same result.
+         */
+        public static final int FAILURE_BLOCKED = 1;
+
+        /**
+         * This uninstall was actively aborted. For example, the user declined
+         * to uninstall. You may try to uninstall again.
+         */
+        public static final int FAILURE_ABORTED = 2;
+
+        /**
          * User action is required to proceed. You can start the given intent
          * activity to involve the user and continue.
          * <p>
@@ -551,7 +587,7 @@
         public abstract void onUserActionRequired(Intent intent);
 
         public abstract void onSuccess();
-        public abstract void onFailure(String msg);
+        public abstract void onFailure(int failureReason, String msg, Bundle extras);
     }
 
     /** {@hide} */
@@ -572,8 +608,9 @@
             if (returnCode == PackageManager.DELETE_SUCCEEDED) {
                 target.onSuccess();
             } else {
+                final int failureReason = PackageManager.deleteStatusToFailureReason(returnCode);
                 msg = PackageManager.deleteStatusToString(returnCode) + ": " + msg;
-                target.onFailure(msg);
+                target.onFailure(failureReason, msg, null);
             }
         }
     }
@@ -603,9 +640,8 @@
          * permission, incompatible certificates, etc. The user may be able to
          * uninstall another app to fix the issue.
          * <p>
-         * The extras bundle may contain {@link #EXTRA_PACKAGE_NAME} if one
-         * specific package was identified as the cause of the conflict. If
-         * unknown, or multiple packages, the extra may be {@code null}.
+         * The extras bundle may contain {@link #EXTRA_PACKAGE_NAME} with the
+         * specific packages identified as the cause of the conflict.
          */
         public static final int FAILURE_CONFLICT = 2;
 
@@ -626,6 +662,15 @@
          */
         public static final int FAILURE_INCOMPATIBLE = 4;
 
+        /**
+         * This install session failed because it was actively aborted. For
+         * example, the user declined requested permissions, or a verifier
+         * rejected the session.
+         *
+         * @see PackageManager#VERIFICATION_REJECT
+         */
+        public static final int FAILURE_ABORTED = 5;
+
         public static final String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME";
 
         /**
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 1e4ed31..b957a15 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -21,6 +21,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
+import android.app.PackageDeleteObserver;
 import android.app.PackageInstallObserver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -28,6 +29,7 @@
 import android.content.IntentFilter;
 import android.content.IntentSender;
 import android.content.pm.PackageInstaller.CommitCallback;
+import android.content.pm.PackageInstaller.UninstallCallback;
 import android.content.pm.PackageParser.PackageParserException;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
@@ -35,6 +37,7 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Environment;
+import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.AndroidException;
 
@@ -770,6 +773,9 @@
      */
     public static final int NO_NATIVE_LIBRARIES = -114;
 
+    /** {@hide} */
+    public static final int INSTALL_FAILED_ABORTED = -115;
+
     /**
      * Flag parameter for {@link #deletePackage} to indicate that you don't want to delete the
      * package's data directory.
@@ -842,7 +848,10 @@
      *
      * @hide
      */
-    public static final int DELETE_FAILED_OWNER_BLOCKED= -4;
+    public static final int DELETE_FAILED_OWNER_BLOCKED = -4;
+
+    /** {@hide} */
+    public static final int DELETE_FAILED_ABORTED = -5;
 
     /**
      * Return code that is passed to the {@link IPackageMoveObserver} by
@@ -3830,6 +3839,7 @@
             case INSTALL_FAILED_USER_RESTRICTED: return "INSTALL_FAILED_USER_RESTRICTED";
             case INSTALL_FAILED_DUPLICATE_PERMISSION: return "INSTALL_FAILED_DUPLICATE_PERMISSION";
             case INSTALL_FAILED_NO_MATCHING_ABIS: return "INSTALL_FAILED_NO_MATCHING_ABIS";
+            case INSTALL_FAILED_ABORTED: return "INSTALL_FAILED_ABORTED";
             default: return Integer.toString(status);
         }
     }
@@ -3857,8 +3867,8 @@
             case INSTALL_FAILED_CONTAINER_ERROR: return CommitCallback.FAILURE_STORAGE;
             case INSTALL_FAILED_INVALID_INSTALL_LOCATION: return CommitCallback.FAILURE_STORAGE;
             case INSTALL_FAILED_MEDIA_UNAVAILABLE: return CommitCallback.FAILURE_STORAGE;
-            case INSTALL_FAILED_VERIFICATION_TIMEOUT: return CommitCallback.FAILURE_UNKNOWN;
-            case INSTALL_FAILED_VERIFICATION_FAILURE: return CommitCallback.FAILURE_UNKNOWN;
+            case INSTALL_FAILED_VERIFICATION_TIMEOUT: return CommitCallback.FAILURE_ABORTED;
+            case INSTALL_FAILED_VERIFICATION_FAILURE: return CommitCallback.FAILURE_ABORTED;
             case INSTALL_FAILED_PACKAGE_CHANGED: return CommitCallback.FAILURE_INVALID;
             case INSTALL_FAILED_UID_CHANGED: return CommitCallback.FAILURE_INVALID;
             case INSTALL_FAILED_VERSION_DOWNGRADE: return CommitCallback.FAILURE_INVALID;
@@ -3876,6 +3886,7 @@
             case INSTALL_FAILED_USER_RESTRICTED: return CommitCallback.FAILURE_INCOMPATIBLE;
             case INSTALL_FAILED_DUPLICATE_PERMISSION: return CommitCallback.FAILURE_CONFLICT;
             case INSTALL_FAILED_NO_MATCHING_ABIS: return CommitCallback.FAILURE_INCOMPATIBLE;
+            case INSTALL_FAILED_ABORTED: return CommitCallback.FAILURE_ABORTED;
             default: return CommitCallback.FAILURE_UNKNOWN;
         }
     }
@@ -3888,7 +3899,57 @@
             case DELETE_FAILED_DEVICE_POLICY_MANAGER: return "DELETE_FAILED_DEVICE_POLICY_MANAGER";
             case DELETE_FAILED_USER_RESTRICTED: return "DELETE_FAILED_USER_RESTRICTED";
             case DELETE_FAILED_OWNER_BLOCKED: return "DELETE_FAILED_OWNER_BLOCKED";
+            case DELETE_FAILED_ABORTED: return "DELETE_FAILED_ABORTED";
             default: return Integer.toString(status);
         }
     }
+
+    /** {@hide} */
+    public static int deleteStatusToFailureReason(int status) {
+        switch (status) {
+            case DELETE_FAILED_INTERNAL_ERROR: return UninstallCallback.FAILURE_UNKNOWN;
+            case DELETE_FAILED_DEVICE_POLICY_MANAGER: return UninstallCallback.FAILURE_BLOCKED;
+            case DELETE_FAILED_USER_RESTRICTED: return UninstallCallback.FAILURE_BLOCKED;
+            case DELETE_FAILED_OWNER_BLOCKED: return UninstallCallback.FAILURE_BLOCKED;
+            case DELETE_FAILED_ABORTED: return UninstallCallback.FAILURE_ABORTED;
+            default: return UninstallCallback.FAILURE_UNKNOWN;
+        }
+    }
+
+    /** {@hide} */
+    public static class LegacyPackageInstallObserver extends PackageInstallObserver {
+        private final IPackageInstallObserver mLegacy;
+
+        public LegacyPackageInstallObserver(IPackageInstallObserver legacy) {
+            mLegacy = legacy;
+        }
+
+        @Override
+        public void onPackageInstalled(String basePackageName, int returnCode, String msg,
+                Bundle extras) {
+            if (mLegacy == null) return;
+            try {
+                mLegacy.packageInstalled(basePackageName, returnCode);
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
+    /** {@hide} */
+    public static class LegacyPackageDeleteObserver extends PackageDeleteObserver {
+        private final IPackageDeleteObserver mLegacy;
+
+        public LegacyPackageDeleteObserver(IPackageDeleteObserver legacy) {
+            mLegacy = legacy;
+        }
+
+        @Override
+        public void onPackageDeleted(String basePackageName, int returnCode, String msg) {
+            if (mLegacy == null) return;
+            try {
+                mLegacy.packageDeleted(basePackageName, returnCode);
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
 }
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index 900b41d..3c290f7 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -233,7 +233,7 @@
             }
 
             if (alphaRes != 0) {
-                alpha = r.getFraction(alphaRes, 1, 1);
+                alpha = r.getFloat(alphaRes);
             }
 
             // Apply alpha modulation.
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 5face69..52d1c79 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -986,6 +986,34 @@
     }
 
     /**
+     * Retrieve a floating-point value for a particular resource ID.
+     *
+     * @param id The desired resource identifier, as generated by the aapt
+     *           tool. This integer encodes the package, type, and resource
+     *           entry. The value 0 is an invalid identifier.
+     *
+     * @return Returns the floating-point value contained in the resource.
+     *
+     * @throws NotFoundException Throws NotFoundException if the given ID does
+     *         not exist or is not a floating-point value.
+     * @hide Pending API council approval.
+     */
+    public float getFloat(int id) {
+        synchronized (mAccessLock) {
+            TypedValue value = mTmpValue;
+            if (value == null) {
+                mTmpValue = value = new TypedValue();
+            }
+            getValue(id, value, true);
+            if (value.type == TypedValue.TYPE_FLOAT) {
+                return value.getFloat();
+            }
+            throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id) + " type #0x"
+                    + Integer.toHexString(value.type) + " is not valid");
+        }
+    }
+
+    /**
      * Return an XmlResourceParser through which you can read a view layout
      * description for the given resource ID.  This parser has limited
      * functionality -- in particular, you can't change its input, and only
diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
index 2533a28..ec233da7 100644
--- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
+++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
@@ -607,7 +607,6 @@
                             Log.e(TAG, "Interrupted while waiting for requests to complete.");
                         }
                         mDeviceState.setIdle();
-                        stopPreview();
                         break;
                     } else {
                         // Queue another capture if we did not get the last burst.
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index ba79f91..7d086e1 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -159,7 +159,7 @@
     private static final long BYTES_PER_MB = 1048576; // 1024^2
     private static final long BYTES_PER_GB = 1073741824; //1024^3
     
-
+    private static final String VERSION_DATA = "vers";
     private static final String UID_DATA = "uid";
     private static final String APK_DATA = "apk";
     private static final String PROCESS_DATA = "pr";
@@ -1463,6 +1463,21 @@
     public abstract long getStartClockTime();
 
     /**
+     * Return platform version tag that we were running in when the battery stats started.
+     */
+    public abstract String getStartPlatformVersion();
+
+    /**
+     * Return platform version tag that we were running in when the battery stats ended.
+     */
+    public abstract String getEndPlatformVersion();
+
+    /**
+     * Return the internal version code of the parcelled format.
+     */
+    public abstract int getParcelVersion();
+
+    /**
      * Return whether we are currently running on battery.
      */
     public abstract boolean getIsOnBattery();
@@ -2008,7 +2023,8 @@
         } else {
             dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
                     getLowDischargeAmountSinceCharge(), getHighDischargeAmountSinceCharge(),
-                    getDischargeAmountScreenOn(), getDischargeAmountScreenOff());
+                    getDischargeAmountScreenOnSinceCharge(),
+                    getDischargeAmountScreenOffSinceCharge());
         }
         
         if (reqUid < 0) {
@@ -3876,6 +3892,9 @@
             if (didPid) {
                 pw.println();
             }
+        }
+
+        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
             if (dumpDurationSteps(pw, "Discharge step durations:", getDischargeStepDurationsArray(),
                     getNumDischargeStepDurations(), false)) {
                 long timeRemaining = computeBatteryTimeRemaining(SystemClock.elapsedRealtime());
@@ -3896,9 +3915,6 @@
                 }
                 pw.println();
             }
-        }
-
-        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
             pw.println("Statistics since last charge:");
             pw.println("  System starts: " + getStartCount()
                     + ", currently on battery: " + getIsOnBattery());
@@ -3915,7 +3931,10 @@
     public void dumpCheckinLocked(Context context, PrintWriter pw,
             List<ApplicationInfo> apps, int flags, long histStart) {
         prepareForDumpLocked();
-        
+
+        dumpLine(pw, 0 /* uid */, "i" /* category */, VERSION_DATA,
+                "10", getParcelVersion(), getStartPlatformVersion(), getEndPlatformVersion());
+
         long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
 
         final boolean filtering =
@@ -3976,7 +3995,7 @@
                 }
             }
         }
-        if (!filtering) {
+        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
             dumpDurationSteps(pw, DISCHARGE_STEP_DATA, getDischargeStepDurationsArray(),
                     getNumDischargeStepDurations(), true);
             String[] lineArgs = new String[1];
@@ -3994,8 +4013,6 @@
                 dumpLine(pw, 0 /* uid */, "i" /* category */, CHARGE_TIME_REMAIN_DATA,
                         (Object[])lineArgs);
             }
-        }
-        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
             dumpCheckinLocked(context, pw, STATS_SINCE_CHARGED, -1);
         }
         if (!filtering || (flags&DUMP_UNPLUGGED_ONLY) != 0) {
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 910f862..a410aa9 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -386,9 +386,6 @@
 
     @Override
     public void scale(float sx, float sy) {
-        // TODO: remove
-        if (sx > 1000000 || sy > 1000000) throw new IllegalArgumentException("invalid scales passed " + sx + ", " + sy);
-
         nScale(mRenderer, sx, sy);
     }
 
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index eee4973..099f153 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -598,9 +598,6 @@
      * @see #getScaleX()
      */
     public boolean setScaleX(float scaleX) {
-        if (scaleX > 1000000) {
-            throw new IllegalArgumentException("Invalid scale: " + scaleX);
-        }
         return nSetScaleX(mNativeRenderNode, scaleX);
     }
 
@@ -622,9 +619,6 @@
      * @see #getScaleY()
      */
     public boolean setScaleY(float scaleY) {
-        if (scaleY > 1000000) {
-            throw new IllegalArgumentException("Invalid scale: " + scaleY);
-        }
         return nSetScaleY(mNativeRenderNode, scaleY);
     }
 
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 328d67c..8c2048d 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4649,16 +4649,18 @@
      *         otherwise is returned.
      */
     public boolean performClick() {
-        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
-
-        ListenerInfo li = mListenerInfo;
+        final boolean result;
+        final ListenerInfo li = mListenerInfo;
         if (li != null && li.mOnClickListener != null) {
             playSoundEffect(SoundEffectConstants.CLICK);
             li.mOnClickListener.onClick(this);
-            return true;
+            result = true;
+        } else {
+            result = false;
         }
 
-        return false;
+        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
+        return result;
     }
 
     /**
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index 1832cc3..571a8f0 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -266,7 +266,6 @@
      * {@link View#fitSystemWindows(android.graphics.Rect)}.</p>
      *
      * @return true if the insets have been fully consumed.
-     * @hide Pending API
      */
     public boolean isConsumed() {
         return mSystemWindowInsetsConsumed && mWindowDecorInsetsConsumed && mStableInsetsConsumed;
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index 33cc66e..d263625 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -351,6 +351,7 @@
         final int selectedPosition = mSelectedPosition;
 
         View child = null;
+        final int nextChildDir = isLayoutRtl ? -1 : +1;
         for (int pos = startPos; pos < last; pos++) {
             // is this the selected item?
             boolean selected = pos == selectedPosition;
@@ -359,9 +360,9 @@
             final int where = flow ? -1 : pos - startPos;
             child = makeAndAddView(pos, y, flow, nextLeft, selected, where);
 
-            nextLeft += (isLayoutRtl ? -1 : +1) * columnWidth;
+            nextLeft += nextChildDir * columnWidth;
             if (pos < last - 1) {
-                nextLeft += horizontalSpacing;
+                nextLeft += nextChildDir * horizontalSpacing;
             }
 
             if (selected && (hasFocus || inClick)) {
diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java
index 546cc5f..f1aaa4d 100644
--- a/core/java/android/widget/MediaController.java
+++ b/core/java/android/widget/MediaController.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import android.content.Context;
+import android.content.res.Resources;
 import android.graphics.PixelFormat;
 import android.media.AudioManager;
 import android.os.Handler;
@@ -55,7 +56,7 @@
  * <p>
  * Functions like show() and hide() have no effect when MediaController
  * is created in an xml layout.
- * 
+ *
  * MediaController will hide and
  * show the buttons according to these rules:
  * <ul>
@@ -70,32 +71,34 @@
  */
 public class MediaController extends FrameLayout {
 
-    private MediaPlayerControl  mPlayer;
-    private Context             mContext;
-    private View                mAnchor;
-    private View                mRoot;
-    private WindowManager       mWindowManager;
-    private Window              mWindow;
-    private View                mDecor;
+    private MediaPlayerControl mPlayer;
+    private Context mContext;
+    private View mAnchor;
+    private View mRoot;
+    private WindowManager mWindowManager;
+    private Window mWindow;
+    private View mDecor;
     private WindowManager.LayoutParams mDecorLayoutParams;
-    private ProgressBar         mProgress;
-    private TextView            mEndTime, mCurrentTime;
-    private boolean             mShowing;
-    private boolean             mDragging;
-    private static final int    sDefaultTimeout = 3000;
-    private static final int    FADE_OUT = 1;
-    private static final int    SHOW_PROGRESS = 2;
-    private boolean             mUseFastForward;
-    private boolean             mFromXml;
-    private boolean             mListenersSet;
+    private ProgressBar mProgress;
+    private TextView mEndTime, mCurrentTime;
+    private boolean mShowing;
+    private boolean mDragging;
+    private static final int sDefaultTimeout = 3000;
+    private static final int FADE_OUT = 1;
+    private static final int SHOW_PROGRESS = 2;
+    private boolean mUseFastForward;
+    private boolean mFromXml;
+    private boolean mListenersSet;
     private View.OnClickListener mNextListener, mPrevListener;
-    StringBuilder               mFormatBuilder;
-    Formatter                   mFormatter;
-    private ImageButton         mPauseButton;
-    private ImageButton         mFfwdButton;
-    private ImageButton         mRewButton;
-    private ImageButton         mNextButton;
-    private ImageButton         mPrevButton;
+    StringBuilder mFormatBuilder;
+    Formatter mFormatter;
+    private ImageButton mPauseButton;
+    private ImageButton mFfwdButton;
+    private ImageButton mRewButton;
+    private ImageButton mNextButton;
+    private ImageButton mPrevButton;
+    private CharSequence mPlayDescription;
+    private CharSequence mPauseDescription;
 
     public MediaController(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -132,7 +135,7 @@
         mDecor.setOnTouchListener(mTouchListener);
         mWindow.setContentView(this);
         mWindow.setBackgroundDrawableResource(android.R.color.transparent);
-        
+
         // While the media controller is up, the volume control keys should
         // affect the media stream type
         mWindow.setVolumeControlStream(AudioManager.STREAM_MUSIC);
@@ -201,7 +204,7 @@
             return false;
         }
     };
-    
+
     public void setMediaPlayer(MediaPlayerControl player) {
         mPlayer = player;
         updatePausePlay();
@@ -249,6 +252,11 @@
     }
 
     private void initControllerView(View v) {
+        Resources res = mContext.getResources();
+        mPlayDescription = res
+                .getText(com.android.internal.R.string.lockscreen_transport_play_description);
+        mPauseDescription = res
+                .getText(com.android.internal.R.string.lockscreen_transport_pause_description);
         mPauseButton = (ImageButton) v.findViewById(com.android.internal.R.id.pause);
         if (mPauseButton != null) {
             mPauseButton.requestFocus();
@@ -271,7 +279,7 @@
             }
         }
 
-        // By default these are hidden. They will be enabled when setPrevNextListeners() is called 
+        // By default these are hidden. They will be enabled when setPrevNextListeners() is called
         mNextButton = (ImageButton) v.findViewById(com.android.internal.R.id.next);
         if (mNextButton != null && !mFromXml && !mListenersSet) {
             mNextButton.setVisibility(View.GONE);
@@ -328,7 +336,7 @@
             // the buttons.
         }
     }
-    
+
     /**
      * Show the controller on screen. It will go away
      * automatically after 'timeout' milliseconds of inactivity.
@@ -347,7 +355,7 @@
             mShowing = true;
         }
         updatePausePlay();
-        
+
         // cause the progress bar to be updated even if mShowing
         // was already true.  This happens, for example, if we're
         // paused with the progress bar showing the user hits play.
@@ -359,7 +367,7 @@
             mHandler.sendMessageDelayed(msg, timeout);
         }
     }
-    
+
     public boolean isShowing() {
         return mShowing;
     }
@@ -525,8 +533,10 @@
 
         if (mPlayer.isPlaying()) {
             mPauseButton.setImageResource(com.android.internal.R.drawable.ic_media_pause);
+            mPauseButton.setContentDescription(mPauseDescription);
         } else {
             mPauseButton.setImageResource(com.android.internal.R.drawable.ic_media_play);
+            mPauseButton.setContentDescription(mPlayDescription);
         }
     }
 
@@ -668,7 +678,7 @@
 
         if (mRoot != null) {
             installPrevNextListeners();
-            
+
             if (mNextButton != null && !mFromXml) {
                 mNextButton.setVisibility(View.VISIBLE);
             }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index a0f7baf..b162e54 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import android.R;
+import android.annotation.Nullable;
 import android.content.ClipData;
 import android.content.ClipboardManager;
 import android.content.Context;
@@ -222,6 +223,8 @@
  * @attr ref android.R.styleable#TextView_imeActionId
  * @attr ref android.R.styleable#TextView_editorExtras
  * @attr ref android.R.styleable#TextView_elegantTextHeight
+ * @attr ref android.R.styleable#TextView_letterSpacing
+ * @attr ref android.R.styleable#TextView_fontFeatureSettings
  */
 @RemoteView
 public class TextView extends View implements ViewTreeObserver.OnPreDrawListener {
@@ -2702,7 +2705,6 @@
      *
      * @see #setLetterSpacing(float)
      * @see Paint#setLetterSpacing
-     * @hide
      */
     public float getLetterSpacing() {
         return mTextPaint.getLetterSpacing();
@@ -2716,7 +2718,6 @@
      * @see Paint#getLetterSpacing
      *
      * @attr ref android.R.styleable#TextView_letterSpacing
-     * @hide
      */
     @android.view.RemotableViewMethod
     public void setLetterSpacing(float letterSpacing) {
@@ -2736,8 +2737,8 @@
      *
      * @see #setFontFeatureSettings(String)
      * @see Paint#setFontFeatureSettings
-     * @hide
      */
+    @Nullable
     public String getFontFeatureSettings() {
         return mTextPaint.getFontFeatureSettings();
     }
@@ -2747,14 +2748,14 @@
      * font-feature-settings attribute:
      * http://dev.w3.org/csswg/css-fonts/#propdef-font-feature-settings
      *
+     * @param fontFeatureSettings font feature settings represented as CSS compatible string
      * @see #getFontFeatureSettings()
      * @see Paint#getFontFeatureSettings
      *
      * @attr ref android.R.styleable#TextView_fontFeatureSettings
-     * @hide
      */
     @android.view.RemotableViewMethod
-    public void setFontFeatureSettings(String fontFeatureSettings) {
+    public void setFontFeatureSettings(@Nullable String fontFeatureSettings) {
         if (fontFeatureSettings != mTextPaint.getFontFeatureSettings()) {
             mTextPaint.setFontFeatureSettings(fontFeatureSettings);
 
diff --git a/core/java/com/android/internal/backup/LocalTransport.java b/core/java/com/android/internal/backup/LocalTransport.java
index 97e1102..d8dffe0 100644
--- a/core/java/com/android/internal/backup/LocalTransport.java
+++ b/core/java/com/android/internal/backup/LocalTransport.java
@@ -273,11 +273,15 @@
 
     @Override
     public int finishBackup() {
-        if (DEBUG) Log.v(TAG, "finishBackup()");
+        if (DEBUG) Log.v(TAG, "finishBackup() of " + mFullTargetPackage);
+        return tearDownFullBackup();
+    }
+
+    // ------------------------------------------------------------------------------------
+    // Full backup handling
+
+    private int tearDownFullBackup() {
         if (mSocket != null) {
-            if (DEBUG) {
-                Log.v(TAG, "Concluding full backup of " + mFullTargetPackage);
-            }
             try {
                 mFullBackupOutputStream.flush();
                 mFullBackupOutputStream.close();
@@ -286,7 +290,7 @@
                 mSocket.close();
             } catch (IOException e) {
                 if (DEBUG) {
-                    Log.w(TAG, "Exception caught in finishBackup()", e);
+                    Log.w(TAG, "Exception caught in tearDownFullBackup()", e);
                 }
                 return TRANSPORT_ERROR;
             } finally {
@@ -296,8 +300,9 @@
         return TRANSPORT_OK;
     }
 
-    // ------------------------------------------------------------------------------------
-    // Full backup handling
+    private File tarballFile(String pkgName) {
+        return new File(mCurrentSetFullDir, pkgName);
+    }
 
     @Override
     public long requestFullBackupTime() {
@@ -329,7 +334,7 @@
         mFullTargetPackage = targetPackage.packageName;
         FileOutputStream tarstream;
         try {
-            File tarball = new File(mCurrentSetFullDir, mFullTargetPackage);
+            File tarball = tarballFile(mFullTargetPackage);
             tarstream = new FileOutputStream(tarball);
         } catch (FileNotFoundException e) {
             return TRANSPORT_ERROR;
@@ -368,6 +373,19 @@
         return TRANSPORT_OK;
     }
 
+    // For now we can't roll back, so just tear everything down.
+    @Override
+    public void cancelFullBackup() {
+        if (DEBUG) {
+            Log.i(TAG, "Canceling full backup of " + mFullTargetPackage);
+        }
+        File archive = tarballFile(mFullTargetPackage);
+        tearDownFullBackup();
+        if (archive.exists()) {
+            archive.delete();
+        }
+    }
+
     // ------------------------------------------------------------------------------------
     // Restore handling
     static final long[] POSSIBLE_SETS = { 2, 3, 4, 5, 6, 7, 8, 9 };
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 50b86d0..ee0d14b 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -29,6 +29,7 @@
 import android.os.BadParcelableException;
 import android.os.BatteryManager;
 import android.os.BatteryStats;
+import android.os.Build;
 import android.os.FileUtils;
 import android.os.Handler;
 import android.os.Looper;
@@ -91,7 +92,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 112 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 113 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS = 2000;
@@ -233,6 +234,8 @@
     int mStartCount;
 
     long mStartClockTime;
+    String mStartPlatformVersion;
+    String mEndPlatformVersion;
 
     long mUptime;
     long mUptimeStart;
@@ -341,7 +344,7 @@
     int mDischargeAmountScreenOff;
     int mDischargeAmountScreenOffSinceCharge;
 
-    static final int MAX_LEVEL_STEPS = 100;
+    static final int MAX_LEVEL_STEPS = 200;
 
     int mInitStepMode = 0;
     int mCurStepMode = 0;
@@ -2840,8 +2843,6 @@
                 }
             }
 
-            mInitStepMode = mCurStepMode;
-            mModStepMode = 0;
             if (state == Display.STATE_ON) {
                 // Screen turning on.
                 final long elapsedRealtime = SystemClock.elapsedRealtime();
@@ -3928,6 +3929,18 @@
         return mStartClockTime;
     }
 
+    @Override public String getStartPlatformVersion() {
+        return mStartPlatformVersion;
+    }
+
+    @Override public String getEndPlatformVersion() {
+        return mEndPlatformVersion;
+    }
+
+    @Override public int getParcelVersion() {
+        return VERSION;
+    }
+
     @Override public boolean getIsOnBattery() {
         return mOnBattery;
     }
@@ -4592,6 +4605,7 @@
                     proc.detach();
                     mProcessStats.removeAt(ip);
                 } else {
+                    proc.reset();
                     active = true;
                 }
             }
@@ -4848,7 +4862,7 @@
             mProcessStats.clear();
             for (int k = 0; k < numProcs; k++) {
                 String processName = in.readString();
-                Uid.Proc proc = new Proc();
+                Uid.Proc proc = new Proc(processName);
                 proc.readFromParcelLocked(in);
                 mProcessStats.put(processName, proc);
             }
@@ -5097,6 +5111,11 @@
          */
         public final class Proc extends BatteryStats.Uid.Proc implements TimeBaseObs {
             /**
+             * The name of this process.
+             */
+            final String mName;
+
+            /**
              * Remains true until removed from the stats.
              */
             boolean mActive = true;
@@ -5190,7 +5209,8 @@
 
             ArrayList<ExcessivePower> mExcessivePower;
 
-            Proc() {
+            Proc(String name) {
+                mName = name;
                 mOnBatteryTimeBase.add(this);
                 mSpeedBins = new SamplingCounter[getCpuSpeedSteps()];
             }
@@ -5205,6 +5225,24 @@
             public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
             }
 
+            void reset() {
+                mUserTime = mSystemTime = mForegroundTime = 0;
+                mStarts = 0;
+                mLoadedUserTime = mLoadedSystemTime = mLoadedForegroundTime = 0;
+                mLoadedStarts = 0;
+                mLastUserTime = mLastSystemTime = mLastForegroundTime = 0;
+                mLastStarts = 0;
+                mUnpluggedUserTime = mUnpluggedSystemTime = mUnpluggedForegroundTime = 0;
+                mUnpluggedStarts = 0;
+                for (int i = 0; i < mSpeedBins.length; i++) {
+                    SamplingCounter c = mSpeedBins[i];
+                    if (c != null) {
+                        c.reset(false);
+                    }
+                }
+                mExcessivePower = null;
+            }
+
             void detach() {
                 mActive = false;
                 mOnBatteryTimeBase.remove(this);
@@ -5793,7 +5831,7 @@
         public Proc getProcessStatsLocked(String name) {
             Proc ps = mProcessStats.get(name);
             if (ps == null) {
-                ps = new Proc();
+                ps = new Proc(name);
                 mProcessStats.put(name, ps);
             }
 
@@ -6147,6 +6185,7 @@
         long uptime = SystemClock.uptimeMillis() * 1000;
         long realtime = SystemClock.elapsedRealtime() * 1000;
         initTimes(uptime, realtime);
+        mStartPlatformVersion = mEndPlatformVersion = Build.ID;
         mDischargeStartLevel = 0;
         mDischargeUnplugLevel = 0;
         mDischargePlugLevel = -1;
@@ -7398,6 +7437,8 @@
             Slog.e("BatteryStats", "Error reading battery statistics", e);
         }
 
+        mEndPlatformVersion = Build.ID;
+
         if (mHistoryBuffer.dataPosition() > 0) {
             mRecordingHistory = true;
             final long elapsedRealtime = SystemClock.elapsedRealtime();
@@ -7554,6 +7595,8 @@
         mUptime = in.readLong();
         mRealtime = in.readLong();
         mStartClockTime = in.readLong();
+        mStartPlatformVersion = in.readString();
+        mEndPlatformVersion = in.readString();
         mOnBatteryTimeBase.readSummaryFromParcel(in);
         mOnBatteryScreenOffTimeBase.readSummaryFromParcel(in);
         mDischargeUnplugLevel = in.readInt();
@@ -7847,6 +7890,8 @@
         out.writeLong(computeUptime(NOW_SYS, STATS_SINCE_CHARGED));
         out.writeLong(computeRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED));
         out.writeLong(mStartClockTime);
+        out.writeString(mStartPlatformVersion);
+        out.writeString(mEndPlatformVersion);
         mOnBatteryTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
         mOnBatteryScreenOffTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
         out.writeInt(mDischargeUnplugLevel);
@@ -8134,6 +8179,8 @@
 
         mStartCount = in.readInt();
         mStartClockTime = in.readLong();
+        mStartPlatformVersion = in.readString();
+        mEndPlatformVersion = in.readString();
         mUptime = in.readLong();
         mUptimeStart = in.readLong();
         mRealtime = in.readLong();
@@ -8289,6 +8336,8 @@
 
         out.writeInt(mStartCount);
         out.writeLong(mStartClockTime);
+        out.writeString(mStartPlatformVersion);
+        out.writeString(mEndPlatformVersion);
         out.writeLong(mUptime);
         out.writeLong(mUptimeStart);
         out.writeLong(mRealtime);
diff --git a/core/java/com/android/internal/util/JournaledFile.java b/core/java/com/android/internal/util/JournaledFile.java
index eeffc16..9f775d3 100644
--- a/core/java/com/android/internal/util/JournaledFile.java
+++ b/core/java/com/android/internal/util/JournaledFile.java
@@ -20,7 +20,7 @@
 import java.io.IOException;
 
 /**
- * @Deprecated Use {@link com.android.internal.os.AtomicFile} instead.  It would
+ * @deprecated Use {@link com.android.internal.os.AtomicFile} instead.  It would
  * be nice to update all existing uses of this to switch to AtomicFile, but since
  * their on-file semantics are slightly different that would run the risk of losing
  * data if at the point of the platform upgrade to the new code it would need to
diff --git a/core/res/res/color/btn_default_material_dark.xml b/core/res/res/color/btn_default_material_dark.xml
index 59555ae..7c904cd 100644
--- a/core/res/res/color/btn_default_material_dark.xml
+++ b/core/res/res/color/btn_default_material_dark.xml
@@ -15,6 +15,8 @@
 -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_enabled="false" android:alpha="0.5" android:color="@color/button_material_dark"/>
+    <item android:state_enabled="false"
+        android:alpha="@dimen/disabled_alpha_material"
+        android:color="@color/button_material_dark"/>
     <item android:color="@color/button_material_dark"/>
 </selector>
diff --git a/core/res/res/color/btn_default_material_light.xml b/core/res/res/color/btn_default_material_light.xml
index 6511a22..738f9ad 100644
--- a/core/res/res/color/btn_default_material_light.xml
+++ b/core/res/res/color/btn_default_material_light.xml
@@ -15,6 +15,8 @@
 -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_enabled="false" android:alpha="0.5" android:color="@color/button_material_light"/>
+    <item android:state_enabled="false"
+        android:alpha="@dimen/disabled_alpha_material"
+        android:color="@color/button_material_light"/>
     <item android:color="@color/button_material_light"/>
 </selector>
diff --git a/core/res/res/color/primary_text_disable_only_material_dark.xml b/core/res/res/color/primary_text_disable_only_material_dark.xml
index cf7acaa..cdae790 100644
--- a/core/res/res/color/primary_text_disable_only_material_dark.xml
+++ b/core/res/res/color/primary_text_disable_only_material_dark.xml
@@ -15,6 +15,8 @@
 -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_enabled="false" android:alpha="0.5" android:color="@android:color/bright_foreground_material_dark"/>
-    <item android:color="@android:color/bright_foreground_material_dark"/>
+    <item android:state_enabled="false"
+        android:alpha="@dimen/disabled_alpha_material"
+        android:color="@color/bright_foreground_material_dark"/>
+    <item android:color="@color/bright_foreground_material_dark"/>
 </selector>
diff --git a/core/res/res/color/primary_text_disable_only_material_light.xml b/core/res/res/color/primary_text_disable_only_material_light.xml
index bf5d2c0..0bf14d0 100644
--- a/core/res/res/color/primary_text_disable_only_material_light.xml
+++ b/core/res/res/color/primary_text_disable_only_material_light.xml
@@ -15,6 +15,8 @@
 -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_enabled="false" android:alpha="0.5" android:color="@android:color/bright_foreground_material_light"/>
-    <item android:color="@android:color/bright_foreground_material_light"/>
+    <item android:state_enabled="false"
+        android:alpha="@dimen/disabled_alpha_material"
+        android:color="@color/bright_foreground_material_light"/>
+    <item android:color="@color/bright_foreground_material_light"/>
 </selector>
diff --git a/core/res/res/color/primary_text_material_dark.xml b/core/res/res/color/primary_text_material_dark.xml
index caef9d0..6ad837b 100644
--- a/core/res/res/color/primary_text_material_dark.xml
+++ b/core/res/res/color/primary_text_material_dark.xml
@@ -15,6 +15,8 @@
 -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_enabled="false" android:alpha="0.5" android:color="@color/primary_text_default_material_dark"/>
+    <item android:state_enabled="false"
+        android:alpha="@dimen/disabled_alpha_material"
+        android:color="@color/primary_text_default_material_dark"/>
     <item android:color="@color/primary_text_default_material_dark"/>
 </selector>
diff --git a/core/res/res/color/primary_text_material_light.xml b/core/res/res/color/primary_text_material_light.xml
index 81a593b..4c19e12 100644
--- a/core/res/res/color/primary_text_material_light.xml
+++ b/core/res/res/color/primary_text_material_light.xml
@@ -15,6 +15,8 @@
 -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_enabled="false" android:alpha="0.5" android:color="@color/primary_text_default_material_light"/>
+    <item android:state_enabled="false"
+        android:alpha="@dimen/disabled_alpha_material"
+        android:color="@color/primary_text_default_material_light"/>
     <item android:color="@color/primary_text_default_material_light"/>
 </selector>
diff --git a/core/res/res/drawable-hdpi/cab_background_bottom_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/cab_background_bottom_mtrl_alpha.9.png
new file mode 100644
index 0000000..92613b7
--- /dev/null
+++ b/core/res/res/drawable-hdpi/cab_background_bottom_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/cab_background_top_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/cab_background_top_mtrl_alpha.9.png
new file mode 100644
index 0000000..e51ef28
--- /dev/null
+++ b/core/res/res/drawable-hdpi/cab_background_top_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/cab_background_bottom_mtrl_alpha.9.png b/core/res/res/drawable-mdpi/cab_background_bottom_mtrl_alpha.9.png
new file mode 100644
index 0000000..df292a0
--- /dev/null
+++ b/core/res/res/drawable-mdpi/cab_background_bottom_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/cab_background_top_mtrl_alpha.9.png b/core/res/res/drawable-mdpi/cab_background_top_mtrl_alpha.9.png
new file mode 100644
index 0000000..ae8cccd
--- /dev/null
+++ b/core/res/res/drawable-mdpi/cab_background_top_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/cab_background_bottom_mtrl_alpha.9.png b/core/res/res/drawable-xhdpi/cab_background_bottom_mtrl_alpha.9.png
new file mode 100644
index 0000000..9a4abd0
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/cab_background_bottom_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/cab_background_top_mtrl_alpha.9.png b/core/res/res/drawable-xhdpi/cab_background_top_mtrl_alpha.9.png
new file mode 100644
index 0000000..ed8d341
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/cab_background_top_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/cab_background_bottom_mtrl_alpha.9.png b/core/res/res/drawable-xxhdpi/cab_background_bottom_mtrl_alpha.9.png
new file mode 100644
index 0000000..22bd8ce
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/cab_background_bottom_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/cab_background_top_mtrl_alpha.9.png b/core/res/res/drawable-xxhdpi/cab_background_top_mtrl_alpha.9.png
new file mode 100644
index 0000000..1dd64b9
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/cab_background_top_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable/cab_background_bottom_material.xml b/core/res/res/drawable/cab_background_bottom_material.xml
new file mode 100644
index 0000000..cfbc854
--- /dev/null
+++ b/core/res/res/drawable/cab_background_bottom_material.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
+    android:paddingMode="stack">
+    <item>
+        <shape android:shape="rectangle">
+            <solid android:color="?attr/colorBackground" />
+        </shape>
+    </item>
+    <item>
+        <nine-patch
+            android:src="@drawable/cab_background_bottom_mtrl_alpha"
+            android:tint="?attr/colorControlActivated" />
+    </item>
+</layer-list>
diff --git a/core/res/res/drawable/cab_background_top_material.xml b/core/res/res/drawable/cab_background_top_material.xml
new file mode 100644
index 0000000..09f7a61
--- /dev/null
+++ b/core/res/res/drawable/cab_background_top_material.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
+    android:paddingMode="stack">
+    <item>
+        <shape android:shape="rectangle">
+            <solid android:color="?attr/colorBackground" />
+        </shape>
+    </item>
+    <item>
+        <nine-patch
+            android:src="@drawable/cab_background_top_mtrl_alpha"
+            android:tint="?attr/colorControlActivated" />
+    </item>
+</layer-list>
diff --git a/core/res/res/drawable/dialog_background_material.xml b/core/res/res/drawable/dialog_background_material.xml
index 7e5b003..2f8d1fa 100644
--- a/core/res/res/drawable/dialog_background_material.xml
+++ b/core/res/res/drawable/dialog_background_material.xml
@@ -14,12 +14,10 @@
      limitations under the License.
 -->
 
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="rectangle">
-
-    <corners
-        android:radius="2dp" />
-    <solid
-        android:color="?attr/colorBackground" />
-
-</shape>
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+    android:inset="16dp">
+    <shape android:shape="rectangle">
+        <corners android:radius="2dp" />
+        <solid android:color="?attr/colorBackground" />
+    </shape>
+</inset>
diff --git a/core/res/res/drawable/ic_corp_icon_badge.xml b/core/res/res/drawable/ic_corp_icon_badge.xml
index d20c431..834ae68 100644
--- a/core/res/res/drawable/ic_corp_icon_badge.xml
+++ b/core/res/res/drawable/ic_corp_icon_badge.xml
@@ -20,13 +20,11 @@
         android:viewportHeight="64.0">
 
     <path
-        android:fillColor="#FF000000"
-        android:pathData="M49.062,50.0m-14.0,0.0a14.0,14.0 0.0,1.0 1.0,28.0 0.0a14.0,14.0 0.0,1.0 1.0,-28.0 0.0"
-        android:fillOpacity="0.2"/>
+        android:fillColor="#33000000"
+        android:pathData="M49.062,50.0m-14.0,0.0a14.0,14.0 0.0,1.0 1.0,28.0 0.0a14.0,14.0 0.0,1.0 1.0,-28.0 0.0"/>
     <path
-        android:fillColor="#FF000000"
-        android:pathData="M49.0,49.5m-14.0,0.0a14.0,14.0 0.0,1.0 1.0,28.0 0.0a14.0,14.0 0.0,1.0 1.0,-28.0 0.0"
-        android:fillOpacity="0.2"/>
+        android:fillColor="#33000000"
+        android:pathData="M49.0,49.5m-14.0,0.0a14.0,14.0 0.0,1.0 1.0,28.0 0.0a14.0,14.0 0.0,1.0 1.0,-28.0 0.0"/>
     <path
         android:pathData="M49.0,49.0m-14.0,0.0a14.0,14.0 0.0,1.0 1.0,28.0 0.0a14.0,14.0 0.0,1.0 1.0,-28.0 0.0"
         android:fillColor="#FF5722"/>
diff --git a/core/res/res/drawable/switch_thumb_material_anim.xml b/core/res/res/drawable/switch_thumb_material_anim.xml
index 71f6cfd..30bc888 100644
--- a/core/res/res/drawable/switch_thumb_material_anim.xml
+++ b/core/res/res/drawable/switch_thumb_material_anim.xml
@@ -31,8 +31,7 @@
             android:src="@drawable/btn_switch_to_on_mtrl_00001"
             android:gravity="center"
             android:tintMode="multiply"
-            android:tint="?attr/colorButtonNormal"
-            android:alpha="?attr/disabledAlpha" />
+            android:tint="?attr/colorButtonNormal" />
     </item>
     <item
         android:state_checked="true"
diff --git a/core/res/res/drawable/switch_track_material.xml b/core/res/res/drawable/switch_track_material.xml
index b400644..0728055 100644
--- a/core/res/res/drawable/switch_track_material.xml
+++ b/core/res/res/drawable/switch_track_material.xml
@@ -18,12 +18,7 @@
     <item android:state_enabled="false" android:state_checked="true">
         <nine-patch android:src="@drawable/switch_track_mtrl_alpha"
             android:tint="?attr/colorControlActivated"
-            android:alpha="0.15" />
-    </item>
-    <item android:state_enabled="false">
-        <nine-patch android:src="@drawable/switch_track_mtrl_alpha"
-            android:tint="?attr/colorButtonNormal"
-            android:alpha="0.15" />
+            android:alpha="0.2" />
     </item>
     <item android:state_checked="true">
         <nine-patch android:src="@drawable/switch_track_mtrl_alpha"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 771690e..f6c0d71 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4926,6 +4926,7 @@
     <declare-styleable name="InsetDrawable">
         <attr name="visible" />
         <attr name="drawable" />
+        <attr name="inset"  format="dimension"/>
         <attr name="insetLeft" format="dimension" />
         <attr name="insetRight" format="dimension" />
         <attr name="insetTop" format="dimension" />
@@ -5208,13 +5209,13 @@
         <attr name="name" />
         <!-- The width a path stroke -->
         <attr name="strokeWidth" format="float" />
-        <!-- The opacity of a path stroke -->
+        <!-- The opacity of a path stroke @hide-->
         <attr name="strokeOpacity" format="float" />
         <!-- The color to stroke the path if not defined implies no stroke-->
         <attr name="strokeColor" format="color" />
         <!-- The color to fill the path if not defined implies no fill-->
         <attr name="fillColor" format="color" />
-        <!-- The level of opacity of the filled area of the path -->
+        <!-- The level of opacity of the filled area of the path @hide-->
         <attr name="fillOpacity" format="float" />
         <!-- The specification of the operations that define the path  -->
         <attr name="pathData" format="string" />
diff --git a/core/res/res/values/dimens_material.xml b/core/res/res/values/dimens_material.xml
index bae8e8d..c21dc59 100644
--- a/core/res/res/values/dimens_material.xml
+++ b/core/res/res/values/dimens_material.xml
@@ -68,4 +68,7 @@
     <dimen name="control_padding_material">4dp</dimen>
     <!-- Default rounded corner for controls -->
     <dimen name="control_corner_material">2dp</dimen>
+
+    <!-- Default alpha value for disabled elements. -->
+    <item name="disabled_alpha_material" format="float" type="dimen">0.26</item>
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 73aaafd..67352d7 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2269,6 +2269,12 @@
   <public type="attr" name="windowReenterTransition" />
   <public type="attr" name="windowSharedElementReturnTransition" />
   <public type="attr" name="windowSharedElementReenterTransition" />
+  <public type="attr" name="contentRatingSystemXml"/>
+  <public type="attr" name="datePickerMode"/>
+  <public type="attr" name="timePickerMode"/>
+  <public type="attr" name="inset" />
+  <public type="attr" name="letterSpacing" />
+  <public type="attr" name="fontFeatureSettings" />
 
   <public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
 
@@ -2561,8 +2567,22 @@
   <!-- WebView error page for when domain lookup fails. @hide @SystemApi -->
   <public type="raw" name="nodomain"/>
 
-  <public type="attr" name="contentRatingSystemXml"/>
-
-  <public type="attr" name="datePickerMode"/>
-  <public type="attr" name="timePickerMode"/>
+  <!-- Base text appearance for SystemUI elements -->
+  <public type="style" name="TextAppearance.StatusBar.Material" />
+  <!-- Base text appearance for notifications -->
+  <public type="style" name="TextAppearance.StatusBar.Material.EventContent" />
+  <!-- Notification text appearance: title -->
+  <public type="style" name="TextAppearance.StatusBar.Material.EventContent.Title" />
+  <!-- Notification text appearance: additional line of text sandwiched
+       between the title and content -->
+  <public type="style" name="TextAppearance.StatusBar.Material.EventContent.Line2" />
+  <!-- Notification text appearance: an annotation, e.g. the
+       number of messages in your inbox -->
+  <public type="style" name="TextAppearance.StatusBar.Material.EventContent.Info" />
+  <!-- Notification text appearance: timestamp -->
+  <public type="style" name="TextAppearance.StatusBar.Material.EventContent.Time" />
+  <!-- Notification text appearance: a way to highlight a bit of text (for
+       example, to separate the sender from the subject of an email if they
+       are all on the same line) -->
+  <public type="style" name="TextAppearance.StatusBar.Material.EventContent.Emphasis" />
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index c34560d..dd1d433 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -154,6 +154,10 @@
     <string name="ClipMmi">Incoming Caller ID</string>
     <!-- Displayed as the title for a success/failure report enabling/disabling caller ID. -->
     <string name="ClirMmi">Outgoing Caller ID</string>
+    <!-- Displayed as the title for a success/failure report enabling/disabling connected line ID. -->
+    <string name="ColpMmi">Connected Line ID</string>
+    <!-- Displayed as the title for a success/failure report enabling/disabling connected line ID restriction. -->
+    <string name="ColrMmi">Connected Line ID Restriction</string>
     <!-- Displayed as the title for a success/failure report enabling/disabling call forwarding. -->
     <string name="CfMmi">Call forwarding</string>
     <!-- Displayed as the title for a success/failure report enabling/disabling call waiting. -->
@@ -2540,15 +2544,19 @@
     Contact your wireless service provider for another SIM card.</string>
 
     <!-- Shown on transport control of lockscreen. Pressing button goes to previous track. -->
-    <string name="lockscreen_transport_prev_description">Previous track button</string>
+    <string name="lockscreen_transport_prev_description">Previous track</string>
     <!-- Shown on transport control of lockscreen. Pressing button goes to next track. -->
-    <string name="lockscreen_transport_next_description">Next track button</string>
+    <string name="lockscreen_transport_next_description">Next track</string>
     <!-- Shown on transport control of lockscreen. Pressing button pauses playback -->
-    <string name="lockscreen_transport_pause_description">Pause button</string>
+    <string name="lockscreen_transport_pause_description">Pause</string>
     <!-- Shown on transport control of lockscreen. Pressing button pauses playback -->
-    <string name="lockscreen_transport_play_description">Play button</string>
+    <string name="lockscreen_transport_play_description">Play</string>
     <!-- Shown on transport control of lockscreen. Pressing button pauses playback -->
-    <string name="lockscreen_transport_stop_description">Stop button</string>
+    <string name="lockscreen_transport_stop_description">Stop</string>
+    <!-- Shown on transport control screens. Pressing button rewinds playback [CHAR LIMIT=NONE]-->
+    <string name="lockscreen_transport_rew_description">Rewind</string>
+    <!-- Shown on transport control screens. Pressing button fast forwards playback [CHAR LIMIT=NONE]-->
+    <string name="lockscreen_transport_ffw_description">Fast forward</string>
 
     <!-- Shown in the lock screen when there is emergency calls only mode. -->
     <string name="emergency_calls_only" msgid="2485604591272668370">Emergency calls only</string>
@@ -5065,5 +5073,5 @@
     <!-- TV content rating system strings for ZA TV -->
 
     <!-- [CHAR_LIMIT=NONE] Battery saver: Feature description -->
-    <string name="battery_saver_description">To help improve battery life, battery saver will reduce your device’s performance and restrict background data.  Email, messaging, and other apps that rely on syncing may not update unless you open them.\n\nBattery saver turns off automatically when your device is charging.</string>
+    <string name="battery_saver_description">To help improve battery life, battery saver reduces your device’s performance and limits vibration and most background data. Email, messaging, and other apps that rely on syncing may not update unless you open them.\n\nBattery saver turns off automatically when your device is charging.</string>
 </resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index a5cac6b..e693d91 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1105,26 +1105,32 @@
 
     <style name="MediaButton.Previous">
         <item name="src">@drawable/ic_media_previous</item>
+        <item name="contentDescription">@string/lockscreen_transport_prev_description</item>
     </style>
 
     <style name="MediaButton.Next">
         <item name="src">@drawable/ic_media_next</item>
+        <item name="contentDescription">@string/lockscreen_transport_next_description</item>
     </style>
 
     <style name="MediaButton.Play">
         <item name="src">@drawable/ic_media_play</item>
+        <item name="contentDescription">@string/lockscreen_transport_play_description</item>
     </style>
 
     <style name="MediaButton.Ffwd">
         <item name="src">@drawable/ic_media_ff</item>
+        <item name="contentDescription">@string/lockscreen_transport_ffw_description</item>
     </style>
 
     <style name="MediaButton.Rew">
         <item name="src">@drawable/ic_media_rew</item>
+        <item name="contentDescription">@string/lockscreen_transport_rew_description</item>
     </style>
 
     <style name="MediaButton.Pause">
         <item name="src">@drawable/ic_media_pause</item>
+        <item name="contentDescription">@string/lockscreen_transport_pause_description</item>
     </style>
 
     <style name="ZoomControls">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6030715..110ddb1 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -382,6 +382,8 @@
   <java-symbol type="string" name="CfMmi" />
   <java-symbol type="string" name="ClipMmi" />
   <java-symbol type="string" name="ClirMmi" />
+  <java-symbol type="string" name="ColpMmi" />
+  <java-symbol type="string" name="ColrMmi" />
   <java-symbol type="string" name="CwMmi" />
   <java-symbol type="string" name="Midnight" />
   <java-symbol type="string" name="Noon" />
@@ -976,6 +978,8 @@
   <java-symbol type="string" name="ssl_ca_cert_noti_by_unknown" />
   <java-symbol type="string" name="ssl_ca_cert_noti_managed" />
   <java-symbol type="string" name="ssl_ca_cert_warning" />
+  <java-symbol type="string" name="lockscreen_transport_play_description" />
+  <java-symbol type="string" name="lockscreen_transport_pause_description" />
 
   <java-symbol type="plurals" name="abbrev_in_num_days" />
   <java-symbol type="plurals" name="abbrev_in_num_hours" />
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index e7001c3..1376dfa 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -46,7 +46,7 @@
         <item name="colorForegroundInverse">@color/bright_foreground_material_light</item>
         <item name="colorBackground">@color/background_material_dark</item>
         <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_material_dark</item>
-        <item name="disabledAlpha">0.5</item>
+        <item name="disabledAlpha">@dimen/disabled_alpha_material</item>
         <item name="backgroundDimAmount">0.6</item>
 
         <!-- Text styles -->
@@ -304,8 +304,8 @@
         <item name="actionButtonStyle">@style/Widget.Material.ActionButton</item>
         <item name="actionOverflowButtonStyle">@style/Widget.Material.ActionButton.Overflow</item>
         <item name="actionOverflowMenuStyle">@style/Widget.Material.PopupMenu.Overflow</item>
-        <item name="actionModeBackground">?attr/colorPrimaryDark</item>
-        <item name="actionModeSplitBackground">?attr/colorPrimaryDark</item>
+        <item name="actionModeBackground">@drawable/cab_background_top_material</item>
+        <item name="actionModeSplitBackground">@drawable/cab_background_bottom_material</item>
         <item name="actionModeCloseDrawable">@drawable/ic_cab_done_material</item>
         <item name="actionBarTabStyle">@style/Widget.Material.ActionBar.TabView</item>
         <item name="actionBarTabBarStyle">@style/Widget.Material.ActionBar.TabBar</item>
@@ -387,7 +387,7 @@
         <item name="colorForegroundInverse">@color/bright_foreground_material_dark</item>
         <item name="colorBackground">@color/background_material_light</item>
         <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_material_light</item>
-        <item name="disabledAlpha">0.5</item>
+        <item name="disabledAlpha">@dimen/disabled_alpha_material</item>
         <item name="backgroundDimAmount">0.6</item>
 
         <!-- Text styles -->
@@ -650,9 +650,8 @@
         <item name="actionButtonStyle">@style/Widget.Material.Light.ActionButton</item>
         <item name="actionOverflowButtonStyle">@style/Widget.Material.Light.ActionButton.Overflow</item>
         <item name="actionOverflowMenuStyle">@style/Widget.Material.Light.PopupMenu.Overflow</item>
-        <item name="actionBarPopupTheme">@null</item>
-        <item name="actionModeBackground">@drawable/cab_background_top_holo_light</item>
-        <item name="actionModeSplitBackground">@drawable/cab_background_bottom_holo_light</item>
+        <item name="actionModeBackground">@drawable/cab_background_top_material</item>
+        <item name="actionModeSplitBackground">@drawable/cab_background_bottom_material</item>
         <item name="actionModeCloseDrawable">@drawable/ic_cab_done_material</item>
         <item name="actionBarTabStyle">@style/Widget.Material.Light.ActionBar.TabView</item>
         <item name="actionBarTabBarStyle">@style/Widget.Material.Light.ActionBar.TabBar</item>
@@ -663,6 +662,7 @@
         <item name="actionBarSize">@dimen/action_bar_default_height_material</item>
         <item name="actionModePopupWindowStyle">@style/Widget.Material.Light.PopupWindow.ActionMode</item>
         <item name="actionBarWidgetTheme">@null</item>
+        <item name="actionBarPopupTheme">@null</item>
         <item name="actionBarTheme">@style/ThemeOverlay.Material.ActionBar</item>
         <item name="actionBarItemBackground">?attr/selectableItemBackgroundBorderless</item>
 
@@ -960,16 +960,8 @@
     </style>
 
     <!-- Theme for the search input bar. -->
-
-    <style name="Theme.Material.SearchBar" parent="Theme.Material.Panel">
-        <item name="actionModeBackground">@drawable/cab_background_top_holo_dark</item>
-        <item name="actionModeSplitBackground">@drawable/cab_background_bottom_holo_light</item>
-    </style>
-
-    <style name="Theme.Material.Light.SearchBar" parent="Theme.Material.Light.Panel">
-        <item name="actionModeBackground">@drawable/cab_background_top_holo_light</item>
-        <item name="actionModeSplitBackground">@drawable/cab_background_bottom_holo_light</item>
-    </style>
+    <style name="Theme.Material.SearchBar" parent="Theme.Material.Panel" />
+    <style name="Theme.Material.Light.SearchBar" parent="Theme.Material.Light.Panel" />
 
     <!-- Menu Themes -->
     <eat-comment />
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
new file mode 100644
index 0000000..a4d4906
--- /dev/null
+++ b/data/fonts/fonts.xml
@@ -0,0 +1,233 @@
+<?xml version="1.0" encoding="utf-8"?>
+<familyset version="22">
+    <!-- first font is default -->
+    <family name="sans-serif">
+        <font weight="100" style="normal">Roboto-Thin.ttf</font>
+        <font weight="100" style="italic">Roboto-ThinItalic.ttf</font>
+        <font weight="300" style="normal">Roboto-Light.ttf</font>
+        <font weight="300" style="italic">Roboto-LightItalic.ttf</font>
+        <font weight="400" style="normal">Roboto-Regular.ttf</font>
+        <font weight="400" style="italic">Roboto-Italic.ttf</font>
+        <font weight="500" style="normal">Roboto-Medium.ttf</font>
+        <font weight="500" style="italic">Roboto-MediumItalic.ttf</font>
+        <font weight="700" style="normal">Roboto-Bold.ttf</font>
+        <font weight="700" style="italic">Roboto-BoldItalic.ttf</font>
+        <font weight="900" style="normal">Roboto-Black.ttf</font>
+        <font weight="900" style="italic">Roboto-BlackItalic.ttf</font>
+    </family>
+
+    <!-- Note that aliases must come after the fonts they reference. -->
+    <alias name="sans-serif-thin" to="sans-serif" weight="100" />
+    <alias name="sans-serif-light" to="sans-serif" weight="300" />
+    <alias name="sans-serif-black" to="sans-serif" weight="900" />
+    <alias name="arial" to="sans-serif" />
+    <alias name="helvetica" to="sans-serif" />
+    <alias name="tahoma" to="sans-serif" />
+    <alias name="verdana" to="sans-serif" />
+
+    <family name="sans-serif-condensed">
+        <font weight="300" style="normal">RobotoCondensed-Light.ttf</font>
+        <font weight="300" style="italic">RobotoCondensed-LightItalic.ttf</font>
+        <font weight="400" style="normal">RobotoCondensed-Regular.ttf</font>
+        <font weight="400" style="italic">RobotoCondensed-Italic.ttf</font>
+        <font weight="700" style="normal">RobotoCondensed-Bold.ttf</font>
+        <font weight="700" style="italic">RobotoCondensed-BoldItalic.ttf</font>
+    </family>
+    <alias name="sans-serif-condensed-light" to="sans-serif-condensed" weight="300" />
+
+    <family name="serif">
+        <font weight="400" style="normal">NotoSerif-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSerif-Bold.ttf</font>
+        <font weight="400" style="italic">NotoSerif-Italic.ttf</font>
+        <font weight="700" style="italic">NotoSerif-BoldItalic.ttf</font>
+    </family>
+    <alias name="times" to="serif" />
+    <alias name="times new roman" to="serif" />
+    <alias name="palatino" to="serif" />
+    <alias name="georgia" to="serif" />
+    <alias name="baskerville" to="serif" />
+    <alias name="goudy" to="serif" />
+    <alias name="fantasy" to="serif" />
+    <alias name="ITC Stone Serif" to="serif" />
+
+    <family name="monospace">
+        <font weight="400" style="normal">DroidSansMono.ttf</font>
+    </family>
+    <alias name="courier" to="monospace" />
+    <alias name="courier new" to="monospace" />
+    <alias name="monaco" to="monospace" />
+
+    <family name="casual">
+        <font weight="400" style="normal">ComingSoon.ttf</font>
+    </family>
+
+    <family name="cursive">
+        <font weight="400" style="normal">DancingScript-Regular.ttf</font>
+        <font weight="700" style="normal">DancingScript-Bold.ttf</font>
+    </family>
+
+    <family name="sans-serif-smallcaps">
+        <font weight="400" style="normal">CarroisGothicSC-Regular.ttf</font>
+    </family>
+
+    <!-- fallback fonts -->
+    <family variant="elegant">
+        <font weight="400" style="normal">NotoNaskh-Regular.ttf</font>
+        <font weight="700" style="normal">NotoNaskh-Bold.ttf</font>
+    </family>
+    <family variant="compact">
+        <font weight="400" style="normal">NotoNaskhUI-Regular.ttf</font>
+        <font weight="700" style="normal">NotoNaskhUI-Bold.ttf</font>
+    </family>
+    <family>
+        <font weight="400" style="normal">NotoSansEthiopic-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansEthiopic-Bold.ttf</font>
+    </family>
+    <family>
+        <font weight="400" style="normal">NotoSansHebrew-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansHebrew-Bold.ttf</font>
+    </family>
+    <family variant="elegant">
+        <font weight="400" style="normal">NotoSansThai-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansThai-Bold.ttf</font>
+    </family>
+    <family variant="compact">
+        <font weight="400" style="normal">NotoSansThaiUI-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansThaiUI-Bold.ttf</font>
+    </family>
+    <family>
+        <font weight="400" style="normal">NotoSansArmenian-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansArmenian-Bold.ttf</font>
+    </family>
+    <family>
+        <font weight="400" style="normal">NotoSansGeorgian-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansGeorgian-Bold.ttf</font>
+    </family>
+    <family variant="elegant">
+        <font weight="400" style="normal">NotoSansDevanagari-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansDevanagari-Bold.ttf</font>
+    </family>
+    <family variant="compact">
+        <font weight="400" style="normal">NotoSansDevanagariUI-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansDevanagariUI-Bold.ttf</font>
+    </family>
+    <!-- Gujarati should come after Devanagari -->
+    <family variant="elegant">
+        <font weight="400" style="normal">NotoSansGujarati-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansGujarati-Bold.ttf</font>
+    </family>
+    <family variant="compact">
+        <font weight="400" style="normal">NotoSansGujaratiUI-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansGujaratiUI-Bold.ttf</font>
+    </family>
+    <!-- Gurmukhi should come after Devanagari -->
+    <family variant="elegant">
+        <font weight="400" style="normal">NotoSansGurmukhi-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansGurmukhi-Bold.ttf</font>
+    </family>
+    <family variant="compact">
+        <font weight="400" style="normal">NotoSansGurmukhiUI-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansGurmukhiUI-Bold.ttf</font>
+    </family>
+    <family variant="elegant">
+        <font weight="400" style="normal">NotoSansTamil-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansTamil-Bold.ttf</font>
+    </family>
+    <family variant="compact">
+        <font weight="400" style="normal">NotoSansTamilUI-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansTamilUI-Bold.ttf</font>
+    </family>
+    <family variant="elegant">
+        <font weight="400" style="normal">NotoSansMalayalam-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansMalayalam-Bold.ttf</font>
+    </family>
+    <family variant="compact">
+        <font weight="400" style="normal">NotoSansMalayalamUI-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansMalayalamUI-Bold.ttf</font>
+    </family>
+    <family variant="elegant">
+        <font weight="400" style="normal">NotoSansBengali-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansBengali-Bold.ttf</font>
+    </family>
+    <family variant="compact">
+        <font weight="400" style="normal">NotoSansBengaliUI-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansBengaliUI-Bold.ttf</font>
+    </family>
+    <family variant="elegant">
+        <font weight="400" style="normal">NotoSansTelugu-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansTelugu-Bold.ttf</font>
+    </family>
+    <family variant="compact">
+        <font weight="400" style="normal">NotoSansTeluguUI-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansTeluguUI-Bold.ttf</font>
+    </family>
+    <family variant="elegant">
+        <font weight="400" style="normal">NotoSansKannada-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansKannada-Bold.ttf</font>
+    </family>
+    <family variant="compact">
+        <font weight="400" style="normal">NotoSansKannadaUI-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansKannadaUI-Bold.ttf</font>
+    </family>
+    <family>
+        <font weight="400" style="normal">NotoSansSinhala-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansSinhala-Bold.ttf</font>
+    </family>
+    <family variant="elegant">
+        <font weight="400" style="normal">NotoSansKhmer-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansKhmer-Bold.ttf</font>
+    </family>
+    <family variant="compact">
+        <font weight="400" style="normal">NotoSansKhmerUI-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansKhmerUI-Bold.ttf</font>
+    </family>
+    <family variant="elegant">
+        <font weight="400" style="normal">NotoSansLao-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansLao-Bold.ttf</font>
+    </family>
+    <family variant="compact">
+        <font weight="400" style="normal">NotoSansLaoUI-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansLaoUI-Bold.ttf</font>
+    </family>
+    <family variant="elegant">
+        <font weight="400" style="normal">NotoSansMyanmar-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansMyanmar-Bold.ttf</font>
+    </family>
+    <family variant="compact">
+        <font weight="400" style="normal">NotoSansMyanmarUI-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansMyanmarUI-Bold.ttf</font>
+    </family>
+    <family>
+        <font weight="400" style="normal">NotoSansCherokee-Regular.ttf</font>
+    </family>
+    <family>
+        <font weight="400" style="normal">NotoSansCanadianAboriginal-Regular.ttf</font>
+    </family>
+    <family>
+        <font weight="400" style="normal">NotoSansYi-Regular.ttf</font>
+    </family>
+    <family lang="zh-Hans">
+        <font weight="400" style="normal">NotoSansHans-Regular.otf</font>
+    </family>
+    <family lang="zh-Hant">
+        <font weight="400" style="normal">NotoSansHant-Regular.otf</font>
+    </family>
+    <family lang="ja">
+        <font weight="400" style="normal">NotoSansJP-Regular.otf</font>
+    </family>
+    <family lang="ko">
+        <font weight="400" style="normal">NotoSansKR-Regular.otf</font>
+    </family>
+    <family>
+        <font weight="400" style="normal">NanumGothic.ttf</font>
+    </family>
+    <family>
+        <font weight="400" style="normal">NotoSansSymbols-Regular-Subsetted.ttf</font>
+    </family>
+    <family>
+        <font weight="400" style="normal">NotoColorEmoji.ttf</font>
+    </family>
+    <family lang="ja">
+        <font weight="400" style="normal">MTLmr3m.ttf</font>
+    </family>
+</familyset>
diff --git a/docs/html/sdk/installing/installing-adt.jd b/docs/html/sdk/installing/installing-adt.jd
index 864e82e..851827c 100644
--- a/docs/html/sdk/installing/installing-adt.jd
+++ b/docs/html/sdk/installing/installing-adt.jd
@@ -1,8 +1,8 @@
 page.title=Installing the Eclipse Plugin
-adt.zip.version=23.0.2
-adt.zip.download=ADT-23.0.2.zip
-adt.zip.bytes=103287135
-adt.zip.checksum=cde1d0a463b5ccce844b63161cfa1cb9
+adt.zip.version=23.0.3
+adt.zip.download=ADT-23.0.3.zip
+adt.zip.bytes=103321934
+adt.zip.checksum=ab2f5e2fbbdddeeb7dfd02cd4046538a
 
 @jd:body
 
diff --git a/docs/html/tools/sdk/eclipse-adt.jd b/docs/html/tools/sdk/eclipse-adt.jd
index 5d04098..cf33200 100644
--- a/docs/html/tools/sdk/eclipse-adt.jd
+++ b/docs/html/tools/sdk/eclipse-adt.jd
@@ -56,6 +56,42 @@
 <div class="toggle-content opened">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+      alt=""/>ADT 23.0.3</a> <em>(August 2014)</em>
+  </p>
+
+  <div class="toggle-content-toggleme">
+<dl>
+  <dt>Dependencies:</dt>
+
+  <dd>
+    <ul>
+      <li>Java 7 or higher is required if you are targeting the L Developer Preview.</li>
+      <li>Java 1.6 or higher is required if you are targeting other releases.</li>
+      <li>Eclipse Indigo (Version 3.7.2) or higher is required.</li>
+      <li>This version of ADT is designed for use with
+        <a href="{@docRoot}tools/sdk/tools-notes.html">SDK Tools r23.0.2</a>.
+        If you haven't already installed SDK Tools r23.0.2 into your SDK, use the
+        Android SDK Manager to do so.</li>
+    </ul>
+  </dd>
+
+  <dt>General Notes:</dt>
+  <dd>
+    <ul>
+      <li>Fixed an issue where ADT displayed a <code>NullPointerException</code> warning dialog
+          when a valid SDK was not configured. (<a href="http://b.android.com/73313">Issue
+          73313</a>)</li>
+      <li>Fixed a minor issue with RenderScript support.</li>
+      <li>Disabled APK compression.</li>
+    </ul>
+  </dd>
+</dl>
+</div>
+</div>
+
+<div class="toggle-content closed">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
       alt=""/>ADT 23.0.2</a> <em>(July 2014)</em>
   </p>
 
diff --git a/docs/html/tools/support-library/features.jd b/docs/html/tools/support-library/features.jd
index 65148bf..78946ee 100644
--- a/docs/html/tools/support-library/features.jd
+++ b/docs/html/tools/support-library/features.jd
@@ -225,8 +225,7 @@
 
 <p>This library provides {@link android.support.v7.media.MediaRouter}, {@link
 android.support.v7.media.MediaRouteProvider}, and related media classes that
-support the <a href="https://developers.google.com/cast/">Google Cast
-developer preview</a>. </p>
+support <a href="https://developers.google.com/cast/docs/android_sender">Google Cast</a>. </p>
 
 <p>In general, the APIs in the v7 mediarouter library provide a means of
 controlling the routing of media channels and streams from the current device to
@@ -258,9 +257,8 @@
 
 <p class="caution">The v7 mediarouter library APIs introduced in Support Library
 r18 are subject to change in later revisions of the Support Library. At this
-time, we recommend using the library only in connection with the <a
-href="https://developers.google.com/cast/">Google Cast
-developer preview</a>. </p>
+time, we recommend using the library only in connection with <a
+href="https://developers.google.com/cast/docs/android_sender">Google Cast</a>. </p>
 
 
 <h2 id="v8">v8 Support Library</h2>
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index ca8d736..1c76d9c 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -1267,7 +1267,6 @@
      * is 0.
      *
      * @return         the paint's letter-spacing for drawing text.
-     * @hide
      */
     public float getLetterSpacing() {
         return native_getLetterSpacing(mNativePaint);
@@ -1279,7 +1278,6 @@
      * expansion will be around 0.05.  Negative values tighten text.
      *
      * @param letterSpacing set the paint's letter-spacing for drawing text.
-     * @hide
      */
     public void setLetterSpacing(float letterSpacing) {
         native_setLetterSpacing(mNativePaint, letterSpacing);
@@ -1289,7 +1287,6 @@
      * Get font feature settings.  Default is null.
      *
      * @return the paint's currently set font feature settings.
-     * @hide
      */
     public String getFontFeatureSettings() {
         return mFontFeatureSettings;
@@ -1302,7 +1299,6 @@
      * http://dev.w3.org/csswg/css-fonts/#propdef-font-feature-settings
      *
      * @param settings the font feature settings string to use, may be null.
-     * @hide
      */
     public void setFontFeatureSettings(String settings) {
         if (settings != null && settings.equals("")) {
diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java
index ee5fe2e..588e776 100644
--- a/graphics/java/android/graphics/drawable/InsetDrawable.java
+++ b/graphics/java/android/graphics/drawable/InsetDrawable.java
@@ -119,20 +119,40 @@
         // Extract the theme attributes, if any.
         state.mThemeAttrs = a.extractThemeAttrs();
 
-        final Drawable dr = a.getDrawable(R.styleable.InsetDrawable_drawable);
-        if (dr != null) {
-            state.mDrawable = dr;
-            dr.setCallback(this);
+        final int N = a.getIndexCount();
+        for (int i = 0; i < N; i++) {
+            final int attr = a.getIndex(i);
+            switch (attr) {
+                case R.styleable.InsetDrawable_drawable:
+                    final Drawable dr = a.getDrawable(attr);
+                    if (dr != null) {
+                        state.mDrawable = dr;
+                        dr.setCallback(this);
+                    }
+                    break;
+                case R.styleable.InsetDrawable_inset:
+                    final int inset = a.getDimensionPixelOffset(attr, Integer.MIN_VALUE);
+                    if (inset != Integer.MIN_VALUE) {
+                        state.mInsetLeft = inset;
+                        state.mInsetTop = inset;
+                        state.mInsetRight = inset;
+                        state.mInsetBottom = inset;
+                    }
+                    break;
+                case R.styleable.InsetDrawable_insetLeft:
+                    state.mInsetLeft = a.getDimensionPixelOffset(attr, state.mInsetLeft);
+                    break;
+                case R.styleable.InsetDrawable_insetTop:
+                    state.mInsetTop = a.getDimensionPixelOffset(attr, state.mInsetTop);
+                    break;
+                case R.styleable.InsetDrawable_insetRight:
+                    state.mInsetRight = a.getDimensionPixelOffset(attr, state.mInsetRight);
+                    break;
+                case R.styleable.InsetDrawable_insetBottom:
+                    state.mInsetBottom = a.getDimensionPixelOffset(attr, state.mInsetBottom);
+                    break;
+            }
         }
-
-        state.mInsetLeft = a.getDimensionPixelOffset(
-                R.styleable.InsetDrawable_insetLeft, state.mInsetLeft);
-        state.mInsetTop = a.getDimensionPixelOffset(
-                R.styleable.InsetDrawable_insetTop, state.mInsetTop);
-        state.mInsetRight = a.getDimensionPixelOffset(
-                R.styleable.InsetDrawable_insetRight, state.mInsetRight);
-        state.mInsetBottom = a.getDimensionPixelOffset(
-                R.styleable.InsetDrawable_insetBottom, state.mInsetBottom);
     }
 
     @Override
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 813797f..2b5823e 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -104,6 +104,8 @@
  * <dt><code>android:translateY</code></dt>
  * <dd>The amount of translation on the Y coordinate.
  * This is defined in the viewport space.</dd>
+ * <dt><code>android:alpha</code></dt>
+ * <dd>The amount of transparency.</dd>
  * </dl></dd>
  * </dl>
  *
@@ -117,15 +119,11 @@
  * <dd>Defines path string. This is using exactly same format as "d" attribute
  * in the SVG's path data. This is defined in the viewport space.</dd>
  * <dt><code>android:fillColor</code></dt>
- * <dd>Defines the color to fill the path (none if not present).</dd>
+ * <dd>Defines the color to fill the path (black if not present).</dd>
  * <dt><code>android:strokeColor</code></dt>
  * <dd>Defines the color to draw the path outline (none if not present).</dd>
  * <dt><code>android:strokeWidth</code></dt>
  * <dd>The width a path stroke.</dd>
- * <dt><code>android:strokeOpacity</code></dt>
- * <dd>The opacity of a path stroke.</dd>
- * <dt><code>android:fillOpacity</code></dt>
- * <dd>The opacity to fill the path with.</dd>
  * <dt><code>android:trimPathStart</code></dt>
  * <dd>The fraction of the path to trim from the start, in the range from 0 to 1.</dd>
  * <dt><code>android:trimPathEnd</code></dt>
@@ -1241,10 +1239,8 @@
 
         int mStrokeColor = 0;
         float mStrokeWidth = 0;
-        float mStrokeOpacity = Float.NaN;
         int mFillColor = Color.BLACK;
         int mFillRule;
-        float mFillOpacity = Float.NaN;
         float mTrimPathStart = 0;
         float mTrimPathEnd = 1;
         float mTrimPathOffset = 0;
@@ -1263,10 +1259,8 @@
 
             mStrokeColor = copy.mStrokeColor;
             mStrokeWidth = copy.mStrokeWidth;
-            mStrokeOpacity = copy.mStrokeOpacity;
             mFillColor = copy.mFillColor;
             mFillRule = copy.mFillRule;
-            mFillOpacity = copy.mFillOpacity;
             mTrimPathStart = copy.mTrimPathStart;
             mTrimPathEnd = copy.mTrimPathEnd;
             mTrimPathOffset = copy.mTrimPathOffset;
@@ -1327,8 +1321,6 @@
 
             mFillColor = a.getColor(R.styleable.VectorDrawablePath_fillColor,
                     mFillColor);
-            mFillOpacity = a.getFloat(R.styleable.VectorDrawablePath_fillOpacity,
-                    mFillOpacity);
             mStrokeLineCap = getStrokeLineCap(a.getInt(
                     R.styleable.VectorDrawablePath_strokeLineCap, -1), mStrokeLineCap);
             mStrokeLineJoin = getStrokeLineJoin(a.getInt(
@@ -1337,8 +1329,6 @@
                     R.styleable.VectorDrawablePath_strokeMiterLimit, mStrokeMiterlimit);
             mStrokeColor = a.getColor(R.styleable.VectorDrawablePath_strokeColor,
                     mStrokeColor);
-            mStrokeOpacity = a.getFloat(R.styleable.VectorDrawablePath_strokeOpacity,
-                    mStrokeOpacity);
             mStrokeWidth = a.getFloat(R.styleable.VectorDrawablePath_strokeWidth,
                     mStrokeWidth);
             mTrimPathEnd = a.getFloat(R.styleable.VectorDrawablePath_trimPathEnd,
@@ -1347,8 +1337,6 @@
                     R.styleable.VectorDrawablePath_trimPathOffset, mTrimPathOffset);
             mTrimPathStart = a.getFloat(
                     R.styleable.VectorDrawablePath_trimPathStart, mTrimPathStart);
-
-            updateColorAlphas();
         }
 
         @Override
@@ -1363,16 +1351,6 @@
             a.recycle();
         }
 
-        private void updateColorAlphas() {
-            if (!Float.isNaN(mFillOpacity)) {
-                mFillColor = applyAlpha(mFillColor, mFillOpacity);
-            }
-
-            if (!Float.isNaN(mStrokeOpacity)) {
-                mStrokeColor = applyAlpha(mStrokeColor, mStrokeOpacity);
-            }
-        }
-
         /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
         @SuppressWarnings("unused")
         int getStroke() {
@@ -1395,16 +1373,6 @@
         }
 
         @SuppressWarnings("unused")
-        float getStrokeOpacity() {
-            return mStrokeOpacity;
-        }
-
-        @SuppressWarnings("unused")
-        void setStrokeOpacity(float strokeOpacity) {
-            mStrokeOpacity = strokeOpacity;
-        }
-
-        @SuppressWarnings("unused")
         int getFill() {
             return mFillColor;
         }
@@ -1415,16 +1383,6 @@
         }
 
         @SuppressWarnings("unused")
-        float getFillOpacity() {
-            return mFillOpacity;
-        }
-
-        @SuppressWarnings("unused")
-        void setFillOpacity(float fillOpacity) {
-            mFillOpacity = fillOpacity;
-        }
-
-        @SuppressWarnings("unused")
         float getTrimPathStart() {
             return mTrimPathStart;
         }
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index 79a2f61..acfa98e 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -69,7 +69,9 @@
 class PlaybackStateStruct {
 protected:
     PlaybackStateStruct(OpenGLRenderer& renderer, int replayFlags, LinearAllocator* allocator)
-            : mRenderer(renderer), mReplayFlags(replayFlags), mAllocator(allocator){}
+            : mRenderer(renderer)
+            , mReplayFlags(replayFlags)
+            , mAllocator(allocator) {}
 
 public:
     OpenGLRenderer& mRenderer;
@@ -78,6 +80,15 @@
     // Allocator with the lifetime of a single frame.
     // replay uses an Allocator owned by the struct, while defer shares the DeferredDisplayList's Allocator
     LinearAllocator * const mAllocator;
+
+    SkPath* allocPathForFrame() {
+        mTempPaths.push_back();
+        return &mTempPaths.back();
+    }
+
+private:
+    // Paths kept alive for the duration of the frame
+    std::vector<SkPath> mTempPaths;
 };
 
 class DeferStateStruct : public PlaybackStateStruct {
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 6883cc5..c6d3db7 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1505,20 +1505,18 @@
 class DrawShadowOp : public DrawOp {
 public:
     DrawShadowOp(const mat4& transformXY, const mat4& transformZ,
-            float casterAlpha, const SkPath* casterOutline, const SkPath* revealClip)
-            : DrawOp(NULL), mTransformXY(transformXY), mTransformZ(transformZ),
-            mCasterAlpha(casterAlpha) {
-        mOutline = *casterOutline;
-        if (revealClip) {
-            // intersect the outline with the convex reveal clip
-            Op(mOutline, *revealClip, kIntersect_PathOp, &mOutline);
-        }
+            float casterAlpha, const SkPath* casterOutline)
+        : DrawOp(NULL)
+        , mTransformXY(transformXY)
+        , mTransformZ(transformZ)
+        , mCasterAlpha(casterAlpha)
+        , mCasterOutline(casterOutline) {
     }
 
     virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
             const DeferredDisplayState& state) {
         renderer.getCaches().tessellationCache.precacheShadows(&state.mMatrix,
-                renderer.getLocalClipBounds(), isCasterOpaque(), &mOutline,
+                renderer.getLocalClipBounds(), isCasterOpaque(), mCasterOutline,
                 &mTransformXY, &mTransformZ, renderer.getLightCenter(), renderer.getLightRadius());
     }
 
@@ -1527,7 +1525,7 @@
         Matrix4 drawTransform;
         renderer.getMatrix(&drawTransform);
         renderer.getCaches().tessellationCache.getShadowBuffers(&drawTransform,
-                renderer.getLocalClipBounds(), isCasterOpaque(), &mOutline,
+                renderer.getLocalClipBounds(), isCasterOpaque(), mCasterOutline,
                 &mTransformXY, &mTransformZ, renderer.getLightCenter(), renderer.getLightRadius(),
                 buffers);
 
@@ -1546,7 +1544,7 @@
     const mat4 mTransformXY;
     const mat4 mTransformZ;
     const float mCasterAlpha;
-    SkPath mOutline;
+    const SkPath* mCasterOutline;
 };
 
 class DrawLayerOp : public DrawOp {
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index e00d2e3..396c7f3 100755
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -58,11 +58,6 @@
 // Defines
 ///////////////////////////////////////////////////////////////////////////////
 
-#define RAD_TO_DEG (180.0f / 3.14159265f)
-#define MIN_ANGLE 0.001f
-
-#define ALPHA_THRESHOLD 0
-
 static GLenum getFilter(const SkPaint* paint) {
     if (!paint || paint->getFilterLevel() != SkPaint::kNone_FilterLevel) {
         return GL_LINEAR;
@@ -692,7 +687,7 @@
             (fboLayer && clip.isEmpty())) {
         mSnapshot->empty = fboLayer;
     } else {
-        mSnapshot->invisible = mSnapshot->invisible || (alpha <= ALPHA_THRESHOLD && fboLayer);
+        mSnapshot->invisible = mSnapshot->invisible || (alpha <= 0 && fboLayer);
     }
 }
 
diff --git a/libs/hwui/PathTessellator.cpp b/libs/hwui/PathTessellator.cpp
index 209341c..e30ac19 100644
--- a/libs/hwui/PathTessellator.cpp
+++ b/libs/hwui/PathTessellator.cpp
@@ -49,6 +49,7 @@
 #include "Matrix.h"
 #include "Vector.h"
 #include "Vertex.h"
+#include "utils/MathUtils.h"
 
 namespace android {
 namespace uirenderer {
@@ -56,12 +57,11 @@
 #define OUTLINE_REFINE_THRESHOLD_SQUARED (0.5f * 0.5f)
 #define ROUND_CAP_THRESH 0.25f
 #define PI 3.1415926535897932f
+#define MAX_DEPTH 15
 
-// temporary error thresholds
-#define ERROR_DEPTH 20
-#define ERROR_SCALE 1e10
-#define ERROR_SQR_INV_THRESH 1e-20
-
+/**
+ * Extracts the x and y scale from the transform as positive values, and clamps them
+ */
 void PathTessellator::extractTessellationScales(const Matrix4& transform,
         float* scaleX, float* scaleY) {
     if (CC_LIKELY(transform.isPureTranslate())) {
@@ -72,11 +72,8 @@
         float m01 = transform.data[Matrix4::kSkewY];
         float m10 = transform.data[Matrix4::kSkewX];
         float m11 = transform.data[Matrix4::kScaleY];
-        *scaleX = sqrt(m00 * m00 + m01 * m01);
-        *scaleY = sqrt(m10 * m10 + m11 * m11);
-
-        LOG_ALWAYS_FATAL_IF(*scaleX > ERROR_SCALE || *scaleY > ERROR_SCALE,
-                "scales %e x %e too large for tessellation", *scaleX, *scaleY);
+        *scaleX = MathUtils::clampTessellationScale(sqrt(m00 * m00 + m01 * m01));
+        *scaleY = MathUtils::clampTessellationScale(sqrt(m10 * m10 + m11 * m11));
     }
 }
 
@@ -109,8 +106,8 @@
         } else {
             float scaleX, scaleY;
             PathTessellator::extractTessellationScales(transform, &scaleX, &scaleY);
-            inverseScaleX = (scaleX != 0) ? (1.0f / scaleX) : 1.0f;
-            inverseScaleY = (scaleY != 0) ? (1.0f / scaleY) : 1.0f;
+            inverseScaleX = 1.0f / scaleX;
+            inverseScaleY = 1.0f / scaleY;
         }
 
         if (isAA && halfStrokeWidth != 0 && inverseScaleX == inverseScaleY &&
@@ -914,9 +911,6 @@
         Vector<Vertex>& outputVertices) {
     ATRACE_CALL();
 
-    LOG_ALWAYS_FATAL_IF(sqrInvScaleX < ERROR_SQR_INV_THRESH || sqrInvScaleY < ERROR_SQR_INV_THRESH,
-            "Invalid scale factors used for approx %e, %e", sqrInvScaleX, sqrInvScaleY);
-
     // TODO: to support joins other than sharp miter, join vertices should be labelled in the
     // perimeter, or resolved into more vertices. Reconsider forceClose-ing in that case.
     SkPath::Iter iter(path, forceClose);
@@ -975,9 +969,6 @@
         float p2x, float p2y, float c2x, float c2y,
         float sqrInvScaleX, float sqrInvScaleY, float thresholdSquared,
         Vector<Vertex>& outputVertices, int depth) {
-    LOG_ALWAYS_FATAL_IF(depth >= ERROR_DEPTH, "ERROR DEPTH exceeded: cubic approx, invscale %e x %e, vertcount %d",
-            sqrInvScaleX, sqrInvScaleY, outputVertices.size());
-
     float dx = p2x - p1x;
     float dy = p2y - p1y;
     float d1 = fabs((c1x - p2x) * dy - (c1y - p2y) * dx);
@@ -985,7 +976,8 @@
     float d = d1 + d2;
 
     // multiplying by sqrInvScaleY/X equivalent to multiplying in dimensional scale factors
-    if (d * d < thresholdSquared * (dx * dx * sqrInvScaleY + dy * dy * sqrInvScaleX)) {
+    if (depth >= MAX_DEPTH
+            || d * d <= thresholdSquared * (dx * dx * sqrInvScaleY + dy * dy * sqrInvScaleX)) {
         // below thresh, draw line by adding endpoint
         pushToVector(outputVertices, p2x, p2y);
     } else {
@@ -1023,14 +1015,13 @@
         float cx, float cy,
         float sqrInvScaleX, float sqrInvScaleY, float thresholdSquared,
         Vector<Vertex>& outputVertices, int depth) {
-    LOG_ALWAYS_FATAL_IF(depth >= ERROR_DEPTH, "ERROR_DEPTH exceeded: quadratic approx, invscale %e x %e, vertcount %d",
-            sqrInvScaleX, sqrInvScaleY, outputVertices.size());
-
     float dx = bx - ax;
     float dy = by - ay;
     float d = (cx - bx) * dy - (cy - by) * dx;
 
-    if (d * d < thresholdSquared * (dx * dx * sqrInvScaleY + dy * dy * sqrInvScaleX)) {
+    // multiplying by sqrInvScaleY/X equivalent to multiplying in dimensional scale factors
+    if (depth >= MAX_DEPTH
+            || d * d <= thresholdSquared * (dx * dx * sqrInvScaleY + dy * dy * sqrInvScaleX)) {
         // below thresh, draw line by adding endpoint
         pushToVector(outputVertices, bx, by);
     } else {
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index f48b774..23940ee 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -534,6 +534,7 @@
     inline void endMark() {}
     inline int level() { return mLevel; }
     inline int replayFlags() { return mDeferStruct.mReplayFlags; }
+    inline SkPath* allocPathForFrame() { return mDeferStruct.allocPathForFrame(); }
 
 private:
     DeferStateStruct& mDeferStruct;
@@ -564,6 +565,7 @@
     }
     inline int level() { return mLevel; }
     inline int replayFlags() { return mReplayStruct.mReplayFlags; }
+    inline SkPath* allocPathForFrame() { return mReplayStruct.allocPathForFrame(); }
 
 private:
     ReplayStateStruct& mReplayStruct;
@@ -612,14 +614,24 @@
     mat4 shadowMatrixZ(transformFromParent);
     applyViewPropertyTransforms(shadowMatrixZ, true);
 
-    const SkPath* outlinePath = properties().getOutline().getPath();
+    const SkPath* casterOutlinePath = properties().getOutline().getPath();
     const SkPath* revealClipPath = properties().getRevealClip().getPath();
     if (revealClipPath && revealClipPath->isEmpty()) return;
 
     float casterAlpha = properties().getAlpha() * properties().getOutline().getAlpha();
+
+    const SkPath* outlinePath = casterOutlinePath;
+    if (revealClipPath) {
+        // if we can't simply use the caster's path directly, create a temporary one
+        SkPath* frameAllocatedPath = handler.allocPathForFrame();
+
+        // intersect the outline with the convex reveal clip
+        Op(*casterOutlinePath, *revealClipPath, kIntersect_PathOp, frameAllocatedPath);
+        outlinePath = frameAllocatedPath;
+    }
+
     DisplayListOp* shadowOp  = new (handler.allocator()) DrawShadowOp(
-            shadowMatrixXY, shadowMatrixZ, casterAlpha,
-            outlinePath, revealClipPath);
+            shadowMatrixXY, shadowMatrixZ, casterAlpha, outlinePath);
     handler(shadowOp, PROPERTY_SAVECOUNT, properties().getClipToBounds());
 }
 
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index 41f48cd..0c8d07f 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -313,7 +313,6 @@
     }
 
     bool setScaleX(float scaleX) {
-        LOG_ALWAYS_FATAL_IF(scaleX > 1000000, "invalid scaleX %e", scaleX);
         return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleX, scaleX);
     }
 
@@ -322,7 +321,6 @@
     }
 
     bool setScaleY(float scaleY) {
-        LOG_ALWAYS_FATAL_IF(scaleY > 1000000, "invalid scaleY %e", scaleY);
         return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleY, scaleY);
     }
 
diff --git a/libs/hwui/utils/MathUtils.h b/libs/hwui/utils/MathUtils.h
index 66bc127..6fb0411 100644
--- a/libs/hwui/utils/MathUtils.h
+++ b/libs/hwui/utils/MathUtils.h
@@ -35,6 +35,9 @@
         return value >= NON_ZERO_EPSILON;
     }
 
+    /**
+     * Clamps alpha value, and snaps when very near 0 or 1
+     */
     inline static float clampAlpha(float alpha) {
         if (alpha <= ALPHA_EPSILON) {
             return 0;
@@ -45,6 +48,20 @@
         }
     }
 
+    /*
+     * Clamps positive tessellation scale values
+     */
+    inline static float clampTessellationScale(float scale) {
+        const float MIN_SCALE = 0.0001;
+        const float MAX_SCALE = 1e10;
+        if (scale < MIN_SCALE) {
+            return MIN_SCALE;
+        } else if (scale > MAX_SCALE) {
+            return MAX_SCALE;
+        }
+        return scale;
+    }
+
     inline static bool areEqual(float valueA, float valueB) {
         return isZero(valueA - valueB);
     }
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 40602c5..8bc2498 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -479,7 +479,7 @@
                                  int channelConfig, int audioFormat, int mode) {
         //--------------
         // sample rate, note these values are subject to change
-        if ( (sampleRateInHz < 4000) || (sampleRateInHz > 48000) ) {
+        if (sampleRateInHz < SAMPLE_RATE_HZ_MIN || sampleRateInHz > SAMPLE_RATE_HZ_MAX) {
             throw new IllegalArgumentException(sampleRateInHz
                     + "Hz is not a supported sample rate.");
         }
diff --git a/media/java/android/media/tv/ITvInputService.aidl b/media/java/android/media/tv/ITvInputService.aidl
index c98a48d..7a853d1 100644
--- a/media/java/android/media/tv/ITvInputService.aidl
+++ b/media/java/android/media/tv/ITvInputService.aidl
@@ -35,6 +35,6 @@
     // For hardware TvInputService
     void notifyHardwareAdded(in TvInputHardwareInfo hardwareInfo);
     void notifyHardwareRemoved(in TvInputHardwareInfo hardwareInfo);
-    void notifyHdmiCecDeviceAdded(in HdmiDeviceInfo deviceInfo);
-    void notifyHdmiCecDeviceRemoved(in HdmiDeviceInfo deviceInfo);
+    void notifyHdmiDeviceAdded(in HdmiDeviceInfo deviceInfo);
+    void notifyHdmiDeviceRemoved(in HdmiDeviceInfo deviceInfo);
 }
diff --git a/media/java/android/media/tv/ITvInputServiceCallback.aidl b/media/java/android/media/tv/ITvInputServiceCallback.aidl
index df648e7..de5d56f 100644
--- a/media/java/android/media/tv/ITvInputServiceCallback.aidl
+++ b/media/java/android/media/tv/ITvInputServiceCallback.aidl
@@ -24,7 +24,7 @@
  * @hide
  */
 oneway interface ITvInputServiceCallback {
-    void addHardwareTvInput(in int deviceID, in TvInputInfo inputInfo);
-    void addHdmiCecTvInput(in int logicalAddress, in TvInputInfo inputInfo);
+    void addHardwareTvInput(in int deviceId, in TvInputInfo inputInfo);
+    void addHdmiTvInput(in int logicalAddress, in TvInputInfo inputInfo);
     void removeTvInput(in String inputId);
 }
diff --git a/media/java/android/media/tv/TvContentRating.java b/media/java/android/media/tv/TvContentRating.java
index 2e4d031..18136e9 100644
--- a/media/java/android/media/tv/TvContentRating.java
+++ b/media/java/android/media/tv/TvContentRating.java
@@ -19,7 +19,6 @@
 import android.annotation.SystemApi;
 import android.net.Uri;
 import android.text.TextUtils;
-import android.util.Log;
 
 import java.util.Arrays;
 import java.util.Collections;
@@ -963,8 +962,6 @@
  * </table>
  */
 public final class TvContentRating {
-    private static final String TAG = "TvContentRating";
-
     /** @hide */
     public static final Uri SYSTEM_CONTENT_RATING_SYSTEM_XML = Uri.parse(
             "android.resource://system/" + com.android.internal.R.xml.tv_content_rating_systems);
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index a826957..ae6f5bc 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -20,7 +20,6 @@
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.ContentUris;
-import android.media.tv.TvContract.Programs;
 import android.net.Uri;
 import android.provider.BaseColumns;
 import android.util.ArraySet;
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index 8feb7e6..8d0e986 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -103,10 +103,10 @@
 
     private static final String XML_START_TAG_NAME = "tv-input";
     private static final String DELIMITER_INFO_IN_ID = "/";
-    private static final String PREFIX_CEC_DEVICE = "CEC";
+    private static final String PREFIX_HDMI_DEVICE = "HDMI";
     private static final String PREFIX_HARDWARE_DEVICE = "HW";
-    private static final int LENGTH_CEC_PHYSICAL_ADDRESS = 4;
-    private static final int LENGTH_CEC_LOGICAL_ADDRESS = 2;
+    private static final int LENGTH_HDMI_PHYSICAL_ADDRESS = 4;
+    private static final int LENGTH_HDMI_LOGICAL_ADDRESS = 2;
 
     private final ResolveInfo mService;
     private final String mId;
@@ -155,7 +155,7 @@
      * instantiating it from the given Context, ResolveInfo, and HdmiDeviceInfo.
      *
      * @param service The ResolveInfo returned from the package manager about this TV input service.
-     * @param cecInfo The HdmiDeviceInfo for a HDMI CEC logical device.
+     * @param deviceInfo The HdmiDeviceInfo for a HDMI CEC logical device.
      * @param parentId The ID of this TV input's parent input. {@code null} if none exists.
      * @param iconUri The {@link android.net.Uri} to load the icon image.
      *        {@see android.content.ContentResolver#openInputStream}. If it is null, the application
@@ -166,12 +166,12 @@
      */
     @SystemApi
     public static TvInputInfo createTvInputInfo(Context context, ResolveInfo service,
-            HdmiDeviceInfo cecInfo, String parentId, String label, Uri iconUri)
+            HdmiDeviceInfo deviceInfo, String parentId, String label, Uri iconUri)
                     throws XmlPullParserException, IOException {
-        boolean isConnectedToHdmiSwitch = (cecInfo.getPhysicalAddress() & 0x0FFF) != 0;
-        return createTvInputInfo(context, service, generateInputIdForHdmiCec(
+        boolean isConnectedToHdmiSwitch = (deviceInfo.getPhysicalAddress() & 0x0FFF) != 0;
+        return createTvInputInfo(context, service, generateInputIdForHdmiDevice(
                 new ComponentName(service.serviceInfo.packageName, service.serviceInfo.name),
-                cecInfo), parentId, TYPE_HDMI, label, iconUri, isConnectedToHdmiSwitch);
+                deviceInfo), parentId, TYPE_HDMI, label, iconUri, isConnectedToHdmiSwitch);
     }
 
     /**
@@ -497,16 +497,16 @@
      * Used to generate an input id from a ComponentName and HdmiDeviceInfo.
      *
      * @param name the component name for generating an input id.
-     * @param cecInfo HdmiDeviceInfo describing this TV input.
-     * @return the generated input id for the given {@code name} and {@code cecInfo}.
+     * @param deviceInfo HdmiDeviceInfo describing this TV input.
+     * @return the generated input id for the given {@code name} and {@code deviceInfo}.
      */
-    private static final String generateInputIdForHdmiCec(
-            ComponentName name, HdmiDeviceInfo cecInfo) {
-        // Example of the format : "/CEC%04X%02X"
-        String format = String.format("%s%s%%0%sX%%0%sX", DELIMITER_INFO_IN_ID, PREFIX_CEC_DEVICE,
-                LENGTH_CEC_PHYSICAL_ADDRESS, LENGTH_CEC_LOGICAL_ADDRESS);
+    private static final String generateInputIdForHdmiDevice(
+            ComponentName name, HdmiDeviceInfo deviceInfo) {
+        // Example of the format : "/HDMI%04X%02X"
+        String format = String.format("%s%s%%0%sX%%0%sX", DELIMITER_INFO_IN_ID, PREFIX_HDMI_DEVICE,
+                LENGTH_HDMI_PHYSICAL_ADDRESS, LENGTH_HDMI_LOGICAL_ADDRESS);
         return name.flattenToShortString() + String.format(format,
-                cecInfo.getPhysicalAddress(), cecInfo.getLogicalAddress());
+                deviceInfo.getPhysicalAddress(), deviceInfo.getLogicalAddress());
     }
 
     /**
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 6a41c61..408ee7b 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -28,7 +28,6 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
@@ -42,7 +41,6 @@
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.Surface;
-import android.view.SurfaceView;
 import android.view.View;
 import android.view.WindowManager;
 import android.view.accessibility.CaptioningManager;
@@ -92,7 +90,7 @@
      * Handler instance to handle request from TV Input Manager Service. Should be run in the main
      * looper to be synchronously run with {@code Session.mHandler}.
      */
-    private Handler mServiceHandler = new ServiceHandler();
+    private final Handler mServiceHandler = new ServiceHandler();
     private final RemoteCallbackList<ITvInputServiceCallback> mCallbacks =
             new RemoteCallbackList<ITvInputServiceCallback>();
 
@@ -142,15 +140,15 @@
             }
 
             @Override
-            public void notifyHdmiCecDeviceAdded(HdmiDeviceInfo cecDeviceInfo) {
-                mServiceHandler.obtainMessage(ServiceHandler.DO_ADD_HDMI_CEC_TV_INPUT,
-                        cecDeviceInfo).sendToTarget();
+            public void notifyHdmiDeviceAdded(HdmiDeviceInfo deviceInfo) {
+                mServiceHandler.obtainMessage(ServiceHandler.DO_ADD_HDMI_TV_INPUT,
+                        deviceInfo).sendToTarget();
             }
 
             @Override
-            public void notifyHdmiCecDeviceRemoved(HdmiDeviceInfo cecDeviceInfo) {
-                mServiceHandler.obtainMessage(ServiceHandler.DO_REMOVE_HDMI_CEC_TV_INPUT,
-                        cecDeviceInfo).sendToTarget();
+            public void notifyHdmiDeviceRemoved(HdmiDeviceInfo deviceInfo) {
+                mServiceHandler.obtainMessage(ServiceHandler.DO_REMOVE_HDMI_TV_INPUT,
+                        deviceInfo).sendToTarget();
             }
         };
     }
@@ -203,27 +201,27 @@
 
     /**
      * Returns a new {@link TvInputInfo} object if this service is responsible for
-     * {@code cecDeviceInfo}; otherwise, return {@code null}. Override to modify default behavior
-     * of ignoring all HDMI CEC logical input device.
+     * {@code deviceInfo}; otherwise, return {@code null}. Override to modify default behavior of
+     * ignoring all HDMI logical input device.
      *
-     * @param cecDeviceInfo {@link HdmiDeviceInfo} object just added.
+     * @param deviceInfo {@link HdmiDeviceInfo} object just added.
      * @hide
      */
     @SystemApi
-    public TvInputInfo onHdmiCecDeviceAdded(HdmiDeviceInfo cecDeviceInfo) {
+    public TvInputInfo onHdmiDeviceAdded(HdmiDeviceInfo deviceInfo) {
         return null;
     }
 
     /**
-     * Returns the input ID for {@code logicalAddress} if it is handled by this service;
-     * otherwise, return {@code null}. Override to modify default behavior of ignoring all HDMI CEC
-     * logical input device.
+     * Returns the input ID for {@code logicalAddress} if it is handled by this service; otherwise,
+     * return {@code null}. Override to modify default behavior of ignoring all HDMI logical input
+     * device.
      *
-     * @param cecDeviceInfo {@link HdmiDeviceInfo} object just removed.
+     * @param deviceInfo {@link HdmiDeviceInfo} object just removed.
      * @hide
      */
     @SystemApi
-    public String onHdmiCecDeviceRemoved(HdmiDeviceInfo cecDeviceInfo) {
+    public String onHdmiDeviceRemoved(HdmiDeviceInfo deviceInfo) {
         return null;
     }
 
@@ -1164,8 +1162,8 @@
         private static final int DO_NOTIFY_SESSION_CREATED = 2;
         private static final int DO_ADD_HARDWARE_TV_INPUT = 3;
         private static final int DO_REMOVE_HARDWARE_TV_INPUT = 4;
-        private static final int DO_ADD_HDMI_CEC_TV_INPUT = 5;
-        private static final int DO_REMOVE_HDMI_CEC_TV_INPUT = 6;
+        private static final int DO_ADD_HDMI_TV_INPUT = 5;
+        private static final int DO_REMOVE_HDMI_TV_INPUT = 6;
 
         private void broadcastAddHardwareTvInput(int deviceId, TvInputInfo inputInfo) {
             int n = mCallbacks.beginBroadcast();
@@ -1179,12 +1177,11 @@
             mCallbacks.finishBroadcast();
         }
 
-        private void broadcastAddHdmiCecTvInput(
-                int logicalAddress, TvInputInfo inputInfo) {
+        private void broadcastAddHdmiTvInput(int logicalAddress, TvInputInfo inputInfo) {
             int n = mCallbacks.beginBroadcast();
             for (int i = 0; i < n; ++i) {
                 try {
-                    mCallbacks.getBroadcastItem(i).addHdmiCecTvInput(logicalAddress, inputInfo);
+                    mCallbacks.getBroadcastItem(i).addHdmiTvInput(logicalAddress, inputInfo);
                 } catch (RemoteException e) {
                     Log.e(TAG, "Error while broadcasting.", e);
                 }
@@ -1286,17 +1283,17 @@
                     }
                     return;
                 }
-                case DO_ADD_HDMI_CEC_TV_INPUT: {
-                    HdmiDeviceInfo cecDeviceInfo = (HdmiDeviceInfo) msg.obj;
-                    TvInputInfo inputInfo = onHdmiCecDeviceAdded(cecDeviceInfo);
+                case DO_ADD_HDMI_TV_INPUT: {
+                    HdmiDeviceInfo deviceInfo = (HdmiDeviceInfo) msg.obj;
+                    TvInputInfo inputInfo = onHdmiDeviceAdded(deviceInfo);
                     if (inputInfo != null) {
-                        broadcastAddHdmiCecTvInput(cecDeviceInfo.getLogicalAddress(), inputInfo);
+                        broadcastAddHdmiTvInput(deviceInfo.getLogicalAddress(), inputInfo);
                     }
                     return;
                 }
-                case DO_REMOVE_HDMI_CEC_TV_INPUT: {
-                    HdmiDeviceInfo cecDeviceInfo = (HdmiDeviceInfo) msg.obj;
-                    String inputId = onHdmiCecDeviceRemoved(cecDeviceInfo);
+                case DO_REMOVE_HDMI_TV_INPUT: {
+                    HdmiDeviceInfo deviceInfo = (HdmiDeviceInfo) msg.obj;
+                    String inputId = onHdmiDeviceRemoved(deviceInfo);
                     if (inputId != null) {
                         broadcastRemoveTvInput(inputId);
                     }
diff --git a/media/jni/android_media_MediaCodecList.cpp b/media/jni/android_media_MediaCodecList.cpp
index ed1eeb9..ecba02a 100644
--- a/media/jni/android_media_MediaCodecList.cpp
+++ b/media/jni/android_media_MediaCodecList.cpp
@@ -21,6 +21,8 @@
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/MediaCodecList.h>
+#include <media/IMediaCodecList.h>
+#include <media/MediaCodecInfo.h>
 
 #include "android_runtime/AndroidRuntime.h"
 #include "jni.h"
@@ -29,20 +31,41 @@
 
 using namespace android;
 
+static sp<IMediaCodecList> getCodecList(JNIEnv *env) {
+    sp<IMediaCodecList> mcl = MediaCodecList::getInstance();
+    if (mcl == NULL) {
+        // This should never happen unless something is really wrong
+        jniThrowException(
+                    env, "java/lang/RuntimeException", "cannot get MediaCodecList");
+    }
+    return mcl;
+}
+
 static jint android_media_MediaCodecList_getCodecCount(
         JNIEnv *env, jobject thiz) {
-    return MediaCodecList::getInstance()->countCodecs();
+    sp<IMediaCodecList> mcl = getCodecList(env);
+    if (mcl == NULL) {
+        // Runtime exception already pending.
+        return 0;
+    }
+    return mcl->countCodecs();
 }
 
 static jstring android_media_MediaCodecList_getCodecName(
         JNIEnv *env, jobject thiz, jint index) {
-    const char *name = MediaCodecList::getInstance()->getCodecName(index);
+    sp<IMediaCodecList> mcl = getCodecList(env);
+    if (mcl == NULL) {
+        // Runtime exception already pending.
+        return NULL;
+    }
 
-    if (name == NULL) {
+    const sp<MediaCodecInfo> &info = mcl->getCodecInfo(index);
+    if (info == NULL) {
         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
         return NULL;
     }
 
+    const char *name = info->getCodecName();
     return env->NewStringUTF(name);
 }
 
@@ -54,33 +77,56 @@
     }
 
     const char *nameStr = env->GetStringUTFChars(name, NULL);
-
     if (nameStr == NULL) {
         // Out of memory exception already pending.
         return -ENOENT;
     }
 
-    jint ret = MediaCodecList::getInstance()->findCodecByName(nameStr);
+    sp<IMediaCodecList> mcl = getCodecList(env);
+    if (mcl == NULL) {
+        // Runtime exception already pending.
+        return -ENOENT;
+    }
+
+    jint ret = mcl->findCodecByName(nameStr);
     env->ReleaseStringUTFChars(name, nameStr);
     return ret;
 }
 
 static jboolean android_media_MediaCodecList_isEncoder(
         JNIEnv *env, jobject thiz, jint index) {
-    return MediaCodecList::getInstance()->isEncoder(index);
+    sp<IMediaCodecList> mcl = getCodecList(env);
+    if (mcl == NULL) {
+        // Runtime exception already pending.
+        return false;
+    }
+
+    const sp<MediaCodecInfo> &info = mcl->getCodecInfo(index);
+    if (info == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+        return false;
+    }
+
+    return info->isEncoder();
 }
 
 static jarray android_media_MediaCodecList_getSupportedTypes(
         JNIEnv *env, jobject thiz, jint index) {
-    Vector<AString> types;
-    status_t err =
-        MediaCodecList::getInstance()->getSupportedTypes(index, &types);
+    sp<IMediaCodecList> mcl = getCodecList(env);
+    if (mcl == NULL) {
+        // Runtime exception already pending.
+        return NULL;
+    }
 
-    if (err != OK) {
+    const sp<MediaCodecInfo> &info = mcl->getCodecInfo(index);
+    if (info == NULL) {
         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
         return NULL;
     }
 
+    Vector<AString> types;
+    info->getSupportedMimes(&types);
+
     jclass clazz = env->FindClass("java/lang/String");
     CHECK(clazz != NULL);
 
@@ -103,6 +149,18 @@
         return NULL;
     }
 
+    sp<IMediaCodecList> mcl = getCodecList(env);
+    if (mcl == NULL) {
+        // Runtime exception already pending.
+        return NULL;
+    }
+
+    const sp<MediaCodecInfo> &info = mcl->getCodecInfo(index);
+    if (info == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+        return NULL;
+    }
+
     const char *typeStr = env->GetStringUTFChars(type, NULL);
 
     if (typeStr == NULL) {
@@ -110,30 +168,27 @@
         return NULL;
     }
 
-    Vector<MediaCodecList::ProfileLevel> profileLevels;
+    Vector<MediaCodecInfo::ProfileLevel> profileLevels;
     Vector<uint32_t> colorFormats;
-    uint32_t flags;
-    sp<AMessage> capabilities;
 
     sp<AMessage> defaultFormat = new AMessage();
     defaultFormat->setString("mime", typeStr);
 
     // TODO query default-format also from codec/codec list
-
-    status_t err =
-        MediaCodecList::getInstance()->getCodecCapabilities(
-                index, typeStr, &profileLevels, &colorFormats, &flags,
-                &capabilities);
-
-    bool isEncoder = MediaCodecList::getInstance()->isEncoder(index);
-
-    env->ReleaseStringUTFChars(type, typeStr);
-    typeStr = NULL;
-
-    if (err != OK) {
+    const sp<MediaCodecInfo::Capabilities> &capabilities =
+        info->getCapabilitiesFor(typeStr);
+    if (capabilities == NULL) {
         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
         return NULL;
     }
+    env->ReleaseStringUTFChars(type, typeStr);
+    typeStr = NULL;
+
+    capabilities->getSupportedColorFormats(&colorFormats);
+    capabilities->getSupportedProfileLevels(&profileLevels);
+    uint32_t flags = capabilities->getFlags();
+    sp<AMessage> details = capabilities->getDetails();
+    bool isEncoder = info->isEncoder();
 
     jobject defaultFormatObj = NULL;
     if (ConvertMessageToMap(env, defaultFormat, &defaultFormatObj)) {
@@ -141,7 +196,7 @@
     }
 
     jobject infoObj = NULL;
-    if (ConvertMessageToMap(env, capabilities, &infoObj)) {
+    if (ConvertMessageToMap(env, details, &infoObj)) {
         env->DeleteLocalRef(defaultFormatObj);
         return NULL;
     }
@@ -164,7 +219,7 @@
         env->GetFieldID(profileLevelClazz, "level", "I");
 
     for (size_t i = 0; i < profileLevels.size(); ++i) {
-        const MediaCodecList::ProfileLevel &src = profileLevels.itemAt(i);
+        const MediaCodecInfo::ProfileLevel &src = profileLevels.itemAt(i);
 
         jobject profileLevelObj = env->AllocObject(profileLevelClazz);
 
@@ -192,26 +247,6 @@
             profileLevelArray, colorFormatsArray, isEncoder, flags,
             defaultFormatObj, infoObj);
 
-#if 0
-    jfieldID profileLevelsField = env->GetFieldID(
-            capsClazz,
-            "profileLevels",
-            "[Landroid/media/MediaCodecInfo$CodecProfileLevel;");
-
-    env->SetObjectField(caps, profileLevelsField, profileLevelArray);
-
-    jfieldID flagsField =
-        env->GetFieldID(capsClazz, "mFlagsVerified", "I");
-
-    env->SetIntField(caps, flagsField, flags);
-
-    jfieldID colorFormatsField = env->GetFieldID(
-            capsClazz, "colorFormats", "[I");
-
-    env->SetObjectField(caps, colorFormatsField, colorFormatsArray);
-
-#endif
-
     env->DeleteLocalRef(profileLevelArray);
     profileLevelArray = NULL;
 
diff --git a/packages/Keyguard/src/com/android/keyguard/AppearAnimationUtils.java b/packages/Keyguard/src/com/android/keyguard/AppearAnimationUtils.java
index 6bb1f2c..e664fb9 100644
--- a/packages/Keyguard/src/com/android/keyguard/AppearAnimationUtils.java
+++ b/packages/Keyguard/src/com/android/keyguard/AppearAnimationUtils.java
@@ -26,38 +26,70 @@
  */
 public class AppearAnimationUtils implements AppearAnimationCreator<View> {
 
-    public static final long APPEAR_DURATION = 220;
+    public static final long DEFAULT_APPEAR_DURATION = 220;
 
-    private final Interpolator mLinearOutSlowIn;
+    private final Interpolator mInterpolator;
     private final float mStartTranslation;
     private final AppearAnimationProperties mProperties = new AppearAnimationProperties();
     private final float mDelayScale;
+    private final long mDuration;
 
     public AppearAnimationUtils(Context ctx) {
-        this(ctx, 1.0f, 1.0f);
+        this(ctx, DEFAULT_APPEAR_DURATION,
+                ctx.getResources().getDimensionPixelSize(R.dimen.appear_y_translation_start),
+                1.0f,
+                AnimationUtils.loadInterpolator(ctx, android.R.interpolator.linear_out_slow_in));
     }
 
-    public AppearAnimationUtils(Context ctx, float delayScaleFactor,
-            float translationScaleFactor) {
-        mLinearOutSlowIn = AnimationUtils.loadInterpolator(
-                ctx, android.R.interpolator.linear_out_slow_in);
+    public AppearAnimationUtils(Context ctx, long duration, float translationScaleFactor,
+            float delayScaleFactor, Interpolator interpolator) {
+        mInterpolator = interpolator;
         mStartTranslation = ctx.getResources().getDimensionPixelOffset(
                 R.dimen.appear_y_translation_start) * translationScaleFactor;
         mDelayScale = delayScaleFactor;
+        mDuration = duration;
     }
 
     public void startAppearAnimation(View[][] objects, final Runnable finishListener) {
         startAppearAnimation(objects, finishListener, this);
     }
 
+    public void startAppearAnimation(View[] objects, final Runnable finishListener) {
+        startAppearAnimation(objects, finishListener, this);
+    }
+
     public <T> void startAppearAnimation(T[][] objects, final Runnable finishListener,
             AppearAnimationCreator<T> creator) {
         AppearAnimationProperties properties = getDelays(objects);
         startAnimations(properties, objects, finishListener, creator);
     }
 
+    public <T> void startAppearAnimation(T[] objects, final Runnable finishListener,
+            AppearAnimationCreator<T> creator) {
+        AppearAnimationProperties properties = getDelays(objects);
+        startAnimations(properties, objects, finishListener, creator);
+    }
+
+    private <T> void startAnimations(AppearAnimationProperties properties, T[] objects,
+            final Runnable finishListener, AppearAnimationCreator<T> creator) {
+        if (properties.maxDelayRowIndex == -1 || properties.maxDelayColIndex == -1) {
+            finishListener.run();
+            return;
+        }
+        for (int row = 0; row < properties.delays.length; row++) {
+            long[] columns = properties.delays[row];
+            long delay = columns[0];
+            Runnable endRunnable = null;
+            if (properties.maxDelayRowIndex == row && properties.maxDelayColIndex == 0) {
+                endRunnable = finishListener;
+            }
+            creator.createAnimation(objects[row], delay, mDuration,
+                    mStartTranslation, mInterpolator, endRunnable);
+        }
+    }
+
     private <T> void startAnimations(AppearAnimationProperties properties, T[][] objects,
-            final Runnable finishListener, AppearAnimationCreator creator) {;
+            final Runnable finishListener, AppearAnimationCreator<T> creator) {
         if (properties.maxDelayRowIndex == -1 || properties.maxDelayColIndex == -1) {
             finishListener.run();
             return;
@@ -70,15 +102,32 @@
                 if (properties.maxDelayRowIndex == row && properties.maxDelayColIndex == col) {
                     endRunnable = finishListener;
                 }
-                creator.createAnimation(objects[row][col], delay, APPEAR_DURATION,
-                        mStartTranslation, mLinearOutSlowIn, endRunnable);
+                creator.createAnimation(objects[row][col], delay, mDuration,
+                        mStartTranslation, mInterpolator, endRunnable);
             }
         }
+    }
 
+    private <T> AppearAnimationProperties getDelays(T[] items) {
+        long maxDelay = -1;
+        mProperties.maxDelayColIndex = -1;
+        mProperties.maxDelayRowIndex = -1;
+        mProperties.delays = new long[items.length][];
+        for (int row = 0; row < items.length; row++) {
+            mProperties.delays[row] = new long[1];
+            long delay = calculateDelay(row, 0);
+            mProperties.delays[row][0] = delay;
+            if (items[row] != null && delay > maxDelay) {
+                maxDelay = delay;
+                mProperties.maxDelayColIndex = 0;
+                mProperties.maxDelayRowIndex = row;
+            }
+        }
+        return mProperties;
     }
 
     private <T> AppearAnimationProperties getDelays(T[][] items) {
-        long maxDelay = 0;
+        long maxDelay = -1;
         mProperties.maxDelayColIndex = -1;
         mProperties.maxDelayRowIndex = -1;
         mProperties.delays = new long[items.length][];
@@ -103,7 +152,7 @@
     }
 
     public Interpolator getInterpolator() {
-        return mLinearOutSlowIn;
+        return mInterpolator;
     }
 
     public float getStartTranslation() {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
index d5dcd71..12bbd35 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
@@ -37,6 +37,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
 import android.widget.Button;
 import android.widget.LinearLayout;
@@ -108,8 +109,10 @@
     public KeyguardPatternView(Context context, AttributeSet attrs) {
         super(context, attrs);
         mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
-        mAppearAnimationUtils = new AppearAnimationUtils(context, 1.5f /* delayScale */,
-                2.0f /* transitionScale */);
+        mAppearAnimationUtils = new AppearAnimationUtils(context,
+                AppearAnimationUtils.DEFAULT_APPEAR_DURATION, 1.5f /* delayScale */,
+                2.0f /* transitionScale */, AnimationUtils.loadInterpolator(
+                        mContext, android.R.interpolator.linear_out_slow_in));
     }
 
     public void setKeyguardCallback(KeyguardSecurityCallback callback) {
@@ -420,7 +423,7 @@
                 this);
         if (!TextUtils.isEmpty(mHelpMessage.getText())) {
             mAppearAnimationUtils.createAnimation(mHelpMessage, 0,
-                    AppearAnimationUtils.APPEAR_DURATION,
+                    AppearAnimationUtils.DEFAULT_APPEAR_DURATION,
                     mAppearAnimationUtils.getStartTranslation(),
                     mAppearAnimationUtils.getInterpolator(),
                     null /* finishRunnable */);
diff --git a/packages/SystemUI/res/layout/data_usage.xml b/packages/SystemUI/res/layout/data_usage.xml
index 63d22b2..8831a05 100644
--- a/packages/SystemUI/res/layout/data_usage.xml
+++ b/packages/SystemUI/res/layout/data_usage.xml
@@ -17,6 +17,9 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
+    android:paddingTop="16dp"
+    android:paddingStart="16dp"
+    android:paddingEnd="16dp"
     android:orientation="vertical" >
 
     <TextView
diff --git a/packages/SystemUI/res/layout/keyguard_user_switcher.xml b/packages/SystemUI/res/layout/keyguard_user_switcher.xml
index 5648065..7c918c2 100644
--- a/packages/SystemUI/res/layout/keyguard_user_switcher.xml
+++ b/packages/SystemUI/res/layout/keyguard_user_switcher.xml
@@ -14,7 +14,8 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License
   -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.systemui.statusbar.AlphaOptimizedLinearLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
         android:id="@+id/keyguard_user_switcher"
         android:orientation="vertical"
         android:layout_height="wrap_content"
@@ -22,4 +23,4 @@
         android:gravity="end"
         android:visibility="gone"
         android:paddingTop="4dp">
-</LinearLayout>
+</com.android.systemui.statusbar.AlphaOptimizedLinearLayout>
diff --git a/packages/SystemUI/res/layout/qs_detail.xml b/packages/SystemUI/res/layout/qs_detail.xml
index c6a7368..5869bf3 100644
--- a/packages/SystemUI/res/layout/qs_detail.xml
+++ b/packages/SystemUI/res/layout/qs_detail.xml
@@ -14,39 +14,43 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:background="@drawable/qs_detail_background"
-    android:padding="16dp" >
-
-    <TextView
-        android:id="@android:id/button1"
-        style="@style/QSBorderlessButton"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:minWidth="88dp"
-        android:layout_alignParentBottom="true"
-        android:layout_alignParentEnd="true"
-        android:text="@string/quick_settings_done"
-        android:textAppearance="@style/TextAppearance.QS.DetailButton" />
-
-    <TextView
-        android:id="@android:id/button2"
-        style="@style/QSBorderlessButton"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_alignParentBottom="true"
-        android:layout_marginEnd="8dp"
-        android:minWidth="132dp"
-        android:layout_toStartOf="@android:id/button1"
-        android:text="@string/quick_settings_more_settings"
-        android:textAppearance="@style/TextAppearance.QS.DetailButton" />
-
-    <FrameLayout
-        android:id="@android:id/content"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:layout_above="@android:id/button1" />
+        android:background="@drawable/qs_detail_background"
+        android:paddingBottom="16dp"
+        android:orientation="vertical">
 
-</RelativeLayout>
\ No newline at end of file
+    <FrameLayout
+            android:id="@android:id/content"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="1" />
+
+    <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingEnd="16dp"
+            android:gravity="end">
+
+        <TextView
+                android:id="@android:id/button2"
+                style="@style/QSBorderlessButton"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginEnd="8dp"
+                android:minWidth="132dp"
+                android:text="@string/quick_settings_more_settings"
+                android:textAppearance="@style/TextAppearance.QS.DetailButton" />
+
+        <TextView
+                android:id="@android:id/button1"
+                style="@style/QSBorderlessButton"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:minWidth="88dp"
+                android:text="@string/quick_settings_done"
+                android:textAppearance="@style/TextAppearance.QS.DetailButton" />
+
+    </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_detail_items.xml b/packages/SystemUI/res/layout/qs_detail_items.xml
index b64005f..f61a43c 100644
--- a/packages/SystemUI/res/layout/qs_detail_items.xml
+++ b/packages/SystemUI/res/layout/qs_detail_items.xml
@@ -17,7 +17,10 @@
 <!-- extends FrameLayout -->
 <com.android.systemui.qs.QSDetailItems xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="match_parent" >
+    android:layout_height="match_parent"
+    android:paddingTop="16dp"
+    android:paddingStart="16dp"
+    android:paddingEnd="16dp">
 
     <LinearLayout
         android:id="@android:id/list"
diff --git a/packages/SystemUI/res/layout/qs_user_detail.xml b/packages/SystemUI/res/layout/qs_user_detail.xml
index 1d6df61..91d3a53 100644
--- a/packages/SystemUI/res/layout/qs_user_detail.xml
+++ b/packages/SystemUI/res/layout/qs_user_detail.xml
@@ -16,14 +16,12 @@
   ~ limitations under the License
   -->
 
-<!-- GridView -->
+<!-- PseudoGridView -->
 <com.android.systemui.qs.tiles.UserDetailView
         xmlns:android="http://schemas.android.com/apk/res/android"
+        xmlns:sysui="http://schemas.android.com/apk/res-auto"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:verticalSpacing="4dp"
-        android:horizontalSpacing="4dp"
-        android:numColumns="3"
-        android:listSelector="@drawable/ripple_drawable">
-
-</com.android.systemui.qs.tiles.UserDetailView>
\ No newline at end of file
+        sysui:verticalSpacing="4dp"
+        sysui:horizontalSpacing="4dp"
+        style="@style/UserDetailView" />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_user_detail_item.xml b/packages/SystemUI/res/layout/qs_user_detail_item.xml
index 5ceed84..2322f16 100644
--- a/packages/SystemUI/res/layout/qs_user_detail_item.xml
+++ b/packages/SystemUI/res/layout/qs_user_detail_item.xml
@@ -25,16 +25,17 @@
         android:orientation="vertical"
         android:gravity="top|center_horizontal"
         android:paddingTop="16dp"
-        android:paddingBottom="20dp"
+        android:minHeight="112dp"
         android:clipChildren="false"
         android:clipToPadding="false"
+        android:background="@drawable/ripple_drawable"
         systemui:activatedFontFamily="sans-serif-medium">
 
     <com.android.systemui.statusbar.phone.UserAvatarView
             android:id="@+id/user_picture"
             android:layout_width="@dimen/max_avatar_size"
             android:layout_height="@dimen/max_avatar_size"
-            android:layout_marginBottom="12dp"
+            android:layout_marginBottom="10dp"
             systemui:frameWidth="2dp"
             systemui:framePadding="6dp"
             systemui:activeFrameColor="@color/current_user_border_color"/>
diff --git a/packages/SystemUI/res/values-sw600dp/styles.xml b/packages/SystemUI/res/values-sw600dp/styles.xml
index 5daf08e..9e5b1d6 100644
--- a/packages/SystemUI/res/values-sw600dp/styles.xml
+++ b/packages/SystemUI/res/values-sw600dp/styles.xml
@@ -34,4 +34,8 @@
         <item name="android:layout_height">@dimen/search_panel_scrim_height</item>
         <item name="android:layout_gravity">bottom</item>
     </style>
+
+    <style name="UserDetailView">
+        <item name="numColumns">4</item>
+    </style>
 </resources>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 8bd3c39..6ecdca3 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -67,5 +67,10 @@
     <declare-styleable name="DateView">
         <attr name="datePattern" format="string" />
     </declare-styleable>
+    <declare-styleable name="PseudoGridView">
+        <attr name="numColumns" format="integer" />
+        <attr name="verticalSpacing" format="dimension" />
+        <attr name="horizontalSpacing" format="dimension" />
+    </declare-styleable>
 </resources>
 
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 5db6912..baaa379 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -289,4 +289,8 @@
         <item name="android:layout_height">@dimen/search_panel_scrim_height</item>
         <item name="android:layout_gravity">bottom</item>
     </style>
+
+    <style name="UserDetailView">
+        <item name="numColumns">3</item>
+    </style>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PseudoGridView.java b/packages/SystemUI/src/com/android/systemui/qs/PseudoGridView.java
new file mode 100644
index 0000000..cb6708e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/PseudoGridView.java
@@ -0,0 +1,213 @@
+/*
+ * 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.qs;
+
+import com.android.systemui.R;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.database.DataSetObserver;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * A view that arranges it's children in a grid with a fixed number of evenly spaced columns.
+ *
+ * {@see android.widget.GridView}
+ */
+public class PseudoGridView extends ViewGroup {
+
+    private int mNumColumns = 3;
+    private int mVerticalSpacing;
+    private int mHorizontalSpacing;
+
+    public PseudoGridView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PseudoGridView);
+
+        final int N = a.getIndexCount();
+        for (int i = 0; i < N; i++) {
+            int attr = a.getIndex(i);
+            switch (attr) {
+                case R.styleable.PseudoGridView_numColumns:
+                    mNumColumns = a.getInt(attr, 3);
+                    break;
+                case R.styleable.PseudoGridView_verticalSpacing:
+                    mVerticalSpacing = a.getDimensionPixelSize(attr, 0);
+                    break;
+                case R.styleable.PseudoGridView_horizontalSpacing:
+                    mHorizontalSpacing = a.getDimensionPixelSize(attr, 0);
+                    break;
+            }
+        }
+
+        a.recycle();
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.UNSPECIFIED) {
+            throw new UnsupportedOperationException("Needs a maximum width");
+        }
+        int width = MeasureSpec.getSize(widthMeasureSpec);
+
+        int childWidth = (width - (mNumColumns - 1) * mHorizontalSpacing) / mNumColumns;
+        int childWidthSpec = MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY);
+        int childHeightSpec = MeasureSpec.UNSPECIFIED;
+        int totalHeight = 0;
+        int children = getChildCount();
+        int rows = (children + mNumColumns - 1) / mNumColumns;
+        for (int row = 0; row < rows; row++) {
+            int startOfRow = row * mNumColumns;
+            int endOfRow = Math.min(startOfRow + mNumColumns, children);
+            int maxHeight = 0;
+            for (int i = startOfRow; i < endOfRow; i++) {
+                View child = getChildAt(i);
+                child.measure(childWidthSpec, childHeightSpec);
+                maxHeight = Math.max(maxHeight, child.getMeasuredHeight());
+            }
+            int maxHeightSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.EXACTLY);
+            for (int i = startOfRow; i < endOfRow; i++) {
+                View child = getChildAt(i);
+                if (child.getMeasuredHeight() != maxHeight) {
+                    child.measure(childWidthSpec, maxHeightSpec);
+                }
+            }
+            totalHeight += maxHeight;
+            if (row > 0) {
+                totalHeight += mVerticalSpacing;
+            }
+        }
+
+        setMeasuredDimension(width, getDefaultSize(totalHeight, heightMeasureSpec));
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        boolean isRtl = isLayoutRtl();
+        int children = getChildCount();
+        int rows = (children + mNumColumns - 1) / mNumColumns;
+        int y = 0;
+        for (int row = 0; row < rows; row++) {
+            int x = isRtl ? getWidth() : 0;
+            int maxHeight = 0;
+            int startOfRow = row * mNumColumns;
+            int endOfRow = Math.min(startOfRow + mNumColumns, children);
+            for (int i = startOfRow; i < endOfRow; i++) {
+                View child = getChildAt(i);
+                int width = child.getMeasuredWidth();
+                int height = child.getMeasuredHeight();
+                if (isRtl) {
+                    x -= width;
+                }
+                child.layout(x, y, x + width, y + height);
+                maxHeight = Math.max(maxHeight, height);
+                if (isRtl) {
+                    x -= mHorizontalSpacing;
+                } else {
+                    x += width + mHorizontalSpacing;
+                }
+            }
+            y += maxHeight;
+            if (row > 0) {
+                y += mVerticalSpacing;
+            }
+        }
+    }
+
+    /**
+     * Bridges between a ViewGroup and a BaseAdapter.
+     * <p>
+     * Usage: {@code ViewGroupAdapterBridge.link(viewGroup, adapter)}
+     * <br />
+     * After this call, the ViewGroup's children will be provided by the adapter.
+     */
+    public static class ViewGroupAdapterBridge extends DataSetObserver {
+
+        private final WeakReference<ViewGroup> mViewGroup;
+        private final BaseAdapter mAdapter;
+        private boolean mReleased;
+
+        public static void link(ViewGroup viewGroup, BaseAdapter adapter) {
+            new ViewGroupAdapterBridge(viewGroup, adapter);
+        }
+
+        private ViewGroupAdapterBridge(ViewGroup viewGroup, BaseAdapter adapter) {
+            mViewGroup = new WeakReference<>(viewGroup);
+            mAdapter = adapter;
+            mReleased = false;
+            mAdapter.registerDataSetObserver(this);
+            refresh();
+        }
+
+        private void refresh() {
+            if (mReleased) {
+                return;
+            }
+            ViewGroup viewGroup = mViewGroup.get();
+            if (viewGroup == null) {
+                release();
+                return;
+            }
+            final int childCount = viewGroup.getChildCount();
+            final int adapterCount = mAdapter.getCount();
+            final int N = Math.max(childCount, adapterCount);
+            for (int i = 0; i < N; i++) {
+                if (i < adapterCount) {
+                    View oldView = null;
+                    if (i < childCount) {
+                        oldView = viewGroup.getChildAt(i);
+                    }
+                    View newView = mAdapter.getView(i, oldView, viewGroup);
+                    if (oldView == null) {
+                        // We ran out of existing views. Add it at the end.
+                        viewGroup.addView(newView);
+                    } else if (oldView != newView) {
+                        // We couldn't rebind the view. Replace it.
+                        viewGroup.removeViewAt(i);
+                        viewGroup.addView(newView, i);
+                    }
+                } else {
+                    int lastIndex = viewGroup.getChildCount() - 1;
+                    viewGroup.removeViewAt(lastIndex);
+                }
+            }
+        }
+
+        @Override
+        public void onChanged() {
+            refresh();
+        }
+
+        @Override
+        public void onInvalidated() {
+            release();
+        }
+
+        private void release() {
+            if (!mReleased) {
+                mReleased = true;
+                mAdapter.unregisterDataSetObserver(this);
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 59f3b3d..3679b4c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -326,8 +326,11 @@
         if (mFooter.hasFooter()) {
             h += mFooter.getView().getHeight();
         }
-        mDetail.measure(exactly(width), exactly(h));
-        setMeasuredDimension(width, h);
+        mDetail.measure(exactly(width), MeasureSpec.UNSPECIFIED);
+        if (mDetail.getMeasuredHeight() < h) {
+            mDetail.measure(exactly(width), exactly(h));
+        }
+        setMeasuredDimension(width, Math.max(h, mDetail.getMeasuredHeight()));
     }
 
     private static int exactly(int size) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
index 759d540..a56b7a7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
@@ -116,4 +116,9 @@
         boolean activated = ArrayUtils.contains(getDrawableState(), android.R.attr.state_activated);
         mName.setTypeface(activated ? mActivatedTypeface : mRegularTypeface);
     }
+
+    @Override
+    public boolean hasOverlappingRendering() {
+        return false;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
index 8cff81a..c524edc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
@@ -17,45 +17,24 @@
 package com.android.systemui.qs.tiles;
 
 import com.android.systemui.R;
+import com.android.systemui.qs.PseudoGridView;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
 
 import android.content.Context;
-import android.content.Intent;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.GridView;
 
 /**
  * Quick settings detail view for user switching.
  */
-public class UserDetailView extends GridView {
+public class UserDetailView extends PseudoGridView {
 
-    public UserDetailView(Context context) {
-        this(context, null);
-    }
+    private Adapter mAdapter;
 
     public UserDetailView(Context context, AttributeSet attrs) {
-        this(context, attrs, android.R.attr.gridViewStyle);
-    }
-
-    public UserDetailView(Context context, AttributeSet attrs, int defStyleAttr) {
-        this(context, attrs, defStyleAttr, 0);
-    }
-
-    public UserDetailView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-
-        setOnItemClickListener(new OnItemClickListener() {
-            @Override
-            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-                UserSwitcherController.UserRecord tag =
-                        (UserSwitcherController.UserRecord) view.getTag();
-                ((Adapter)getAdapter()).switchTo(tag);
-            }
-        });
+        super(context, attrs);
     }
 
     public static UserDetailView inflate(Context context, ViewGroup parent, boolean attach) {
@@ -64,10 +43,12 @@
     }
 
     public void createAndSetAdapter(UserSwitcherController controller) {
-        setAdapter(new Adapter(mContext, controller));
+        mAdapter = new Adapter(mContext, controller);
+        ViewGroupAdapterBridge.link(this, mAdapter);
     }
 
-    public static class Adapter extends UserSwitcherController.BaseUserAdapter {
+    public static class Adapter extends UserSwitcherController.BaseUserAdapter
+            implements OnClickListener {
 
         private Context mContext;
 
@@ -81,6 +62,9 @@
             UserSwitcherController.UserRecord item = getItem(position);
             UserDetailItemView v = UserDetailItemView.convertOrInflate(
                     mContext, convertView, parent);
+            if (v != convertView) {
+                v.setOnClickListener(this);
+            }
             String name = getName(mContext, item);
             if (item.picture == null) {
                 v.bind(name, getDrawable(mContext, item));
@@ -91,5 +75,12 @@
             v.setTag(item);
             return v;
         }
+
+        @Override
+        public void onClick(View view) {
+            UserSwitcherController.UserRecord tag =
+                    (UserSwitcherController.UserRecord) view.getTag();
+            switchTo(tag);
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index a55c0f2..bb5fe54 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -328,7 +328,7 @@
         TaskStackViewLayoutAlgorithm algo = tsv.getStackAlgorithm();
         Rect taskStackBounds = new Rect(mTaskStackBounds);
         taskStackBounds.bottom -= mSystemInsets.bottom;
-        tsv.computeRects(mWindowRect.width(), mWindowRect.height(), taskStackBounds);
+        tsv.computeRects(mWindowRect.width(), mWindowRect.height(), taskStackBounds, mTriggeredFromAltTab);
         tsv.getScroller().setStackScrollToInitialState();
 
         // Find the running task in the TaskStack
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 58d5df7..34e8860 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -386,7 +386,7 @@
             sourceView = stackView;
             transform = stackView.getStackAlgorithm().getStackTransform(task, stackScroll, transform, null);
             offsetX = transform.rect.left;
-            offsetY = Math.min(transform.rect.top, mConfig.displayRect.height());
+            offsetY = mConfig.displayRect.height();
         } else {
             transform = stackView.getStackAlgorithm().getStackTransform(task, stackScroll, transform, null);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 9e7dbf4..46996bb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -349,9 +349,9 @@
     }
 
     /** Updates the min and max virtual scroll bounds */
-    void updateMinMaxScroll(boolean boundScrollToNewMinMax) {
+    void updateMinMaxScroll(boolean boundScrollToNewMinMax, boolean launchedWithAltTab) {
         // Compute the min and max scroll values
-        mLayoutAlgorithm.computeMinMaxScroll(mStack.getTasks());
+        mLayoutAlgorithm.computeMinMaxScroll(mStack.getTasks(), launchedWithAltTab);
 
         // Debug logging
         if (boundScrollToNewMinMax) {
@@ -388,17 +388,17 @@
                 };
             }
 
+            // Scroll the view into position (just center it in the curve)
             if (scrollToNewPosition) {
-                // Scroll the view into position
-                // XXX: We probably want this to be centered in view instead of p = 0f
-                float newScroll = mStackScroller.getBoundedStackScroll(
-                        mLayoutAlgorithm.getStackScrollForTaskIndex(t));
+                float newScroll = mLayoutAlgorithm.getStackScrollForTaskIndex(t) - 0.5f;
+                newScroll = mStackScroller.getBoundedStackScroll(newScroll);
                 mStackScroller.animateScroll(mStackScroller.getStackScroll(), newScroll, postScrollRunnable);
             } else {
                 if (postScrollRunnable != null) {
                     postScrollRunnable.run();
                 }
             }
+
         }
     }
 
@@ -435,12 +435,13 @@
     }
 
     /** Computes the stack and task rects */
-    public void computeRects(int windowWidth, int windowHeight, Rect taskStackBounds) {
+    public void computeRects(int windowWidth, int windowHeight, Rect taskStackBounds,
+                             boolean launchedWithAltTab) {
         // Compute the rects in the stack algorithm
         mLayoutAlgorithm.computeRects(windowWidth, windowHeight, taskStackBounds);
 
         // Update the scroll bounds
-        updateMinMaxScroll(false);
+        updateMinMaxScroll(false, launchedWithAltTab);
     }
 
     /**
@@ -455,7 +456,7 @@
         // Compute our stack/task rects
         Rect taskStackBounds = new Rect(mTaskStackBounds);
         taskStackBounds.bottom -= mConfig.systemInsets.bottom;
-        computeRects(width, height, taskStackBounds);
+        computeRects(width, height, taskStackBounds, mConfig.launchedWithAltTab);
 
         // If this is the first layout, then scroll to the front of the stack and synchronize the
         // stack views immediately to load all the views
@@ -543,9 +544,8 @@
             mStartEnterAnimationContext = null;
         }
 
-        // Update the focused task index to be the next item to the top task
+        // When Alt-Tabbing, we scroll to and focus the previous task
         if (mConfig.launchedWithAltTab) {
-            // When alt-tabbing, we focus the next previous task
             focusTask(Math.max(0, mStack.getTaskCount() - 2), false);
         }
     }
@@ -661,7 +661,7 @@
         mCb.onTaskViewDismissed(removedTask);
 
         // Update the min/max scroll and animate other task views into their new positions
-        updateMinMaxScroll(true);
+        updateMinMaxScroll(true, mConfig.launchedWithAltTab);
         requestSynchronizeStackViewsWithModel(200);
 
         // Update the new front most task
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
index b1482bb..633e6fa 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
@@ -18,7 +18,6 @@
 
 import android.graphics.Rect;
 import com.android.systemui.recents.RecentsConfiguration;
-import com.android.systemui.recents.misc.Console;
 import com.android.systemui.recents.misc.Utilities;
 import com.android.systemui.recents.model.Task;
 
@@ -87,8 +86,9 @@
                 left + size, mStackRect.top + size);
     }
 
-    /** Computes the minimum and maximum scroll progress values */
-    void computeMinMaxScroll(ArrayList<Task> tasks) {
+    /** Computes the minimum and maximum scroll progress values.  This method may be called before
+     * the RecentsConfiguration is set, so we need to pass in the alt-tab state. */
+    void computeMinMaxScroll(ArrayList<Task> tasks, boolean launchedWithAltTab) {
         // Clear the progress map
         mTaskProgressMap.clear();
 
@@ -130,7 +130,12 @@
 
         mMinScrollP = 0f;
         mMaxScrollP = pAtFrontMostCardTop - ((1f - pTaskHeightOffset - pNavBarOffset));
-        mInitialScrollP = pAtSecondFrontMostCardTop - ((1f - pTaskHeightOffset - pNavBarOffset));
+        if (launchedWithAltTab) {
+            // Center the second most task, since that will be focused first
+            mInitialScrollP = pAtSecondFrontMostCardTop - 0.5f;
+        } else {
+            mInitialScrollP = pAtSecondFrontMostCardTop - ((1f - pTaskHeightOffset - pNavBarOffset));
+        }
     }
 
     /** Update/get the transform */
@@ -151,6 +156,7 @@
         // If the task top is outside of the bounds below the screen, then immediately reset it
         if (pTaskRelative > 1f) {
             transformOut.reset();
+            transformOut.rect.set(mTaskRect);
             return transformOut;
         }
         // The check for the top is trickier, since we want to show the next task if it is at all
@@ -158,6 +164,7 @@
         if (pTaskRelative < 0f) {
             if (prevTransform != null && Float.compare(prevTransform.p, 0f) <= 0) {
                 transformOut.reset();
+                transformOut.rect.set(mTaskRect);
                 return transformOut;
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index bf66c41..b66c310 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -16,10 +16,14 @@
 
 package com.android.systemui.statusbar.phone;
 
+import android.animation.LayoutTransition;
 import android.content.Context;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.View;
+import android.view.ViewTreeObserver;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
 import android.widget.ImageView;
 import android.widget.RelativeLayout;
 import android.widget.TextView;
@@ -48,6 +52,7 @@
     private KeyguardUserSwitcher mKeyguardUserSwitcher;
 
     private int mSystemIconsSwitcherHiddenExpandedMargin;
+    private Interpolator mFastOutSlowInInterpolator;
 
     public KeyguardStatusBarView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -61,6 +66,8 @@
         mMultiUserAvatar = (ImageView) findViewById(R.id.multi_user_avatar);
         mBatteryLevel = (TextView) findViewById(R.id.battery_level);
         loadDimens();
+        mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(getContext(),
+                android.R.interpolator.fast_out_slow_in);
         updateUserSwitcher();
     }
 
@@ -70,7 +77,14 @@
     }
 
     private void updateVisibilities() {
-        mMultiUserSwitch.setVisibility(!mKeyguardUserSwitcherShowing ? VISIBLE : GONE);
+        if (mMultiUserSwitch.getParent() != this && !mKeyguardUserSwitcherShowing) {
+            if (mMultiUserSwitch.getParent() != null) {
+                getOverlay().remove(mMultiUserSwitch);
+            }
+            addView(mMultiUserSwitch, 0);
+        } else if (mMultiUserSwitch.getParent() == this && mKeyguardUserSwitcherShowing) {
+            removeView(mMultiUserSwitch);
+        }
         mBatteryLevel.setVisibility(mBatteryCharging ? View.VISIBLE : View.GONE);
     }
 
@@ -137,12 +151,71 @@
         updateUserSwitcher();
     }
 
-    public void setKeyguardUserSwitcherShowing(boolean showing) {
+    public void setKeyguardUserSwitcherShowing(boolean showing, boolean animate) {
         mKeyguardUserSwitcherShowing = showing;
+        if (animate) {
+            animateNextLayoutChange();
+        }
         updateVisibilities();
         updateSystemIconsLayoutParams();
     }
 
+    private void animateNextLayoutChange() {
+        final int systemIconsCurrentX = mSystemIconsSuperContainer.getLeft();
+        final boolean userSwitcherVisible = mMultiUserSwitch.getParent() == this;
+        getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+            @Override
+            public boolean onPreDraw() {
+                getViewTreeObserver().removeOnPreDrawListener(this);
+                boolean userSwitcherHiding = userSwitcherVisible
+                        && mMultiUserSwitch.getParent() != KeyguardStatusBarView.this;
+                mSystemIconsSuperContainer.setX(systemIconsCurrentX);
+                mSystemIconsSuperContainer.animate()
+                        .translationX(0)
+                        .setDuration(400)
+                        .setStartDelay(userSwitcherHiding ? 300 : 0)
+                        .setInterpolator(mFastOutSlowInInterpolator)
+                        .start();
+                if (userSwitcherHiding) {
+                    getOverlay().add(mMultiUserSwitch);
+                    mMultiUserSwitch.animate()
+                            .alpha(0f)
+                            .setDuration(300)
+                            .setStartDelay(0)
+                            .setInterpolator(PhoneStatusBar.ALPHA_OUT)
+                            .withEndAction(new Runnable() {
+                                @Override
+                                public void run() {
+                                    mMultiUserSwitch.setAlpha(1f);
+                                    getOverlay().remove(mMultiUserSwitch);
+                                }
+                            })
+                            .start();
+
+                } else {
+                    mMultiUserSwitch.setAlpha(0f);
+                    mMultiUserSwitch.animate()
+                            .alpha(1f)
+                            .setDuration(300)
+                            .setStartDelay(200)
+                            .setInterpolator(PhoneStatusBar.ALPHA_IN);
+                }
+                return true;
+            }
+        });
+
+    }
+
+    @Override
+    public void setVisibility(int visibility) {
+        super.setVisibility(visibility);
+        if (visibility != View.VISIBLE) {
+            mSystemIconsSuperContainer.animate().cancel();
+            mMultiUserSwitch.animate().cancel();
+            mMultiUserSwitch.setAlpha(1f);
+        }
+    }
+
     @Override
     public boolean hasOverlappingRendering() {
         return false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
index af30266..47325c8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
@@ -65,7 +65,7 @@
         if (um.isUserSwitcherEnabled()) {
             if (mKeyguardMode) {
                 if (mKeyguardUserSwitcher != null) {
-                    mKeyguardUserSwitcher.show();
+                    mKeyguardUserSwitcher.show(true /* animate */);
                 }
             } else {
                 mQsPanel.showDetailAdapter(true,
@@ -78,4 +78,9 @@
             getContext().startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
         }
     }
+
+    @Override
+    public boolean hasOverlappingRendering() {
+        return false;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index e70422b..74ae4a4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -950,7 +950,7 @@
                         ? View.VISIBLE
                         : View.INVISIBLE);
         if (mKeyguardUserSwitcher != null && mQsExpanded && !mStackScrollerOverscrolling) {
-            mKeyguardUserSwitcher.hide();
+            mKeyguardUserSwitcher.hide(true /* animate */);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 1d678af..75e31e4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -3341,7 +3341,7 @@
 
     public void showKeyguard() {
         setBarState(StatusBarState.KEYGUARD);
-        updateKeyguardState(false /* goingToFullShade */);
+        updateKeyguardState(false /* goingToFullShade */, false /* fromShadeLocked */);
         instantExpandNotificationsPanel();
         mLeaveOpenOnKeyguardHide = false;
         if (mDraggedDownRow != null) {
@@ -3413,7 +3413,7 @@
         } else {
             instantCollapseNotificationPanel();
         }
-        updateKeyguardState(staying);
+        updateKeyguardState(staying, false /* fromShadeLocked */);
         return staying;
     }
 
@@ -3449,14 +3449,15 @@
                 && mStatusBarKeyguardViewManager.isSecure());
     }
 
-    private void updateKeyguardState(boolean goingToFullShade) {
+    private void updateKeyguardState(boolean goingToFullShade, boolean fromShadeLocked) {
         if (mState == StatusBarState.KEYGUARD) {
             mKeyguardIndicationController.setVisible(true);
             mNotificationPanel.resetViews();
-            mKeyguardUserSwitcher.setKeyguard(true);
+            mKeyguardUserSwitcher.setKeyguard(true, fromShadeLocked);
         } else {
             mKeyguardIndicationController.setVisible(false);
-            mKeyguardUserSwitcher.setKeyguard(false);
+            mKeyguardUserSwitcher.setKeyguard(false,
+                    goingToFullShade || mState == StatusBarState.SHADE_LOCKED || fromShadeLocked);
         }
         if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
             mScrimController.setKeyguardShowing(true);
@@ -3686,7 +3687,7 @@
         } else {
             mNotificationPanel.animateToFullShade(0 /* delay */);
             setBarState(StatusBarState.SHADE_LOCKED);
-            updateKeyguardState(false /* goingToFullShade */);
+            updateKeyguardState(false /* goingToFullShade */, false /* fromShadeLocked */);
             if (row != null) {
                 row.setUserLocked(false);
             }
@@ -3699,7 +3700,7 @@
     public void goToKeyguard() {
         if (mState == StatusBarState.SHADE_LOCKED) {
             setBarState(StatusBarState.KEYGUARD);
-            updateKeyguardState(false /* goingToFullShade */);
+            updateKeyguardState(false /* goingToFullShade */, true /* fromShadeLocked*/);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
index 203196e..18583ee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
@@ -16,18 +16,25 @@
 
 package com.android.systemui.statusbar.policy;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
 import android.content.Context;
 import android.database.DataSetObserver;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewStub;
+import android.view.animation.AnimationUtils;
 import android.widget.TextView;
 
+import com.android.keyguard.AppearAnimationUtils;
 import com.android.systemui.R;
 import com.android.systemui.qs.tiles.UserDetailItemView;
 import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
 import com.android.systemui.statusbar.phone.NotificationPanelView;
+import com.android.systemui.statusbar.phone.PhoneStatusBar;
 import com.android.systemui.statusbar.phone.StatusBarHeaderView;
 import com.android.systemui.statusbar.phone.UserAvatarView;
 
@@ -43,33 +50,42 @@
     private final KeyguardStatusBarView mStatusBarView;
     private final Adapter mAdapter;
     private final boolean mSimpleUserSwitcher;
+    private final AppearAnimationUtils mAppearAnimationUtils;
+    private final KeyguardUserSwitcherScrim mBackground;
+    private ObjectAnimator mBgAnimator;
 
     public KeyguardUserSwitcher(Context context, ViewStub userSwitcher,
             KeyguardStatusBarView statusBarView, NotificationPanelView panelView,
             UserSwitcherController userSwitcherController) {
         if (context.getResources().getBoolean(R.bool.config_keyguardUserSwitcher) || ALWAYS_ON) {
             mUserSwitcher = (ViewGroup) userSwitcher.inflate();
-            mUserSwitcher.setBackground(new KeyguardUserSwitcherScrim(mUserSwitcher));
+            mBackground = new KeyguardUserSwitcherScrim(mUserSwitcher);
+            mUserSwitcher.setBackground(mBackground);
             mStatusBarView = statusBarView;
             mStatusBarView.setKeyguardUserSwitcher(this);
             panelView.setKeyguardUserSwitcher(this);
             mAdapter = new Adapter(context, userSwitcherController);
             mAdapter.registerDataSetObserver(mDataSetObserver);
             mSimpleUserSwitcher = userSwitcherController.isSimpleUserSwitcher();
+            mAppearAnimationUtils = new AppearAnimationUtils(context, 400, -0.5f, 0.5f,
+                    AnimationUtils.loadInterpolator(
+                            context, android.R.interpolator.fast_out_slow_in));
         } else {
             mUserSwitcher = null;
             mStatusBarView = null;
             mAdapter = null;
             mSimpleUserSwitcher = false;
+            mAppearAnimationUtils = null;
+            mBackground = null;
         }
     }
 
-    public void setKeyguard(boolean keyguard) {
+    public void setKeyguard(boolean keyguard, boolean animate) {
         if (mUserSwitcher != null) {
             if (keyguard && shouldExpandByDefault()) {
-                show();
+                show(animate);
             } else {
-                hide();
+                hide(animate);
             }
         }
     }
@@ -82,22 +98,81 @@
         return mSimpleUserSwitcher;
     }
 
-    public void show() {
-        if (mUserSwitcher != null) {
-            // TODO: animate
+    public void show(boolean animate) {
+        if (mUserSwitcher != null && mUserSwitcher.getVisibility() != View.VISIBLE) {
+            cancelAnimations();
             mUserSwitcher.setVisibility(View.VISIBLE);
-            mStatusBarView.setKeyguardUserSwitcherShowing(true);
+            mStatusBarView.setKeyguardUserSwitcherShowing(true, animate);
+            if (animate) {
+                startAppearAnimation();
+            }
         }
     }
 
-    public void hide() {
+    public void hide(boolean animate) {
         if (mUserSwitcher != null && mUserSwitcher.getVisibility() == View.VISIBLE) {
-            // TODO: animate
-            mUserSwitcher.setVisibility(View.GONE);
-            mStatusBarView.setKeyguardUserSwitcherShowing(false);
+            cancelAnimations();
+            if (animate) {
+                startDisappearAnimation();
+            } else {
+                mUserSwitcher.setVisibility(View.GONE);
+            }
+            mStatusBarView.setKeyguardUserSwitcherShowing(false, animate);
         }
     }
 
+    private void cancelAnimations() {
+        int count = mUserSwitcher.getChildCount();
+        for (int i = 0; i < count; i++) {
+            mUserSwitcher.getChildAt(i).animate().cancel();
+        }
+        if (mBgAnimator != null) {
+            mBgAnimator.cancel();
+        }
+        mUserSwitcher.animate().cancel();
+    }
+
+    private void startAppearAnimation() {
+        int count = mUserSwitcher.getChildCount();
+        View[] objects = new View[count];
+        for (int i = 0; i < count; i++) {
+            objects[i] = mUserSwitcher.getChildAt(i);
+        }
+        mUserSwitcher.setClipChildren(false);
+        mUserSwitcher.setClipToPadding(false);
+        mAppearAnimationUtils.startAppearAnimation(objects, new Runnable() {
+            @Override
+            public void run() {
+                mUserSwitcher.setClipChildren(true);
+                mUserSwitcher.setClipToPadding(true);
+            }
+        });
+        mBgAnimator = ObjectAnimator.ofInt(mBackground, "alpha", 0, 255);
+        mBgAnimator.setDuration(400);
+        mBgAnimator.setInterpolator(PhoneStatusBar.ALPHA_IN);
+        mBgAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mBgAnimator = null;
+            }
+        });
+        mBgAnimator.start();
+    }
+
+    private void startDisappearAnimation() {
+        mUserSwitcher.animate()
+                .alpha(0f)
+                .setDuration(300)
+                .setInterpolator(PhoneStatusBar.ALPHA_OUT)
+                .withEndAction(new Runnable() {
+                    @Override
+                    public void run() {
+                        mUserSwitcher.setVisibility(View.GONE);
+                        mUserSwitcher.setAlpha(1f);
+                    }
+                });
+    }
+
     private void refresh() {
         final int childCount = mUserSwitcher.getChildCount();
         final int adapterCount = mAdapter.getCount();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherScrim.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherScrim.java
index 3356afd..4363037 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherScrim.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherScrim.java
@@ -19,6 +19,7 @@
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.ColorFilter;
+import android.graphics.LightingColorFilter;
 import android.graphics.Paint;
 import android.graphics.PixelFormat;
 import android.graphics.RadialGradient;
@@ -41,7 +42,9 @@
 
     private int mDarkColor;
     private int mTop;
+    private int mAlpha;
     private Paint mRadialGradientPaint = new Paint();
+    private int mLayoutWidth;
 
     public KeyguardUserSwitcherScrim(View host) {
         host.addOnLayoutChangeListener(this);
@@ -56,13 +59,21 @@
         float width = bounds.width() * OUTER_EXTENT;
         float height = (mTop + bounds.height()) * OUTER_EXTENT;
         canvas.translate(0, -mTop);
-        canvas.scale(1, height/width);
+        canvas.scale(1, height / width);
         canvas.drawRect(isLtr ? bounds.right - width : 0, 0,
                 isLtr ? bounds.right : bounds.left + width, width, mRadialGradientPaint);
     }
 
     @Override
     public void setAlpha(int alpha) {
+        mAlpha = alpha;
+        updatePaint();
+        invalidateSelf();
+    }
+
+    @Override
+    public int getAlpha() {
+        return mAlpha;
     }
 
     @Override
@@ -78,15 +89,24 @@
     public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
             int oldTop, int oldRight, int oldBottom) {
         if (left != oldLeft || top != oldTop || right != oldRight || bottom != oldBottom) {
-            int width = right - left;
-            float radius = width * OUTER_EXTENT;
-            boolean isLtr = getLayoutDirection() == LayoutDirection.LTR;
-            mRadialGradientPaint.setShader(
-                    new RadialGradient(isLtr ? width : 0, 0, radius,
-                            new int[] { mDarkColor, Color.TRANSPARENT},
-                            new float[] { Math.max(0f, width * INNER_EXTENT / radius), 1f},
-                            Shader.TileMode.CLAMP));
+            mLayoutWidth = right - left;
             mTop = top;
+            updatePaint();
         }
     }
+
+    private void updatePaint() {
+        if (mLayoutWidth == 0) {
+            return;
+        }
+        float radius = mLayoutWidth * OUTER_EXTENT;
+        boolean isLtr = getLayoutDirection() == LayoutDirection.LTR;
+        mRadialGradientPaint.setShader(
+                new RadialGradient(isLtr ? mLayoutWidth : 0, 0, radius,
+                        new int[] { Color.argb(
+                                        (int) (Color.alpha(mDarkColor) * mAlpha / 255f), 0, 0, 0),
+                                Color.TRANSPARENT },
+                        new float[] { Math.max(0f, mLayoutWidth * INNER_EXTENT / radius), 1f },
+                        Shader.TileMode.CLAMP));
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index c48f3f5..a1993f7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -465,12 +465,12 @@
 
         @Override
         public View createDetailView(Context context, View convertView, ViewGroup parent) {
+            UserDetailView v;
             if (!(convertView instanceof UserDetailView)) {
-                convertView = UserDetailView.inflate(context, parent, false);
-            }
-            UserDetailView v = (UserDetailView) convertView;
-            if (v.getAdapter() == null) {
+                v = UserDetailView.inflate(context, parent, false);
                 v.createAndSetAdapter(UserSwitcherController.this);
+            } else {
+                v = (UserDetailView) convertView;
             }
             return v;
         }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 6761f24..f9baccd 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -251,10 +251,7 @@
     private int mNetworkPreference;
     private int mActiveDefaultNetwork = -1;
     // 0 is full bad, 100 is full good
-    private int mDefaultInetCondition = 0;
     private int mDefaultInetConditionPublished = 0;
-    private boolean mInetConditionChangeInFlight = false;
-    private int mDefaultConnectionSequence = 0;
 
     private Object mDnsLock = new Object();
     private int mNumDnsEntries;
@@ -274,19 +271,6 @@
     private static final int EVENT_CHANGE_MOBILE_DATA_ENABLED = 2;
 
     /**
-     * used internally to synchronize inet condition reports
-     * arg1 = networkType
-     * arg2 = condition (0 bad, 100 good)
-     */
-    private static final int EVENT_INET_CONDITION_CHANGE = 4;
-
-    /**
-     * used internally to mark the end of inet condition hold periods
-     * arg1 = networkType
-     */
-    private static final int EVENT_INET_CONDITION_HOLD_END = 5;
-
-    /**
      * used internally to clear a wakelock when transitioning
      * from one net to another.  Clear happens when we get a new
      * network - EVENT_EXPIRE_NET_TRANSITION_WAKELOCK happens
@@ -490,10 +474,6 @@
             mTypeLists[type] = new ArrayList<NetworkAgentInfo>();
         }
 
-        private boolean isDefaultNetwork(NetworkAgentInfo nai) {
-            return mNetworkForRequestId.get(mDefaultRequest.requestId) == nai;
-        }
-
         public boolean isTypeSupported(int type) {
             return isNetworkTypeValid(type) && mTypeLists[type] != null;
         }
@@ -2052,6 +2032,9 @@
                 nai.networkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED,
                         null, null);
             }
+            if (isDefaultNetwork(nai)) {
+                mDefaultInetConditionPublished = 0;
+            }
             notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOST);
             nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_DISCONNECTED);
             mNetworkAgentInfos.remove(msg.replyTo);
@@ -2222,18 +2205,6 @@
                     }
                     break;
                 }
-                case EVENT_INET_CONDITION_CHANGE: {
-                    int netType = msg.arg1;
-                    int condition = msg.arg2;
-                    handleInetConditionChange(netType, condition);
-                    break;
-                }
-                case EVENT_INET_CONDITION_HOLD_END: {
-                    int netType = msg.arg1;
-                    int sequence = msg.arg2;
-                    handleInetConditionHoldEnd(netType, sequence);
-                    break;
-                }
                 case EVENT_APPLY_GLOBAL_HTTP_PROXY: {
                     handleDeprecatedGlobalHttpProxy();
                     break;
@@ -2428,99 +2399,15 @@
 
     // 100 percent is full good, 0 is full bad.
     public void reportInetCondition(int networkType, int percentage) {
-        if (VDBG) log("reportNetworkCondition(" + networkType + ", " + percentage + ")");
-        mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.STATUS_BAR,
-                "ConnectivityService");
-
-        if (DBG) {
-            int pid = getCallingPid();
-            int uid = getCallingUid();
-            String s = pid + "(" + uid + ") reports inet is " +
-                (percentage > 50 ? "connected" : "disconnected") + " (" + percentage + ") on " +
-                "network Type " + networkType + " at " + GregorianCalendar.getInstance().getTime();
-            mInetLog.add(s);
-            while(mInetLog.size() > INET_CONDITION_LOG_MAX_SIZE) {
-                mInetLog.remove(0);
-            }
-        }
-        mHandler.sendMessage(mHandler.obtainMessage(
-            EVENT_INET_CONDITION_CHANGE, networkType, percentage));
+        if (percentage > 50) return;  // don't handle good network reports
+        NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
+        if (nai != null) reportBadNetwork(nai.network);
     }
 
     public void reportBadNetwork(Network network) {
         //TODO
     }
 
-    private void handleInetConditionChange(int netType, int condition) {
-        if (mActiveDefaultNetwork == -1) {
-            if (DBG) log("handleInetConditionChange: no active default network - ignore");
-            return;
-        }
-        if (mActiveDefaultNetwork != netType) {
-            if (DBG) log("handleInetConditionChange: net=" + netType +
-                            " != default=" + mActiveDefaultNetwork + " - ignore");
-            return;
-        }
-        if (VDBG) {
-            log("handleInetConditionChange: net=" +
-                    netType + ", condition=" + condition +
-                    ",mActiveDefaultNetwork=" + mActiveDefaultNetwork);
-        }
-        mDefaultInetCondition = condition;
-        int delay;
-        if (mInetConditionChangeInFlight == false) {
-            if (VDBG) log("handleInetConditionChange: starting a change hold");
-            // setup a new hold to debounce this
-            if (mDefaultInetCondition > 50) {
-                delay = Settings.Global.getInt(mContext.getContentResolver(),
-                        Settings.Global.INET_CONDITION_DEBOUNCE_UP_DELAY, 500);
-            } else {
-                delay = Settings.Global.getInt(mContext.getContentResolver(),
-                        Settings.Global.INET_CONDITION_DEBOUNCE_DOWN_DELAY, 3000);
-            }
-            mInetConditionChangeInFlight = true;
-            mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_INET_CONDITION_HOLD_END,
-                    mActiveDefaultNetwork, mDefaultConnectionSequence), delay);
-        } else {
-            // we've set the new condition, when this hold ends that will get picked up
-            if (VDBG) log("handleInetConditionChange: currently in hold - not setting new end evt");
-        }
-    }
-
-    private void handleInetConditionHoldEnd(int netType, int sequence) {
-        if (DBG) {
-            log("handleInetConditionHoldEnd: net=" + netType +
-                    ", condition=" + mDefaultInetCondition +
-                    ", published condition=" + mDefaultInetConditionPublished);
-        }
-        mInetConditionChangeInFlight = false;
-
-        if (mActiveDefaultNetwork == -1) {
-            if (DBG) log("handleInetConditionHoldEnd: no active default network - ignoring");
-            return;
-        }
-        if (mDefaultConnectionSequence != sequence) {
-            if (DBG) log("handleInetConditionHoldEnd: event hold for obsolete network - ignoring");
-            return;
-        }
-        // TODO: Figure out why this optimization sometimes causes a
-        //       change in mDefaultInetCondition to be missed and the
-        //       UI to not be updated.
-        //if (mDefaultInetConditionPublished == mDefaultInetCondition) {
-        //    if (DBG) log("no change in condition - aborting");
-        //    return;
-        //}
-        NetworkInfo networkInfo = getNetworkInfoForType(mActiveDefaultNetwork);
-        if (networkInfo.isConnected() == false) {
-            if (DBG) log("handleInetConditionHoldEnd: default network not connected - ignoring");
-            return;
-        }
-        mDefaultInetConditionPublished = mDefaultInetCondition;
-        sendInetConditionBroadcast(networkInfo);
-        return;
-    }
-
     public ProxyInfo getProxy() {
         // this information is already available as a world read/writable jvm property
         // so this API change wouldn't have a benifit.  It also breaks the passing
@@ -4206,6 +4093,10 @@
 
     private final NetworkRequest mDefaultRequest;
 
+    private boolean isDefaultNetwork(NetworkAgentInfo nai) {
+        return mNetworkForRequestId.get(mDefaultRequest.requestId) == nai;
+    }
+
     public void registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
             LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
             int currentScore, NetworkMisc networkMisc) {
@@ -4532,6 +4423,7 @@
                             mLegacyTypeTracker.remove(currentNetwork.networkInfo.getType(),
                                                       currentNetwork);
                         }
+                        mDefaultInetConditionPublished = 100;
                         mLegacyTypeTracker.add(newNetwork.networkInfo.getType(), newNetwork);
                     }
                 }
@@ -4581,8 +4473,6 @@
                 // to connected after our normal pause unless somebody reports us as
                 // really disconnected
                 mDefaultInetConditionPublished = 0;
-                mDefaultConnectionSequence++;
-                mInetConditionChangeInFlight = false;
                 // TODO - read the tcp buffer size config string from somewhere
                 // updateNetworkSettings();
             }
diff --git a/services/core/java/com/android/server/DockObserver.java b/services/core/java/com/android/server/DockObserver.java
index af38664..d05c280 100644
--- a/services/core/java/com/android/server/DockObserver.java
+++ b/services/core/java/com/android/server/DockObserver.java
@@ -201,9 +201,6 @@
             // There are many components in the system watching for this so as to
             // adjust audio routing, screen orientation, etc.
             getContext().sendStickyBroadcastAsUser(intent, UserHandle.ALL);
-
-            // Release the wake lock that was acquired when the message was posted.
-            mWakeLock.release();
         }
     }
 
@@ -213,6 +210,7 @@
             switch (msg.what) {
                 case MSG_DOCK_STATE_CHANGED:
                     handleDockStateChange();
+                    mWakeLock.release();
                     break;
             }
         }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index fb4fa7f..ad5b2ba 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -617,6 +617,7 @@
                         }
 
                         addAndStartAction(new HotplugDetectionAction(HdmiCecLocalDeviceTv.this));
+                        addAndStartAction(new PowerStatusMonitorAction(HdmiCecLocalDeviceTv.this));
 
                         // If there is AVR, initiate System Audio Auto initiation action,
                         // which turns on and off system audio according to last system
@@ -1300,6 +1301,7 @@
         //     LocalDeviceTv.onAddressAllocated() -> launchDeviceDiscovery().
         removeAction(DeviceDiscoveryAction.class);
         removeAction(HotplugDetectionAction.class);
+        removeAction(PowerStatusMonitorAction.class);
         // Remove recording actions.
         removeAction(OneTouchRecordAction.class);
         removeAction(TimerRecordingAction.class);
@@ -1521,4 +1523,22 @@
             }
         });
     }
+
+    void updateDevicePowerStatus(int logicalAddress, int newPowerStatus) {
+        HdmiDeviceInfo info = getDeviceInfo(logicalAddress);
+        if (info == null) {
+            Slog.w(TAG, "Can not update power status of non-existing device:" + logicalAddress);
+            return;
+        }
+
+        if (info.getDevicePowerStatus() == newPowerStatus) {
+            return;
+        }
+
+        HdmiDeviceInfo newInfo = HdmiUtils.cloneHdmiDeviceInfo(info, newPowerStatus);
+        // addDeviceInfo replaces old device info with new one if exists.
+        addDeviceInfo(newInfo);
+
+        // TODO: notify this update to others.
+    }
 }
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index cccc44c..81b99f0 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -317,7 +317,10 @@
                     if (logicalAddress == Constants.ADDR_UNREGISTERED) {
                         Slog.e(TAG, "Failed to allocate address:[device_type:" + deviceType + "]");
                     } else {
-                        HdmiDeviceInfo deviceInfo = createDeviceInfo(logicalAddress, deviceType);
+                        // Set POWER_STATUS_ON to all local devices because they share lifetime
+                        // with system.
+                        HdmiDeviceInfo deviceInfo = createDeviceInfo(logicalAddress, deviceType,
+                                HdmiControlManager.POWER_STATUS_ON);
                         localDevice.setDeviceInfo(deviceInfo);
                         mCecController.addLocalDevice(deviceType, localDevice);
                         mCecController.addLogicalAddress(logicalAddress);
@@ -653,7 +656,7 @@
         }
     }
 
-    private HdmiDeviceInfo createDeviceInfo(int logicalAddress, int deviceType) {
+    private HdmiDeviceInfo createDeviceInfo(int logicalAddress, int deviceType, int powerStatus) {
         // TODO: find better name instead of model name.
         String displayName = Build.MODEL;
         return new HdmiDeviceInfo(logicalAddress,
diff --git a/services/core/java/com/android/server/hdmi/HdmiUtils.java b/services/core/java/com/android/server/hdmi/HdmiUtils.java
index a52e0d2..23f19ff 100644
--- a/services/core/java/com/android/server/hdmi/HdmiUtils.java
+++ b/services/core/java/com/android/server/hdmi/HdmiUtils.java
@@ -266,4 +266,14 @@
         }
         return true;
     }
+
+    /**
+     * Clone {@link HdmiDeviceInfo} with new power status.
+     */
+    static HdmiDeviceInfo cloneHdmiDeviceInfo(HdmiDeviceInfo info, int newPowerStatus) {
+        return new HdmiDeviceInfo(info.getLogicalAddress(),
+                info.getPhysicalAddress(), info.getPortId(), info.getDeviceType(),
+                info.getVendorId(), info.getDisplayName(), newPowerStatus);
+    }
+
 }
diff --git a/services/core/java/com/android/server/hdmi/PowerStatusMonitorAction.java b/services/core/java/com/android/server/hdmi/PowerStatusMonitorAction.java
new file mode 100644
index 0000000..03fbb95
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/PowerStatusMonitorAction.java
@@ -0,0 +1,146 @@
+/*
+ * 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.server.hdmi;
+
+import static android.hardware.hdmi.HdmiControlManager.POWER_STATUS_UNKNOWN;
+
+import android.hardware.hdmi.HdmiDeviceInfo;
+import android.util.SparseIntArray;
+
+import com.android.server.hdmi.HdmiControlService.SendMessageCallback;
+
+import java.util.List;
+
+/**
+ * Action that check each device's power status.
+ */
+public class PowerStatusMonitorAction extends HdmiCecFeatureAction {
+    private static final String TAG = "PowerStatusMonitorAction";
+
+    // State that waits for <Report Power Status> once sending <Give Device Power Status>
+    // to all external devices.
+    private static final int STATE_WAIT_FOR_REPORT_POWER_STATUS = 1;
+    // State that waits for next monitoring
+    private static final int STATE_WAIT_FOR_NEXT_MONITORING = 2;
+
+    private static final int INVALID_POWER_STATUS = POWER_STATUS_UNKNOWN - 1;
+
+    // Monitoring interval (60s)
+    private static final int MONITIROING_INTERNAL_MS = 60000;
+
+    // Timeout once sending <Give Device Power Status>
+    private static final int REPORT_POWER_STATUS_TIMEOUT_MS = 5000;
+
+    // Container for current power status of all external devices.
+    // The key is a logical address a device and the value is current power status of it
+    // Whenever the action receives <Report Power Status> from a device,
+    // it removes an entry of the given device.
+    // If this is non-empty when timeout for STATE_WAIT_FOR_REPORT_POWER_STATUS happens,
+    // updates power status of all remaining devices into POWER_STATUS_UNKNOWN.
+    private final SparseIntArray mPowerStatus = new SparseIntArray();
+
+    PowerStatusMonitorAction(HdmiCecLocalDevice source) {
+        super(source);
+    }
+
+    @Override
+    boolean start() {
+        queryPowerStatus();
+        return true;
+    }
+
+    @Override
+    boolean processCommand(HdmiCecMessage cmd) {
+        if (mState != STATE_WAIT_FOR_REPORT_POWER_STATUS) {
+            return false;
+        }
+        return handleReportPowerStatus(cmd);
+    }
+
+    private boolean handleReportPowerStatus(HdmiCecMessage cmd) {
+        int sourceAddress = cmd.getSource();
+        int oldStatus = mPowerStatus.get(sourceAddress, INVALID_POWER_STATUS);
+        if (oldStatus == INVALID_POWER_STATUS) {
+            // if no device exists for incoming message, hands it over to other actions.
+            return false;
+        }
+        int newStatus = cmd.getParams()[0];
+        updatePowerStatus(sourceAddress, newStatus, true);
+        return true;
+    }
+
+    @Override
+    void handleTimerEvent(int state) {
+        switch (mState) {
+            case STATE_WAIT_FOR_NEXT_MONITORING:
+                queryPowerStatus();
+                break;
+            case STATE_WAIT_FOR_REPORT_POWER_STATUS:
+                handleTimeout();
+                break;
+        }
+    }
+
+    private void handleTimeout() {
+        for (int i = 0; i < mPowerStatus.size(); ++i) {
+            int logicalAddress = mPowerStatus.keyAt(i);
+            updatePowerStatus(logicalAddress, POWER_STATUS_UNKNOWN, false);
+        }
+        mPowerStatus.clear();
+        mState = STATE_WAIT_FOR_NEXT_MONITORING;
+    }
+
+    private void resetPowerStatus(List<HdmiDeviceInfo> deviceInfos) {
+        mPowerStatus.clear();
+        for (HdmiDeviceInfo info : deviceInfos) {
+            mPowerStatus.append(info.getLogicalAddress(), info.getDevicePowerStatus());
+        }
+    }
+
+    private void queryPowerStatus() {
+        List<HdmiDeviceInfo> deviceInfos = tv().getDeviceInfoList(false);
+        resetPowerStatus(deviceInfos);
+        for (HdmiDeviceInfo info : deviceInfos) {
+            final int logicalAddress = info.getLogicalAddress();
+            sendCommand(HdmiCecMessageBuilder.buildGiveDevicePowerStatus(getSourceAddress(),
+                    logicalAddress),
+                    new SendMessageCallback() {
+                        @Override
+                        public void onSendCompleted(int error) {
+                            // If fails to send <Give Device Power Status>,
+                            // update power status into UNKNOWN.
+                            if (error != Constants.SEND_RESULT_SUCCESS) {
+                               updatePowerStatus(logicalAddress, POWER_STATUS_UNKNOWN, true);
+                            }
+                        }
+                    });
+        }
+
+        mState = STATE_WAIT_FOR_REPORT_POWER_STATUS;
+
+        // Add both timers, monitoring and timeout.
+        addTimer(STATE_WAIT_FOR_NEXT_MONITORING, MONITIROING_INTERNAL_MS);
+        addTimer(STATE_WAIT_FOR_REPORT_POWER_STATUS, REPORT_POWER_STATUS_TIMEOUT_MS);
+    }
+
+    private void updatePowerStatus(int logicalAddress, int newStatus, boolean remove) {
+        tv().updateDevicePowerStatus(logicalAddress, newStatus);
+
+        if (remove) {
+            mPowerStatus.delete(logicalAddress);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index b4faea1..c7e3fb7 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -37,15 +37,17 @@
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
 import android.content.Context;
-import android.content.pm.IPackageDeleteObserver;
+import android.content.Intent;
 import android.content.pm.IPackageDeleteObserver2;
 import android.content.pm.IPackageInstaller;
 import android.content.pm.IPackageInstallerCallback;
 import android.content.pm.IPackageInstallerSession;
 import android.content.pm.InstallSessionInfo;
 import android.content.pm.InstallSessionParams;
+import android.content.pm.PackageInstaller;
 import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
+import android.net.Uri;
 import android.os.Binder;
 import android.os.Environment;
 import android.os.FileUtils;
@@ -199,6 +201,10 @@
         }
     }
 
+    public static boolean isStageFile(File file) {
+        return sStageFilter.accept(null, file.getName());
+    }
+
     @Deprecated
     public File allocateSessionDir() throws IOException {
         synchronized (mSessions) {
@@ -545,8 +551,21 @@
             int userId) {
         mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "uninstall");
 
-        // TODO: enforce installer of record or permission
-        mPm.deletePackage(packageName, observer, userId, flags);
+        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DELETE_PACKAGES)
+                == PackageManager.PERMISSION_GRANTED) {
+            // Sweet, call straight through!
+            mPm.deletePackage(packageName, observer, userId, flags);
+
+        } else {
+            // Take a short detour to confirm with user
+            final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE);
+            intent.setData(Uri.fromParts("package", packageName, null));
+            intent.putExtra(PackageInstaller.EXTRA_CALLBACK, observer.asBinder());
+            try {
+                observer.onUserActionRequired(intent);
+            } catch (RemoteException ignored) {
+            }
+        }
     }
 
     @Override
@@ -559,6 +578,15 @@
     }
 
     @Override
+    public void setPermissionsResult(int sessionId, boolean accepted) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, TAG);
+
+        synchronized (mSessions) {
+            mSessions.get(sessionId).setPermissionsResult(accepted);
+        }
+    }
+
+    @Override
     public void registerCallback(IPackageInstallerCallback callback, int userId) {
         mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "registerCallback");
         enforceCallerCanReadSessions();
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 5443fbc..a3184f0 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -16,6 +16,7 @@
 
 package com.android.server.pm;
 
+import static android.content.pm.PackageManager.INSTALL_FAILED_ABORTED;
 import static android.content.pm.PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
 import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
 import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
@@ -30,6 +31,7 @@
 import android.content.pm.IPackageInstallerSession;
 import android.content.pm.InstallSessionInfo;
 import android.content.pm.InstallSessionParams;
+import android.content.pm.PackageInstaller;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageParser;
 import android.content.pm.PackageParser.ApkLite;
@@ -106,10 +108,24 @@
     @GuardedBy("mLock")
     private boolean mSealed = false;
     @GuardedBy("mLock")
-    private boolean mPermissionsConfirmed = false;
+    private boolean mPermissionsAccepted = false;
     @GuardedBy("mLock")
     private boolean mDestroyed = false;
 
+    private int mFinalStatus;
+    private String mFinalMessage;
+
+    /**
+     * Path to the resolved base APK for this session, which may point at an APK
+     * inside the session (when the session defines the base), or it may point
+     * at the existing base APK (when adding splits to an existing app).
+     * <p>
+     * This is used when confirming permissions, since we can't fully stage the
+     * session inside an ASEC before confirming with user.
+     */
+    @GuardedBy("mLock")
+    private String mResolvedBaseCodePath;
+
     @GuardedBy("mLock")
     private ArrayList<FileBridge> mBridges = new ArrayList<>();
 
@@ -134,12 +150,7 @@
                 } catch (PackageManagerException e) {
                     Slog.e(TAG, "Install failed: " + e);
                     destroyInternal();
-                    try {
-                        mRemoteObserver.onPackageInstalled(mPackageName, e.error, e.getMessage(),
-                                null);
-                    } catch (RemoteException ignored) {
-                    }
-                    mCallback.onSessionFinished(PackageInstallerSession.this, false);
+                    dispatchSessionFinished(e.error, e.getMessage(), null);
                 }
 
                 return true;
@@ -169,9 +180,9 @@
 
         if (mPm.checkPermission(android.Manifest.permission.INSTALL_PACKAGES,
                 installerPackageName) == PackageManager.PERMISSION_GRANTED) {
-            mPermissionsConfirmed = true;
+            mPermissionsAccepted = true;
         } else {
-            mPermissionsConfirmed = false;
+            mPermissionsAccepted = false;
         }
 
         computeProgressLocked();
@@ -182,7 +193,9 @@
 
         info.sessionId = sessionId;
         info.installerPackageName = installerPackageName;
+        info.resolvedBaseCodePath = mResolvedBaseCodePath;
         info.progress = mProgress;
+        info.sealed = mSealed;
         info.open = openCount.get() > 0;
 
         info.mode = params.mode;
@@ -355,11 +368,19 @@
 
         Preconditions.checkNotNull(mPackageName);
         Preconditions.checkNotNull(mSignatures);
+        Preconditions.checkNotNull(mResolvedBaseCodePath);
 
-        if (!mPermissionsConfirmed) {
-            // TODO: async confirm permissions with user
-            // when they confirm, we'll kick off another install() pass
-            throw new SecurityException("Caller must hold INSTALL permission");
+        if (!mPermissionsAccepted) {
+            // User needs to accept permissions; give installer an intent they
+            // can use to involve user.
+            final Intent intent = new Intent(PackageInstaller.ACTION_CONFIRM_PERMISSIONS);
+            intent.setPackage("com.android.packageinstaller");
+            intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
+            try {
+                mRemoteObserver.onUserActionRequired(intent);
+            } catch (RemoteException ignored) {
+            }
+            return;
         }
 
         // Inherit any packages and native libraries from existing install that
@@ -386,12 +407,7 @@
             public void onPackageInstalled(String basePackageName, int returnCode, String msg,
                     Bundle extras) {
                 destroyInternal();
-                try {
-                    remoteObserver.onPackageInstalled(basePackageName, returnCode, msg, extras);
-                } catch (RemoteException ignored) {
-                }
-                final boolean success = (returnCode == PackageManager.INSTALL_SUCCEEDED);
-                mCallback.onSessionFinished(PackageInstallerSession.this, success);
+                dispatchSessionFinished(returnCode, msg, extras);
             }
         };
 
@@ -409,6 +425,7 @@
         mPackageName = null;
         mVersionCode = -1;
         mSignatures = null;
+        mResolvedBaseCodePath = null;
 
         final File[] files = sessionStageDir.listFiles();
         if (ArrayUtils.isEmpty(files)) {
@@ -445,18 +462,25 @@
                     info.signatures);
 
             // Take this opportunity to enforce uniform naming
-            final String name;
+            final String targetName;
             if (info.splitName == null) {
-                name = "base.apk";
+                targetName = "base.apk";
             } else {
-                name = "split_" + info.splitName + ".apk";
+                targetName = "split_" + info.splitName + ".apk";
             }
-            if (!FileUtils.isValidExtFilename(name)) {
+            if (!FileUtils.isValidExtFilename(targetName)) {
                 throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
-                        "Invalid filename: " + name);
+                        "Invalid filename: " + targetName);
             }
-            if (!file.getName().equals(name)) {
-                file.renameTo(new File(file.getParentFile(), name));
+
+            final File targetFile = new File(sessionStageDir, targetName);
+            if (!file.equals(targetFile)) {
+                file.renameTo(targetFile);
+            }
+
+            // Base is coming from session
+            if (info.splitName == null) {
+                mResolvedBaseCodePath = targetFile.getAbsolutePath();
             }
         }
 
@@ -472,13 +496,18 @@
             }
 
         } else {
-            // Partial installs must be consistent with existing install.
+            // Partial installs must be consistent with existing install
             final ApplicationInfo app = mPm.getApplicationInfo(mPackageName, 0, userId);
             if (app == null) {
                 throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
                         "Missing existing base package for " + mPackageName);
             }
 
+            // Base might be inherited from existing install
+            if (mResolvedBaseCodePath == null) {
+                mResolvedBaseCodePath = app.getBaseCodePath();
+            }
+
             final ApkLite info;
             try {
                 info = PackageParser.parseApkLite(new File(app.getBaseCodePath()),
@@ -537,6 +566,21 @@
         if (LOGD) Slog.d(TAG, "Spliced " + n + " existing APKs into stage");
     }
 
+    void setPermissionsResult(boolean accepted) {
+        if (!mSealed) {
+            throw new SecurityException("Must be sealed to accept permissions");
+        }
+
+        if (accepted) {
+            // Mark and kick off another install pass
+            mPermissionsAccepted = true;
+            mHandler.obtainMessage(MSG_COMMIT).sendToTarget();
+        } else {
+            destroyInternal();
+            dispatchSessionFinished(INSTALL_FAILED_ABORTED, "User rejected permissions", null);
+        }
+    }
+
     @Override
     public void close() {
         if (openCount.decrementAndGet() == 0) {
@@ -546,11 +590,23 @@
 
     @Override
     public void abandon() {
-        try {
-            destroyInternal();
-        } finally {
-            mCallback.onSessionFinished(this, false);
+        destroyInternal();
+        dispatchSessionFinished(INSTALL_FAILED_ABORTED, "Session was abandoned", null);
+    }
+
+    private void dispatchSessionFinished(int returnCode, String msg, Bundle extras) {
+        mFinalStatus = returnCode;
+        mFinalMessage = msg;
+
+        if (mRemoteObserver != null) {
+            try {
+                mRemoteObserver.onPackageInstalled(mPackageName, returnCode, msg, extras);
+            } catch (RemoteException ignored) {
+            }
         }
+
+        final boolean success = (returnCode == PackageManager.INSTALL_SUCCEEDED);
+        mCallback.onSessionFinished(this, success);
     }
 
     private void destroyInternal() {
@@ -578,9 +634,11 @@
         pw.printPair("mClientProgress", mClientProgress);
         pw.printPair("mProgress", mProgress);
         pw.printPair("mSealed", mSealed);
-        pw.printPair("mPermissionsConfirmed", mPermissionsConfirmed);
+        pw.printPair("mPermissionsAccepted", mPermissionsAccepted);
         pw.printPair("mDestroyed", mDestroyed);
         pw.printPair("mBridges", mBridges.size());
+        pw.printPair("mFinalStatus", mFinalStatus);
+        pw.printPair("mFinalMessage", mFinalMessage);
         pw.println();
 
         pw.decreaseIndent();
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 4bf6636..cef127e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -85,7 +85,6 @@
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
 import android.app.IActivityManager;
-import android.app.PackageDeleteObserver;
 import android.app.admin.IDevicePolicyManager;
 import android.app.backup.IBackupManager;
 import android.content.BroadcastReceiver;
@@ -115,6 +114,7 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageInfoLite;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.LegacyPackageDeleteObserver;
 import android.content.pm.PackageParser.ActivityIntentInfo;
 import android.content.pm.PackageParser.PackageLite;
 import android.content.pm.PackageParser.PackageParserException;
@@ -4084,7 +4084,8 @@
         }
 
         for (File file : files) {
-            final boolean isPackage = isApkFile(file) || file.isDirectory();
+            final boolean isPackage = (isApkFile(file) || file.isDirectory())
+                    && !PackageInstallerService.isStageFile(file);
             if (!isPackage) {
                 // Ignore entries which are not apk's
                 continue;
@@ -13450,20 +13451,4 @@
             return false;
         }
     }
-
-    private static class LegacyPackageDeleteObserver extends PackageDeleteObserver {
-        private final IPackageDeleteObserver mLegacy;
-
-        public LegacyPackageDeleteObserver(IPackageDeleteObserver legacy) {
-            mLegacy = legacy;
-        }
-
-        @Override
-        public void onPackageDeleted(String basePackageName, int returnCode, String msg) {
-            try {
-                mLegacy.packageDeleted(basePackageName, returnCode);
-            } catch (RemoteException ignored) {
-            }
-        }
-    }
 }
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index 74f725f..71f43b4 100644
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -37,13 +37,12 @@
 import android.media.AudioPortConfig;
 import android.media.tv.ITvInputHardware;
 import android.media.tv.ITvInputHardwareCallback;
-import android.media.tv.TvInputHardwareInfo;
 import android.media.tv.TvContract;
+import android.media.tv.TvInputHardwareInfo;
 import android.media.tv.TvInputInfo;
 import android.media.tv.TvStreamConfig;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -59,12 +58,10 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 /**
  * A helper class for TvInputManagerService to handle TV input hardware.
@@ -82,11 +79,11 @@
     private final TvInputHal mHal = new TvInputHal(this);
     private final SparseArray<Connection> mConnections = new SparseArray<>();
     private final List<TvInputHardwareInfo> mHardwareList = new ArrayList<>();
-    private List<HdmiDeviceInfo> mHdmiCecDeviceList = new LinkedList<>();
+    private final List<HdmiDeviceInfo> mHdmiDeviceList = new LinkedList<>();
     /* A map from a device ID to the matching TV input ID. */
     private final SparseArray<String> mHardwareInputIdMap = new SparseArray<>();
     /* A map from a HDMI logical address to the matching TV input ID. */
-    private final SparseArray<String> mHdmiCecInputIdMap = new SparseArray<>();
+    private final SparseArray<String> mHdmiInputIdMap = new SparseArray<>();
     private final Map<String, TvInputInfo> mInputMap = new ArrayMap<>();
 
     private final AudioManager mAudioManager;
@@ -119,7 +116,7 @@
                 try {
                     mHdmiControlService.addHotplugEventListener(mHdmiHotplugEventListener);
                     mHdmiControlService.addDeviceEventListener(mHdmiDeviceEventListener);
-                    mHdmiCecDeviceList.addAll(mHdmiControlService.getInputDevices());
+                    mHdmiDeviceList.addAll(mHdmiControlService.getInputDevices());
                     mHdmiControlService.setInputChangeListener(mHdmiInputChangeListener);
                 } catch (RemoteException e) {
                     Slog.w(TAG, "Error registering listeners to HdmiControlService:", e);
@@ -163,12 +160,11 @@
             buildHardwareListLocked();
             TvInputHardwareInfo info = connection.getHardwareInfoLocked();
             if (info.getType() == TvInputHardwareInfo.TV_INPUT_TYPE_HDMI) {
-                // Remove HDMI CEC devices linked with this hardware.
-                for (Iterator<HdmiDeviceInfo> it = mHdmiCecDeviceList.iterator();
-                        it.hasNext(); ) {
+                // Remove HDMI devices linked with this hardware.
+                for (Iterator<HdmiDeviceInfo> it = mHdmiDeviceList.iterator(); it.hasNext();) {
                     HdmiDeviceInfo deviceInfo = it.next();
                     if (deviceInfo.getPortId() == info.getHdmiPortId()) {
-                        mHandler.obtainMessage(ListenerHandler.HDMI_CEC_DEVICE_REMOVED, 0, 0,
+                        mHandler.obtainMessage(ListenerHandler.HDMI_DEVICE_REMOVED, 0, 0,
                                 deviceInfo).sendToTarget();
                         it.remove();
                     }
@@ -220,9 +216,9 @@
         }
     }
 
-    public List<HdmiDeviceInfo> getHdmiCecInputDeviceList() {
+    public List<HdmiDeviceInfo> getHdmiDeviceList() {
         synchronized (mLock) {
-            return Collections.unmodifiableList(mHdmiCecDeviceList);
+            return Collections.unmodifiableList(mHdmiDeviceList);
         }
     }
 
@@ -283,7 +279,7 @@
         return -1;
     }
 
-    public void addHdmiCecTvInput(int logicalAddress, TvInputInfo info) {
+    public void addHdmiTvInput(int logicalAddress, TvInputInfo info) {
         if (info.getType() != TvInputInfo.TYPE_HDMI) {
             throw new IllegalArgumentException("info (" + info + ") has non-HDMI type.");
         }
@@ -293,13 +289,13 @@
             if (parentIndex < 0) {
                 throw new IllegalArgumentException("info (" + info + ") has invalid parentId.");
             }
-            String oldInputId = mHdmiCecInputIdMap.get(logicalAddress);
+            String oldInputId = mHdmiInputIdMap.get(logicalAddress);
             if (oldInputId != null) {
                 Slog.w(TAG, "Trying to override previous registration: old = "
                         + mInputMap.get(oldInputId) + ":" + logicalAddress + ", new = "
                         + info + ":" + logicalAddress);
             }
-            mHdmiCecInputIdMap.put(logicalAddress, info.getId());
+            mHdmiInputIdMap.put(logicalAddress, info.getId());
             mInputMap.put(info.getId(), info);
         }
     }
@@ -311,9 +307,9 @@
             if (hardwareIndex >= 0) {
                 mHardwareInputIdMap.removeAt(hardwareIndex);
             }
-            int cecIndex = indexOfEqualValue(mHdmiCecInputIdMap, inputId);
-            if (cecIndex >= 0) {
-                mHdmiCecInputIdMap.removeAt(cecIndex);
+            int deviceIndex = indexOfEqualValue(mHdmiInputIdMap, inputId);
+            if (deviceIndex >= 0) {
+                mHdmiInputIdMap.removeAt(deviceIndex);
             }
         }
     }
@@ -864,16 +860,16 @@
         public void onStateChanged(String inputId, int state);
         public void onHardwareDeviceAdded(TvInputHardwareInfo info);
         public void onHardwareDeviceRemoved(TvInputHardwareInfo info);
-        public void onHdmiCecDeviceAdded(HdmiDeviceInfo cecDevice);
-        public void onHdmiCecDeviceRemoved(HdmiDeviceInfo cecDevice);
+        public void onHdmiDeviceAdded(HdmiDeviceInfo device);
+        public void onHdmiDeviceRemoved(HdmiDeviceInfo device);
     }
 
     private class ListenerHandler extends Handler {
         private static final int STATE_CHANGED = 1;
         private static final int HARDWARE_DEVICE_ADDED = 2;
         private static final int HARDWARE_DEVICE_REMOVED = 3;
-        private static final int HDMI_CEC_DEVICE_ADDED = 4;
-        private static final int HDMI_CEC_DEVICE_REMOVED = 5;
+        private static final int HDMI_DEVICE_ADDED = 4;
+        private static final int HDMI_DEVICE_REMOVED = 5;
 
         @Override
         public final void handleMessage(Message msg) {
@@ -894,14 +890,14 @@
                     mListener.onHardwareDeviceRemoved(info);
                     break;
                 }
-                case HDMI_CEC_DEVICE_ADDED: {
+                case HDMI_DEVICE_ADDED: {
                     HdmiDeviceInfo info = (HdmiDeviceInfo) msg.obj;
-                    mListener.onHdmiCecDeviceAdded(info);
+                    mListener.onHdmiDeviceAdded(info);
                     break;
                 }
-                case HDMI_CEC_DEVICE_REMOVED: {
+                case HDMI_DEVICE_REMOVED: {
                     HdmiDeviceInfo info = (HdmiDeviceInfo) msg.obj;
-                    mListener.onHdmiCecDeviceRemoved(info);
+                    mListener.onHdmiDeviceRemoved(info);
                     break;
                 }
                 default: {
@@ -939,21 +935,21 @@
         public void onStatusChanged(HdmiDeviceInfo deviceInfo, boolean activated) {
             synchronized (mLock) {
                 if (activated) {
-                    if (!mHdmiCecDeviceList.contains(deviceInfo)) {
-                        mHdmiCecDeviceList.add(deviceInfo);
+                    if (!mHdmiDeviceList.contains(deviceInfo)) {
+                        mHdmiDeviceList.add(deviceInfo);
                     } else {
                         Slog.w(TAG, "The list already contains " + deviceInfo + "; ignoring.");
                         return;
                     }
                 } else {
-                    if (!mHdmiCecDeviceList.remove(deviceInfo)) {
+                    if (!mHdmiDeviceList.remove(deviceInfo)) {
                         Slog.w(TAG, "The list doesn't contain " + deviceInfo + "; ignoring.");
                         return;
                     }
                 }
                 Message msg = mHandler.obtainMessage(
-                        activated ? ListenerHandler.HDMI_CEC_DEVICE_ADDED
-                        : ListenerHandler.HDMI_CEC_DEVICE_REMOVED,
+                        activated ? ListenerHandler.HDMI_DEVICE_ADDED
+                        : ListenerHandler.HDMI_DEVICE_REMOVED,
                         0, 0, deviceInfo);
                 if (findHardwareInfoForHdmiPortLocked(deviceInfo.getPortId()) != null) {
                     msg.sendToTarget();
@@ -970,7 +966,7 @@
             String inputId;
             synchronized (mLock) {
                 if (device.isCecDevice()) {
-                    inputId = mHdmiCecInputIdMap.get(device.getLogicalAddress());
+                    inputId = mHdmiInputIdMap.get(device.getLogicalAddress());
                 } else {
                     TvInputHardwareInfo hardwareInfo =
                             findHardwareInfoForHdmiPortLocked(device.getPortId());
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 14d1ec4..c5e30d5 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -1933,13 +1933,13 @@
                         }
                     }
 
-                    List<HdmiDeviceInfo> cecDeviceInfoList =
-                            mTvInputHardwareManager.getHdmiCecInputDeviceList();
-                    for (HdmiDeviceInfo cecDeviceInfo : cecDeviceInfoList) {
+                    List<HdmiDeviceInfo> deviceInfoList =
+                            mTvInputHardwareManager.getHdmiDeviceList();
+                    for (HdmiDeviceInfo deviceInfo : deviceInfoList) {
                         try {
-                            serviceState.mService.notifyHdmiCecDeviceAdded(cecDeviceInfo);
+                            serviceState.mService.notifyHdmiDeviceAdded(deviceInfo);
                         } catch (RemoteException e) {
-                            Slog.e(TAG, "error in notifyHdmiCecDeviceAdded", e);
+                            Slog.e(TAG, "error in notifyHdmiDeviceAdded", e);
                         }
                     }
                 }
@@ -2025,11 +2025,11 @@
         }
 
         @Override
-        public void addHdmiCecTvInput(int logicalAddress, TvInputInfo inputInfo) {
+        public void addHdmiTvInput(int logicalAddress, TvInputInfo inputInfo) {
             ensureHardwarePermission();
             ensureValidInput(inputInfo);
             synchronized (mLock) {
-                mTvInputHardwareManager.addHdmiCecTvInput(logicalAddress, inputInfo);
+                mTvInputHardwareManager.addHdmiTvInput(logicalAddress, inputInfo);
                 addTvInputLocked(inputInfo);
             }
         }
@@ -2275,32 +2275,32 @@
         }
 
         @Override
-        public void onHdmiCecDeviceAdded(HdmiDeviceInfo cecDeviceInfo) {
+        public void onHdmiDeviceAdded(HdmiDeviceInfo deviceInfo) {
             synchronized (mLock) {
                 UserState userState = getUserStateLocked(mCurrentUserId);
                 // Broadcast the event to all hardware inputs.
                 for (ServiceState serviceState : userState.serviceStateMap.values()) {
                     if (!serviceState.mIsHardware || serviceState.mService == null) continue;
                     try {
-                        serviceState.mService.notifyHdmiCecDeviceAdded(cecDeviceInfo);
+                        serviceState.mService.notifyHdmiDeviceAdded(deviceInfo);
                     } catch (RemoteException e) {
-                        Slog.e(TAG, "error in notifyHdmiCecDeviceAdded", e);
+                        Slog.e(TAG, "error in notifyHdmiDeviceAdded", e);
                     }
                 }
             }
         }
 
         @Override
-        public void onHdmiCecDeviceRemoved(HdmiDeviceInfo cecDeviceInfo) {
+        public void onHdmiDeviceRemoved(HdmiDeviceInfo deviceInfo) {
             synchronized (mLock) {
                 UserState userState = getUserStateLocked(mCurrentUserId);
                 // Broadcast the event to all hardware inputs.
                 for (ServiceState serviceState : userState.serviceStateMap.values()) {
                     if (!serviceState.mIsHardware || serviceState.mService == null) continue;
                     try {
-                        serviceState.mService.notifyHdmiCecDeviceRemoved(cecDeviceInfo);
+                        serviceState.mService.notifyHdmiDeviceRemoved(deviceInfo);
                     } catch (RemoteException e) {
-                        Slog.e(TAG, "error in notifyHdmiCecDeviceRemoved", e);
+                        Slog.e(TAG, "error in notifyHdmiDeviceRemoved", e);
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 304d2d4..4e711ba 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2347,6 +2347,7 @@
             origId = Binder.clearCallingIdentity();
 
             if (addToken) {
+                Slog.w("BadTokenDebug", "addWindow: Adding token=" + token + " attrs.token=" + attrs.token);
                 mTokenMap.put(attrs.token, token);
             }
             win.attach();
@@ -2429,7 +2430,7 @@
             // relayout to be displayed, so we'll do it there.
 
             if (focusChanged) {
-                finishUpdateFocusedWindowAfterAssignLayersLocked(false /*updateInputWindows*/);
+                mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/);
             }
             mInputMonitor.updateInputWindowsLw(false /*force*/);
 
@@ -2546,12 +2547,15 @@
                 if (displayContent != null) {
                     displayContent.layoutNeeded = true;
                 }
-                updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
-                        false /*updateInputWindows*/);
+                final boolean focusChanged = updateFocusedWindowLocked(
+                        UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
                 performLayoutAndPlaceSurfacesLocked();
                 if (win.mAppToken != null) {
                     win.mAppToken.updateReportedVisibilityLocked();
                 }
+                if (focusChanged) {
+                    mInputMonitor.updateInputWindowsLw(false /*force*/);
+                }
                 //dump();
                 Binder.restoreCallingIdentity(origId);
                 return;
@@ -2625,7 +2629,9 @@
                 + token.windows.size());
         if (token.windows.size() == 0) {
             if (!token.explicit) {
-                mTokenMap.remove(token.token);
+                WindowToken wtoken = mTokenMap.remove(token.token);
+                Slog.w("BadTokenDebug", "removeWindowInnerLocked: Removing token=" + token + " removed=" +
+                        wtoken + " Callers=" + Debug.getCallers(4));
             } else if (atoken != null) {
                 atoken.firstWindowDrawn = false;
             }
@@ -3411,6 +3417,7 @@
                 return;
             }
             wtoken = new WindowToken(this, token, type, true);
+            Slog.w("BadTokenDebug", "addWindowToken: Adding token=" + token + " wtoken=" + wtoken);
             mTokenMap.put(token, wtoken);
             if (type == TYPE_WALLPAPER) {
                 mWallpaperTokens.add(wtoken);
@@ -3429,6 +3436,8 @@
         synchronized(mWindowMap) {
             DisplayContent displayContent = null;
             WindowToken wtoken = mTokenMap.remove(token);
+            Slog.w("BadTokenDebug", "removeWindowToken: Removing token=" + token + " removed=" + wtoken
+                    + " Callers=" + Debug.getCallers(3));
             if (wtoken != null) {
                 boolean delayed = false;
                 if (!wtoken.hidden) {
@@ -3545,6 +3554,7 @@
                 task.addAppToken(addPos, atoken);
             }
 
+            Slog.w("BadTokenDebug", "addAppToken: Adding token=" + token.asBinder() + " atoken=" + atoken);
             mTokenMap.put(token.asBinder(), atoken);
 
             // Application tokens start out hidden.
@@ -3910,7 +3920,7 @@
             final boolean changed = mFocusedApp != newFocus;
             if (changed) {
                 mFocusedApp = newFocus;
-                mInputMonitor.setFocusedAppLw(null);
+                mInputMonitor.setFocusedAppLw(newFocus);
             }
 
             if (moveFocusNow && changed) {
@@ -4633,6 +4643,7 @@
         final long origId = Binder.clearCallingIdentity();
         synchronized(mWindowMap) {
             WindowToken basewtoken = mTokenMap.remove(token);
+            Slog.w("BadTokenDebug", "removeAppToke: Removing token=" + token + " removed=" + basewtoken);
             if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) {
                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken);
                 delayed = setTokenVisibilityLocked(wtoken, null, false,
@@ -8917,7 +8928,7 @@
                     && !moveInputMethodWindowsIfNeededLocked(true)) {
                 assignLayersLocked(windows);
             }
-            updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, false /*updateInputWindows*/);
+            updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, true /*updateInputWindows*/);
             mFocusMayChange = false;
         }
 
@@ -9152,10 +9163,11 @@
         final long currentTime = SystemClock.uptimeMillis();
 
         int i;
+        boolean updateInputWindowsNeeded = false;
 
         if (mFocusMayChange) {
             mFocusMayChange = false;
-            updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+            updateInputWindowsNeeded = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
                     false /*updateInputWindows*/);
         }
 
@@ -9517,6 +9529,7 @@
             mFocusMayChange = false;
             if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
                     false /*updateInputWindows*/)) {
+                updateInputWindowsNeeded = true;
                 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
             }
         }
@@ -9697,6 +9710,9 @@
             mDisplayContents.valueAt(displayNdx).checkForDeferredActions();
         }
 
+        if (updateInputWindowsNeeded) {
+            mInputMonitor.updateInputWindowsLw(false /*force*/);
+        }
         setFocusedStackFrame();
 
         // Check to see if we are now in a state where the screen should
@@ -10012,7 +10028,7 @@
             if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
                 // If we defer assigning layers, then the caller is responsible for
                 // doing this part.
-                finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows);
+                mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows);
             }
 
             Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
@@ -10021,10 +10037,6 @@
         return false;
     }
 
-    private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) {
-        mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows);
-    }
-
     private WindowState computeFocusedWindowLocked() {
         if (mAnimator.mUniverseBackground != null
                 && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) {
diff --git a/telecomm/java/android/telecomm/Call.java b/telecomm/java/android/telecomm/Call.java
index 3374d51..55cb8b1 100644
--- a/telecomm/java/android/telecomm/Call.java
+++ b/telecomm/java/android/telecomm/Call.java
@@ -69,6 +69,11 @@
      */
     public static final int STATE_PRE_DIAL_WAIT = 8;
 
+    /**
+     * The state of an outgoing {@code Call}, before Telecomm broadcast intent has returned.
+     */
+    public static final int STATE_CONNECTING = 9;
+
     public static class Details {
         private final Uri mHandle;
         private final int mHandlePresentation;
@@ -771,6 +776,8 @@
         switch (parcelableCallState) {
             case NEW:
                 return STATE_NEW;
+            case CONNECTING:
+                return STATE_CONNECTING;
             case PRE_DIAL_WAIT:
                 return STATE_PRE_DIAL_WAIT;
             case DIALING:
diff --git a/telecomm/java/android/telecomm/CallState.java b/telecomm/java/android/telecomm/CallState.java
index 9cb05db..cfa78d4 100644
--- a/telecomm/java/android/telecomm/CallState.java
+++ b/telecomm/java/android/telecomm/CallState.java
@@ -32,6 +32,12 @@
     NEW,
 
     /**
+     * Indicates an outgoing call has been initiated and is waiting for the broadcast intent to
+     * return and provide call details before proceeding.
+     */
+    CONNECTING,
+
+    /**
      * Indicates that the call is about to go into the outgoing and dialing state but is waiting for
      * user input before it proceeds. For example, where no default {@link PhoneAccount} is set,
      * this is the state where the InCallUI is waiting for the user to select a
diff --git a/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibility.java b/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibility.java
index f5c4c34..5bf59c7 100644
--- a/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibility.java
+++ b/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibility.java
@@ -97,11 +97,11 @@
         String packageName = mArgs.getString(PACKAGE_TO_LAUNCH);
         if (packageName != null) {
             Log.d(TAG, "Launching app " + packageName);
-            Collection<ProcessErrorStateInfo> err = launchActivity(packageName);
+            ProcessErrorStateInfo err = launchActivity(packageName);
             // Make sure there are no errors when launching the application,
             // otherwise raise an
             // exception with the first error encountered.
-            assertNull(getFirstError(err), err);
+            assertNull(getStackTrace(err), err);
             assertTrue("App crashed after launch.", processStillUp(packageName));
         } else {
             Log.d(TAG, "Missing argument, use " + PACKAGE_TO_LAUNCH +
@@ -110,20 +110,32 @@
     }
 
     /**
-     * Gets the first error in collection and return the long message for it.
+     * Gets the stack trace for the error.
      *
-     * @param in {@link Collection} of {@link ProcessErrorStateInfo} to parse.
+     * @param in {@link ProcessErrorStateInfo} to parse.
      * @return {@link String} the long message of the error.
      */
-    private String getFirstError(Collection<ProcessErrorStateInfo> in) {
+    private String getStackTrace(ProcessErrorStateInfo in) {
         if (in == null) {
             return null;
+        } else {
+            return in.stackTrace;
         }
-        ProcessErrorStateInfo err = in.iterator().next();
-        if (err != null) {
-            return err.stackTrace;
+    }
+
+    /**
+     * Returns the process name that the package is going to use.
+     *
+     * @param packageName name of the package
+     * @return process name of the package
+     */
+    private String getProcessName(String packageName) {
+        try {
+            PackageInfo pi = mPackageManager.getPackageInfo(packageName, 0);
+            return pi.applicationInfo.processName;
+        } catch (NameNotFoundException e) {
+            return packageName;
         }
-        return null;
     }
 
     /**
@@ -134,7 +146,7 @@
      * @return {@link Collection} of {@link ProcessErrorStateInfo} detected
      *         during the app launch.
      */
-    private Collection<ProcessErrorStateInfo> launchActivity(String packageName) {
+    private ProcessErrorStateInfo launchActivity(String packageName) {
         Intent homeIntent = new Intent(Intent.ACTION_MAIN);
         homeIntent.addCategory(Intent.CATEGORY_HOME);
         homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -146,16 +158,7 @@
             return null;
         }
 
-        // We check for any Crash or ANR dialogs that are already up, and we
-        // ignore them. This is
-        // so that we don't report crashes that were caused by prior apps (which
-        // those particular
-        // tests should have caught and reported already). Otherwise, test
-        // failures would cascade
-        // from the initial broken app to many/all of the tests following that
-        // app's launch.
-        final Collection<ProcessErrorStateInfo> preErr =
-                mActivityManager.getProcessesInErrorState();
+        String processName = getProcessName(packageName);
 
         // Launch Activity
         mContext.startActivity(intent);
@@ -179,13 +182,16 @@
         // possible to occur.
         final Collection<ProcessErrorStateInfo> postErr =
                 mActivityManager.getProcessesInErrorState();
-        // Take the difference between the error processes we see now, and the
-        // ones that were
-        // present when we started
-        if (preErr != null && postErr != null) {
-            postErr.removeAll(preErr);
+
+        if (postErr == null) {
+            return null;
         }
-        return postErr;
+        for (ProcessErrorStateInfo error : postErr) {
+            if (error.processName.equals(processName)) {
+                return error;
+            }
+        }
+        return null;
     }
 
     /**
@@ -195,22 +201,16 @@
      * @return True if package is running, false otherwise.
      */
     private boolean processStillUp(String packageName) {
-        try {
-            PackageInfo packageInfo = mPackageManager.getPackageInfo(packageName, 0);
-            String processName = packageInfo.applicationInfo.processName;
-            List<RunningAppProcessInfo> runningApps = mActivityManager.getRunningAppProcesses();
-            for (RunningAppProcessInfo app : runningApps) {
-                if (app.processName.equalsIgnoreCase(processName)) {
-                    Log.d(TAG, "Found process " + app.processName);
-                    return true;
-                }
+        String processName = getProcessName(packageName);
+        List<RunningAppProcessInfo> runningApps = mActivityManager.getRunningAppProcesses();
+        for (RunningAppProcessInfo app : runningApps) {
+            if (app.processName.equalsIgnoreCase(processName)) {
+                Log.d(TAG, "Found process " + app.processName);
+                return true;
             }
-            Log.d(TAG, "Failed to find process " + processName + " with package name "
-                    + packageName);
-        } catch (NameNotFoundException e) {
-            Log.w(TAG, "Failed to find package " + packageName);
-            return false;
         }
+        Log.d(TAG, "Failed to find process " + processName + " with package name "
+                + packageName);
         return false;
     }
 }
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable05.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable05.xml
index 5b1f6ab..bbf1a17 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable05.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable05.xml
@@ -28,8 +28,7 @@
                 l-5.046875,0.0 0.0-1.0Z" />
         <path
             android:name="two"
-            android:fillColor="#ffff00"
-            android:fillOpacity="0"
+            android:fillColor="#00ffff00"
             android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0-5.5625,0.0 0.0-1.0q 0.671875-0.6875 1.828125-1.859375
                         q 1.1718752-1.1875 1.4687502-1.53125 0.578125-0.625 0.796875-1.0625
                         q 0.234375-0.453125 0.234375-0.875 0.0-0.703125-0.5-1.140625
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_schedule.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_schedule.xml
index 8cabca8..1aad743 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_icon_schedule.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_icon_schedule.xml
@@ -21,10 +21,10 @@
 
     <group>
         <path
-            android:fillOpacity="0.9"
+            android:fillColor="#E6000000"
             android:pathData="M11.994999,2.0C6.4679985,2.0 2.0,6.4780006 2.0,12.0s4.468,10.0 9.995,10.0S22.0,17.522 22.0,12.0S17.521,2.0 11.994999,2.0zM12.0,20.0c-4.42,0.0 -8.0,-3.582 -8.0,-8.0s3.58,-8.0 8.0,-8.0s8.0,3.582 8.0,8.0S16.419998,20.0 12.0,20.0z" />
         <path
-            android:fillOpacity="0.9"
+            android:fillColor="#E6000000"
             android:pathData="M12.5,6.0l-1.5,0.0 0.0,7.0 5.3029995,3.1819992 0.75,-1.249999 -4.5529995,-2.7320004z" />
     </group>
 
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 4f1d15e..ec284c5 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -1739,7 +1739,7 @@
 
 static status_t writeLayoutClasses(
     FILE* fp, const sp<AaptAssets>& assets,
-    const sp<AaptSymbols>& symbols, int indent, bool includePrivate)
+    const sp<AaptSymbols>& symbols, int indent, bool includePrivate, bool nonConstantId)
 {
     const char* indentStr = getIndentSpace(indent);
     if (!includePrivate) {
@@ -1957,8 +1957,13 @@
                         getSymbolName(name8).string());
                 fprintf(fp, "%s*/\n", indentStr);
                 ann.printAnnotations(fp, indentStr);
+
+                const char * id_format = nonConstantId ?
+                        "%spublic static int %s_%s = %d;\n" :
+                        "%spublic static final int %s_%s = %d;\n";
+
                 fprintf(fp,
-                        "%spublic static final int %s_%s = %d;\n",
+                        id_format,
                         indentStr, nclassName.string(),
                         flattenSymbol(name8).string(), (int)pos);
             }
@@ -2177,7 +2182,7 @@
     }
 
     if (styleableSymbols != NULL) {
-        err = writeLayoutClasses(fp, assets, styleableSymbols, indent, includePrivate);
+        err = writeLayoutClasses(fp, assets, styleableSymbols, indent, includePrivate, nonConstantId);
         if (err != NO_ERROR) {
             return err;
         }
diff --git a/tools/layoutlib/rename_font/build_font_single.py b/tools/layoutlib/rename_font/build_font_single.py
new file mode 100755
index 0000000..d648b04
--- /dev/null
+++ b/tools/layoutlib/rename_font/build_font_single.py
@@ -0,0 +1,207 @@
+#!/usr/bin/env python
+
+# 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.
+
+"""
+Rename the PS name of the input font.
+
+OpenType fonts (*.otf) are not currently supported. They are copied to the destination without renaming.
+XML files are also copied in case they are passed there by mistake.
+
+Usage: build_font.py /path/to/input_font.ttf /path/to/output_font.ttf
+
+"""
+
+import glob
+import os
+import re
+import shutil
+import sys
+import xml.etree.ElementTree as etree
+
+# Prevent .pyc files from being created.
+sys.dont_write_bytecode = True
+
+# fontTools is available at platform/external/fonttools
+from fontTools import ttx
+
+
+class FontInfo(object):
+  family = None
+  style = None
+  version = None
+  ends_in_regular = False
+  fullname = None
+
+
+class InvalidFontException(Exception):
+  pass
+
+
+# A constant to copy the font without modifying. This is useful when running
+# locally and speed up the time to build the SDK.
+COPY_ONLY = False
+
+# These constants represent the value of nameID parameter in the namerecord for
+# different information.
+# see http://scripts.sil.org/cms/scripts/page.php?item_id=IWS-Chapter08#3054f18b
+NAMEID_FAMILY = 1
+NAMEID_STYLE = 2
+NAMEID_FULLNAME = 4
+NAMEID_VERSION = 5
+
+# A list of extensions to process.
+EXTENSIONS = ['.ttf', '.otf', '.xml']
+
+def main(argv):
+  if len(argv) < 2:
+    sys.exit('Usage: build_font.py /path/to/input/font.ttf /path/to/out/font.ttf')
+  dest_path = argv[-1]
+  input_path = argv[0]
+  extension = os.path.splitext(input_path)[1].lower()
+  if extension in EXTENSIONS:
+    if not COPY_ONLY and extension == '.ttf':
+      convert_font(input_path, dest_path)
+      return
+    shutil.copy(input_path, dest_path)
+
+
+def convert_font(input_path, dest_path):
+  filename = os.path.basename(input_path)
+  print 'Converting font: ' + filename
+  # the path to the output file. The file name is the fontfilename.ttx
+  ttx_path = dest_path[:-1] + 'x'
+  try:
+    # run ttx to generate an xml file in the output folder which represents all
+    # its info
+    ttx_args = ['-q', '-o', ttx_path, input_path]
+    ttx.main(ttx_args)
+    # now parse the xml file to change its PS name.
+    tree = etree.parse(ttx_path)
+    root = tree.getroot()
+    for name in root.iter('name'):
+      update_tag(name, get_font_info(name))
+    tree.write(ttx_path, xml_declaration=True, encoding='utf-8')
+    # generate the udpated font now.
+    ttx_args = ['-q', '-o', dest_path, ttx_path]
+    ttx.main(ttx_args)
+  except InvalidFontException:
+    # In case of invalid fonts, we exit.
+    print filename + ' is not a valid font'
+    raise
+  except Exception as e:
+    print 'Error converting font: ' + filename
+    print e
+    # Some fonts are too big to be handled by the ttx library.
+    # Just copy paste them.
+    shutil.copy(input_path, dest_path)
+  try:
+    # delete the temp ttx file is it exists.
+    os.remove(ttx_path)
+  except OSError:
+    pass
+
+
+def get_font_info(tag):
+  """ Returns a list of FontInfo representing the various sets of namerecords
+      found in the name table of the font. """
+  fonts = []
+  font = None
+  last_name_id = sys.maxint
+  for namerecord in tag.iter('namerecord'):
+    if 'nameID' in namerecord.attrib:
+      name_id = int(namerecord.attrib['nameID'])
+      # A new font should be created for each platform, encoding and language
+      # id. But, since the nameIDs are sorted, we use the easy approach of
+      # creating a new one when the nameIDs reset.
+      if name_id <= last_name_id and font is not None:
+        fonts.append(font)
+        font = None
+      last_name_id = name_id
+      if font is None:
+        font = FontInfo()
+      if name_id == NAMEID_FAMILY:
+        font.family = namerecord.text.strip()
+      if name_id == NAMEID_STYLE:
+        font.style = namerecord.text.strip()
+      if name_id == NAMEID_FULLNAME:
+        font.ends_in_regular = ends_in_regular(namerecord.text)
+        font.fullname = namerecord.text.strip()
+      if name_id == NAMEID_VERSION:
+        font.version = get_version(namerecord.text)
+  if font is not None:
+    fonts.append(font)
+  return fonts
+
+
+def update_tag(tag, fonts):
+  last_name_id = sys.maxint
+  fonts_iterator = fonts.__iter__()
+  font = None
+  for namerecord in tag.iter('namerecord'):
+    if 'nameID' in namerecord.attrib:
+      name_id = int(namerecord.attrib['nameID'])
+      if name_id <= last_name_id:
+        font = fonts_iterator.next()
+        font = update_font_name(font)
+      last_name_id = name_id
+      if name_id == NAMEID_FAMILY:
+        namerecord.text = font.family
+      if name_id == NAMEID_FULLNAME:
+        namerecord.text = font.fullname
+
+
+def update_font_name(font):
+  """ Compute the new font family name and font fullname. If the font has a
+      valid version, it's sanitized and appended to the font family name. The
+      font fullname is then created by joining the new family name and the
+      style. If the style is 'Regular', it is appended only if the original font
+      had it. """
+  if font.family is None or font.style is None:
+    raise InvalidFontException('Font doesn\'t have proper family name or style')
+  if font.version is not None:
+    new_family = font.family + font.version
+  else:
+    new_family = font.family
+  if font.style is 'Regular' and not font.ends_in_regular:
+    font.fullname = new_family
+  else:
+    font.fullname = new_family + ' ' + font.style
+  font.family = new_family
+  return font
+
+
+def ends_in_regular(string):
+  """ According to the specification, the font fullname should not end in
+      'Regular' for plain fonts. However, some fonts don't obey this rule. We
+      keep the style info, to minimize the diff. """
+  string = string.strip().split()[-1]
+  return string is 'Regular'
+
+
+def get_version(string):
+  # The string must begin with 'Version n.nn '
+  # to extract n.nn, we return the second entry in the split strings.
+  string = string.strip()
+  if not string.startswith('Version '):
+    raise InvalidFontException('mal-formed font version')
+  return sanitize(string.split()[1])
+
+
+def sanitize(string):
+  return re.sub(r'[^\w-]+', '', string)
+
+if __name__ == '__main__':
+  main(sys.argv[1:])
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index dfed174..1ca54bc 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -343,6 +343,7 @@
      * Wi-Fi configurations changed, {@link #EXTRA_WIFI_CONFIGURATION} will not be present.
      * @hide
      */
+    @SystemApi
     public static final String CONFIGURED_NETWORKS_CHANGED_ACTION =
         "android.net.wifi.CONFIGURED_NETWORKS_CHANGE";
     /**
@@ -351,6 +352,7 @@
      * broadcast is sent.
      * @hide
      */
+    @SystemApi
     public static final String EXTRA_WIFI_CONFIGURATION = "wifiConfiguration";
     /**
      * Multiple network configurations have changed.
@@ -358,6 +360,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static final String EXTRA_MULTIPLE_NETWORKS_CHANGED = "multipleChanges";
     /**
      * The lookup key for an integer indicating the reason a Wi-Fi network configuration
@@ -365,23 +368,27 @@
      * @see #CONFIGURED_NETWORKS_CHANGED_ACTION
      * @hide
      */
+    @SystemApi
     public static final String EXTRA_CHANGE_REASON = "changeReason";
     /**
      * The configuration is new and was added.
      * @hide
      */
+    @SystemApi
     public static final int CHANGE_REASON_ADDED = 0;
     /**
      * The configuration was removed and is no longer present in the system's list of
      * configured networks.
      * @hide
      */
+    @SystemApi
     public static final int CHANGE_REASON_REMOVED = 1;
     /**
      * The configuration has changed as a result of explicit action or because the system
      * took an automated action such as disabling a malfunctioning configuration.
      * @hide
      */
+    @SystemApi
     public static final int CHANGE_REASON_CONFIG_CHANGE = 2;
     /**
      * An access point scan has completed, and results are available from the supplicant.
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index c5c44b5..e7bcb23 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -100,7 +100,7 @@
      */
     public static class ChannelSpec {
         /**
-         * channel frequency in KHz; for example channel 1 is specified as 2412
+         * channel frequency in MHz; for example channel 1 is specified as 2412
          */
         public int frequency;
         /**
@@ -158,6 +158,7 @@
             dest.writeInt(band);
             dest.writeInt(periodInMs);
             dest.writeInt(reportEvents);
+            dest.writeInt(numBssidsPerScan);
 
             if (channels != null) {
                 dest.writeInt(channels.length);
@@ -181,6 +182,7 @@
                         settings.band = in.readInt();
                         settings.periodInMs = in.readInt();
                         settings.reportEvents = in.readInt();
+                        settings.numBssidsPerScan = in.readInt();
                         int num_channels = in.readInt();
                         settings.channels = new ChannelSpec[num_channels];
                         for (int i = 0; i < num_channels; i++) {