Merge "Expose StaticLayout.Builder publicly" into mnc-dev
diff --git a/api/current.txt b/api/current.txt
index e6cd4d7..de401b2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1188,7 +1188,7 @@
     field public static final int summaryColumn = 16843426; // 0x10102a2
     field public static final int summaryOff = 16843248; // 0x10101f0
     field public static final int summaryOn = 16843247; // 0x10101ef
-    field public static final int supportsAssistGesture = 16844011; // 0x10104eb
+    field public static final int supportsAssist = 16844011; // 0x10104eb
     field public static final int supportsRtl = 16843695; // 0x10103af
     field public static final int supportsSwitchingToNextInputMethod = 16843755; // 0x10103eb
     field public static final int supportsUploading = 16843419; // 0x101029b
@@ -12486,6 +12486,25 @@
     enum_constant public static final android.graphics.drawable.GradientDrawable.Orientation TR_BL;
   }
 
+  public final class Icon implements android.os.Parcelable {
+    method public static android.graphics.drawable.Icon createWithBitmap(android.graphics.Bitmap);
+    method public static android.graphics.drawable.Icon createWithContentUri(java.lang.String);
+    method public static android.graphics.drawable.Icon createWithContentUri(android.net.Uri);
+    method public static android.graphics.drawable.Icon createWithData(byte[], int, int);
+    method public static android.graphics.drawable.Icon createWithFilePath(java.lang.String);
+    method public static android.graphics.drawable.Icon createWithResource(android.content.res.Resources, int);
+    method public int describeContents();
+    method public android.graphics.drawable.Drawable loadDrawable(android.content.Context);
+    method public void loadDrawableAsync(android.content.Context, android.os.Message);
+    method public void loadDrawableAsync(android.content.Context, android.os.Handler, android.graphics.drawable.Icon.OnDrawableLoadedListener);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.graphics.drawable.Icon> CREATOR;
+  }
+
+  public static abstract interface Icon.OnDrawableLoadedListener {
+    method public abstract void onDrawableLoaded(android.graphics.drawable.Drawable);
+  }
+
   public class InsetDrawable extends android.graphics.drawable.DrawableWrapper {
     ctor public InsetDrawable(android.graphics.drawable.Drawable, int);
     ctor public InsetDrawable(android.graphics.drawable.Drawable, int, int, int, int);
@@ -18438,6 +18457,7 @@
     method public void onLinkPropertiesChanged(android.net.Network, android.net.LinkProperties);
     method public void onLosing(android.net.Network, int);
     method public void onLost(android.net.Network);
+    method public void onPreCheck(android.net.Network);
   }
 
   public static abstract interface ConnectivityManager.OnNetworkActiveListener {
@@ -27163,7 +27183,8 @@
   public static final class Telephony.Carriers implements android.provider.BaseColumns {
     field public static final java.lang.String APN = "apn";
     field public static final java.lang.String AUTH_TYPE = "authtype";
-    field public static final java.lang.String BEARER = "bearer";
+    field public static final deprecated java.lang.String BEARER = "bearer";
+    field public static final java.lang.String BEARER_BITMASK = "bearer_bitmask";
     field public static final java.lang.String CARRIER_ENABLED = "carrier_enabled";
     field public static final android.net.Uri CONTENT_URI;
     field public static final java.lang.String CURRENT = "current";
@@ -30306,17 +30327,17 @@
     method public int getHandlePresentation();
     method public android.telecom.StatusHints getStatusHints();
     method public int getVideoState();
+    method public static boolean hasProperty(int, int);
+    method public boolean hasProperty(int);
+    method public static java.lang.String propertiesToString(int);
     field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000
     field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000
-    field public static final int CAPABILITY_GENERIC_CONFERENCE = 16384; // 0x4000
-    field public static final int CAPABILITY_HIGH_DEF_AUDIO = 32768; // 0x8000
     field public static final int CAPABILITY_HOLD = 1; // 0x1
     field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80
     field public static final int CAPABILITY_MERGE_CONFERENCE = 4; // 0x4
     field public static final int CAPABILITY_MUTE = 64; // 0x40
     field public static final int CAPABILITY_RESPOND_VIA_TEXT = 32; // 0x20
     field public static final int CAPABILITY_SEPARATE_FROM_CONFERENCE = 4096; // 0x1000
-    field public static final int CAPABILITY_SHOW_CALLBACK_NUMBER = 131072; // 0x20000
     field public static final int CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL = 768; // 0x300
     field public static final int CAPABILITY_SUPPORTS_VT_LOCAL_RX = 256; // 0x100
     field public static final int CAPABILITY_SUPPORTS_VT_LOCAL_TX = 512; // 0x200
@@ -30325,12 +30346,11 @@
     field public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 2048; // 0x800
     field public static final int CAPABILITY_SUPPORT_HOLD = 2; // 0x2
     field public static final int CAPABILITY_SWAP_CONFERENCE = 8; // 0x8
-    field public static final int CAPABILITY_WIFI = 65536; // 0x10000
-  }
-
-  public class CallProperties {
-    ctor public CallProperties();
-    field public static final int CONFERENCE = 1; // 0x1
+    field public static final int PROPERTY_CONFERENCE = 1; // 0x1
+    field public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 4; // 0x4
+    field public static final int PROPERTY_GENERIC_CONFERENCE = 2; // 0x2
+    field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10
+    field public static final int PROPERTY_WIFI = 8; // 0x8
   }
 
   public final class CameraCapabilities implements android.os.Parcelable {
diff --git a/api/system-current.txt b/api/system-current.txt
index acfa300..59578c2 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1263,7 +1263,7 @@
     field public static final int summaryColumn = 16843426; // 0x10102a2
     field public static final int summaryOff = 16843248; // 0x10101f0
     field public static final int summaryOn = 16843247; // 0x10101ef
-    field public static final int supportsAssistGesture = 16844011; // 0x10104eb
+    field public static final int supportsAssist = 16844011; // 0x10104eb
     field public static final int supportsRtl = 16843695; // 0x10103af
     field public static final int supportsSwitchingToNextInputMethod = 16843755; // 0x10103eb
     field public static final int supportsUploading = 16843419; // 0x101029b
@@ -12780,6 +12780,25 @@
     enum_constant public static final android.graphics.drawable.GradientDrawable.Orientation TR_BL;
   }
 
+  public final class Icon implements android.os.Parcelable {
+    method public static android.graphics.drawable.Icon createWithBitmap(android.graphics.Bitmap);
+    method public static android.graphics.drawable.Icon createWithContentUri(java.lang.String);
+    method public static android.graphics.drawable.Icon createWithContentUri(android.net.Uri);
+    method public static android.graphics.drawable.Icon createWithData(byte[], int, int);
+    method public static android.graphics.drawable.Icon createWithFilePath(java.lang.String);
+    method public static android.graphics.drawable.Icon createWithResource(android.content.res.Resources, int);
+    method public int describeContents();
+    method public android.graphics.drawable.Drawable loadDrawable(android.content.Context);
+    method public void loadDrawableAsync(android.content.Context, android.os.Message);
+    method public void loadDrawableAsync(android.content.Context, android.os.Handler, android.graphics.drawable.Icon.OnDrawableLoadedListener);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.graphics.drawable.Icon> CREATOR;
+  }
+
+  public static abstract interface Icon.OnDrawableLoadedListener {
+    method public abstract void onDrawableLoaded(android.graphics.drawable.Drawable);
+  }
+
   public class InsetDrawable extends android.graphics.drawable.DrawableWrapper {
     ctor public InsetDrawable(android.graphics.drawable.Drawable, int);
     ctor public InsetDrawable(android.graphics.drawable.Drawable, int, int, int, int);
@@ -19906,6 +19925,7 @@
     method public void onLinkPropertiesChanged(android.net.Network, android.net.LinkProperties);
     method public void onLosing(android.net.Network, int);
     method public void onLost(android.net.Network);
+    method public void onPreCheck(android.net.Network);
   }
 
   public static abstract interface ConnectivityManager.OnNetworkActiveListener {
@@ -29176,7 +29196,8 @@
   public static final class Telephony.Carriers implements android.provider.BaseColumns {
     field public static final java.lang.String APN = "apn";
     field public static final java.lang.String AUTH_TYPE = "authtype";
-    field public static final java.lang.String BEARER = "bearer";
+    field public static final deprecated java.lang.String BEARER = "bearer";
+    field public static final java.lang.String BEARER_BITMASK = "bearer_bitmask";
     field public static final java.lang.String CARRIER_ENABLED = "carrier_enabled";
     field public static final android.net.Uri CONTENT_URI;
     field public static final java.lang.String CURRENT = "current";
@@ -32422,17 +32443,17 @@
     method public int getHandlePresentation();
     method public android.telecom.StatusHints getStatusHints();
     method public int getVideoState();
+    method public static boolean hasProperty(int, int);
+    method public boolean hasProperty(int);
+    method public static java.lang.String propertiesToString(int);
     field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000
     field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000
-    field public static final int CAPABILITY_GENERIC_CONFERENCE = 16384; // 0x4000
-    field public static final int CAPABILITY_HIGH_DEF_AUDIO = 32768; // 0x8000
     field public static final int CAPABILITY_HOLD = 1; // 0x1
     field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80
     field public static final int CAPABILITY_MERGE_CONFERENCE = 4; // 0x4
     field public static final int CAPABILITY_MUTE = 64; // 0x40
     field public static final int CAPABILITY_RESPOND_VIA_TEXT = 32; // 0x20
     field public static final int CAPABILITY_SEPARATE_FROM_CONFERENCE = 4096; // 0x1000
-    field public static final int CAPABILITY_SHOW_CALLBACK_NUMBER = 131072; // 0x20000
     field public static final int CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL = 768; // 0x300
     field public static final int CAPABILITY_SUPPORTS_VT_LOCAL_RX = 256; // 0x100
     field public static final int CAPABILITY_SUPPORTS_VT_LOCAL_TX = 512; // 0x200
@@ -32441,18 +32462,17 @@
     field public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 2048; // 0x800
     field public static final int CAPABILITY_SUPPORT_HOLD = 2; // 0x2
     field public static final int CAPABILITY_SWAP_CONFERENCE = 8; // 0x8
-    field public static final int CAPABILITY_WIFI = 65536; // 0x10000
+    field public static final int PROPERTY_CONFERENCE = 1; // 0x1
+    field public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 4; // 0x4
+    field public static final int PROPERTY_GENERIC_CONFERENCE = 2; // 0x2
+    field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10
+    field public static final int PROPERTY_WIFI = 8; // 0x8
   }
 
   public static abstract deprecated class Call.Listener extends android.telecom.Call.Callback {
     ctor public Call.Listener();
   }
 
-  public class CallProperties {
-    ctor public CallProperties();
-    field public static final int CONFERENCE = 1; // 0x1
-  }
-
   public final class CameraCapabilities implements android.os.Parcelable {
     ctor public CameraCapabilities(int, int);
     method public int describeContents();
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index 9d1d312..b0fda9c 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -26,6 +26,10 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.WorkSource;
+import android.text.TextUtils;
+import libcore.util.ZoneInfoDB;
+
+import java.io.IOException;
 
 /**
  * This class provides access to the system alarm services.  These allow you
@@ -151,6 +155,7 @@
 
     private final IAlarmManager mService;
     private final boolean mAlwaysExact;
+    private final int mTargetSdkVersion;
 
 
     /**
@@ -159,8 +164,8 @@
     AlarmManager(IAlarmManager service, Context ctx) {
         mService = service;
 
-        final int sdkVersion = ctx.getApplicationInfo().targetSdkVersion;
-        mAlwaysExact = (sdkVersion < Build.VERSION_CODES.KITKAT);
+        mTargetSdkVersion = ctx.getApplicationInfo().targetSdkVersion;
+        mAlwaysExact = (mTargetSdkVersion < Build.VERSION_CODES.KITKAT);
     }
 
     private long legacyExactLength() {
@@ -585,12 +590,38 @@
     }
 
     /**
-     * Set the system default time zone.
-     * Requires the permission android.permission.SET_TIME_ZONE.
+     * Sets the system's persistent default time zone. This is the time zone for all apps, even
+     * after a reboot. Use {@link java.util.TimeZone#setDefault} if you just want to change the
+     * time zone within your app, and even then prefer to pass an explicit
+     * {@link java.util.TimeZone} to APIs that require it rather than changing the time zone for
+     * all threads.
      *
-     * @param timeZone in the format understood by {@link java.util.TimeZone}
+     * <p> On android M and above, it is an error to pass in a non-Olson timezone to this
+     * function. Note that this is a bad idea on all Android releases because POSIX and
+     * the {@code TimeZone} class have opposite interpretations of {@code '+'} and {@code '-'}
+     * in the same non-Olson ID.
+     *
+     * @param timeZone one of the Olson ids from the list returned by
+     *     {@link java.util.TimeZone#getAvailableIDs}
      */
     public void setTimeZone(String timeZone) {
+        if (TextUtils.isEmpty(timeZone)) {
+            return;
+        }
+
+        // Reject this timezone if it isn't an Olson zone we recognize.
+        if (mTargetSdkVersion >= Build.VERSION_CODES.MNC) {
+            boolean hasTimeZone = false;
+            try {
+                hasTimeZone = ZoneInfoDB.getInstance().hasTimeZone(timeZone);
+            } catch (IOException ignored) {
+            }
+
+            if (!hasTimeZone) {
+                throw new IllegalArgumentException("Timezone: " + timeZone + " is not an Olson ID");
+            }
+        }
+
         try {
             mService.setTimeZone(timeZone);
         } catch (RemoteException ex) {
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 8a3c9c8..6b161b9 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -223,8 +223,10 @@
     public static final int OP_PROCESS_OUTGOING_CALLS = 54;
     /** @hide User the fingerprint API. */
     public static final int OP_USE_FINGERPRINT = 55;
+    /** @hide Access to body sensors such as heart rate, etc. */
+    public static final int OP_BODY_SENSORS = 56;
     /** @hide */
-    public static final int _NUM_OP = 56;
+    public static final int _NUM_OP = 57;
 
     /** Access to coarse location information. */
     public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -280,9 +282,6 @@
     /** @hide Allows an application to send SMS messages. */
     public static final String OPSTR_SEND_SMS
             = "android:send_sms";
-    /** @hide Allows an application to add system alert windows. */
-    public static final String OPSTR_SYSTEM_ALERT_WINDOW
-            = "android:system_alert_window";
     /** @hide Required to be able to access the camera device. */
     public static final String OPSTR_CAMERA
             = "android:camera";
@@ -295,6 +294,15 @@
     /** @hide Required to access phone state related information. */
     public static final String OPSTR_ADD_VOICEMAIL
             = "android:add_voicemail";
+    /** @hide Access APIs for SIP calling over VOIP or WiFi */
+    public static final String OPSTR_USE_SIP
+            = "android:use_sip";
+    /** @hide Use the fingerprint API. */
+    public static final String OPSTR_USE_FINGERPRINT
+            = "android:use_fingerprint";
+    /** @hide Access to body sensors such as heart rate, etc. */
+    public static final String OPSTR_BODY_SENSORS
+            = "android:body_sensors";
 
     /**
      * This maps each operation to the operation that serves as the
@@ -360,7 +368,8 @@
             OP_ADD_VOICEMAIL,
             OP_USE_SIP,
             OP_PROCESS_OUTGOING_CALLS,
-            OP_USE_FINGERPRINT
+            OP_USE_FINGERPRINT,
+            OP_BODY_SENSORS
     };
 
     /**
@@ -372,30 +381,30 @@
             OPSTR_FINE_LOCATION,
             null,
             null,
+            OPSTR_READ_CONTACTS,
+            OPSTR_WRITE_CONTACTS,
+            OPSTR_READ_CALL_LOG,
+            OPSTR_WRITE_CALL_LOG,
+            OPSTR_READ_CALENDAR,
+            OPSTR_WRITE_CALENDAR,
+            null,
+            null,
+            null,
+            OPSTR_CALL_PHONE,
+            OPSTR_READ_SMS,
+            null,
+            OPSTR_RECEIVE_SMS,
+            null,
+            OPSTR_RECEIVE_MMS,
+            OPSTR_RECEIVE_WAP_PUSH,
+            OPSTR_SEND_SMS,
             null,
             null,
             null,
             null,
             null,
-            null,
-            null,
-            null,
-            null,
-            null,
-            null,
-            null,
-            null,
-            null,
-            null,
-            null,
-            null,
-            null,
-            null,
-            null,
-            null,
-            null,
-            null,
-            null,
+            OPSTR_CAMERA,
+            OPSTR_RECORD_AUDIO,
             null,
             null,
             null,
@@ -419,11 +428,12 @@
             null,
             null,
             null,
+            OPSTR_READ_PHONE_STATE,
+            OPSTR_ADD_VOICEMAIL,
+            OPSTR_USE_SIP,
             null,
-            null,
-            null,
-            null,
-            null
+            OPSTR_USE_FINGERPRINT,
+            OPSTR_BODY_SENSORS
     };
 
     /**
@@ -486,7 +496,8 @@
             "ADD_VOICEMAIL",
             "USE_SIP",
             "PROCESS_OUTGOING_CALLS",
-            "USE_FINGERPRINT"
+            "USE_FINGERPRINT",
+            "BODY_SENSORS"
     };
 
     /**
@@ -549,7 +560,8 @@
             Manifest.permission.ADD_VOICEMAIL,
             Manifest.permission.USE_SIP,
             Manifest.permission.PROCESS_OUTGOING_CALLS,
-            Manifest.permission.USE_FINGERPRINT
+            Manifest.permission.USE_FINGERPRINT,
+            Manifest.permission.BODY_SENSORS
     };
 
     /**
@@ -613,7 +625,8 @@
             null, // ADD_VOICEMAIL
             null, // USE_SIP
             null, // PROCESS_OUTGOING_CALLS
-            null  // USE_FINGERPRINT
+            null, // USE_FINGERPRINT
+            null  // BODY_SENSORS
     };
 
     /**
@@ -676,7 +689,8 @@
             false, //ADD_VOICEMAIL
             false, // USE_SIP
             false, // PROCESS_OUTGOING_CALLS
-            false  // USE_FINGERPRINT
+            false, // USE_FINGERPRINT
+            false  // BODY_SENSORS
     };
 
     /**
@@ -738,6 +752,7 @@
             AppOpsManager.MODE_ALLOWED,
             AppOpsManager.MODE_ALLOWED,
             AppOpsManager.MODE_ALLOWED,
+            AppOpsManager.MODE_ALLOWED,
             AppOpsManager.MODE_ALLOWED
     };
 
@@ -804,37 +819,19 @@
             false,
             false,
             false,
+            false,
             false
     };
 
     /**
-     * This is a mapping from a permission name to public app op name.
+     * Mapping from an app op name to the app op code.
      */
-    private static final ArrayMap<String, String> sPermToOp = new ArrayMap<>();
-    static {
-        sPermToOp.put(Manifest.permission.ACCESS_COARSE_LOCATION, OPSTR_COARSE_LOCATION);
-        sPermToOp.put(Manifest.permission.ACCESS_FINE_LOCATION, OPSTR_FINE_LOCATION);
-        sPermToOp.put(Manifest.permission.PACKAGE_USAGE_STATS, OPSTR_GET_USAGE_STATS);
-        sPermToOp.put(Manifest.permission.READ_CONTACTS, OPSTR_READ_CONTACTS);
-        sPermToOp.put(Manifest.permission.WRITE_CONTACTS, OPSTR_WRITE_CONTACTS);
-        sPermToOp.put(Manifest.permission.READ_CALL_LOG, OPSTR_READ_CALL_LOG);
-        sPermToOp.put(Manifest.permission.WRITE_CALL_LOG, OPSTR_WRITE_CALL_LOG);
-        sPermToOp.put(Manifest.permission.READ_CALENDAR, OPSTR_READ_CALENDAR);
-        sPermToOp.put(Manifest.permission.WRITE_CALENDAR, OPSTR_WRITE_CALENDAR);
-        sPermToOp.put(Manifest.permission.CALL_PHONE, OPSTR_CALL_PHONE);
-        sPermToOp.put(Manifest.permission.READ_SMS, OPSTR_READ_SMS);
-        sPermToOp.put(Manifest.permission.RECEIVE_SMS, OPSTR_RECEIVE_SMS);
-        sPermToOp.put(Manifest.permission.RECEIVE_MMS, OPSTR_RECEIVE_MMS);
-        sPermToOp.put(Manifest.permission.RECEIVE_WAP_PUSH, OPSTR_RECEIVE_WAP_PUSH);
-        sPermToOp.put(Manifest.permission.SEND_SMS, OPSTR_SEND_SMS);
-        sPermToOp.put(Manifest.permission.SYSTEM_ALERT_WINDOW, OPSTR_SYSTEM_ALERT_WINDOW);
-        sPermToOp.put(Manifest.permission.CAMERA, OPSTR_CAMERA);
-        sPermToOp.put(Manifest.permission.RECORD_AUDIO, OPSTR_RECORD_AUDIO);
-        sPermToOp.put(Manifest.permission.READ_PHONE_STATE, OPSTR_READ_PHONE_STATE);
-        sPermToOp.put(Manifest.permission.ADD_VOICEMAIL, OPSTR_ADD_VOICEMAIL);
-    }
+    private static HashMap<String, Integer> sOpStrToOp = new HashMap<>();
 
-    private static HashMap<String, Integer> sOpStrToOp = new HashMap<String, Integer>();
+    /**
+     * Mapping from a permission to the corresponding app op.
+     */
+    private static HashMap<String, Integer> sPermToOp = new HashMap<>();
 
     static {
         if (sOpToSwitch.length != _NUM_OP) {
@@ -874,6 +871,11 @@
                 sOpStrToOp.put(sOpToString[i], i);
             }
         }
+        for (int i=0; i<_NUM_OP; i++) {
+            if (sOpPerms[i] != null) {
+                sPermToOp.put(sOpPerms[i], i);
+            }
+        }
     }
 
     /**
@@ -922,6 +924,14 @@
     }
 
     /**
+     * Retrieve the app op code for a permission, or null if there is not one.
+     * @hide
+     */
+    public static int permissionToOpCode(String permission) {
+        return sPermToOp.get(permission);
+    }
+
+    /**
      * Retrieve whether the op allows the system (and system ui) to
      * bypass the user restriction.
      * @hide
@@ -1185,7 +1195,11 @@
      */
     @SystemApi
     public static String permissionToOp(String permission) {
-        return sPermToOp.get(permission);
+        final Integer opCode = sPermToOp.get(permission);
+        if (opCode == null) {
+            return null;
+        }
+        return sOpToString[opCode];
     }
 
     /**
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index cf9813f..9f71ea5 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2926,7 +2926,7 @@
      *         the user has already been set up.
      */
     @SystemApi
-    public boolean setActiveProfileOwner(ComponentName admin, String ownerName)
+    public boolean setActiveProfileOwner(ComponentName admin, @Deprecated String ownerName)
             throws IllegalArgumentException {
         if (mService != null) {
             try {
@@ -2992,8 +2992,8 @@
      * @throws IllegalArgumentException if admin is null, the package isn't installed, or the
      * preconditions mentioned are not met.
      */
-    public boolean setProfileOwner(ComponentName admin, String ownerName, int userHandle)
-            throws IllegalArgumentException {
+    public boolean setProfileOwner(ComponentName admin, @Deprecated String ownerName,
+            int userHandle) throws IllegalArgumentException {
         if (admin == null) {
             throw new NullPointerException("admin cannot be null");
         }
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index 00248cc..1205708 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -1053,6 +1053,20 @@
         }
     }
 
+    /**
+     * @hide
+     */
+    public boolean isBoundWidgetPackage(String packageName, int userId) {
+        if (mService == null) {
+            return false;
+        }
+        try {
+            return mService.isBoundWidgetPackage(packageName, userId);
+        } catch (RemoteException re) {
+            throw new RuntimeException("system server dead?", re);
+        }
+    }
+
     private boolean bindAppWidgetIdIfAllowed(int appWidgetId, int profileId,
             ComponentName provider, Bundle options) {
         if (mService == null) {
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 3044a94..9b4dcc6 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -34,6 +34,7 @@
 import android.os.ServiceManager;
 import android.app.ActivityThread;
 import android.os.SystemProperties;
+import android.provider.Settings;
 import android.os.Binder;
 import android.util.Log;
 import android.util.Pair;
@@ -389,7 +390,7 @@
      * @hide
      */
     public static final String ACTION_BLE_STATE_CHANGED =
-        "anrdoid.bluetooth.adapter.action.BLE_STATE_CHANGED";
+        "android.bluetooth.adapter.action.BLE_STATE_CHANGED";
 
     /**
      * Broadcast Action: The notifys Bluetooth ACL connected event. This will be
@@ -632,24 +633,6 @@
     }
 
     /**
-     * Returns true if LE only mode is enabled, that is apps
-     * have authorization to turn only BT ON and the calling
-     * app has privilage to do so
-     */
-    private boolean isLEAlwaysOnEnabled() {
-        boolean ret = false;
-        if (SystemProperties.getBoolean("ro.bluetooth.blealwayson", true) == true) {
-            Log.v(TAG, "LE always on mode is enabled");
-            // TODO: System API authorization check
-            ret = true;
-        } else {
-            Log.v(TAG, "LE always on mode is disabled");
-            ret = false;
-        }
-        return ret;
-    }
-
-    /**
      * Turns off Bluetooth LE which was earlier turned on by calling EnableBLE().
      *
      * <p> If the internal Adapter state is STATE_BLE_ON, this would trigger the transition
@@ -676,7 +659,7 @@
      * @hide
      */
     public boolean disableBLE() {
-        if (isLEAlwaysOnEnabled() != true) return false;
+        if (!isBleScanAlwaysAvailable()) return false;
 
         int state = getLeState();
         if (state == BluetoothAdapter.STATE_ON) {
@@ -738,7 +721,7 @@
      * @hide
      */
     public boolean enableBLE() {
-        if (isLEAlwaysOnEnabled() != true) return false;
+        if (!isBleScanAlwaysAvailable()) return false;
 
         if (isLeEnabled() == true) {
             if (DBG) Log.d(TAG, "enableBLE(): BT is already enabled..!");
@@ -1243,8 +1226,12 @@
      */
     @SystemApi
     public boolean isBleScanAlwaysAvailable() {
-        // TODO: implement after Settings UI change.
-        return false;
+        try {
+            return mManagerService.isBleScanAlwaysAvailable();
+        } catch (RemoteException e) {
+            Log.e(TAG, "remote expection when calling isBleScanAlwaysAvailable", e);
+            return false;
+        }
     }
 
     /**
diff --git a/core/java/android/bluetooth/IBluetoothManager.aidl b/core/java/android/bluetooth/IBluetoothManager.aidl
index 8d1ce99..0b81ee8 100644
--- a/core/java/android/bluetooth/IBluetoothManager.aidl
+++ b/core/java/android/bluetooth/IBluetoothManager.aidl
@@ -44,6 +44,8 @@
 
     String getAddress();
     String getName();
+
+    boolean isBleScanAlwaysAvailable();
     int updateBleAppCount(IBinder b, boolean enable);
     boolean isBleAppPresent();
 }
diff --git a/core/java/android/bluetooth/le/ScanSettings.java b/core/java/android/bluetooth/le/ScanSettings.java
index 123514e..dad486d 100644
--- a/core/java/android/bluetooth/le/ScanSettings.java
+++ b/core/java/android/bluetooth/le/ScanSettings.java
@@ -187,7 +187,7 @@
         mScanResultType = scanResultType;
         mReportDelayMillis = reportDelayMillis;
         mNumOfMatchesPerFilter = numOfMatchesPerFilter;
-        mMatchMode = numOfMatchesPerFilter;
+        mMatchMode = matchMode;
     }
 
     private ScanSettings(Parcel in) {
diff --git a/core/java/android/content/pm/IntentFilterVerificationInfo.java b/core/java/android/content/pm/IntentFilterVerificationInfo.java
index e50b0ff..96000dd 100644
--- a/core/java/android/content/pm/IntentFilterVerificationInfo.java
+++ b/core/java/android/content/pm/IntentFilterVerificationInfo.java
@@ -48,19 +48,18 @@
     private static final String ATTR_PACKAGE_NAME = "packageName";
     private static final String ATTR_STATUS = "status";
 
-    private ArrayList<String> mDomains;
+    private ArraySet<String> mDomains = new ArraySet<>();
     private String mPackageName;
     private int mMainStatus;
 
     public IntentFilterVerificationInfo() {
         mPackageName = null;
-        mDomains = new ArrayList<>();
         mMainStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
     }
 
     public IntentFilterVerificationInfo(String packageName, ArrayList<String> domains) {
         mPackageName = packageName;
-        mDomains = domains;
+        mDomains.addAll(domains);
         mMainStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
     }
 
@@ -73,14 +72,6 @@
         readFromParcel(source);
     }
 
-    public ArrayList<String> getDomains() {
-        return mDomains;
-    }
-
-    public ArraySet<String> getDomainsSet() {
-        return new ArraySet<>(mDomains);
-    }
-
     public String getPackageName() {
         return mPackageName;
     }
@@ -98,6 +89,14 @@
         }
     }
 
+    public ArraySet<String> getDomains() {
+        return mDomains;
+    }
+
+    public void setDomains(ArrayList<String> list) {
+        mDomains = new ArraySet<>(list);
+    }
+
     public String getDomainsString() {
         StringBuilder sb = new StringBuilder();
         for (String str : mDomains) {
@@ -145,7 +144,6 @@
         }
         mMainStatus = status;
 
-        mDomains = new ArrayList<>();
         int outerDepth = parser.getDepth();
         int type;
         while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
@@ -201,15 +199,16 @@
     private void readFromParcel(Parcel source) {
         mPackageName = source.readString();
         mMainStatus = source.readInt();
-        mDomains = new ArrayList<>();
-        source.readStringList(mDomains);
+        ArrayList<String> list = new ArrayList<>();
+        source.readStringList(list);
+        mDomains.addAll(list);
     }
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeString(mPackageName);
         dest.writeInt(mMainStatus);
-        dest.writeStringList(mDomains);
+        dest.writeStringList(new ArrayList<>(mDomains));
     }
 
     public static final Creator<IntentFilterVerificationInfo> CREATOR =
@@ -221,5 +220,4 @@
                     return new IntentFilterVerificationInfo[size];
                 }
             };
-
 }
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index 11037fd..22a9e9c 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -41,16 +41,19 @@
  */
 public class SystemSensorManager extends SensorManager {
     private static native void nativeClassInit();
-    private static native int nativeGetNextSensor(Sensor sensor, int next);
-    private static native int nativeEnableDataInjection(boolean enable);
+    private static native long nativeCreate(String opPackageName);
+    private static native int nativeGetNextSensor(long nativeInstance, Sensor sensor, int next);
+    private static native int nativeEnableDataInjection(long nativeInstance, boolean enable);
 
     private static boolean sSensorModuleInitialized = false;
-    private static final Object sSensorModuleLock = new Object();
-    private static final ArrayList<Sensor> sFullSensorsList = new ArrayList<Sensor>();
-    private static final SparseArray<Sensor> sHandleToSensor = new SparseArray<Sensor>();
     private static InjectEventQueue mInjectEventQueue = null;
     private static boolean mDataInjectionMode = false;
 
+    private final Object mLock = new Object();
+
+    private final ArrayList<Sensor> mFullSensorsList = new ArrayList<>();
+    private final SparseArray<Sensor> mHandleToSensor = new SparseArray<>();
+
     // Listener list
     private final HashMap<SensorEventListener, SensorEventQueue> mSensorListeners =
             new HashMap<SensorEventListener, SensorEventQueue>();
@@ -60,44 +63,44 @@
     // Looper associated with the context in which this instance was created.
     private final Looper mMainLooper;
     private final int mTargetSdkLevel;
-    private final String mPackageName;
+    private final Context mContext;
     private final boolean mHasDataInjectionPermissions;
+    private final long mNativeInstance;
 
     /** {@hide} */
     public SystemSensorManager(Context context, Looper mainLooper) {
         mMainLooper = mainLooper;
         mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion;
-        mPackageName = context.getPackageName();
-        synchronized(sSensorModuleLock) {
+        mContext = context;
+        mNativeInstance = nativeCreate(context.getOpPackageName());
+
+        synchronized(mLock) {
             if (!sSensorModuleInitialized) {
                 sSensorModuleInitialized = true;
-
                 nativeClassInit();
-
-                // initialize the sensor list
-                final ArrayList<Sensor> fullList = sFullSensorsList;
-                int i = 0;
-                do {
-                    Sensor sensor = new Sensor();
-                    i = nativeGetNextSensor(sensor, i);
-                    if (i>=0) {
-                        //Log.d(TAG, "found sensor: " + sensor.getName() +
-                        //        ", handle=" + sensor.getHandle());
-                        fullList.add(sensor);
-                        sHandleToSensor.append(sensor.getHandle(), sensor);
-                    }
-                } while (i>0);
             }
             mHasDataInjectionPermissions = context.checkSelfPermission(
                     Manifest.permission.HARDWARE_TEST) == PackageManager.PERMISSION_GRANTED;
         }
+
+        // initialize the sensor list
+        int i = 0;
+        while(true) {
+            Sensor sensor = new Sensor();
+            i = nativeGetNextSensor(mNativeInstance, sensor, i);
+            if (i <= 0) {
+                break;
+            }
+            mFullSensorsList.add(sensor);
+            mHandleToSensor.append(sensor.getHandle(), sensor);
+        }
     }
 
 
     /** @hide */
     @Override
     protected List<Sensor> getFullSensorList() {
-        return sFullSensorsList;
+        return mFullSensorsList;
     }
 
 
@@ -232,8 +235,8 @@
             throw new SecurityException("Permission denial. Calling enableDataInjection without "
                     + Manifest.permission.HARDWARE_TEST);
         }
-        synchronized (sSensorModuleLock) {
-            int ret = nativeEnableDataInjection(enable);
+        synchronized (mLock) {
+            int ret = nativeEnableDataInjection(mNativeInstance, enable);
             // The HAL does not support injection. Ignore.
             if (ret != 0) {
                 Log.e(TAG, "HAL does not support data injection");
@@ -255,7 +258,7 @@
             throw new SecurityException("Permission denial. Calling injectSensorData without "
                     + Manifest.permission.HARDWARE_TEST);
         }
-        synchronized (sSensorModuleLock) {
+        synchronized (mLock) {
             if (!mDataInjectionMode) {
                 Log.e(TAG, "Data injection mode not activated before calling injectSensorData");
                 return false;
@@ -284,15 +287,17 @@
      * SensorManager instance.
      */
     private static abstract class BaseEventQueue {
-        private native long nativeInitBaseEventQueue(WeakReference<BaseEventQueue> eventQWeak,
-               MessageQueue msgQ, float[] scratch, String packageName, int mode);
+        private static native long nativeInitBaseEventQueue(long nativeManager,
+                WeakReference<BaseEventQueue> eventQWeak, MessageQueue msgQ, float[] scratch,
+                String packageName, int mode, String opPackageName);
         private static native int nativeEnableSensor(long eventQ, int handle, int rateUs,
                 int maxBatchReportLatencyUs);
         private static native int nativeDisableSensor(long eventQ, int handle);
         private static native void nativeDestroySensorEventQueue(long eventQ);
         private static native int nativeFlushSensor(long eventQ);
         private static native int nativeInjectSensorData(long eventQ, int handle,
-                                                    float[] values,int accuracy, long timestamp);
+                float[] values,int accuracy, long timestamp);
+
         private long nSensorEventQueue;
         private final SparseBooleanArray mActiveSensors = new SparseBooleanArray();
         protected final SparseIntArray mSensorAccuracies = new SparseIntArray();
@@ -305,8 +310,9 @@
         protected static final int OPERATING_MODE_DATA_INJECTION = 1;
 
         BaseEventQueue(Looper looper, SystemSensorManager manager, int mode) {
-            nSensorEventQueue = nativeInitBaseEventQueue(new WeakReference<BaseEventQueue>(this),
-                    looper.getQueue(), mScratch, manager.mPackageName, mode);
+            nSensorEventQueue = nativeInitBaseEventQueue(manager.mNativeInstance,
+                    new WeakReference<>(this), looper.getQueue(), mScratch,
+                    manager.mContext.getPackageName(), mode, manager.mContext.getOpPackageName());
             mCloseGuard.open("dispose");
             mManager = manager;
         }
@@ -339,7 +345,7 @@
             for (int i=0 ; i<mActiveSensors.size(); i++) {
                 if (mActiveSensors.valueAt(i) == true) {
                     int handle = mActiveSensors.keyAt(i);
-                    Sensor sensor = sHandleToSensor.get(handle);
+                    Sensor sensor = mManager.mHandleToSensor.get(handle);
                     if (sensor != null) {
                         disableSensor(sensor);
                         mActiveSensors.put(handle, false);
@@ -452,7 +458,7 @@
         @Override
         protected void dispatchSensorEvent(int handle, float[] values, int inAccuracy,
                 long timestamp) {
-            final Sensor sensor = sHandleToSensor.get(handle);
+            final Sensor sensor = mManager.mHandleToSensor.get(handle);
             SensorEvent t = null;
             synchronized (mSensorsEvents) {
                 t = mSensorsEvents.get(handle);
@@ -481,7 +487,7 @@
         @SuppressWarnings("unused")
         protected void dispatchFlushCompleteEvent(int handle) {
             if (mListener instanceof SensorEventListener2) {
-                final Sensor sensor = sHandleToSensor.get(handle);
+                final Sensor sensor = mManager.mHandleToSensor.get(handle);
                 ((SensorEventListener2)mListener).onFlushCompleted(sensor);
             }
             return;
@@ -519,7 +525,7 @@
         @Override
         protected void dispatchSensorEvent(int handle, float[] values, int accuracy,
                 long timestamp) {
-            final Sensor sensor = sHandleToSensor.get(handle);
+            final Sensor sensor = mManager.mHandleToSensor.get(handle);
             TriggerEvent t = null;
             synchronized (mTriggerEvents) {
                 t = mTriggerEvents.get(handle);
@@ -546,7 +552,7 @@
         }
     }
 
-    static final class InjectEventQueue extends BaseEventQueue {
+    final class InjectEventQueue extends BaseEventQueue {
         public InjectEventQueue(Looper looper, SystemSensorManager manager) {
             super(looper, manager, OPERATING_MODE_DATA_INJECTION);
         }
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index f6791a4..e9564b3 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -580,7 +580,8 @@
          * indicating that the camera device is in use already.
          *
          * <p>
-         * This error can be produced when opening the camera fails.
+         * This error can be produced when opening the camera fails due to the camera
+        *  being used by a higher-priority camera API client.
          * </p>
          *
          * @see #onError
@@ -678,7 +679,7 @@
          * {@link CameraAccessException}. The disconnection could be due to a
          * change in security policy or permissions; the physical disconnection
          * of a removable camera device; or the camera being needed for a
-         * higher-priority use case.</p>
+         * higher-priority camera API client.</p>
          *
          * <p>There may still be capture callbacks that are invoked
          * after this method is called, or new image buffers that are delivered
@@ -688,8 +689,9 @@
          * about the disconnection.</p>
          *
          * <p>You should clean up the camera with {@link CameraDevice#close} after
-         * this happens, as it is not recoverable until opening the camera again
-         * after it becomes {@link CameraManager.AvailabilityCallback#onCameraAvailable available}.
+         * this happens, as it is not recoverable until the camera can be opened
+         * again. For most use cases, this will be when the camera again becomes
+         * {@link CameraManager.AvailabilityCallback#onCameraAvailable available}.
          * </p>
          *
          * @param camera the device that has been disconnected
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 1a00a05..e2d2f61 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -77,8 +77,8 @@
     }
 
     /**
-     * Return the list of currently connected camera devices by
-     * identifier.
+     * Return the list of currently connected camera devices by identifier, including
+     * cameras that may be in use by other camera API clients.
      *
      * <p>Non-removable cameras use integers starting at 0 for their
      * identifiers, while removable cameras have a unique identifier for each
@@ -103,6 +103,11 @@
      * <p>The first time a callback is registered, it is immediately called
      * with the availability status of all currently known camera devices.</p>
      *
+     * <p>{@link AvailabilityCallback#onCameraUnavailable(String)} will be called whenever a camera
+     * device is opened by any camera API client. As of API level 23, other camera API clients may
+     * still be able to open such a camera device, evicting the existing client if they have higher
+     * priority than the existing client of a camera device. See open() for more details.</p>
+     *
      * <p>Since this callback will be registered with the camera service, remember to unregister it
      * once it is no longer needed; otherwise the callback will continue to receive events
      * indefinitely and it may prevent other resources from being released. Specifically, the
@@ -259,14 +264,14 @@
     }
 
     /**
-     * Helper for openning a connection to a camera with the given ID.
+     * Helper for opening a connection to a camera with the given ID.
      *
      * @param cameraId The unique identifier of the camera device to open
      * @param callback The callback for the camera. Must not be null.
      * @param handler  The handler to invoke the callback on. Must not be null.
      *
      * @throws CameraAccessException if the camera is disabled by device policy,
-     * or too many camera devices are already open, or the cameraId does not match
+     * too many camera devices are already open, or the cameraId does not match
      * any currently available camera device.
      *
      * @throws SecurityException if the application does not have permission to
@@ -330,7 +335,8 @@
                         deviceImpl.setRemoteFailure(e);
 
                         if (e.getReason() == CameraAccessException.CAMERA_DISABLED ||
-                                e.getReason() == CameraAccessException.CAMERA_DISCONNECTED) {
+                                e.getReason() == CameraAccessException.CAMERA_DISCONNECTED ||
+                                e.getReason() == CameraAccessException.CAMERA_IN_USE) {
                             // Per API docs, these failures call onError and throw
                             throw e.asChecked();
                         }
@@ -369,7 +375,19 @@
      * <p>Use {@link #getCameraIdList} to get the list of available camera
      * devices. Note that even if an id is listed, open may fail if the device
      * is disconnected between the calls to {@link #getCameraIdList} and
-     * {@link #openCamera}.</p>
+     * {@link #openCamera}, or if a higher-priority camera API client begins using the
+     * camera device.</p>
+     *
+     * <p>As of API level 23, devices for which the
+     * {@link AvailabilityCallback#onCameraUnavailable(String)} callback has been called due to the
+     * device being in use by a lower-priority, background camera API client can still potentially
+     * be opened by calling this method when the calling camera API client has a higher priority
+     * than the current camera API client using this device.  In general, if the top, foreground
+     * activity is running within your application process, your process will be given the highest
+     * priority when accessing the camera, and this method will succeed even if the camera device is
+     * in use by another camera API client. Any lower-priority application that loses control of the
+     * camera in this way will receive an
+     * {@link android.hardware.camera2.CameraDevice.StateCallback#onDisconnected} callback.</p>
      *
      * <p>Once the camera is successfully opened, {@link CameraDevice.StateCallback#onOpened} will
      * be invoked with the newly opened {@link CameraDevice}. The camera device can then be set up
@@ -401,7 +419,7 @@
      *             {@code null} to use the current thread's {@link android.os.Looper looper}.
      *
      * @throws CameraAccessException if the camera is disabled by device policy,
-     * or the camera has become or was disconnected.
+     * has been disconnected, or is being used by a higher-priority camera API client.
      *
      * @throws IllegalArgumentException if cameraId or the callback was null,
      * or the cameraId does not match any currently or previously available
@@ -477,8 +495,7 @@
     }
 
     /**
-     * A callback for camera devices becoming available or
-     * unavailable to open.
+     * A callback for camera devices becoming available or unavailable to open.
      *
      * <p>Cameras become available when they are no longer in use, or when a new
      * removable camera is connected. They become unavailable when some
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index c531e7e..2d63e3f 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -341,7 +341,8 @@
      * one.  This is used by applications needing to talk to the carrier's
      * Multimedia Messaging Service servers.
      *
-     * @deprecated Applications should instead use {@link #requestNetwork} to request a network that
+     * @deprecated Applications should instead use
+     *         {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request a network that
      *         provides the {@link NetworkCapabilities#NET_CAPABILITY_MMS} capability.
      */
     public static final int TYPE_MOBILE_MMS  = 2;
@@ -351,7 +352,8 @@
      * one.  This is used by applications needing to talk to the carrier's
      * Secure User Plane Location servers for help locating the device.
      *
-     * @deprecated Applications should instead use {@link #requestNetwork} to request a network that
+     * @deprecated Applications should instead use
+     *         {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request a network that
      *         provides the {@link NetworkCapabilities#NET_CAPABILITY_SUPL} capability.
      */
     public static final int TYPE_MOBILE_SUPL = 3;
@@ -367,7 +369,8 @@
      * same network interface as {@link #TYPE_MOBILE} but the routing setup
      * is different.
      *
-     * @deprecated Applications should instead use {@link #requestNetwork} to request a network that
+     * @deprecated Applications should instead use
+     *         {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request a network that
      *         uses the {@link NetworkCapabilities#TRANSPORT_CELLULAR} transport.
      */
     public static final int TYPE_MOBILE_HIPRI = 5;
@@ -910,7 +913,8 @@
      * implementation+feature combination, except that the value {@code -1}
      * always indicates failure.
      *
-     * @deprecated Deprecated in favor of the cleaner {@link #requestNetwork} api.
+     * @deprecated Deprecated in favor of the cleaner
+     *             {@link #requestNetwork(NetworkRequest, NetworkCallback)} API.
      * @removed
      */
     public int startUsingNetworkFeature(int networkType, String feature) {
@@ -958,7 +962,7 @@
      * implementation+feature combination, except that the value {@code -1}
      * always indicates failure.
      *
-     * @deprecated Deprecated in favor of the cleaner {@link #requestNetwork} api.
+     * @deprecated Deprecated in favor of the cleaner {@link unregisterNetworkCallback} API.
      * @removed
      */
     public int stopUsingNetworkFeature(int networkType, String feature) {
@@ -1236,8 +1240,9 @@
      * @param hostAddress the IP address of the host to which the route is desired
      * @return {@code true} on success, {@code false} on failure
      *
-     * @deprecated Deprecated in favor of the {@link #requestNetwork},
-     *             {@link #bindProcessToNetwork} and {@link Network#getSocketFactory} api.
+     * @deprecated Deprecated in favor of the
+     *             {@link #requestNetwork(NetworkRequest, NetworkCallback)},
+     *             {@link #bindProcessToNetwork} and {@link Network#getSocketFactory} API.
      * @removed
      */
     public boolean requestRouteToHost(int networkType, int hostAddress) {
@@ -1256,7 +1261,7 @@
      * @return {@code true} on success, {@code false} on failure
      * @hide
      * @deprecated Deprecated in favor of the {@link #requestNetwork} and
-     *             {@link #bindProcessToNetwork} api.
+     *             {@link #bindProcessToNetwork} API.
      * @removed
      */
     public boolean requestRouteToHostAddress(int networkType, InetAddress hostAddress) {
@@ -2144,14 +2149,22 @@
         public static final int CANCELED     = 8;
 
         /**
-         * @hide
-         * Called whenever the framework connects to a network that it may use to
-         * satisfy this request
+         * Called when the framework connects to a new network to evaluate whether it satisfies this
+         * request. If evaluation succeeds, this callback may be followed by an {@link #onAvailable}
+         * callback. There is no guarantee that this new network will satisfy any requests, or that
+         * the network will stay connected for longer than the time necessary to evaluate it.
+         * <p>
+         * Most applications <b>should not</b> act on this callback, and should instead use
+         * {@link #onAvailable}. This callback is intended for use by applications that can assist
+         * the framework in properly evaluating the network &mdash; for example, an application that
+         * can automatically log in to a captive portal without user intervention.
+         *
+         * @param network The {@link Network} of the network that is being evaluated.
          */
         public void onPreCheck(Network network) {}
 
         /**
-         * Called when the framework connects and has declared new network ready for use.
+         * Called when the framework connects and has declared a new network ready for use.
          * This callback may be called more than once if the {@link Network} that is
          * satisfying the request changes.
          *
@@ -2251,116 +2264,82 @@
         @Override
         public void handleMessage(Message message) {
             Log.d(TAG, "CM callback handler got msg " + message.what);
+            NetworkRequest request = (NetworkRequest) getObject(message, NetworkRequest.class);
+            Network network = (Network) getObject(message, Network.class);
             switch (message.what) {
                 case CALLBACK_PRECHECK: {
-                    NetworkRequest request = (NetworkRequest)getObject(message,
-                            NetworkRequest.class);
-                    NetworkCallback callbacks = getCallbacks(request);
-                    if (callbacks != null) {
-                        callbacks.onPreCheck((Network)getObject(message, Network.class));
-                    } else {
-                        Log.e(TAG, "callback not found for PRECHECK message");
+                    NetworkCallback callback = getCallback(request, "PRECHECK");
+                    if (callback != null) {
+                        callback.onPreCheck(network);
                     }
                     break;
                 }
                 case CALLBACK_AVAILABLE: {
-                    NetworkRequest request = (NetworkRequest)getObject(message,
-                            NetworkRequest.class);
-                    NetworkCallback callbacks = getCallbacks(request);
-                    if (callbacks != null) {
-                        callbacks.onAvailable((Network)getObject(message, Network.class));
-                    } else {
-                        Log.e(TAG, "callback not found for AVAILABLE message");
+                    NetworkCallback callback = getCallback(request, "AVAILABLE");
+                    if (callback != null) {
+                        callback.onAvailable(network);
                     }
                     break;
                 }
                 case CALLBACK_LOSING: {
-                    NetworkRequest request = (NetworkRequest)getObject(message,
-                            NetworkRequest.class);
-                    NetworkCallback callbacks = getCallbacks(request);
-                    if (callbacks != null) {
-                        callbacks.onLosing((Network)getObject(message, Network.class),
-                                message.arg1);
-                    } else {
-                        Log.e(TAG, "callback not found for LOSING message");
+                    NetworkCallback callback = getCallback(request, "LOSING");
+                    if (callback != null) {
+                        callback.onLosing(network, message.arg1);
                     }
                     break;
                 }
                 case CALLBACK_LOST: {
-                    NetworkRequest request = (NetworkRequest)getObject(message,
-                            NetworkRequest.class);
-
-                    NetworkCallback callbacks = getCallbacks(request);
-                    if (callbacks != null) {
-                        callbacks.onLost((Network)getObject(message, Network.class));
-                    } else {
-                        Log.e(TAG, "callback not found for LOST message");
+                    NetworkCallback callback = getCallback(request, "LOST");
+                    if (callback != null) {
+                        callback.onLost(network);
                     }
                     break;
                 }
                 case CALLBACK_UNAVAIL: {
-                    NetworkRequest request = (NetworkRequest)getObject(message,
-                            NetworkRequest.class);
-                    NetworkCallback callbacks = null;
-                    synchronized(mCallbackMap) {
-                        callbacks = mCallbackMap.get(request);
-                    }
-                    if (callbacks != null) {
-                        callbacks.onUnavailable();
-                    } else {
-                        Log.e(TAG, "callback not found for UNAVAIL message");
+                    NetworkCallback callback = getCallback(request, "UNAVAIL");
+                    if (callback != null) {
+                        callback.onUnavailable();
                     }
                     break;
                 }
                 case CALLBACK_CAP_CHANGED: {
-                    NetworkRequest request = (NetworkRequest)getObject(message,
-                            NetworkRequest.class);
-                    NetworkCallback callbacks = getCallbacks(request);
-                    if (callbacks != null) {
-                        Network network = (Network)getObject(message, Network.class);
+                    NetworkCallback callback = getCallback(request, "CAP_CHANGED");
+                    if (callback != null) {
                         NetworkCapabilities cap = (NetworkCapabilities)getObject(message,
                                 NetworkCapabilities.class);
 
-                        callbacks.onCapabilitiesChanged(network, cap);
-                    } else {
-                        Log.e(TAG, "callback not found for CAP_CHANGED message");
+                        callback.onCapabilitiesChanged(network, cap);
                     }
                     break;
                 }
                 case CALLBACK_IP_CHANGED: {
-                    NetworkRequest request = (NetworkRequest)getObject(message,
-                            NetworkRequest.class);
-                    NetworkCallback callbacks = getCallbacks(request);
-                    if (callbacks != null) {
-                        Network network = (Network)getObject(message, Network.class);
+                    NetworkCallback callback = getCallback(request, "IP_CHANGED");
+                    if (callback != null) {
                         LinkProperties lp = (LinkProperties)getObject(message,
                                 LinkProperties.class);
 
-                        callbacks.onLinkPropertiesChanged(network, lp);
-                    } else {
-                        Log.e(TAG, "callback not found for IP_CHANGED message");
+                        callback.onLinkPropertiesChanged(network, lp);
                     }
                     break;
                 }
                 case CALLBACK_RELEASED: {
-                    NetworkRequest req = (NetworkRequest)getObject(message, NetworkRequest.class);
-                    NetworkCallback callbacks = null;
+                    NetworkCallback callback = null;
                     synchronized(mCallbackMap) {
-                        callbacks = mCallbackMap.remove(req);
+                        callback = mCallbackMap.remove(request);
                     }
-                    if (callbacks != null) {
+                    if (callback != null) {
                         synchronized(mRefCount) {
                             if (mRefCount.decrementAndGet() == 0) {
                                 getLooper().quit();
                             }
                         }
                     } else {
-                        Log.e(TAG, "callback not found for CANCELED message");
+                        Log.e(TAG, "callback not found for RELEASED message");
                     }
                     break;
                 }
                 case CALLBACK_EXIT: {
-                    Log.d(TAG, "Listener quiting");
+                    Log.d(TAG, "Listener quitting");
                     getLooper().quit();
                     break;
                 }
@@ -2374,10 +2353,16 @@
         private Object getObject(Message msg, Class c) {
             return msg.getData().getParcelable(c.getSimpleName());
         }
-        private NetworkCallback getCallbacks(NetworkRequest req) {
+
+        private NetworkCallback getCallback(NetworkRequest req, String name) {
+            NetworkCallback callback;
             synchronized(mCallbackMap) {
-                return mCallbackMap.get(req);
+                callback = mCallbackMap.get(req);
             }
+            if (callback == null) {
+                Log.e(TAG, "callback not found for " + name + " message");
+            }
+            return callback;
         }
     }
 
@@ -2601,10 +2586,10 @@
 
     /**
      * Unregisters callbacks about and possibly releases networks originating from
-     * {@link #requestNetwork} and {@link #registerNetworkCallback} calls.  If the
-     * given {@code NetworkCallback} had previously been used with {@code #requestNetwork},
-     * any networks that had been connected to only to satisfy that request will be
-     * disconnected.
+     * {@link #requestNetwork(NetworkRequest, NetworkCallback)} and {@link #registerNetworkCallback}
+     * calls.  If the given {@code NetworkCallback} had previously been used with
+     * {@code #requestNetwork}, any networks that had been connected to only to satisfy that request
+     * will be disconnected.
      *
      * @param networkCallback The {@link NetworkCallback} used when making the request.
      */
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 8c8bfab..ab70485 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -37,6 +37,11 @@
      * @hide
      */
     public NetworkCapabilities() {
+        clearAll();
+        mNetworkCapabilities =
+                (1 << NET_CAPABILITY_NOT_RESTRICTED) |
+                (1 << NET_CAPABILITY_TRUSTED) |
+                (1 << NET_CAPABILITY_NOT_VPN);
     }
 
     public NetworkCapabilities(NetworkCapabilities nc) {
@@ -50,11 +55,21 @@
     }
 
     /**
+     * Completely clears the contents of this object, removing even the capabilities that are set
+     * by default when the object is constructed.
+     * @hide
+     */
+    public void clearAll() {
+        mNetworkCapabilities = mTransportTypes = 0;
+        mLinkUpBandwidthKbps = mLinkDownBandwidthKbps = 0;
+        mNetworkSpecifier = null;
+    }
+
+    /**
      * Represents the network's capabilities.  If any are specified they will be satisfied
      * by any Network that matches all of them.
      */
-    private long mNetworkCapabilities = (1 << NET_CAPABILITY_NOT_RESTRICTED) |
-            (1 << NET_CAPABILITY_TRUSTED) | (1 << NET_CAPABILITY_NOT_VPN);
+    private long mNetworkCapabilities;
 
     /**
      * Indicates this is a network that has the ability to reach the
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index e3e16eb..8e0584a 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.os.storage.StorageManager;
 import android.os.storage.StorageVolume;
+import android.text.TextUtils;
 import android.util.Log;
 
 import java.io.File;
@@ -242,6 +243,15 @@
         return DATA_DIRECTORY;
     }
 
+    /** {@hide} */
+    public static File getDataAppDirectory(String volumeUuid) {
+        if (TextUtils.isEmpty(volumeUuid)) {
+            return new File("/data/app");
+        } else {
+            return new File("/mnt/expand/" + volumeUuid + "/app");
+        }
+    }
+
     /**
      * Return the primary external storage directory. This directory may not
      * currently be accessible if it has been mounted by the user on their
diff --git a/core/java/android/os/IPermissionController.aidl b/core/java/android/os/IPermissionController.aidl
index 0cc1603..5e8590a 100644
--- a/core/java/android/os/IPermissionController.aidl
+++ b/core/java/android/os/IPermissionController.aidl
@@ -21,4 +21,5 @@
 interface IPermissionController {
     boolean checkPermission(String permission, int pid, int uid);
     String[] getPackagesForUid(int uid);
+    boolean isRuntimePermission(String permission);
 }
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 8c1f44f..1273772b 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -502,7 +502,25 @@
      * {@SystemApi}
      */
     public final void writeBlob(byte[] b) {
-        nativeWriteBlob(mNativePtr, b, 0, (b != null) ? b.length : 0);
+        writeBlob(b, 0, (b != null) ? b.length : 0);
+    }
+
+    /**
+     * Write a blob of data into the parcel at the current {@link #dataPosition},
+     * growing {@link #dataCapacity} if needed.
+     * @param b Bytes to place into the parcel.
+     * @param offset Index of first byte to be written.
+     * @param len Number of bytes to write.
+     * {@hide}
+     * {@SystemApi}
+     */
+    public final void writeBlob(byte[] b, int offset, int len) {
+        if (b == null) {
+            writeInt(-1);
+            return;
+        }
+        Arrays.checkOffsetAndCount(b.length, offset, len);
+        nativeWriteBlob(mNativePtr, b, offset, len);
     }
 
     /**
diff --git a/core/java/android/service/voice/VoiceInteractionServiceInfo.java b/core/java/android/service/voice/VoiceInteractionServiceInfo.java
index 4bc97c9..997d586 100644
--- a/core/java/android/service/voice/VoiceInteractionServiceInfo.java
+++ b/core/java/android/service/voice/VoiceInteractionServiceInfo.java
@@ -43,7 +43,7 @@
     private String mSessionService;
     private String mRecognitionService;
     private String mSettingsActivity;
-    private boolean mSupportsAssistGesture;
+    private boolean mSupportsAssist;
 
     public VoiceInteractionServiceInfo(PackageManager pm, ComponentName comp)
             throws PackageManager.NameNotFoundException {
@@ -95,8 +95,8 @@
                     com.android.internal.R.styleable.VoiceInteractionService_recognitionService);
             mSettingsActivity = array.getString(
                     com.android.internal.R.styleable.VoiceInteractionService_settingsActivity);
-            mSupportsAssistGesture = array.getBoolean(
-                    com.android.internal.R.styleable.VoiceInteractionService_supportsAssistGesture,
+            mSupportsAssist = array.getBoolean(
+                    com.android.internal.R.styleable.VoiceInteractionService_supportsAssist,
                     false);
             array.recycle();
             if (mSessionService == null) {
@@ -145,7 +145,7 @@
         return mSettingsActivity;
     }
 
-    public boolean getSupportsAssistGesture() {
-        return mSupportsAssistGesture;
+    public boolean getSupportsAssist() {
+        return mSupportsAssist;
     }
 }
diff --git a/core/java/android/view/GhostView.java b/core/java/android/view/GhostView.java
index d58e7c0..bc38e1a 100644
--- a/core/java/android/view/GhostView.java
+++ b/core/java/android/view/GhostView.java
@@ -41,7 +41,7 @@
         final ViewGroup parent = (ViewGroup) mView.getParent();
         setGhostedVisibility(View.INVISIBLE);
         parent.mRecreateDisplayList = true;
-        parent.getDisplayList();
+        parent.updateDisplayListIfDirty();
     }
 
     @Override
@@ -49,7 +49,7 @@
         if (canvas instanceof DisplayListCanvas) {
             DisplayListCanvas dlCanvas = (DisplayListCanvas) canvas;
             mView.mRecreateDisplayList = true;
-            RenderNode renderNode = mView.getDisplayList();
+            RenderNode renderNode = mView.updateDisplayListIfDirty();
             if (renderNode.isValid()) {
                 dlCanvas.insertReorderBarrier(); // enable shadow for this rendernode
                 dlCanvas.drawRenderNode(renderNode);
@@ -84,7 +84,7 @@
             final ViewGroup parent = (ViewGroup) mView.getParent();
             if (parent != null) {
                 parent.mRecreateDisplayList = true;
-                parent.getDisplayList();
+                parent.updateDisplayListIfDirty();
             }
         }
     }
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 6db46e9..85b22fb 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -246,6 +246,9 @@
             mSurface = null;
             mLayer = null;
 
+            // Make sure if/when new layer gets re-created, transform matrix will
+            // be re-applied.
+            mMatrixChanged = true;
             mHadSurface = true;
         }
     }
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 87d5d9a..390d81d 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -269,7 +269,7 @@
         view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED)
                 == View.PFLAG_INVALIDATED;
         view.mPrivateFlags &= ~View.PFLAG_INVALIDATED;
-        view.getDisplayList();
+        view.updateDisplayListIfDirty();
         view.mRecreateDisplayList = false;
     }
 
@@ -285,7 +285,7 @@
                 callbacks.onHardwarePreDraw(canvas);
 
                 canvas.insertReorderBarrier();
-                canvas.drawRenderNode(view.getDisplayList());
+                canvas.drawRenderNode(view.updateDisplayListIfDirty());
                 canvas.insertInorderBarrier();
 
                 callbacks.onHardwarePostDraw(canvas);
@@ -360,7 +360,7 @@
     @Override
     boolean copyLayerInto(final HardwareLayer layer, final Bitmap bitmap) {
         return nCopyLayerInto(mNativeProxy,
-                layer.getDeferredLayerUpdater(), bitmap.getSkBitmap());
+                layer.getDeferredLayerUpdater(), bitmap);
     }
 
     @Override
@@ -531,7 +531,7 @@
 
     private static native long nCreateTextureLayer(long nativeProxy);
     private static native void nBuildLayer(long nativeProxy, long node);
-    private static native boolean nCopyLayerInto(long nativeProxy, long layer, long bitmap);
+    private static native boolean nCopyLayerInto(long nativeProxy, long layer, Bitmap bitmap);
     private static native void nPushLayerUpdate(long nativeProxy, long layer);
     private static native void nCancelLayerUpdate(long nativeProxy, long layer);
     private static native void nDetachSurfaceTexture(long nativeProxy, long layer);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 81ad5ad..963b7a6 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -11091,25 +11091,34 @@
     }
 
     /**
-     * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
-     * completely transparent and 1 means the view is completely opaque.</p>
+     * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
+     * completely transparent and 1 means the view is completely opaque.
      *
-     * <p> Note that setting alpha to a translucent value (0 < alpha < 1) can have significant
-     * performance implications, especially for large views. It is best to use the alpha property
-     * sparingly and transiently, as in the case of fading animations.</p>
+     * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
+     * can have significant performance implications, especially for large views. It is best to use
+     * the alpha property sparingly and transiently, as in the case of fading animations.</p>
      *
      * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
      * strongly recommended for performance reasons to either override
-     * {@link #hasOverlappingRendering()} to return false if appropriate, or setting a
-     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view.</p>
+     * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
+     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
+     * of the animation. On versions {@link android.os.Build.VERSION_CODES#MNC} and below,
+     * the default path for rendering an unlayered View with alpha could add multiple milliseconds
+     * of rendering cost, even for simple or small views. Starting with
+     * {@link android.os.Build.VERSION_CODES#MNC}, {@link #LAYER_TYPE_HARDWARE} is automatically
+     * applied to the view at the rendering level.</p>
      *
      * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
      * responsible for applying the opacity itself.</p>
      *
-     * <p>Note that if the view is backed by a
-     * {@link #setLayerType(int, android.graphics.Paint) layer} and is associated with a
-     * {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an alpha value less than
-     * 1.0 will supersede the alpha of the layer paint.</p>
+     * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
+     * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
+     * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
+     * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
+     *
+     * <p>Starting with {@link android.os.Build.VERSION_CODES#MNC}, setting a translucent alpha
+     * value will clip a View to its bounds, unless the View returns <code>false</code> from
+     * {@link #hasOverlappingRendering}.</p>
      *
      * @param alpha The opacity of the view.
      *
@@ -14702,11 +14711,16 @@
         return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
     }
 
-    private void updateDisplayListIfDirty() {
+    /**
+     * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
+     * @hide
+     */
+    @NonNull
+    public RenderNode updateDisplayListIfDirty() {
         final RenderNode renderNode = mRenderNode;
         if (!canHaveDisplayList()) {
             // can't populate RenderNode, don't try
-            return;
+            return renderNode;
         }
 
         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
@@ -14720,7 +14734,7 @@
                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                 dispatchGetDisplayList();
 
-                return; // no work needed
+                return renderNode; // no work needed
             }
 
             // If we got here, we're recreating it. Mark it as such to ensure that
@@ -14769,19 +14783,7 @@
             mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
         }
-    }
-
-    /**
-     * Returns a RenderNode with View draw content recorded, which can be
-     * used to draw this view again without executing its draw method.
-     *
-     * @return A RenderNode ready to replay, or null if caching is not enabled.
-     *
-     * @hide
-     */
-    public RenderNode getDisplayList() {
-        updateDisplayListIfDirty();
-        return mRenderNode;
+        return renderNode;
     }
 
     private void resetDisplayList() {
@@ -15543,7 +15545,7 @@
         if (drawingWithRenderNode) {
             // Delay getting the display list until animation-driven alpha values are
             // set up and possibly passed on to the view
-            renderNode = getDisplayList();
+            renderNode = updateDisplayListIfDirty();
             if (!renderNode.isValid()) {
                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
                 // to getDisplayList(), the display list will be marked invalid and we should not
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index d0d4201..ef57dc3 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3524,10 +3524,9 @@
     }
 
     private void recreateChildDisplayList(View child) {
-        child.mRecreateDisplayList = (child.mPrivateFlags & PFLAG_INVALIDATED)
-                == PFLAG_INVALIDATED;
+        child.mRecreateDisplayList = (child.mPrivateFlags & PFLAG_INVALIDATED) != 0;
         child.mPrivateFlags &= ~PFLAG_INVALIDATED;
-        child.getDisplayList();
+        child.updateDisplayListIfDirty();
         child.mRecreateDisplayList = false;
     }
 
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 4158340..fda6e63 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2322,10 +2322,8 @@
      * @hide
      */
     void outputDisplayList(View view) {
-        RenderNode renderNode = view.getDisplayList();
-        if (renderNode != null) {
-            renderNode.output();
-        }
+        RenderNode renderNode = view.updateDisplayListIfDirty();
+        renderNode.output();
     }
 
     /**
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index c9d9a8c..1df43d0 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -3638,11 +3638,8 @@
 
         startNestedScroll(SCROLL_AXIS_VERTICAL);
 
-        if (mFastScroll != null) {
-            boolean intercepted = mFastScroll.onTouchEvent(ev);
-            if (intercepted) {
-                return true;
-            }
+        if (mFastScroll != null && mFastScroll.onTouchEvent(ev)) {
+            return true;
         }
 
         initVelocityTrackerIfNotExists();
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 35e7389..9b36b84 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -578,7 +578,12 @@
     }
 
     private void hideCursorControllers() {
-        if (mSuggestionsPopupWindow != null && !mSuggestionsPopupWindow.isShowingUp()) {
+        // When mTextView is not ExtractEditText, we need to distinguish two kinds of focus-lost.
+        // One is the true focus lost where suggestions pop-up (if any) should be dismissed, and the
+        // other is an side effect of showing the suggestions pop-up itself. We use isShowingUp()
+        // to distinguish one from the other.
+        if (mSuggestionsPopupWindow != null && ((mTextView instanceof ExtractEditText) ||
+                !mSuggestionsPopupWindow.isShowingUp())) {
             // Should be done before hide insertion point controller since it triggers a show of it
             mSuggestionsPopupWindow.hide();
         }
@@ -1397,12 +1402,11 @@
             InputMethodManager imm = InputMethodManager.peekInstance();
             if (imm != null) {
                 if (imm.isActive(mTextView)) {
-                    boolean reported = false;
                     if (ims.mContentChanged || ims.mSelectionModeChanged) {
                         // We are in extract mode and the content has changed
                         // in some way... just report complete new text to the
                         // input method.
-                        reported = reportExtractedText();
+                        reportExtractedText();
                     }
                 }
             }
@@ -1919,10 +1923,6 @@
         mSuggestionsPopupWindow.show();
     }
 
-    boolean areSuggestionsShown() {
-        return mSuggestionsPopupWindow != null && mSuggestionsPopupWindow.isShowing();
-    }
-
     void onScrollChanged() {
         if (mPositionListener != null) {
             mPositionListener.onScrollChanged();
@@ -4620,8 +4620,6 @@
     }
 
     static class InputMethodState {
-        Rect mCursorRectInWindow = new Rect();
-        float[] mTmpOffset = new float[2];
         ExtractedTextRequest mExtractedTextRequest;
         final ExtractedText mExtractedText = new ExtractedText();
         int mBatchEditNesting;
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index 552b274..f06f3c21 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -1389,7 +1389,8 @@
                     // to intercept events. If it does, we will receive a CANCEL
                     // event.
                     if (!mList.isInScrollingContainer()) {
-                        beginDrag();
+                        // This will get dispatched to onTouchEvent(). Start
+                        // dragging there.
                         return true;
                     }
 
@@ -1406,6 +1407,8 @@
                     final float pos = getPosFromMotionEvent(mInitialTouchY);
                     scrollTo(pos);
 
+                    // This may get dispatched to onTouchEvent(), but it
+                    // doesn't really matter since we'll already be in a drag.
                     return onTouchEvent(ev);
                 }
                 break;
@@ -1440,6 +1443,15 @@
         }
 
         switch (me.getActionMasked()) {
+            case MotionEvent.ACTION_DOWN: {
+                if (isPointInside(me.getX(), me.getY())) {
+                    if (!mList.isInScrollingContainer()) {
+                        beginDrag();
+                        return true;
+                    }
+                }
+            } break;
+
             case MotionEvent.ACTION_UP: {
                 if (mPendingDrag >= 0) {
                     // Allow a tap to scroll.
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index 99bf9f3..86c1b2f 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -30,6 +30,7 @@
     void startWatchingMode(int op, String packageName, IAppOpsCallback callback);
     void stopWatchingMode(IAppOpsCallback callback);
     IBinder getToken(IBinder clientToken);
+    int permissionToOpCode(String permission);
 
     // Remaining methods are only used in Java.
     int checkPackage(int uid, String packageName);
@@ -42,5 +43,4 @@
 
     void setUserRestrictions(in Bundle restrictions, int userHandle);
     void removeUser(int userHandle);
-
 }
diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
index d149c5b9..4c6db24 100644
--- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
+++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
@@ -105,5 +105,5 @@
      * Indicates whether the currently active voice interaction service is capable of handling the
      * assist gesture.
      */
-    boolean activeServiceSupportsAssistGesture();
+    boolean activeServiceSupportsAssist();
 }
diff --git a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
index 008d38b..7d3db02 100644
--- a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
+++ b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
@@ -65,5 +65,6 @@
             in IBinder connection);
     void unbindRemoteViewsService(String callingPackage, int appWidgetId, in Intent intent);
     int[] getAppWidgetIds(in ComponentName providerComponent);
+    boolean isBoundWidgetPackage(String packageName, int userId);
 }
 
diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java
index 3f96174..6173832 100644
--- a/core/java/com/android/internal/logging/MetricsLogger.java
+++ b/core/java/com/android/internal/logging/MetricsLogger.java
@@ -32,6 +32,7 @@
     public static final int NOTIFICATION_ZEN_MODE_EXTERNAL_RULE = 145;
     public static final int ACTION_BAN_APP_NOTES = 146;
     public static final int NOTIFICATION_ZEN_MODE_EVENT_RULE = 147;
+    public static final int ACTION_DISMISS_ALL_NOTES = 148;
 
     public static void visible(Context context, int category) throws IllegalArgumentException {
         if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) {
diff --git a/core/java/com/android/internal/widget/SwipeDismissLayout.java b/core/java/com/android/internal/widget/SwipeDismissLayout.java
index 191662c..6d4e058 100644
--- a/core/java/com/android/internal/widget/SwipeDismissLayout.java
+++ b/core/java/com/android/internal/widget/SwipeDismissLayout.java
@@ -216,6 +216,8 @@
         if (mVelocityTracker == null) {
             return super.onTouchEvent(ev);
         }
+        // offset because the view is translated during swipe
+        ev.offsetLocation(mTranslationX, 0);
         switch (ev.getActionMasked()) {
             case MotionEvent.ACTION_UP:
                 updateDismiss(ev);
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index 6591d29..d0f7591 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -80,11 +80,12 @@
 
 ///////////////////////////////////////////////////////////////////////////////////////////////
 
-static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong bitmapHandle,
+static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jobject jbitmap,
                                       jint tileModeX, jint tileModeY)
 {
-    const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
-    SkShader* s = SkShader::CreateBitmapShader(*bitmap,
+    SkBitmap bitmap;
+    GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
+    SkShader* s = SkShader::CreateBitmapShader(bitmap,
                                         (SkShader::TileMode)tileModeX,
                                         (SkShader::TileMode)tileModeY);
 
@@ -249,7 +250,7 @@
 };
 
 static JNINativeMethod gBitmapShaderMethods[] = {
-    { "nativeCreate",     "(JII)J",  (void*)BitmapShader_constructor },
+    { "nativeCreate",     "(Landroid/graphics/Bitmap;II)J",  (void*)BitmapShader_constructor },
 };
 
 static JNINativeMethod gLinearGradientMethods[] = {
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index 5d08532..50a1069 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -40,22 +40,21 @@
 
 // Native wrapper constructor used by Canvas(Bitmap)
 static jlong initRaster(JNIEnv* env, jobject, jobject jbitmap) {
-    SkBitmap* bitmap = nullptr;
+    SkBitmap bitmap;
     if (jbitmap != NULL) {
-        bitmap = GraphicsJNI::getSkBitmapDeprecated(env, jbitmap);
+        GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
     }
-    return reinterpret_cast<jlong>(Canvas::create_canvas(
-            bitmap ? *bitmap : SkBitmap()));
+    return reinterpret_cast<jlong>(Canvas::create_canvas(bitmap));
 }
 
 // Set the given bitmap as the new draw target (wrapped in a new SkCanvas),
 // optionally copying canvas matrix & clip state.
 static void setBitmap(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap) {
-    SkBitmap* bitmap = nullptr;
+    SkBitmap bitmap;
     if (jbitmap != NULL) {
-        bitmap = GraphicsJNI::getSkBitmapDeprecated(env, jbitmap);
+        GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
     }
-    get_canvas(canvasHandle)->setBitmap(bitmap ? *bitmap : SkBitmap());
+    get_canvas(canvasHandle)->setBitmap(bitmap);
 }
 
 static jboolean isOpaque(JNIEnv*, jobject, jlong canvasHandle) {
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index 0cf596c..f5f8b1f 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -134,13 +134,21 @@
     return internedString;
 }
 
-static jint
-nativeGetNextSensor(JNIEnv *env, jclass clazz, jobject sensor, jint next)
+static jlong
+nativeCreate
+(JNIEnv *env, jclass clazz, jstring opPackageName)
 {
-    SensorManager& mgr(SensorManager::getInstance());
+    ScopedUtfChars opPackageNameUtf(env, opPackageName);
+    return (jlong) new SensorManager(String16(opPackageNameUtf.c_str()));
+}
+
+static jint
+nativeGetNextSensor(JNIEnv *env, jclass clazz, jlong sensorManager, jobject sensor, jint next)
+{
+    SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
 
     Sensor const* const* sensorList;
-    size_t count = mgr.getSensorList(&sensorList);
+    size_t count = mgr->getSensorList(&sensorList);
     if (size_t(next) >= count) {
         return -1;
     }
@@ -174,9 +182,10 @@
     return size_t(next) < count ? next : 0;
 }
 
-static int nativeEnableDataInjection(JNIEnv *_env, jclass _this, jboolean enable) {
-     SensorManager& mgr(SensorManager::getInstance());
-     return mgr.enableDataInjection(enable);
+static int nativeEnableDataInjection(JNIEnv *_env, jclass _this, jlong sensorManager,
+        jboolean enable) {
+    SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
+    return mgr->enableDataInjection(enable);
 }
 
 //----------------------------------------------------------------------------
@@ -281,12 +290,12 @@
     }
 };
 
-static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jobject eventQWeak, jobject msgQ,
-        jfloatArray scratch, jstring packageName, jint mode) {
-    SensorManager& mgr(SensorManager::getInstance());
+static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jlong sensorManager,
+        jobject eventQWeak, jobject msgQ, jfloatArray scratch, jstring packageName, jint mode) {
+    SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
     ScopedUtfChars packageUtf(env, packageName);
     String8 clientName(packageUtf.c_str());
-    sp<SensorEventQueue> queue(mgr.createEventQueue(clientName, mode));
+    sp<SensorEventQueue> queue(mgr->createEventQueue(clientName, mode));
 
     sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, msgQ);
     if (messageQueue == NULL) {
@@ -339,20 +348,23 @@
     {"nativeClassInit",
             "()V",
             (void*)nativeClassInit },
+    {"nativeCreate",
+             "(Ljava/lang/String;)J",
+             (void*)nativeCreate },
 
     {"nativeGetNextSensor",
-            "(Landroid/hardware/Sensor;I)I",
+            "(JLandroid/hardware/Sensor;I)I",
             (void*)nativeGetNextSensor },
 
     {"nativeEnableDataInjection",
-            "(Z)I",
+            "(JZ)I",
             (void*)nativeEnableDataInjection },
 };
 
 static JNINativeMethod gBaseEventQueueMethods[] = {
     {"nativeInitBaseEventQueue",
-     "(Ljava/lang/ref/WeakReference;Landroid/os/MessageQueue;[FLjava/lang/String;I)J",
-     (void*)nativeInitSensorEventQueue },
+             "(JLjava/lang/ref/WeakReference;Landroid/os/MessageQueue;[FLjava/lang/String;ILjava/lang/String;)J",
+             (void*)nativeInitSensorEventQueue },
 
     {"nativeEnableSensor",
             "(JIII)I",
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index d4fb572..2692ad8 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -270,49 +270,10 @@
 
             if ((strstr(name, "[heap]") == name)) {
                 whichHeap = HEAP_NATIVE;
-            } else if (strncmp(name, "/dev/ashmem", 11) == 0) {
-                if (strncmp(name, "/dev/ashmem/dalvik-", 19) == 0) {
-                    whichHeap = HEAP_DALVIK_OTHER;
-                    if (strstr(name, "/dev/ashmem/dalvik-LinearAlloc") == name) {
-                        subHeap = HEAP_DALVIK_LINEARALLOC;
-                    } else if ((strstr(name, "/dev/ashmem/dalvik-alloc space") == name) ||
-                               (strstr(name, "/dev/ashmem/dalvik-main space") == name)) {
-                        // This is the regular Dalvik heap.
-                        whichHeap = HEAP_DALVIK;
-                        subHeap = HEAP_DALVIK_NORMAL;
-                    } else if (strstr(name, "/dev/ashmem/dalvik-large object space") == name) {
-                        whichHeap = HEAP_DALVIK;
-                        subHeap = HEAP_DALVIK_LARGE;
-                    } else if (strstr(name, "/dev/ashmem/dalvik-non moving space") == name) {
-                        whichHeap = HEAP_DALVIK;
-                        subHeap = HEAP_DALVIK_NON_MOVING;
-                    } else if (strstr(name, "/dev/ashmem/dalvik-zygote space") == name) {
-                        whichHeap = HEAP_DALVIK;
-                        subHeap = HEAP_DALVIK_ZYGOTE;
-                    } else if (strstr(name, "/dev/ashmem/dalvik-indirect ref") == name) {
-                        subHeap = HEAP_DALVIK_INDIRECT_REFERENCE_TABLE;
-                    } else if (strstr(name, "/dev/ashmem/dalvik-jit-code-cache") == name) {
-                        subHeap = HEAP_DALVIK_CODE_CACHE;
-                    } else {
-                        subHeap = HEAP_DALVIK_ACCOUNTING;  // Default to accounting.
-                    }
-                } else if (strncmp(name, "/dev/ashmem/CursorWindow", 24) == 0) {
-                    whichHeap = HEAP_CURSOR;
-                } else if (strncmp(name, "/dev/ashmem/libc malloc", 23) == 0) {
-                    whichHeap = HEAP_NATIVE;
-                } else {
-                    whichHeap = HEAP_ASHMEM;
-                }
             } else if (strncmp(name, "[anon:libc_malloc]", 18) == 0) {
                 whichHeap = HEAP_NATIVE;
             } else if (strncmp(name, "[stack", 6) == 0) {
                 whichHeap = HEAP_STACK;
-            } else if (strncmp(name, "/dev/", 5) == 0) {
-                if (strncmp(name, "/dev/kgsl-3d0", 13) == 0) {
-                    whichHeap = HEAP_GL_DEV;
-                } else {
-                    whichHeap = HEAP_UNKNOWN_DEV;
-                }
             } else if (nameLen > 3 && strcmp(name+nameLen-3, ".so") == 0) {
                 whichHeap = HEAP_SO;
                 is_swappable = true;
@@ -325,7 +286,7 @@
             } else if (nameLen > 4 && strcmp(name+nameLen-4, ".ttf") == 0) {
                 whichHeap = HEAP_TTF;
                 is_swappable = true;
-            } else if ((nameLen > 4 && strcmp(name+nameLen-4, ".dex") == 0) ||
+            } else if ((nameLen > 4 && strstr(name, ".dex") != NULL) ||
                        (nameLen > 5 && strcmp(name+nameLen-5, ".odex") == 0)) {
                 whichHeap = HEAP_DEX;
                 is_swappable = true;
@@ -335,6 +296,45 @@
             } else if (nameLen > 4 && strcmp(name+nameLen-4, ".art") == 0) {
                 whichHeap = HEAP_ART;
                 is_swappable = true;
+            } else if (strncmp(name, "/dev/", 5) == 0) {
+                if (strncmp(name, "/dev/kgsl-3d0", 13) == 0) {
+                    whichHeap = HEAP_GL_DEV;
+                } else if (strncmp(name, "/dev/ashmem", 11) == 0) {
+                    if (strncmp(name, "/dev/ashmem/dalvik-", 19) == 0) {
+                        whichHeap = HEAP_DALVIK_OTHER;
+                        if (strstr(name, "/dev/ashmem/dalvik-LinearAlloc") == name) {
+                            subHeap = HEAP_DALVIK_LINEARALLOC;
+                        } else if ((strstr(name, "/dev/ashmem/dalvik-alloc space") == name) ||
+                                   (strstr(name, "/dev/ashmem/dalvik-main space") == name)) {
+                            // This is the regular Dalvik heap.
+                            whichHeap = HEAP_DALVIK;
+                            subHeap = HEAP_DALVIK_NORMAL;
+                        } else if (strstr(name, "/dev/ashmem/dalvik-large object space") == name) {
+                            whichHeap = HEAP_DALVIK;
+                            subHeap = HEAP_DALVIK_LARGE;
+                        } else if (strstr(name, "/dev/ashmem/dalvik-non moving space") == name) {
+                            whichHeap = HEAP_DALVIK;
+                            subHeap = HEAP_DALVIK_NON_MOVING;
+                        } else if (strstr(name, "/dev/ashmem/dalvik-zygote space") == name) {
+                            whichHeap = HEAP_DALVIK;
+                            subHeap = HEAP_DALVIK_ZYGOTE;
+                        } else if (strstr(name, "/dev/ashmem/dalvik-indirect ref") == name) {
+                            subHeap = HEAP_DALVIK_INDIRECT_REFERENCE_TABLE;
+                        } else if (strstr(name, "/dev/ashmem/dalvik-jit-code-cache") == name) {
+                            subHeap = HEAP_DALVIK_CODE_CACHE;
+                        } else {
+                            subHeap = HEAP_DALVIK_ACCOUNTING;  // Default to accounting.
+                        }
+                    } else if (strncmp(name, "/dev/ashmem/CursorWindow", 24) == 0) {
+                        whichHeap = HEAP_CURSOR;
+                    } else if (strncmp(name, "/dev/ashmem/libc malloc", 23) == 0) {
+                        whichHeap = HEAP_NATIVE;
+                    } else {
+                        whichHeap = HEAP_ASHMEM;
+                    }
+                } else {
+                    whichHeap = HEAP_UNKNOWN_DEV;
+                }
             } else if (strncmp(name, "[anon:", 6) == 0) {
                 whichHeap = HEAP_UNKNOWN;
             } else if (nameLen > 0) {
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 11b3805..4ccbb41 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -21,6 +21,7 @@
 #include "jni.h"
 #include <nativehelper/JNIHelp.h>
 #include "core_jni_helpers.h"
+#include <GraphicsJNI.h>
 #include <ScopedPrimitiveArray.h>
 
 #include <EGL/egl.h>
@@ -347,10 +348,11 @@
 }
 
 static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz,
-        jlong proxyPtr, jlong layerPtr, jlong bitmapPtr) {
+        jlong proxyPtr, jlong layerPtr, jobject jbitmap) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
-    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
+    SkBitmap bitmap;
+    GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
     return proxy->copyLayerInto(layer, bitmap);
 }
 
@@ -458,7 +460,7 @@
     { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
     { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
     { "nBuildLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_buildLayer },
-    { "nCopyLayerInto", "(JJJ)Z", (void*) android_view_ThreadedRenderer_copyLayerInto },
+    { "nCopyLayerInto", "(JJLandroid/graphics/Bitmap;)Z", (void*) android_view_ThreadedRenderer_copyLayerInto },
     { "nPushLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_pushLayerUpdate },
     { "nCancelLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_cancelLayerUpdate },
     { "nDetachSurfaceTexture", "(JJ)V", (void*) android_view_ThreadedRenderer_detachSurfaceTexture },
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 52b31b2..fe5862b 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -7304,8 +7304,8 @@
         <attr name="recognitionService" format="string" />
         <attr name="settingsActivity" />
         <!-- Flag indicating whether this voice interaction service is capable of handling the
-             assist gesture. -->
-        <attr name="supportsAssistGesture" format="boolean" />
+             assist action. -->
+        <attr name="supportsAssist" format="boolean" />
     </declare-styleable>
 
     <!-- Use <code>voice-enrollment-application</code>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index cf21a1c..79b81a7 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2663,7 +2663,7 @@
   <public type="attr" name="autoVerify" />
   <public type="attr" name="breakStrategy" />
 
-  <public type="attr" name="supportsAssistGesture" />
+  <public type="attr" name="supportsAssist" />
   <public type="attr" name="thumbPosition" />
 
   <!-- Placeholder for a removed attribute. Remove this before M release. -->
diff --git a/data/fonts/fallback_fonts.xml b/data/fonts/fallback_fonts.xml
index dc364a12..0aa588b 100644
--- a/data/fonts/fallback_fonts.xml
+++ b/data/fonts/fallback_fonts.xml
@@ -402,12 +402,12 @@
     </family>
     <family>
         <fileset>
-            <file lang="zh-Hans">NotoSansHans-Regular.otf</file>
+            <file lang="zh-Hans">NotoSansSC-Regular.otf</file>
         </fileset>
     </family>
     <family>
         <fileset>
-            <file lang="zh-Hant">NotoSansHant-Regular.otf</file>
+            <file lang="zh-Hant">NotoSansTC-Regular.otf</file>
         </fileset>
     </family>
     <family>
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index 44ea1c9..f903aab 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -329,10 +329,10 @@
         <font weight="400" style="normal">NotoSansYi-Regular.ttf</font>
     </family>
     <family lang="zh-Hans">
-        <font weight="400" style="normal">NotoSansHans-Regular.otf</font>
+        <font weight="400" style="normal">NotoSansSC-Regular.otf</font>
     </family>
     <family lang="zh-Hant">
-        <font weight="400" style="normal">NotoSansHant-Regular.otf</font>
+        <font weight="400" style="normal">NotoSansTC-Regular.otf</font>
     </family>
     <family lang="ja">
         <font weight="400" style="normal">NotoSansJP-Regular.otf</font>
diff --git a/graphics/java/android/graphics/BitmapShader.java b/graphics/java/android/graphics/BitmapShader.java
index f2f890e..bd74bc8 100644
--- a/graphics/java/android/graphics/BitmapShader.java
+++ b/graphics/java/android/graphics/BitmapShader.java
@@ -42,8 +42,7 @@
         mBitmap = bitmap;
         mTileX = tileX;
         mTileY = tileY;
-        final long b = bitmap.getSkBitmap();
-        init(nativeCreate(b, tileX.nativeInt, tileY.nativeInt));
+        init(nativeCreate(bitmap, tileX.nativeInt, tileY.nativeInt));
     }
 
     /**
@@ -56,6 +55,6 @@
         return copy;
     }
 
-    private static native long nativeCreate(long native_bitmap, int shaderTileModeX,
+    private static native long nativeCreate(Bitmap bitmap, int shaderTileModeX,
             int shaderTileModeY);
 }
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 9fe8e0c..7a1ecf7 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -81,10 +81,6 @@
      */
     protected int mScreenDensity = Bitmap.DENSITY_NONE;
 
-    // Used by native code
-    @SuppressWarnings("UnusedDeclaration")
-    private int mSurfaceFormat;
-
     // Maximum bitmap size as defined in Skia's native code
     // (see SkCanvas.cpp, SkDraw.cpp)
     private static final int MAXMIMUM_BITMAP_SIZE = 32766;
diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java
new file mode 100644
index 0000000..47a1f77
--- /dev/null
+++ b/graphics/java/android/graphics/drawable/Icon.java
@@ -0,0 +1,482 @@
+/*
+ * Copyright (C) 2015 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.graphics.drawable;
+
+import android.annotation.DrawableRes;
+import android.content.ContentResolver;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.lang.IllegalArgumentException;
+import java.lang.Override;
+
+/**
+ * An umbrella container for several serializable graphics representations, including Bitmaps,
+ * compressed bitmap images (e.g. JPG or PNG), and drawable resources (including vectors).
+ *
+ * <a href="https://developer.android.com/training/displaying-bitmaps/index.html">Much ink</a>
+ * has been spilled on the best way to load images, and many clients may have different needs when
+ * it comes to threading and fetching. This class is therefore focused on encapsulation rather than
+ * behavior.
+ */
+
+public final class Icon implements Parcelable {
+    private static final String TAG = "Icon";
+
+    private static final int TYPE_BITMAP   = 1;
+    private static final int TYPE_RESOURCE = 2;
+    private static final int TYPE_DATA     = 3;
+    private static final int TYPE_URI      = 4;
+
+    private final int mType;
+
+    // To avoid adding unnecessary overhead, we have a few basic objects that get repurposed
+    // based on the value of mType.
+
+    // TYPE_BITMAP: Bitmap
+    // TYPE_RESOURCE: Resources
+    // TYPE_DATA: DataBytes
+    private Object          mObj1;
+
+    // TYPE_RESOURCE: package name
+    // TYPE_URI: uri string
+    private String          mString1;
+
+    // TYPE_RESOURCE: resId
+    // TYPE_DATA: data length
+    private int             mInt1;
+
+    // TYPE_DATA: data offset
+    private int             mInt2;
+
+    // Internal accessors for different mType variants
+    private Bitmap getBitmap() {
+        if (mType != TYPE_BITMAP) {
+            throw new IllegalStateException("called getBitmap() on " + this);
+        }
+        return (Bitmap) mObj1;
+    }
+
+    private int getDataLength() {
+        if (mType != TYPE_DATA) {
+            throw new IllegalStateException("called getDataLength() on " + this);
+        }
+        synchronized (this) {
+            return mInt1;
+        }
+    }
+
+    private int getDataOffset() {
+        if (mType != TYPE_DATA) {
+            throw new IllegalStateException("called getDataOffset() on " + this);
+        }
+        synchronized (this) {
+            return mInt2;
+        }
+    }
+
+    private byte[] getDataBytes() {
+        if (mType != TYPE_DATA) {
+            throw new IllegalStateException("called getDataBytes() on " + this);
+        }
+        synchronized (this) {
+            return (byte[]) mObj1;
+        }
+    }
+
+    private Resources getResources() {
+        if (mType != TYPE_RESOURCE) {
+            throw new IllegalStateException("called getResources() on " + this);
+        }
+        return (Resources) mObj1;
+    }
+
+    private String getResPackage() {
+        if (mType != TYPE_RESOURCE) {
+            throw new IllegalStateException("called getResPackage() on " + this);
+        }
+        return mString1;
+    }
+
+    private int getResId() {
+        if (mType != TYPE_RESOURCE) {
+            throw new IllegalStateException("called getResId() on " + this);
+        }
+        return mInt1;
+    }
+
+    private String getUriString() {
+        if (mType != TYPE_URI) {
+            throw new IllegalStateException("called getUriString() on " + this);
+        }
+        return mString1;
+    }
+
+    private Uri getUri() {
+        return Uri.parse(getUriString());
+    }
+
+    // Convert a int32 into a four-char string
+    private static final String typeToString(int x) {
+        switch (x) {
+            case TYPE_BITMAP: return "BITMAP";
+            case TYPE_DATA: return "DATA";
+            case TYPE_RESOURCE: return "RESOURCE";
+            case TYPE_URI: return "URI";
+            default: return "UNKNOWN";
+        }
+    }
+
+    /**
+     * Invokes {@link #loadDrawable(Context)} on the given {@link android.os.Handler Handler}
+     * and then sends <code>andThen</code> to the same Handler when finished.
+     *
+     * @param context {@link android.content.Context Context} in which to load the drawable; see
+     *                {@link #loadDrawable(Context)}
+     * @param andThen {@link android.os.Message} to send to its target once the drawable
+     *                is available. The {@link android.os.Message#obj obj}
+     *                property is populated with the Drawable.
+     */
+    public void loadDrawableAsync(Context context, Message andThen) {
+        if (andThen.getTarget() == null) {
+            throw new IllegalArgumentException("callback message must have a target handler");
+        }
+        new LoadDrawableTask(context, andThen).runAsync();
+    }
+
+    /**
+     * Invokes {@link #loadDrawable(Context)} on a background thread
+     * and then runs <code>andThen</code> on the UI thread when finished.
+     *
+     * @param context {@link android.content.Context Context} in which to load the drawable; see
+     *                {@link #loadDrawable(Context)}
+     * @param handler {@link android.os.Handler} on which to run <code>andThen</code>.
+     * @param listener a callback to run on the provided
+     *                 Handler once the drawable is available.
+     */
+    public void loadDrawableAsync(Context context, Handler handler,
+            final OnDrawableLoadedListener listener) {
+        new LoadDrawableTask(context, handler, listener).runAsync();
+    }
+
+    /**
+     * Returns a Drawable that can be used to draw the image inside this Icon, constructing it
+     * if necessary. Depending on the type of image, this may not be something you want to do on
+     * the UI thread, so consider using
+     * {@link #loadDrawableAsync(Context, Message) loadDrawableAsync} instead.
+     *
+     * @param context {@link android.content.Context Context} in which to load the drawable; used
+     *                to access {@link android.content.res.Resources Resources}, for example.
+     * @return A fresh instance of a drawable for this image, yours to keep.
+     */
+    public Drawable loadDrawable(Context context) {
+        switch (mType) {
+            case TYPE_BITMAP:
+                return new BitmapDrawable(context.getResources(), getBitmap());
+            case TYPE_RESOURCE:
+                if (getResources() == null) {
+                    if (getResPackage() == null || "android".equals(getResPackage())) {
+                        mObj1 = Resources.getSystem();
+                    } else {
+                        final PackageManager pm = context.getPackageManager();
+                        try {
+                            mObj1 = pm.getResourcesForApplication(getResPackage());
+                        } catch (PackageManager.NameNotFoundException e) {
+                            Log.e(TAG,
+                                    String.format("Unable to find package '%s'", getResPackage()),
+                                    e);
+                            break;
+                        }
+                    }
+                }
+                return getResources().getDrawable(getResId(), context.getTheme());
+            case TYPE_DATA:
+                return new BitmapDrawable(context.getResources(),
+                    BitmapFactory.decodeByteArray(getDataBytes(), getDataOffset(), getDataLength())
+                );
+            case TYPE_URI:
+                final Uri uri = getUri();
+                final String scheme = uri.getScheme();
+                InputStream is = null;
+                if (ContentResolver.SCHEME_CONTENT.equals(scheme)
+                        || ContentResolver.SCHEME_FILE.equals(scheme)) {
+                    try {
+                        is = context.getContentResolver().openInputStream(uri);
+                    } catch (Exception e) {
+                        Log.w(TAG, "Unable to load image from URI: " + uri, e);
+                    }
+                } else {
+                    try {
+                        is = new FileInputStream(new File(mString1));
+                    } catch (FileNotFoundException e) {
+                        Log.w(TAG, "Unable to load image from path: " + uri, e);
+                    }
+                }
+                if (is != null) {
+                    return new BitmapDrawable(context.getResources(),
+                            BitmapFactory.decodeStream(is));
+                }
+                break;
+        }
+        return null;
+    }
+
+    private Icon(int mType) {
+        this.mType = mType;
+    }
+
+    /**
+     * Create a Icon pointing to a drawable resource.
+     * @param res Resources for a package containing the resource in question
+     * @param resid ID of the drawable resource
+     */
+    public static Icon createWithResource(Resources res, @DrawableRes int resid) {
+        final Icon rep = new Icon(TYPE_RESOURCE);
+        rep.mObj1 = res;
+        rep.mInt1 = resid;
+        rep.mString1 = res.getResourcePackageName(resid);
+        return rep;
+    }
+
+    /**
+     * Create a Icon pointing to a bitmap in memory.
+     * @param bits A valid {@link android.graphics.Bitmap} object
+     */
+    public static Icon createWithBitmap(Bitmap bits) {
+        final Icon rep = new Icon(TYPE_BITMAP);
+        rep.mObj1 = bits;
+        return rep;
+    }
+
+    /**
+     * Create a Icon pointing to a compressed bitmap stored in a byte array.
+     * @param data Byte array storing compressed bitmap data of a type that
+     *             {@link android.graphics.BitmapFactory}
+     *             can decode (see {@link android.graphics.Bitmap.CompressFormat}).
+     * @param offset Offset into <code>data</code> at which the bitmap data starts
+     * @param length Length of the bitmap data
+     */
+    public static Icon createWithData(byte[] data, int offset, int length) {
+        final Icon rep = new Icon(TYPE_DATA);
+        rep.mObj1 = data;
+        rep.mInt1 = length;
+        rep.mInt2 = offset;
+        return rep;
+    }
+
+    /**
+     * Create a Icon pointing to a content specified by URI.
+     *
+     * @param uri A uri referring to local content:// or file:// image data.
+     */
+    public static Icon createWithContentUri(String uri) {
+        final Icon rep = new Icon(TYPE_URI);
+        rep.mString1 = uri;
+        return rep;
+    }
+
+    /**
+     * Create a Icon pointing to a content specified by URI.
+     *
+     * @param uri A uri referring to local content:// or file:// image data.
+     */
+    public static Icon createWithContentUri(Uri uri) {
+        final Icon rep = new Icon(TYPE_URI);
+        rep.mString1 = uri.toString();
+        return rep;
+    }
+
+    /**
+     * Create a Icon pointing to
+     *
+     * @param path A path to a file that contains compressed bitmap data of
+     *           a type that {@link android.graphics.BitmapFactory} can decode.
+     */
+    public static Icon createWithFilePath(String path) {
+        final Icon rep = new Icon(TYPE_URI);
+        rep.mString1 = path;
+        return rep;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder("Icon(typ=").append(typeToString(mType));
+        switch (mType) {
+            case TYPE_BITMAP:
+                sb.append(" size=")
+                        .append(getBitmap().getWidth())
+                        .append("x")
+                        .append(getBitmap().getHeight());
+                break;
+            case TYPE_RESOURCE:
+                sb.append(" pkg=")
+                        .append(getResPackage())
+                        .append(" id=")
+                        .append(String.format("%08x", getResId()));
+                break;
+            case TYPE_DATA:
+                sb.append(" len=").append(getDataLength());
+                if (getDataOffset() != 0) {
+                    sb.append(" off=").append(getDataOffset());
+                }
+                break;
+            case TYPE_URI:
+                sb.append(" uri=").append(getUriString());
+                break;
+        }
+        sb.append(")");
+        return sb.toString();
+    }
+
+    /**
+     * Parcelable interface
+     */
+    public int describeContents() {
+        return (mType == TYPE_BITMAP || mType == TYPE_DATA)
+                ? Parcelable.CONTENTS_FILE_DESCRIPTOR : 0;
+    }
+
+    // ===== Parcelable interface ======
+
+    private Icon(Parcel in) {
+        this(in.readInt());
+        switch (mType) {
+            case TYPE_BITMAP:
+                final Bitmap bits = Bitmap.CREATOR.createFromParcel(in);
+                mObj1 = bits;
+                break;
+            case TYPE_RESOURCE:
+                final String pkg = in.readString();
+                final int resId = in.readInt();
+                mString1 = pkg;
+                mInt1 = resId;
+                break;
+            case TYPE_DATA:
+                final int len = in.readInt();
+                final byte[] a = in.readBlob();
+                if (len != a.length) {
+                    throw new RuntimeException("internal unparceling error: blob length ("
+                            + a.length + ") != expected length (" + len + ")");
+                }
+                mInt1 = len;
+                mObj1 = a;
+                break;
+            case TYPE_URI:
+                final String uri = in.readString();
+                mString1 = uri;
+                break;
+            default:
+                throw new RuntimeException("invalid "
+                        + this.getClass().getSimpleName() + " type in parcel: " + mType);
+        }
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        switch (mType) {
+            case TYPE_BITMAP:
+                final Bitmap bits = getBitmap();
+                dest.writeInt(TYPE_BITMAP);
+                getBitmap().writeToParcel(dest, flags);
+                break;
+            case TYPE_RESOURCE:
+                dest.writeInt(TYPE_RESOURCE);
+                dest.writeString(getResPackage());
+                dest.writeInt(getResId());
+                break;
+            case TYPE_DATA:
+                dest.writeInt(TYPE_DATA);
+                dest.writeInt(getDataLength());
+                dest.writeBlob(getDataBytes(), getDataOffset(), getDataLength());
+                break;
+            case TYPE_URI:
+                dest.writeInt(TYPE_URI);
+                dest.writeString(getUriString());
+                break;
+        }
+    }
+
+    public static final Parcelable.Creator<Icon> CREATOR
+            = new Parcelable.Creator<Icon>() {
+        public Icon createFromParcel(Parcel in) {
+            return new Icon(in);
+        }
+
+        public Icon[] newArray(int size) {
+            return new Icon[size];
+        }
+    };
+
+    /**
+     * Implement this interface to receive notification when
+     * {@link #loadDrawableAsync(Context, Handler, OnDrawableLoadedListener) loadDrawableAsync}
+     * is finished and your Drawable is ready.
+     */
+    public interface OnDrawableLoadedListener {
+        void onDrawableLoaded(Drawable d);
+    }
+
+    /**
+     * Wrapper around loadDrawable that does its work on a pooled thread and then
+     * fires back the given (targeted) Message.
+     */
+    private class LoadDrawableTask implements Runnable {
+        final Context mContext;
+        final Message mMessage;
+
+        public LoadDrawableTask(Context context, final Handler handler,
+                final OnDrawableLoadedListener listener) {
+            mContext = context;
+            mMessage = Message.obtain(handler, new Runnable() {
+                    @Override
+                    public void run() {
+                        listener.onDrawableLoaded((Drawable) mMessage.obj);
+                    }
+                });
+        }
+
+        public LoadDrawableTask(Context context, Message message) {
+            mContext = context;
+            mMessage = message;
+        }
+
+        @Override
+        public void run() {
+            mMessage.obj = loadDrawable(mContext);
+            mMessage.sendToTarget();
+        }
+
+        public void runAsync() {
+            AsyncTask.THREAD_POOL_EXECUTOR.execute(this);
+        }
+    }
+}
diff --git a/graphics/tests/graphicstests/AndroidManifest.xml b/graphics/tests/graphicstests/AndroidManifest.xml
index 5fb5959..e019e28 100644
--- a/graphics/tests/graphicstests/AndroidManifest.xml
+++ b/graphics/tests/graphicstests/AndroidManifest.xml
@@ -24,6 +24,7 @@
     <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
     <uses-permission android:name="android.permission.WRITE_APN_SETTINGS" />
     <uses-permission android:name="android.permission.BROADCAST_STICKY" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 
  
     <application>
diff --git a/graphics/tests/graphicstests/res/drawable-nodpi/landscape.png b/graphics/tests/graphicstests/res/drawable-nodpi/landscape.png
new file mode 100644
index 0000000..ddb3180
--- /dev/null
+++ b/graphics/tests/graphicstests/res/drawable-nodpi/landscape.png
Binary files differ
diff --git a/graphics/tests/graphicstests/src/android/graphics/drawable/IconTest.java b/graphics/tests/graphicstests/src/android/graphics/drawable/IconTest.java
new file mode 100644
index 0000000..2b9bf50
--- /dev/null
+++ b/graphics/tests/graphicstests/src/android/graphics/drawable/IconTest.java
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 2006 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.graphics.drawable;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.lang.Override;
+import java.util.Arrays;
+import java.util.ArrayList;
+
+import junit.framework.TestCase;
+
+import com.android.frameworks.graphicstests.R;
+
+public class IconTest extends AndroidTestCase {
+    public static final String TAG = IconTest.class.getSimpleName();
+    public static void L(String s, Object... parts) {
+        Log.d(TAG, (parts.length == 0) ? s : String.format(s, parts));
+    }
+
+    @SmallTest
+    public void testWithBitmap() throws Exception {
+        final Bitmap bm1 = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888);
+        final Bitmap bm2 = Bitmap.createBitmap(100, 200, Bitmap.Config.RGB_565);
+        final Bitmap bm3 = ((BitmapDrawable) getContext().getDrawable(R.drawable.landscape))
+                .getBitmap();
+
+        final Canvas can1 = new Canvas(bm1);
+        can1.drawColor(0xFFFF0000);
+        final Canvas can2 = new Canvas(bm2);
+        can2.drawColor(0xFF00FF00);
+
+        final Icon im1 = Icon.createWithBitmap(bm1);
+        final Icon im2 = Icon.createWithBitmap(bm2);
+        final Icon im3 = Icon.createWithBitmap(bm3);
+
+        final Drawable draw1 = im1.loadDrawable(mContext);
+        final Drawable draw2 = im2.loadDrawable(mContext);
+        final Drawable draw3 = im3.loadDrawable(mContext);
+
+        final Bitmap test1 = Bitmap.createBitmap(draw1.getIntrinsicWidth(),
+                draw1.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
+        final Bitmap test2 = Bitmap.createBitmap(draw2.getIntrinsicWidth(),
+                draw2.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
+        final Bitmap test3 = Bitmap.createBitmap(draw3.getIntrinsicWidth(),
+                draw3.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
+
+        draw1.setBounds(0, 0, draw1.getIntrinsicWidth(), draw1.getIntrinsicHeight());
+        draw1.draw(new Canvas(test1));
+
+        draw2.setBounds(0, 0, draw2.getIntrinsicWidth(), draw2.getIntrinsicHeight());
+        draw2.draw(new Canvas(test2));
+
+        draw3.setBounds(0, 0, draw3.getIntrinsicWidth(), draw3.getIntrinsicHeight());
+        draw3.draw(new Canvas(test3));
+
+        final File dir = getContext().getExternalFilesDir(null);
+        L("writing temp bitmaps to %s...", dir);
+
+        bm1.compress(Bitmap.CompressFormat.PNG, 100,
+                new FileOutputStream(new File(dir, "bitmap1-original.png")));
+        test1.compress(Bitmap.CompressFormat.PNG, 100,
+                new FileOutputStream(new File(dir, "bitmap1-test.png")));
+        if (!equalBitmaps(bm1, test1)) {
+            findBitmapDifferences(bm1, test1);
+            fail("bitmap1 differs, check " + dir);
+        }
+
+        bm2.compress(Bitmap.CompressFormat.PNG, 100,
+                new FileOutputStream(new File(dir, "bitmap2-original.png")));
+        test2.compress(Bitmap.CompressFormat.PNG, 100,
+                new FileOutputStream(new File(dir, "bitmap2-test.png")));
+        if (!equalBitmaps(bm2, test2)) {
+            findBitmapDifferences(bm2, test2);
+            fail("bitmap2 differs, check " + dir);
+        }
+
+        bm3.compress(Bitmap.CompressFormat.PNG, 100,
+                new FileOutputStream(new File(dir, "bitmap3-original.png")));
+        test3.compress(Bitmap.CompressFormat.PNG, 100,
+                new FileOutputStream(new File(dir, "bitmap3-test.png")));
+        if (!equalBitmaps(bm3, test3)) {
+            findBitmapDifferences(bm3, test3);
+            fail("bitmap3 differs, check " + dir);
+        }
+    }
+
+    @SmallTest
+    public void testWithBitmapResource() throws Exception {
+        final Bitmap res1 = ((BitmapDrawable) getContext().getDrawable(R.drawable.landscape))
+                .getBitmap();
+
+        final Icon im1 = Icon.createWithResource(getContext().getResources(),
+                R.drawable.landscape);
+        final Drawable draw1 = im1.loadDrawable(mContext);
+        final Bitmap test1 = Bitmap.createBitmap(draw1.getIntrinsicWidth(),
+                draw1.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
+        draw1.setBounds(0, 0, test1.getWidth(), test1.getHeight());
+        draw1.draw(new Canvas(test1));
+
+        final File dir = getContext().getExternalFilesDir(null);
+        res1.compress(Bitmap.CompressFormat.PNG, 100,
+                new FileOutputStream(new File(dir, "res1-original.png")));
+        test1.compress(Bitmap.CompressFormat.PNG, 100,
+                new FileOutputStream(new File(dir, "res1-test.png")));
+        if (!equalBitmaps(res1, test1)) {
+            findBitmapDifferences(res1, test1);
+            fail("res1 differs, check " + dir);
+        }
+    }
+
+    @SmallTest
+    public void testWithFile() throws Exception {
+        final Bitmap bit1 = ((BitmapDrawable) getContext().getDrawable(R.drawable.landscape))
+                .getBitmap();
+        final File dir = getContext().getExternalFilesDir(null);
+        final File file1 = new File(dir, "file1-original.png");
+        bit1.compress(Bitmap.CompressFormat.PNG, 100,
+                new FileOutputStream(file1));
+
+        final Icon im1 = Icon.createWithFilePath(file1.toString());
+        final Drawable draw1 = im1.loadDrawable(mContext);
+        final Bitmap test1 = Bitmap.createBitmap(draw1.getIntrinsicWidth(),
+                draw1.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
+        draw1.setBounds(0, 0, test1.getWidth(), test1.getHeight());
+        draw1.draw(new Canvas(test1));
+
+        test1.compress(Bitmap.CompressFormat.PNG, 100,
+                new FileOutputStream(new File(dir, "file1-test.png")));
+        if (!equalBitmaps(bit1, test1)) {
+            findBitmapDifferences(bit1, test1);
+            fail("testWithFile: file1 differs, check " + dir);
+        }
+    }
+
+    @SmallTest
+    public void testAsync() throws Exception {
+        final Bitmap bit1 = ((BitmapDrawable) getContext().getDrawable(R.drawable.landscape))
+                .getBitmap();
+        final File dir = getContext().getExternalFilesDir(null);
+        final File file1 = new File(dir, "async-original.png");
+        bit1.compress(Bitmap.CompressFormat.PNG, 100,
+                new FileOutputStream(file1));
+
+        final Icon im1 = Icon.createWithFilePath(file1.toString());
+        final HandlerThread thd = new HandlerThread("testAsync");
+        thd.start();
+        final Handler h = new Handler(thd.getLooper());
+        L(TAG, "asyncTest: dispatching load to thread: " + thd);
+        im1.loadDrawableAsync(mContext, h, new Icon.OnDrawableLoadedListener() {
+            @Override
+            public void onDrawableLoaded(Drawable draw1) {
+                L(TAG, "asyncTest: thread: loading drawable");
+                L(TAG, "asyncTest: thread: loaded: %dx%d", draw1.getIntrinsicWidth(),
+                    draw1.getIntrinsicHeight());
+                final Bitmap test1 = Bitmap.createBitmap(draw1.getIntrinsicWidth(),
+                        draw1.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
+                draw1.setBounds(0, 0, test1.getWidth(), test1.getHeight());
+                draw1.draw(new Canvas(test1));
+
+                try {
+                    test1.compress(Bitmap.CompressFormat.PNG, 100,
+                            new FileOutputStream(new File(dir, "async-test.png")));
+                } catch (java.io.FileNotFoundException ex) {
+                    fail("couldn't create test file: " + ex);
+                }
+                if (!equalBitmaps(bit1, test1)) {
+                    findBitmapDifferences(bit1, test1);
+                    fail("testAsync: file1 differs, check " + dir);
+                }
+            }
+        });
+        L(TAG, "asyncTest: awaiting result");
+        Thread.sleep(500); // ;_;
+        assertTrue("async-test.png does not exist!", new File(dir, "async-test.png").exists());
+        L(TAG, "asyncTest: done");
+    }
+
+    @SmallTest
+    public void testParcel() throws Exception {
+        final Bitmap originalbits = ((BitmapDrawable) getContext().getDrawable(R.drawable.landscape))
+                .getBitmap();
+
+        final ByteArrayOutputStream ostream = new ByteArrayOutputStream(
+                originalbits.getWidth() * originalbits.getHeight() * 2); // guess 50% compression
+        originalbits.compress(Bitmap.CompressFormat.PNG, 100, ostream);
+        final byte[] pngdata = ostream.toByteArray();
+
+        L("starting testParcel; bitmap: %d bytes, PNG: %d bytes",
+                originalbits.getByteCount(),
+                pngdata.length);
+
+        final File dir = getContext().getExternalFilesDir(null);
+        final File originalfile = new File(dir, "parcel-original.png");
+        new FileOutputStream(originalfile).write(pngdata);
+
+        ArrayList<Icon> imgs = new ArrayList<>();
+        final Icon file1 = Icon.createWithFilePath(originalfile.getAbsolutePath());
+        imgs.add(file1);
+        final Icon bit1 = Icon.createWithBitmap(originalbits);
+        imgs.add(bit1);
+        final Icon data1 = Icon.createWithData(pngdata, 0, pngdata.length);
+        imgs.add(data1);
+        final Icon res1 = Icon.createWithResource(getContext().getResources(), R.drawable.landscape);
+        imgs.add(res1);
+
+        ArrayList<Icon> test = new ArrayList<>();
+        final Parcel parcel = Parcel.obtain();
+        int pos = 0;
+        parcel.writeInt(imgs.size());
+        for (Icon img : imgs) {
+            img.writeToParcel(parcel, 0);
+            L("used %d bytes parceling: %s", parcel.dataPosition() - pos, img);
+            pos = parcel.dataPosition();
+        }
+
+        parcel.setDataPosition(0); // rewind
+        final int N = parcel.readInt();
+        for (int i=0; i<N; i++) {
+            Icon img = Icon.CREATOR.createFromParcel(parcel);
+            L("test %d: read from parcel: %s", i, img);
+            final File testfile = new File(dir,
+                    String.format("parcel-test%02d.png", i));
+
+            final Drawable draw1 = img.loadDrawable(mContext);
+            if (draw1 == null) {
+                fail("null drawable from img: " + img);
+            }
+            final Bitmap test1 = Bitmap.createBitmap(draw1.getIntrinsicWidth(),
+                    draw1.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
+            draw1.setBounds(0, 0, test1.getWidth(), test1.getHeight());
+            draw1.draw(new Canvas(test1));
+
+            try {
+                test1.compress(Bitmap.CompressFormat.PNG, 100,
+                        new FileOutputStream(testfile));
+            } catch (java.io.FileNotFoundException ex) {
+                fail("couldn't create test file " + testfile + ": " + ex);
+            }
+            if (!equalBitmaps(originalbits, test1)) {
+                findBitmapDifferences(originalbits, test1);
+                fail(testfile + " differs from original: " + originalfile);
+            }
+
+        }
+    }
+
+
+    // ======== utils ========
+
+    static final char[] GRADIENT = " .:;+=xX$#".toCharArray();
+    static float[] hsv = new float[3];
+    static char colorToChar(int color) {
+        int sum = ((color >> 16) & 0xff)
+                + ((color >> 8)  & 0xff)
+                + ((color)       & 0xff);
+        return GRADIENT[sum * (GRADIENT.length-1) / (3*0xff)];
+    }
+    static void printBits(int[] a, int w, int h) {
+        final StringBuilder sb = new StringBuilder();
+        for (int i=0; i<w; i++) {
+            for (int j=0; j<h; j++) {
+                sb.append(colorToChar(a[i+w*j]));
+            }
+            sb.append('\n');
+        }
+        L(sb.toString());
+    }
+    static void printBits(Bitmap a) {
+        final int w = a.getWidth();
+        final int h = a.getHeight();
+        int[] aPix = new int[w * h];
+        printBits(aPix, w, h);
+    }
+    boolean equalBitmaps(Bitmap a, Bitmap b) {
+        if (a.getWidth() != b.getWidth() || a.getHeight() != b.getHeight()) return false;
+        
+        final int w = a.getWidth();
+        final int h = a.getHeight();
+        int[] aPix = new int[w * h];
+        int[] bPix = new int[w * h];
+
+        a.getPixels(aPix, 0, w, 0, 0, w, h);
+        b.getPixels(bPix, 0, w, 0, 0, w, h);
+
+        return Arrays.equals(aPix, bPix);
+    }
+
+    void findBitmapDifferences(Bitmap a, Bitmap b) {
+        if (a.getWidth() != b.getWidth() || a.getHeight() != b.getHeight()) {
+            L("different sizes: %dx%d vs %dx%d",
+                        a.getWidth(), a.getHeight(), b.getWidth(), b.getHeight());
+            return;
+        }
+        
+        final int w = a.getWidth();
+        final int h = a.getHeight();
+        int[] aPix = new int[w * h];
+        int[] bPix = new int[w * h];
+
+        a.getPixels(aPix, 0, w, 0, 0, w, h);
+        b.getPixels(bPix, 0, w, 0, 0, w, h);
+
+        L("bitmap a (%dx%d)", w, h);
+        printBits(aPix, w, h);
+        L("bitmap b (%dx%d)", w, h);
+        printBits(bPix, w, h);
+
+        StringBuffer sb = new StringBuffer("Different pixels: ");
+        for (int i=0; i<w; i++) {
+            for (int j=0; j<h; j++) {
+                if (aPix[i+w*j] != bPix[i+w*j]) {
+                    sb.append(" ").append(i).append(",").append(j);
+                }
+            }
+        }
+        L(sb.toString());
+    }
+}
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index cc87241..d15fa39 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -293,11 +293,11 @@
     return (void*) success;
 }
 
-bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
+bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap) {
     SETUP_TASK(copyLayerInto);
     args->context = mContext;
     args->layer = layer;
-    args->bitmap = bitmap;
+    args->bitmap = &bitmap;
     return (bool) postAndWait(task);
 }
 
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 29c6f08..cc475fa 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -83,7 +83,7 @@
 
     ANDROID_API DeferredLayerUpdater* createTextureLayer();
     ANDROID_API void buildLayer(RenderNode* node);
-    ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
+    ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap);
     ANDROID_API void pushLayerUpdate(DeferredLayerUpdater* layer);
     ANDROID_API void cancelLayerUpdate(DeferredLayerUpdater* layer);
     ANDROID_API void detachSurfaceTexture(DeferredLayerUpdater* layer);
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index a33fa59..77adb39 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1953,21 +1953,16 @@
 
         TrackInfo(Parcel in) {
             mTrackType = in.readInt();
-            // TODO: parcel in the full MediaFormat
+            // TODO: parcel in the full MediaFormat; currently we are using createSubtitleFormat
+            // even for audio/video tracks, meaning we only set the mime and language.
+            String mime = in.readString();
             String language = in.readString();
+            mFormat = MediaFormat.createSubtitleFormat(mime, language);
 
-            if (mTrackType == MEDIA_TRACK_TYPE_TIMEDTEXT) {
-                mFormat = MediaFormat.createSubtitleFormat(
-                    MEDIA_MIMETYPE_TEXT_SUBRIP, language);
-            } else if (mTrackType == MEDIA_TRACK_TYPE_SUBTITLE) {
-                String mime = in.readString();
-                mFormat = MediaFormat.createSubtitleFormat(mime, language);
+            if (mTrackType == MEDIA_TRACK_TYPE_SUBTITLE) {
                 mFormat.setInteger(MediaFormat.KEY_IS_AUTOSELECT, in.readInt());
                 mFormat.setInteger(MediaFormat.KEY_IS_DEFAULT, in.readInt());
                 mFormat.setInteger(MediaFormat.KEY_IS_FORCED_SUBTITLE, in.readInt());
-            } else {
-                mFormat = new MediaFormat();
-                mFormat.setString(MediaFormat.KEY_LANGUAGE, language);
             }
         }
 
diff --git a/media/java/android/media/MediaSync.java b/media/java/android/media/MediaSync.java
index dc6760d..ecc87e7 100644
--- a/media/java/android/media/MediaSync.java
+++ b/media/java/android/media/MediaSync.java
@@ -199,6 +199,7 @@
     private final Object mAudioLock = new Object();
     private AudioTrack mAudioTrack = null;
     private List<AudioBuffer> mAudioBuffers = new LinkedList<AudioBuffer>();
+    // this is only used for paused/running decisions, so it is not affected by clock drift
     private float mPlaybackRate = 0.0f;
 
     private long mNativeContext;
@@ -459,36 +460,11 @@
      * @throws IllegalArgumentException if the settings are not supported.
      */
     public void setPlaybackSettings(@NonNull PlaybackSettings settings) {
-        float rate;
-        try {
-            rate = settings.getSpeed();
-
-            // rate is specified
-            if (mAudioTrack != null) {
-                try {
-                    if (rate == 0.0) {
-                        mAudioTrack.pause();
-                    } else {
-                        mAudioTrack.setPlaybackSettings(settings);
-                        mAudioTrack.play();
-                    }
-                } catch (IllegalStateException e) {
-                    throw e;
-                }
-            }
-
-            synchronized(mAudioLock) {
-                mPlaybackRate = rate;
-            }
-            if (mPlaybackRate != 0.0 && mAudioThread != null) {
-                postRenderAudio(0);
-            }
-            native_setPlaybackRate(mPlaybackRate);
-        } catch (IllegalStateException e) {
-            // rate is not specified; still, propagate settings to audio track
-            if (mAudioTrack != null) {
-                mAudioTrack.setPlaybackSettings(settings);
-            }
+        synchronized(mAudioLock) {
+            mPlaybackRate = native_setPlaybackSettings(settings);;
+        }
+        if (mPlaybackRate != 0.0 && mAudioThread != null) {
+            postRenderAudio(0);
         }
     }
 
@@ -501,18 +477,9 @@
      *     been initialized.
      */
     @NonNull
-    public PlaybackSettings getPlaybackSettings() {
-        if (mAudioTrack != null) {
-            return mAudioTrack.getPlaybackSettings();
-        } else {
-            PlaybackSettings settings = new PlaybackSettings();
-            settings.allowDefaults();
-            settings.setSpeed(mPlaybackRate);
-            return settings;
-        }
-    }
+    public native PlaybackSettings getPlaybackSettings();
 
-    private native final void native_setPlaybackRate(float rate);
+    private native float native_setPlaybackSettings(@NonNull PlaybackSettings settings);
 
     /**
      * Sets A/V sync mode.
@@ -523,7 +490,16 @@
      * initialized.
      * @throws IllegalArgumentException if settings are not supported.
      */
-    public native void setSyncSettings(@NonNull SyncSettings settings);
+    public void setSyncSettings(@NonNull SyncSettings settings) {
+        synchronized(mAudioLock) {
+            mPlaybackRate = native_setSyncSettings(settings);;
+        }
+        if (mPlaybackRate != 0.0 && mAudioThread != null) {
+            postRenderAudio(0);
+        }
+    }
+
+    private native float native_setSyncSettings(@NonNull SyncSettings settings);
 
     /**
      * Gets the A/V sync mode.
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 2c61779..5b55a61 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -174,6 +174,8 @@
     } else {  // Throw exception!
         if ( opStatus == (status_t) INVALID_OPERATION ) {
             jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        } else if ( opStatus == (status_t) BAD_VALUE ) {
+            jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
         } else if ( opStatus == (status_t) PERMISSION_DENIED ) {
             jniThrowException(env, "java/lang/SecurityException", NULL);
         } else if ( opStatus != (status_t) OK ) {
@@ -442,8 +444,33 @@
             pbs.audioFallbackModeSet, pbs.audioRate.mFallbackMode,
             pbs.audioStretchModeSet, pbs.audioRate.mStretchMode);
 
-    // TODO: pass playback settings to mediaplayer when audiotrack supports it
-    process_media_player_call(env, thiz, mp->setPlaybackRate(pbs.audioRate.mSpeed), NULL, NULL);
+    AudioPlaybackRate rate;
+    status_t err = mp->getPlaybackSettings(&rate);
+    if (err == OK) {
+        bool updatedRate = false;
+        if (pbs.speedSet) {
+            rate.mSpeed = pbs.audioRate.mSpeed;
+            updatedRate = true;
+        }
+        if (pbs.pitchSet) {
+            rate.mPitch = pbs.audioRate.mPitch;
+            updatedRate = true;
+        }
+        if (pbs.audioFallbackModeSet) {
+            rate.mFallbackMode = pbs.audioRate.mFallbackMode;
+            updatedRate = true;
+        }
+        if (pbs.audioStretchModeSet) {
+            rate.mStretchMode = pbs.audioRate.mStretchMode;
+            updatedRate = true;
+        }
+        if (updatedRate) {
+            err = mp->setPlaybackSettings(rate);
+        }
+    }
+    process_media_player_call(
+            env, thiz, err,
+            "java/lang/IllegalStateException", "unexpected error");
 }
 
 static jobject
@@ -457,15 +484,9 @@
 
     PlaybackSettings pbs;
     AudioPlaybackRate &audioRate = pbs.audioRate;
-
-    audioRate.mSpeed = 1.0f;
-    audioRate.mPitch = 1.0f;
-    audioRate.mFallbackMode = AUDIO_TIMESTRETCH_FALLBACK_DEFAULT;
-    audioRate.mStretchMode = AUDIO_TIMESTRETCH_STRETCH_DEFAULT;
-
-    // TODO: get this from mediaplayer when audiotrack supports it
-    // process_media_player_call(
-    //        env, thiz, mp->getPlaybackSettings(&audioRate), NULL, NULL);
+    process_media_player_call(
+            env, thiz, mp->getPlaybackSettings(&audioRate),
+            "java/lang/IllegalStateException", "unexpected error");
     ALOGV("getPlaybackSettings: %f %f %d %d",
             audioRate.mSpeed, audioRate.mPitch, audioRate.mFallbackMode, audioRate.mStretchMode);
 
@@ -489,13 +510,35 @@
     SyncSettings scs;
     scs.fillFromJobject(env, gSyncSettingsFields, settings);
     ALOGV("setSyncSettings: %d:%d %d:%d %d:%f %d:%f",
-            scs.syncSourceSet, scs.syncSource,
-            scs.audioAdjustModeSet, scs.audioAdjustMode,
-            scs.toleranceSet, scs.tolerance,
-            scs.frameRateSet, scs.frameRate);
+          scs.syncSourceSet, scs.sync.mSource,
+          scs.audioAdjustModeSet, scs.sync.mAudioAdjustMode,
+          scs.toleranceSet, scs.sync.mTolerance,
+          scs.frameRateSet, scs.frameRate);
 
-    // TODO: pass sync settings to mediaplayer when it supports it
-    // process_media_player_call(env, thiz, mp->setSyncSettings(scs), NULL, NULL);
+    AVSyncSettings avsync;
+    float videoFrameRate;
+    status_t err = mp->getSyncSettings(&avsync, &videoFrameRate);
+    if (err == OK) {
+        bool updatedSync = scs.frameRateSet;
+        if (scs.syncSourceSet) {
+            avsync.mSource = scs.sync.mSource;
+            updatedSync = true;
+        }
+        if (scs.audioAdjustModeSet) {
+            avsync.mAudioAdjustMode = scs.sync.mAudioAdjustMode;
+            updatedSync = true;
+        }
+        if (scs.toleranceSet) {
+            avsync.mTolerance = scs.sync.mTolerance;
+            updatedSync = true;
+        }
+        if (updatedSync) {
+            err = mp->setSyncSettings(avsync, scs.frameRateSet ? scs.frameRate : -1.f);
+        }
+    }
+    process_media_player_call(
+            env, thiz, err,
+            "java/lang/IllegalStateException", "unexpected error");
 }
 
 static jobject
@@ -508,21 +551,27 @@
     }
 
     SyncSettings scs;
-    scs.syncSource = 0; // SYNC_SOURCE_DEFAULT
-    scs.audioAdjustMode = 0; // AUDIO_ADJUST_MODE_DEFAULT
-    scs.tolerance = 0.f;
-    scs.frameRate = 0.f;
+    scs.frameRate = -1.f;
+    process_media_player_call(
+            env, thiz, mp->getSyncSettings(&scs.sync, &scs.frameRate),
+            "java/lang/IllegalStateException", "unexpected error");
 
-    // TODO: get this from mediaplayer when it supports it
-    // process_media_player_call(
-    //        env, thiz, mp->getSyncSettings(&scs), NULL, NULL);
     ALOGV("getSyncSettings: %d %d %f %f",
-            scs.syncSource, scs.audioAdjustMode, scs.tolerance, scs.frameRate);
+            scs.sync.mSource, scs.sync.mAudioAdjustMode, scs.sync.mTolerance, scs.frameRate);
+
+    // sanity check settings
+    if (scs.sync.mSource >= AVSYNC_SOURCE_MAX
+            || scs.sync.mAudioAdjustMode >= AVSYNC_AUDIO_ADJUST_MODE_MAX
+            || scs.sync.mTolerance < 0.f
+            || scs.sync.mTolerance >= AVSYNC_TOLERANCE_MAX) {
+        jniThrowException(env,  "java/lang/IllegalStateException", NULL);
+        return NULL;
+    }
 
     scs.syncSourceSet = true;
     scs.audioAdjustModeSet = true;
     scs.toleranceSet = true;
-    scs.frameRateSet = false;
+    scs.frameRateSet = scs.frameRate >= 0.f;
 
     return scs.asJobject(env, gSyncSettingsFields);
 }
diff --git a/media/jni/android_media_MediaSync.cpp b/media/jni/android_media_MediaSync.cpp
index f192262..8ad4b71 100644
--- a/media/jni/android_media_MediaSync.cpp
+++ b/media/jni/android_media_MediaSync.cpp
@@ -21,6 +21,7 @@
 #include "android_media_MediaSync.h"
 
 #include "android_media_AudioTrack.h"
+#include "android_media_PlaybackSettings.h"
 #include "android_media_SyncSettings.h"
 #include "android_runtime/AndroidRuntime.h"
 #include "android_runtime/android_view_Surface.h"
@@ -29,6 +30,7 @@
 
 #include <gui/Surface.h>
 
+#include <media/AudioResamplerPublic.h>
 #include <media/AudioTrack.h>
 #include <media/stagefright/MediaClock.h>
 #include <media/stagefright/MediaSync.h>
@@ -47,6 +49,7 @@
 };
 
 static fields_t gFields;
+static PlaybackSettings::fields_t gPlaybackSettingsFields;
 static SyncSettings::fields_t gSyncSettingsFields;
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -62,10 +65,8 @@
     return mSync->configureSurface(bufferProducer);
 }
 
-status_t JMediaSync::configureAudioTrack(
-        const sp<AudioTrack> &audioTrack,
-        int32_t nativeSampleRateInHz) {
-    return mSync->configureAudioTrack(audioTrack, nativeSampleRateInHz);
+status_t JMediaSync::configureAudioTrack(const sp<AudioTrack> &audioTrack) {
+    return mSync->configureAudioTrack(audioTrack);
 }
 
 status_t JMediaSync::createInputSurface(
@@ -73,14 +74,34 @@
     return mSync->createInputSurface(bufferProducer);
 }
 
-status_t JMediaSync::setPlaybackRate(float rate) {
-    return mSync->setPlaybackRate(rate);
-}
-
 sp<const MediaClock> JMediaSync::getMediaClock() {
     return mSync->getMediaClock();
 }
 
+status_t JMediaSync::setPlaybackSettings(const AudioPlaybackRate& rate) {
+    return mSync->setPlaybackSettings(rate);
+}
+
+void JMediaSync::getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */) {
+    mSync->getPlaybackSettings(rate);
+}
+
+status_t JMediaSync::setSyncSettings(const AVSyncSettings& syncSettings) {
+    return mSync->setSyncSettings(syncSettings);
+}
+
+void JMediaSync::getSyncSettings(AVSyncSettings* syncSettings /* nonnull */) {
+    mSync->getSyncSettings(syncSettings);
+}
+
+status_t JMediaSync::setVideoFrameRateHint(float rate) {
+    return mSync->setVideoFrameRateHint(rate);
+}
+
+float JMediaSync::getVideoFrameRate() {
+    return mSync->getVideoFrameRate();
+}
+
 status_t JMediaSync::updateQueuedAudioData(
         int sizeInBytes, int64_t presentationTimeUs) {
     return mSync->updateQueuedAudioData(sizeInBytes, presentationTimeUs);
@@ -176,7 +197,7 @@
 }
 
 static void android_media_MediaSync_native_configureAudioTrack(
-        JNIEnv *env, jobject thiz, jobject jaudioTrack, jint nativeSampleRateInHz) {
+        JNIEnv *env, jobject thiz, jobject jaudioTrack) {
     ALOGV("android_media_MediaSync_configureAudioTrack");
 
     sp<JMediaSync> sync = getMediaSync(env, thiz);
@@ -194,7 +215,7 @@
         }
     }
 
-    status_t err = sync->configureAudioTrack(audioTrack, nativeSampleRateInHz);
+    status_t err = sync->configureAudioTrack(audioTrack);
 
     if (err == INVALID_OPERATION) {
         throwExceptionAsNecessary(
@@ -287,29 +308,132 @@
     return (jlong)playTimeUs;
 }
 
-static void
-android_media_MediaSync_setSyncSettings(JNIEnv *env, jobject thiz, jobject settings)
-{
+static jfloat android_media_MediaSync_setPlaybackSettings(
+        JNIEnv *env, jobject thiz, jobject settings) {
     sp<JMediaSync> sync = getMediaSync(env, thiz);
     if (sync == NULL) {
         throwExceptionAsNecessary(env, INVALID_OPERATION);
-        return;
+        return (jfloat)0.f;
+    }
+
+    PlaybackSettings pbs;
+    pbs.fillFromJobject(env, gPlaybackSettingsFields, settings);
+    ALOGV("setPlaybackSettings: %d:%f %d:%f %d:%u %d:%u",
+            pbs.speedSet, pbs.audioRate.mSpeed,
+            pbs.pitchSet, pbs.audioRate.mPitch,
+            pbs.audioFallbackModeSet, pbs.audioRate.mFallbackMode,
+            pbs.audioStretchModeSet, pbs.audioRate.mStretchMode);
+
+    AudioPlaybackRate rate;
+    sync->getPlaybackSettings(&rate);
+    bool updatedRate = false;
+    if (pbs.speedSet) {
+        rate.mSpeed = pbs.audioRate.mSpeed;
+        updatedRate = true;
+    }
+    if (pbs.pitchSet) {
+        rate.mPitch = pbs.audioRate.mPitch;
+        updatedRate = true;
+    }
+    if (pbs.audioFallbackModeSet) {
+        rate.mFallbackMode = pbs.audioRate.mFallbackMode;
+        updatedRate = true;
+    }
+    if (pbs.audioStretchModeSet) {
+        rate.mStretchMode = pbs.audioRate.mStretchMode;
+        updatedRate = true;
+    }
+    if (updatedRate) {
+        status_t err = sync->setPlaybackSettings(rate);
+        if (err != OK) {
+            throwExceptionAsNecessary(env, err);
+            return (jfloat)0.f;
+        }
+    }
+
+    sp<const MediaClock> mediaClock = sync->getMediaClock();
+    if (mediaClock == NULL) {
+        return (jfloat)0.f;
+    }
+
+    return (jfloat)mediaClock->getPlaybackRate();
+}
+
+static jobject android_media_MediaSync_getPlaybackSettings(
+        JNIEnv *env, jobject thiz) {
+    sp<JMediaSync> sync = getMediaSync(env, thiz);
+    if (sync == NULL) {
+        throwExceptionAsNecessary(env, INVALID_OPERATION);
+        return NULL;
+    }
+
+    PlaybackSettings pbs;
+    AudioPlaybackRate &audioRate = pbs.audioRate;
+    sync->getPlaybackSettings(&audioRate);
+    ALOGV("getPlaybackSettings: %f %f %d %d",
+            audioRate.mSpeed, audioRate.mPitch, audioRate.mFallbackMode, audioRate.mStretchMode);
+
+    pbs.speedSet = true;
+    pbs.pitchSet = true;
+    pbs.audioFallbackModeSet = true;
+    pbs.audioStretchModeSet = true;
+
+    return pbs.asJobject(env, gPlaybackSettingsFields);
+}
+
+static jfloat android_media_MediaSync_setSyncSettings(
+        JNIEnv *env, jobject thiz, jobject settings) {
+    sp<JMediaSync> sync = getMediaSync(env, thiz);
+    if (sync == NULL) {
+        throwExceptionAsNecessary(env, INVALID_OPERATION);
+        return (jfloat)0.f;
     }
 
     SyncSettings scs;
     scs.fillFromJobject(env, gSyncSettingsFields, settings);
     ALOGV("setSyncSettings: %d:%d %d:%d %d:%f %d:%f",
-            scs.syncSourceSet, scs.syncSource,
-            scs.audioAdjustModeSet, scs.audioAdjustMode,
-            scs.toleranceSet, scs.tolerance,
+            scs.syncSourceSet, scs.sync.mSource,
+            scs.audioAdjustModeSet, scs.sync.mAudioAdjustMode,
+            scs.toleranceSet, scs.sync.mTolerance,
             scs.frameRateSet, scs.frameRate);
 
-    // TODO: pass sync settings to mediasync when it supports it
+    AVSyncSettings avsync;
+    sync->getSyncSettings(&avsync);
+    bool updatedSync = false;
+    status_t err = OK;
+    if (scs.syncSourceSet) {
+        avsync.mSource = scs.sync.mSource;
+        updatedSync = true;
+    }
+    if (scs.audioAdjustModeSet) {
+        avsync.mAudioAdjustMode = scs.sync.mAudioAdjustMode;
+        updatedSync = true;
+    }
+    if (scs.toleranceSet) {
+        avsync.mTolerance = scs.sync.mTolerance;
+        updatedSync = true;
+    }
+    if (updatedSync) {
+        err = sync->setSyncSettings(avsync);
+    }
+
+    if (scs.frameRateSet && err == OK) {
+        err = sync->setVideoFrameRateHint(scs.frameRate);
+    }
+    if (err != OK) {
+        throwExceptionAsNecessary(env, err);
+        return (jfloat)0.f;
+    }
+
+    sp<const MediaClock> mediaClock = sync->getMediaClock();
+    if (mediaClock == NULL) {
+        return (jfloat)0.f;
+    }
+
+    return (jfloat)mediaClock->getPlaybackRate();
 }
 
-static jobject
-android_media_MediaSync_getSyncSettings(JNIEnv *env, jobject thiz)
-{
+static jobject android_media_MediaSync_getSyncSettings(JNIEnv *env, jobject thiz) {
     sp<JMediaSync> sync = getMediaSync(env, thiz);
     if (sync == NULL) {
         throwExceptionAsNecessary(env, INVALID_OPERATION);
@@ -317,21 +441,25 @@
     }
 
     SyncSettings scs;
-    scs.syncSource = 0; // SYNC_SOURCE_DEFAULT
-    scs.audioAdjustMode = 0; // AUDIO_ADJUST_MODE_DEFAULT
-    scs.tolerance = 0.f;
-    scs.frameRate = 0.f;
+    sync->getSyncSettings(&scs.sync);
+    scs.frameRate = sync->getVideoFrameRate();
 
-    // TODO: get this from mediaplayer when it supports it
-    // process_media_player_call(
-    //        env, thiz, mp->getSyncSettings(&scs), NULL, NULL);
     ALOGV("getSyncSettings: %d %d %f %f",
-            scs.syncSource, scs.audioAdjustMode, scs.tolerance, scs.frameRate);
+            scs.sync.mSource, scs.sync.mAudioAdjustMode, scs.sync.mTolerance, scs.frameRate);
+
+    // sanity check settings
+    if (scs.sync.mSource >= AVSYNC_SOURCE_MAX
+            || scs.sync.mAudioAdjustMode >= AVSYNC_AUDIO_ADJUST_MODE_MAX
+            || scs.sync.mTolerance < 0.f
+            || scs.sync.mTolerance >= AVSYNC_TOLERANCE_MAX) {
+        throwExceptionAsNecessary(env, INVALID_OPERATION);
+        return NULL;
+    }
 
     scs.syncSourceSet = true;
     scs.audioAdjustModeSet = true;
     scs.toleranceSet = true;
-    scs.frameRateSet = false;
+    scs.frameRateSet = scs.frameRate >= 0.f;
 
     return scs.asJobject(env, gSyncSettingsFields);
 }
@@ -359,6 +487,7 @@
     CHECK(gFields.mediaTimestampClockRateID != NULL);
 
     gSyncSettingsFields.init(env);
+    gPlaybackSettingsFields.init(env);
 }
 
 static void android_media_MediaSync_native_setup(JNIEnv *env, jobject thiz) {
@@ -367,21 +496,6 @@
     setMediaSync(env, thiz, sync);
 }
 
-static void android_media_MediaSync_native_setPlaybackRate(
-        JNIEnv *env, jobject thiz, jfloat rate) {
-    sp<JMediaSync> sync = getMediaSync(env, thiz);
-    if (sync == NULL) {
-        throwExceptionAsNecessary(env, INVALID_OPERATION);
-        return;
-    }
-
-    status_t err = sync->setPlaybackRate(rate);
-    if (err != NO_ERROR) {
-        throwExceptionAsNecessary(env, err);
-        return;
-    }
-}
-
 static void android_media_MediaSync_native_finalize(JNIEnv *env, jobject thiz) {
     android_media_MediaSync_release(env, thiz);
 }
@@ -416,11 +530,17 @@
 
     { "native_release", "()V", (void *)android_media_MediaSync_release },
 
-    { "native_setPlaybackRate", "(F)V", (void *)android_media_MediaSync_native_setPlaybackRate },
+    { "native_setPlaybackSettings", "(Landroid/media/PlaybackSettings;)F",
+      (void *)android_media_MediaSync_setPlaybackSettings },
 
-    { "setSyncSettings", "(Landroid/media/SyncSettings;)V", (void *)android_media_MediaSync_setSyncSettings},
+    { "getPlaybackSettings", "()Landroid/media/PlaybackSettings;",
+      (void *)android_media_MediaSync_getPlaybackSettings },
 
-    { "getSyncSettings", "()Landroid/media/SyncSettings;", (void *)android_media_MediaSync_getSyncSettings},
+    { "native_setSyncSettings", "(Landroid/media/SyncSettings;)F",
+      (void *)android_media_MediaSync_setSyncSettings },
+
+    { "getSyncSettings", "()Landroid/media/SyncSettings;",
+      (void *)android_media_MediaSync_getSyncSettings },
 
     { "native_finalize", "()V", (void *)android_media_MediaSync_native_finalize },
 };
diff --git a/media/jni/android_media_MediaSync.h b/media/jni/android_media_MediaSync.h
index cf81a72..80f5d63 100644
--- a/media/jni/android_media_MediaSync.h
+++ b/media/jni/android_media_MediaSync.h
@@ -18,11 +18,13 @@
 #define _ANDROID_MEDIA_MEDIASYNC_H_
 
 #include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/MediaSync.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
 
 namespace android {
 
+struct AudioPlaybackRate;
 class AudioTrack;
 struct IGraphicBufferProducer;
 struct MediaClock;
@@ -32,17 +34,21 @@
     JMediaSync();
 
     status_t configureSurface(const sp<IGraphicBufferProducer> &bufferProducer);
-    status_t configureAudioTrack(
-            const sp<AudioTrack> &audioTrack, int32_t nativeSampleRateInHz);
+    status_t configureAudioTrack(const sp<AudioTrack> &audioTrack);
 
     status_t createInputSurface(sp<IGraphicBufferProducer>* bufferProducer);
 
     status_t updateQueuedAudioData(int sizeInBytes, int64_t presentationTimeUs);
 
-    status_t setPlaybackRate(float rate);
-
     status_t getPlayTimeForPendingAudioFrames(int64_t *outTimeUs);
 
+    status_t setPlaybackSettings(const AudioPlaybackRate& rate);
+    void getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */);
+    status_t setSyncSettings(const AVSyncSettings& syncSettings);
+    void getSyncSettings(AVSyncSettings* syncSettings /* nonnull */);
+    status_t setVideoFrameRateHint(float rate);
+    float getVideoFrameRate();
+
     sp<const MediaClock> getMediaClock();
 
 protected:
diff --git a/media/jni/android_media_SyncSettings.cpp b/media/jni/android_media_SyncSettings.cpp
index 2f0605e..5da35e7 100644
--- a/media/jni/android_media_SyncSettings.cpp
+++ b/media/jni/android_media_SyncSettings.cpp
@@ -57,9 +57,9 @@
 }
 
 void SyncSettings::fillFromJobject(JNIEnv *env, const fields_t& fields, jobject settings) {
-    syncSource = env->GetIntField(settings, fields.sync_source);
-    audioAdjustMode = env->GetIntField(settings, fields.audio_adjust_mode);
-    tolerance = env->GetFloatField(settings, fields.tolerance);
+    sync.mSource = (AVSyncSource)env->GetIntField(settings, fields.sync_source);
+    sync.mAudioAdjustMode = (AVSyncAudioAdjustMode)env->GetIntField(settings, fields.audio_adjust_mode);
+    sync.mTolerance = env->GetFloatField(settings, fields.tolerance);
     frameRate = env->GetFloatField(settings, fields.frame_rate);
     int set = env->GetIntField(settings, fields.set);
 
@@ -74,9 +74,9 @@
     if (settings == NULL) {
         return NULL;
     }
-    env->SetIntField(settings, fields.sync_source, (jint)syncSource);
-    env->SetIntField(settings, fields.audio_adjust_mode, (jint)audioAdjustMode);
-    env->SetFloatField(settings, fields.tolerance, (jfloat)tolerance);
+    env->SetIntField(settings, fields.sync_source, (jint)sync.mSource);
+    env->SetIntField(settings, fields.audio_adjust_mode, (jint)sync.mAudioAdjustMode);
+    env->SetFloatField(settings, fields.tolerance, (jfloat)sync.mTolerance);
     env->SetFloatField(settings, fields.frame_rate, (jfloat)frameRate);
     env->SetIntField(
             settings, fields.set,
diff --git a/media/jni/android_media_SyncSettings.h b/media/jni/android_media_SyncSettings.h
index 586533f..23530db 100644
--- a/media/jni/android_media_SyncSettings.h
+++ b/media/jni/android_media_SyncSettings.h
@@ -19,13 +19,12 @@
 
 #include "jni.h"
 
+#include <media/stagefright/MediaSync.h>
+
 namespace android {
 
 struct SyncSettings {
-    // keep this here until it is implemented
-    int syncSource;
-    int audioAdjustMode;
-    float tolerance;
+    AVSyncSettings sync;
     float frameRate;
 
     bool syncSourceSet;
diff --git a/native/android/sensor.cpp b/native/android/sensor.cpp
index 73b52aa..4e7c6be 100644
--- a/native/android/sensor.cpp
+++ b/native/android/sensor.cpp
@@ -38,11 +38,6 @@
 
 /*****************************************************************************/
 
-ASensorManager* ASensorManager_getInstance()
-{
-    return &SensorManager::getInstance();
-}
-
 int ASensorManager_getSensorList(ASensorManager* manager,
         ASensorList* list)
 {
diff --git a/packages/IntentFilterVerifier/Android.mk b/packages/IntentFilterVerifier/Android.mk
deleted file mode 100644
index 99feda5..0000000
--- a/packages/IntentFilterVerifier/Android.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-# Build the IntentFilterVerifier.
-include $(CLEAR_VARS)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-        volley \
-
-LOCAL_JAVA_LIBRARIES += org.apache.http.legacy
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := IntentFilterVerifier
-
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_PROGUARD_FLAGS := $(proguard.flags)
-
-include $(BUILD_PACKAGE)
-
-# Build the test package.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/packages/IntentFilterVerifier/AndroidManifest.xml b/packages/IntentFilterVerifier/AndroidManifest.xml
deleted file mode 100644
index 3829cc5..0000000
--- a/packages/IntentFilterVerifier/AndroidManifest.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 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.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.verifier.intentfilter"
-        coreApp="true">
-    <uses-permission android:name="android.permission.INTENT_FILTER_VERIFICATION_AGENT"/>
-    <uses-permission android:name="android.permission.INTERNET"/>
-    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
-
-    <application
-            android:label="@string/service_name"
-            android:allowBackup="false">
-
-        <receiver
-                android:name="com.android.verifier.intentfilter.IntentVerificationReceiver"
-                android:permission="android.permission.BIND_INTENT_FILTER_VERIFIER" >
-            <intent-filter
-                    android:priority="-1" >
-                <action android:name="android.intent.action.INTENT_FILTER_NEEDS_VERIFICATION" />
-                <data android:mimeType="application/vnd.android.package-archive" />
-            </intent-filter>
-        </receiver>
-
-        <service android:name=".IntentVerificationService"
-                 android:label="@string/service_name"
-                 android:exported="false"/>
-
-    </application>
-
-</manifest>
diff --git a/packages/IntentFilterVerifier/CleanSpec.mk b/packages/IntentFilterVerifier/CleanSpec.mk
deleted file mode 100644
index e4575ae..0000000
--- a/packages/IntentFilterVerifier/CleanSpec.mk
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright (C) 2015 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.
-#
-
-# If you don't need to do a full clean build but would like to touch
-# a file or delete some intermediate files, add a clean step to the end
-# of the list.  These steps will only be run once, if they haven't been
-# run before.
-#
-# E.g.:
-#     $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
-#     $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
-#
-# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
-# files that are missing or have been moved.
-#
-# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
-# Use $(OUT_DIR) to refer to the "out" directory.
-#
-# If you need to re-do something that's already mentioned, just copy
-# the command and add it to the bottom of the list.  E.g., if a change
-# that you made last week required touching a file and a change you
-# made today requires touching the same file, just copy the old
-# touch step and add it to the end of the list.
-#
-# *****************************************************************
-# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THE BANNER
-# *****************************************************************
-
-# For example:
-#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
-#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
-#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
-#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
-
-# ******************************************************************
-# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
-# ******************************************************************
diff --git a/packages/IntentFilterVerifier/proguard.flags b/packages/IntentFilterVerifier/proguard.flags
deleted file mode 100644
index 6e4bec3..0000000
--- a/packages/IntentFilterVerifier/proguard.flags
+++ /dev/null
@@ -1 +0,0 @@
--verbose
\ No newline at end of file
diff --git a/packages/IntentFilterVerifier/res/values/strings.xml b/packages/IntentFilterVerifier/res/values/strings.xml
deleted file mode 100644
index 22f3cd5..0000000
--- a/packages/IntentFilterVerifier/res/values/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Package name shown to users when they look at installed applications
-         and running processes. This service verifies packages that are
-         requested to be installed. [CHAR LIMIT=50] -->
-    <string name="service_name">Basic Intent Filter Verification Service</string>
-
-</resources>
diff --git a/packages/IntentFilterVerifier/src/com/android/verifier/intentfilter/IntentVerificationReceiver.java b/packages/IntentFilterVerifier/src/com/android/verifier/intentfilter/IntentVerificationReceiver.java
deleted file mode 100644
index de25f8c..0000000
--- a/packages/IntentFilterVerifier/src/com/android/verifier/intentfilter/IntentVerificationReceiver.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2015 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.verifier.intentfilter;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.os.Bundle;
-import android.util.Log;
-import android.util.Slog;
-
-import java.util.Arrays;
-import java.util.List;
-
-public class IntentVerificationReceiver extends BroadcastReceiver {
-    static final String TAG = IntentVerificationReceiver.class.getName();
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        final String action = intent.getAction();
-        if (Intent.ACTION_INTENT_FILTER_NEEDS_VERIFICATION.equals(action)) {
-            Bundle extras = intent.getExtras();
-            if (extras != null) {
-                int verificationId = extras.getInt(
-                        PackageManager.EXTRA_INTENT_FILTER_VERIFICATION_ID);
-                String hosts = extras.getString(
-                        PackageManager.EXTRA_INTENT_FILTER_VERIFICATION_HOSTS);
-
-                Log.d(TAG, "Received IntentFilter verification broadcast with verificationId: "
-                        + verificationId);
-
-                if (canDoVerification(context)) {
-                    Intent serviceIntent = new Intent(context, IntentVerificationService.class);
-                    serviceIntent.fillIn(intent, 0);
-                    serviceIntent.putExtras(intent.getExtras());
-
-                    Slog.d(TAG, "Starting Intent Verification Service.");
-
-                    context.startService(serviceIntent);
-                } else {
-                    sendVerificationFailure(context, verificationId, hosts);
-                }
-            }
-
-        } else {
-            Log.w(TAG, "Unexpected action: " + action);
-        }
-    }
-
-    private void sendVerificationFailure(Context context, int verificationId, String hosts) {
-        List<String> list = Arrays.asList(hosts.split(" "));
-        context.getPackageManager().verifyIntentFilter(
-                verificationId, PackageManager.INTENT_FILTER_VERIFICATION_FAILURE, list);
-
-        Log.d(TAG, "No network! Failing IntentFilter verification with verificationId: " +
-                verificationId + " and hosts: " + hosts);
-    }
-
-    private boolean canDoVerification(Context context) {
-        return hasNetwork(context);
-    }
-
-    public boolean hasNetwork(Context context) {
-        ConnectivityManager cm =
-                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
-        if (cm != null) {
-            NetworkInfo info = cm.getActiveNetworkInfo();
-            return (info != null) && info.isConnected();
-        } else {
-            return false;
-        }
-    }
-}
diff --git a/packages/IntentFilterVerifier/src/com/android/verifier/intentfilter/IntentVerificationRequest.java b/packages/IntentFilterVerifier/src/com/android/verifier/intentfilter/IntentVerificationRequest.java
deleted file mode 100644
index 8f9c86f..0000000
--- a/packages/IntentFilterVerifier/src/com/android/verifier/intentfilter/IntentVerificationRequest.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2015 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.verifier.intentfilter;
-
-import com.android.volley.Response;
-import com.android.volley.toolbox.JsonArrayRequest;
-import org.json.JSONArray;
-
-public class IntentVerificationRequest extends JsonArrayRequest {
-
-    public IntentVerificationRequest(String url, Response.Listener<JSONArray> listener,
-            Response.ErrorListener errorListener) {
-        super(url, listener, errorListener);
-    }
-}
diff --git a/packages/IntentFilterVerifier/src/com/android/verifier/intentfilter/IntentVerificationService.java b/packages/IntentFilterVerifier/src/com/android/verifier/intentfilter/IntentVerificationService.java
deleted file mode 100644
index 3e4db6c..0000000
--- a/packages/IntentFilterVerifier/src/com/android/verifier/intentfilter/IntentVerificationService.java
+++ /dev/null
@@ -1,468 +0,0 @@
-/*
- * Copyright (C) 2015 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.verifier.intentfilter;
-
-import android.app.Service;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.Signature;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.text.TextUtils;
-import android.util.Log;
-import android.util.Slog;
-import com.android.volley.RequestQueue;
-import com.android.volley.Response;
-import com.android.volley.VolleyError;
-import com.android.volley.toolbox.Volley;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Set;
-
-public class IntentVerificationService extends Service {
-    private static final String TAG = "IntentVerificationService";
-
-    private static final String WELL_KNOWN_ASSOCIATIONS_JSON = "/.well-known/associations.json";
-    private static final String DEFAULT_SCHEME = "https";
-
-    private static final String JSON_KEY_TARGET = "target";
-    private static final String JSON_KEY_NAMESPACE = "namespace";
-    private static final String JSON_KEY_PACKAGE_NAME = "package_name";
-    private static final String JSON_KEY_CERT_FINGERPRINTS = "sha256_cert_fingerprints";
-
-    private static final String JSON_VAL_ANDROID_APP = "android_app";
-
-    private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
-            'A', 'B', 'C', 'D', 'E', 'F' };
-
-    private ConnectivityManager mConnectivityManager;
-    private Looper mHandlerLooper;
-    private VerificationHandler mHandler;
-    private RequestQueue mRequestQueue;
-
-    private static class VerificationState {
-        public final int verificationId;
-        public final String hosts;
-        public final String packageName;
-        public final Set<String> fingerprints;
-        public int responseCode = PackageManager.INTENT_FILTER_VERIFICATION_SUCCESS;
-        public int counter;
-        public int numberOfHosts;
-        public ArrayList<String> failedHosts = new ArrayList<>();
-
-        private final Object lock = new Object();
-
-        public VerificationState(int id, String h, String p, Set<String> fps) {
-            verificationId = id;
-            hosts = h;
-            packageName = p;
-            fingerprints = fps;
-            numberOfHosts = hosts.split(" ").length;
-        }
-        public boolean setResponseCodeAndCheckMax(int code) {
-            synchronized (lock) {
-                if (code == PackageManager.INTENT_FILTER_VERIFICATION_FAILURE) {
-                    responseCode = code;
-                    counter++;
-                } else if (code == PackageManager.INTENT_FILTER_VERIFICATION_SUCCESS) {
-                    counter++;
-                }
-                return (counter == numberOfHosts);
-            }
-        }
-
-        public void addFailedHost(String host) {
-            synchronized (failedHosts) {
-                failedHosts.add(host);
-            }
-        }
-
-        public ArrayList<String> getFailedHosts() {
-            return failedHosts;
-        }
-    }
-
-    private HashMap<Integer, VerificationState> mVerificationMap =
-            new HashMap<Integer, VerificationState>();
-
-    private class VerificationHandler extends Handler {
-        private static final int MSG_STOP_SERVICE = 0;
-        private static final int MSG_VERIFY_INTENT_START = 1;
-        private static final int MSG_VERIFY_INTENT_DONE = 2;
-
-        private static final long SHUTDOWN_DELAY_MILLIS = 8 * 1000;
-
-        private final Context mContext;
-
-        public VerificationHandler(Context context, Looper looper) {
-            super(looper);
-
-            mContext = context;
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_VERIFY_INTENT_START:
-                    final Intent intent = (Intent) msg.obj;
-                    Bundle extras = intent.getExtras();
-                    boolean immediate = false;
-
-                    if (extras != null) {
-                        immediate = doVerification(extras);
-                    }
-
-                    // There was no network, so we can stop soon
-                    if (immediate) {
-                        stopDelayed();
-                    }
-                    break;
-
-                case MSG_VERIFY_INTENT_DONE:
-                    VerificationState vs = (VerificationState) msg.obj;
-                    processVerificationDone(mContext, vs);
-                    clearVerificationState(vs);
-                    break;
-
-                case MSG_STOP_SERVICE:
-                    stopSelf();
-                    break;
-
-                default:
-                    Slog.i(TAG, "Unknown message posted " + msg.toString());
-                    break;
-
-            }
-        }
-
-        private void stopDelayed() {
-            removeMessages(MSG_STOP_SERVICE);
-            sendEmptyMessageDelayed(MSG_STOP_SERVICE, SHUTDOWN_DELAY_MILLIS);
-        }
-    }
-
-    private VerificationState getVerificationState(int id, String hosts, String packageName,
-            Set<String> fingerprints) {
-        synchronized (mVerificationMap) {
-            VerificationState vs = mVerificationMap.get(id);
-            if (vs == null) {
-                vs = new VerificationState(id, hosts, packageName, fingerprints);
-            }
-            return vs;
-        }
-    }
-
-    private void clearVerificationState(VerificationState vs) {
-        mVerificationMap.remove(vs);
-    }
-
-    private boolean doVerification(Bundle extras) {
-        String scheme = extras.getString(PackageManager.EXTRA_INTENT_FILTER_VERIFICATION_URI_SCHEME);
-        if (TextUtils.isEmpty(scheme)) {
-            scheme = DEFAULT_SCHEME;
-        }
-
-        int verificationId = extras.getInt(PackageManager.EXTRA_INTENT_FILTER_VERIFICATION_ID);
-        String hosts = extras.getString(PackageManager.EXTRA_INTENT_FILTER_VERIFICATION_HOSTS);
-        String packageName = extras.getString(
-                PackageManager.EXTRA_INTENT_FILTER_VERIFICATION_PACKAGE_NAME);
-
-        Set<String> fingerprints = getFingerprints(packageName);
-
-        Log.d(TAG, "Received IntentFilter verification broadcast with verificationId:" +
-                verificationId + " hosts:'" + hosts + "' scheme:" + scheme);
-
-        VerificationState vs = getVerificationState(verificationId, hosts, packageName,
-                fingerprints);
-
-        if (hasNetwork()) {
-            sendNetworkVerifications(scheme, vs);
-            return false;
-        }
-
-        // No network, so fail immediately
-        sendFailureResponseIfNeeded(vs);
-
-        return true;
-    }
-
-    private Set<String> getFingerprints(String packageName) {
-        Context context = getApplicationContext();
-        try {
-            Signature[] signatures = context.getPackageManager().getPackageInfo(packageName,
-                    PackageManager.GET_SIGNATURES).signatures;
-            if (signatures.length > 0) {
-                HashSet<String> result = new HashSet<String>();
-                for (Signature sig : signatures) {
-                    String fingerprint = computeNormalizedSha256Fingerprint(sig.toByteArray());
-                    result.add(fingerprint);
-                }
-                return result;
-            }
-        } catch (PackageManager.NameNotFoundException e) {
-            Log.e(TAG, "Cannot get signatures for package name: " + packageName);
-        }
-        return Collections.EMPTY_SET;
-    }
-
-    private static String computeNormalizedSha256Fingerprint(byte[] signature) {
-        MessageDigest digester;
-        try {
-            digester = MessageDigest.getInstance("SHA-256");
-        } catch (NoSuchAlgorithmException e) {
-            throw new AssertionError("No SHA-256 implementation found.");
-        }
-        digester.update(signature);
-        return byteArrayToHexString(digester.digest());
-    }
-
-    private static String byteArrayToHexString(byte[] array) {
-        if (array.length == 0) {
-            return "";
-        }
-        char[] buf = new char[array.length * 3 - 1];
-
-        int bufIndex = 0;
-        for (int i = 0; i < array.length; i++) {
-            byte b = array[i];
-            if (i > 0) {
-                buf[bufIndex++] = ':';
-            }
-            buf[bufIndex++] = HEX_DIGITS[(b >>> 4) & 0x0F];
-            buf[bufIndex++] = HEX_DIGITS[b & 0x0F];
-        }
-        return new String(buf);
-    }
-
-    private static String getAssociationPath() {
-        return WELL_KNOWN_ASSOCIATIONS_JSON;
-    }
-
-    private void sendNetworkVerifications(String scheme, final VerificationState vs) {
-        final int verificationId = vs.verificationId;
-        final String hosts = vs.hosts;
-
-        String[] array = hosts.split(" ");
-        for (final String host : array) {
-            try {
-                final URL url = new URL(scheme, host, getAssociationPath());
-                final String urlStr = url.toString();
-                Log.d(TAG, "Using verification URL: " + urlStr);
-                IntentVerificationRequest req = new IntentVerificationRequest(urlStr,
-                    new Response.Listener<JSONArray>() {
-                        @Override
-                        public void onResponse(JSONArray response) {
-                            Log.d(TAG, "From: " + urlStr + " received response: "
-                                    + response.toString());
-                            handleResponse(vs, host, response);
-                        }
-                    }, new Response.ErrorListener() {
-                        @Override
-                        public void onErrorResponse(VolleyError error) {
-                            Slog.d(TAG, "From: " + urlStr + " got error: " + error.getMessage()
-                                    + (error.networkResponse != null ? " with status code: "
-                                    + error.networkResponse.statusCode : ""));
-                            handleError(vs, host);
-                        }
-                    }
-                );
-                mRequestQueue.add(req);
-            } catch (MalformedURLException e) {
-                Log.w(TAG, "Cannot send verificationId: " + verificationId + " to host: " + host);
-            }
-        }
-    }
-
-    private void handleError(VerificationState vs, String host) {
-        vs.addFailedHost(host);
-        sendFailureResponseIfNeeded(vs);
-    }
-
-    private void handleResponse(VerificationState vs, String host, JSONArray response) {
-        try {
-            if (response.length() == 0) {
-                Log.d(TAG, "Domain response is empty!");
-                handleError(vs, host);
-                return;
-            }
-
-            JSONObject firstRelation = (JSONObject) response.get(0);
-            if (firstRelation == null) {
-                Log.d(TAG, "Domain response is should have a relation!");
-                handleError(vs, host);
-                return;
-            }
-
-            JSONObject target = (JSONObject) firstRelation.get(JSON_KEY_TARGET);
-            if (target == null) {
-                Log.d(TAG, "Domain response target is empty!");
-                handleError(vs, host);
-                return;
-            }
-
-            String nameSpace = target.getString(JSON_KEY_NAMESPACE);
-            if (TextUtils.isEmpty(nameSpace) || !nameSpace.equals(JSON_VAL_ANDROID_APP)) {
-                Log.d(TAG, "Domain response target name space is not valid: " + nameSpace);
-                handleError(vs, host);
-                return;
-            }
-
-            String packageName = target.getString(JSON_KEY_PACKAGE_NAME);
-            JSONArray certFingerprints = target.getJSONArray(JSON_KEY_CERT_FINGERPRINTS);
-
-            // Early exits is the JSON response is not correct for the package name or signature
-            if (TextUtils.isEmpty(packageName)) {
-                Log.d(TAG, "Domain response has empty package name!");
-                handleError(vs, host);
-                return;
-            }
-            if (certFingerprints.length() == 0) {
-                Log.d(TAG, "Domain response has empty cert signature!");
-                handleError(vs, host);
-                return;
-            }
-            // Now do the real test on package name and signature
-            if (!packageName.equalsIgnoreCase(vs.packageName)) {
-                Log.d(TAG, "Domain response has package name mismatch!" + packageName +
-                        " vs " + vs.packageName);
-                handleError(vs, host);
-                return;
-            }
-            final int count = certFingerprints.length();
-            for (int i = 0; i < count; i++) {
-                String fingerprint = certFingerprints.getString(i);
-                if (!vs.fingerprints.contains(fingerprint)) {
-                    Log.d(TAG, "Domain response has cert fingerprint mismatch! " +
-                            "The domain fingerprint '" + fingerprint + "' is not from the App");
-                    handleError(vs, host);
-                    return;
-                }
-            }
-            sendSuccessResponseIfNeeded(vs);
-        } catch (JSONException e) {
-            Log.d(TAG, "Domain response is not well formed", e);
-            handleError(vs, host);
-        }
-    }
-
-    private void sendSuccessResponseIfNeeded(VerificationState vs) {
-        if (vs.setResponseCodeAndCheckMax(PackageManager.INTENT_FILTER_VERIFICATION_SUCCESS)) {
-            sendMessage(vs);
-        }
-    }
-
-    private void sendFailureResponseIfNeeded(VerificationState vs) {
-        if (vs.setResponseCodeAndCheckMax(PackageManager.INTENT_FILTER_VERIFICATION_FAILURE)) {
-            sendMessage(vs);
-        }
-    }
-
-    private void sendMessage(VerificationState vs) {
-        Message msg = mHandler.obtainMessage(VerificationHandler.MSG_VERIFY_INTENT_DONE);
-        msg.obj = vs;
-        mHandler.sendMessage(msg);
-    }
-
-    private void processVerificationDone(Context context, VerificationState state) {
-        int verificationId = state.verificationId;
-        String hosts = state.hosts;
-        int responseCode = state.responseCode;
-
-        final PackageManager pm = context.getPackageManager();
-
-        // Callback the PackageManager
-        pm.verifyIntentFilter(verificationId, responseCode, state.getFailedHosts());
-        Log.d(TAG, "IntentFilter with verificationId: " + verificationId + " and hosts: " +
-                hosts + " got verification code: " + responseCode);
-    }
-
-    /**
-     * We only connect to this service from the same process.
-     */
-    public class LocalBinder extends Binder {
-        IntentVerificationService getService() { return IntentVerificationService.this; }
-    }
-
-    private final IBinder mBinder = new LocalBinder();
-
-    @Override
-    public IBinder onBind(Intent intent) {
-        return mBinder;
-    }
-
-    @Override
-    public int onStartCommand(Intent intent, int flags, int startId) {
-        Slog.i(TAG, "Received start id " + startId + ": " + intent);
-
-        final Message msg = mHandler.obtainMessage(VerificationHandler.MSG_VERIFY_INTENT_START);
-        msg.obj = intent;
-        mHandler.sendMessage(msg);
-
-        return START_STICKY;
-    }
-
-    @Override
-    public void onCreate() {
-        super.onCreate();
-
-        Slog.d(TAG, "Starting up...");
-
-        final HandlerThread handlerThread = new HandlerThread("IntentVerificationService");
-        handlerThread.start();
-        mHandlerLooper = handlerThread.getLooper();
-
-        mHandler = new VerificationHandler(getApplicationContext(), mHandlerLooper);
-
-        mRequestQueue = Volley.newRequestQueue(this);
-        mRequestQueue.start();
-
-        mConnectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
-    }
-
-    @Override
-    public void onDestroy() {
-        super.onDestroy();
-
-        Slog.d(TAG, "Shutting down...");
-
-        mHandlerLooper.quit();
-        mRequestQueue.stop();
-    }
-
-    private boolean hasNetwork() {
-        NetworkInfo info = mConnectivityManager.getActiveNetworkInfo();
-        return (info != null) && info.isConnected();
-    }
-}
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index a0ef5e2..b0b78f2 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -16,9 +16,6 @@
 */
 -->
 <resources>
-    <!-- Margin at the edge of the screen to ignore touch events for in the windowshade. -->
-    <dimen name="status_bar_edge_ignore">5dp</dimen>
-
     <!-- Recent Applications parameters -->
     <!-- Upper width limit for application icon -->
     <dimen name="status_bar_recents_app_icon_max_width">48dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index f3a2912..00b8df2 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -400,6 +400,8 @@
     <string name="accessibility_recents_all_items_dismissed">All recent applications dismissed.</string>
     <!-- Content description to tell the user an application has been launched from recents -->
     <string name="accessibility_recents_item_launched">Starting <xliff:g id="app" example="Calendar">%s</xliff:g>.</string>
+    <!-- Content description of individual recents task. -->
+    <string name="accessibility_recents_task_header"><xliff:g id="app" example="Chrome">%1$s</xliff:g> <xliff:g id="activity_label" example="www.google.com">%2$s</xliff:g></string>
     <!-- Content description to tell the user a notification has been removed from the notification shade -->
     <string name="accessibility_notification_dismissed">Notification dismissed.</string>
 
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistGestureManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistGestureManager.java
index 36be355..d9f2324 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistGestureManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistGestureManager.java
@@ -196,7 +196,7 @@
 
     private boolean getVoiceInteractorSupportsAssistGesture() {
         try {
-            return mVoiceInteractionManagerService.activeServiceSupportsAssistGesture();
+            return mVoiceInteractionManagerService.activeServiceSupportsAssist();
         } catch (RemoteException e) {
             Log.w(TAG, "Failed to call activeServiceSupportsAssistGesture", e);
             return false;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index d60df9c..e3fb16a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -438,6 +438,33 @@
         return info.loadLabel(mPm).toString();
     }
 
+    /** Returns the application label */
+    public String getApplicationLabel(Intent baseIntent, int userId) {
+        if (mPm == null) return null;
+
+        // If we are mocking, then return a mock label
+        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
+            return "Recent Task";
+        }
+
+        ResolveInfo ri = mPm.resolveActivityAsUser(baseIntent, 0, userId);
+        CharSequence label = (ri != null) ? ri.loadLabel(mPm) : null;
+        return (label != null) ? label.toString() : null;
+    }
+
+    /** Returns the content description for a given task */
+    public String getContentDescription(Intent baseIntent, int userId, String activityLabel,
+            Resources res) {
+        String applicationLabel = getApplicationLabel(baseIntent, userId);
+        if (applicationLabel == null) {
+            return getBadgedLabel(activityLabel, userId);
+        }
+        String badgedApplicationLabel = getBadgedLabel(applicationLabel, userId);
+        return applicationLabel.equals(activityLabel) ? badgedApplicationLabel
+                : res.getString(R.string.accessibility_recents_task_header,
+                        badgedApplicationLabel, activityLabel);
+    }
+
     /**
      * Returns the activity icon for the ActivityInfo for a user, badging if
      * necessary.
@@ -464,6 +491,16 @@
         return icon;
     }
 
+    /**
+     * Returns the given label for a user, badging if necessary.
+     */
+    public String getBadgedLabel(String label, int userId) {
+        if (userId != UserHandle.myUserId()) {
+            label = mPm.getUserBadgedLabel(label, new UserHandle(userId)).toString();
+        }
+        return label;
+    }
+
     /** Returns the package name of the home activity. */
     public String getHomeActivityPackageName() {
         if (mPm == null) return null;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
index 5d98dda..40cd211 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -130,6 +130,8 @@
             // Load the label, icon, and color
             String activityLabel = loader.getAndUpdateActivityLabel(taskKey, t.taskDescription,
                     mSystemServicesProxy, infoHandle);
+            String contentDescription = loader.getAndUpdateContentDescription(taskKey,
+                    activityLabel, mSystemServicesProxy, res);
             Drawable activityIcon = loader.getAndUpdateActivityIcon(taskKey, t.taskDescription,
                     mSystemServicesProxy, res, infoHandle, false);
             int activityColor = loader.getActivityPrimaryColor(t.taskDescription, mConfig);
@@ -148,9 +150,9 @@
 
             // Add the task to the stack
             Task task = new Task(taskKey, (t.id != RecentsTaskLoader.INVALID_TASK_ID),
-                    t.affiliatedTaskId, t.affiliatedTaskColor, activityLabel, activityIcon,
-                    activityColor, (i == (taskCount - 1)), mConfig.lockToAppEnabled, icon,
-                    iconFilename);
+                    t.affiliatedTaskId, t.affiliatedTaskColor, activityLabel, contentDescription,
+                    activityIcon, activityColor, (i == (taskCount - 1)), mConfig.lockToAppEnabled,
+                    icon, iconFilename);
             task.thumbnail = loader.getAndUpdateThumbnail(taskKey, mSystemServicesProxy, false);
             if (DEBUG) Log.d(TAG, "\tthumbnail: " + taskKey + ", " + task.thumbnail);
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
index 3192fe6..b2aa2b6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -259,6 +259,7 @@
     DrawableLruCache mApplicationIconCache;
     BitmapLruCache mThumbnailCache;
     StringLruCache mActivityLabelCache;
+    StringLruCache mContentDescriptionCache;
     TaskResourceLoadQueue mLoadQueue;
     TaskResourceLoader mLoader;
 
@@ -298,6 +299,7 @@
         mApplicationIconCache = new DrawableLruCache(iconCacheSize);
         mThumbnailCache = new BitmapLruCache(thumbnailCacheSize);
         mActivityLabelCache = new StringLruCache(100);
+        mContentDescriptionCache = new StringLruCache(100);
         mLoader = new TaskResourceLoader(mLoadQueue, mApplicationIconCache, mThumbnailCache,
                 mDefaultThumbnail, mDefaultApplicationIcon);
     }
@@ -348,6 +350,24 @@
         return label;
     }
 
+    /** Returns the content description using as many cached values as we can. */
+    public String getAndUpdateContentDescription(Task.TaskKey taskKey, String activityLabel,
+            SystemServicesProxy ssp, Resources res) {
+        // Return the cached content description if it exists
+        String label = mContentDescriptionCache.getAndInvalidateIfModified(taskKey);
+        if (label != null) {
+            return label;
+        }
+        label = ssp.getContentDescription(taskKey.baseIntent, taskKey.userId, activityLabel, res);
+        if (label != null) {
+            mContentDescriptionCache.put(taskKey, label);
+        } else {
+            Log.w(TAG, "Missing content description for " + taskKey.baseIntent.getComponent()
+                    + " u=" + taskKey.userId);
+        }
+        return label;
+    }
+
     /** Returns the activity icon using as many cached values as we can. */
     public Drawable getAndUpdateActivityIcon(Task.TaskKey taskKey,
             ActivityManager.TaskDescription td, SystemServicesProxy ssp,
@@ -541,6 +561,7 @@
                 mApplicationIconCache.evictAll();
                 // The cache is small, only clear the label cache when we are critical
                 mActivityLabelCache.evictAll();
+                mContentDescriptionCache.evictAll();
                 break;
             default:
                 break;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index 0cd55d7..c14adf4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -124,6 +124,7 @@
     public boolean isLaunchTarget;
     public Drawable applicationIcon;
     public Drawable activityIcon;
+    public String contentDescription;
     public String activityLabel;
     public int colorPrimary;
     public boolean useLightOnPrimaryColor;
@@ -140,8 +141,8 @@
     }
 
     public Task(TaskKey key, boolean isActive, int taskAffiliation, int taskAffiliationColor,
-                String activityTitle, Drawable activityIcon, int colorPrimary,
-                boolean lockToThisTask, boolean lockToTaskEnabled, Bitmap icon,
+                String activityTitle, String contentDescription, Drawable activityIcon,
+                int colorPrimary, boolean lockToThisTask, boolean lockToTaskEnabled, Bitmap icon,
                 String iconFilename) {
         boolean isInAffiliationGroup = (taskAffiliation != key.id);
         boolean hasAffiliationGroupColor = isInAffiliationGroup && (taskAffiliationColor != 0);
@@ -149,6 +150,7 @@
         this.taskAffiliation = taskAffiliation;
         this.taskAffiliationColor = taskAffiliationColor;
         this.activityLabel = activityTitle;
+        this.contentDescription = contentDescription;
         this.activityIcon = activityIcon;
         this.colorPrimary = hasAffiliationGroupColor ? taskAffiliationColor : colorPrimary;
         this.useLightOnPrimaryColor = Utilities.computeContrastBetweenColors(this.colorPrimary,
@@ -166,6 +168,7 @@
         this.taskAffiliation = o.taskAffiliation;
         this.taskAffiliationColor = o.taskAffiliationColor;
         this.activityLabel = o.activityLabel;
+        this.contentDescription = o.contentDescription;
         this.activityIcon = o.activityIcon;
         this.colorPrimary = o.colorPrimary;
         this.useLightOnPrimaryColor = o.useLightOnPrimaryColor;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index 60a91bf..f397bc3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -190,10 +190,12 @@
         } else if (t.applicationIcon != null) {
             mApplicationIcon.setImageDrawable(t.applicationIcon);
         }
-        mApplicationIcon.setContentDescription(t.activityLabel);
+        mApplicationIcon.setContentDescription(t.contentDescription);
         if (!mActivityDescription.getText().toString().equals(t.activityLabel)) {
             mActivityDescription.setText(t.activityLabel);
         }
+        mActivityDescription.setContentDescription(t.contentDescription);
+
         // Try and apply the system ui tint
         int existingBgColor = getBackgroundColor();
         if (existingBgColor != t.colorPrimary) {
@@ -207,7 +209,7 @@
         mDismissButton.setImageDrawable(t.useLightOnPrimaryColor ?
                 mLightDismissDrawable : mDarkDismissDrawable);
         mDismissButton.setContentDescription(String.format(mDismissContentDescription,
-                t.activityLabel));
+                t.contentDescription));
         mMoveTaskButton.setVisibility((mConfig.multiStackEnabled) ? View.VISIBLE : View.INVISIBLE);
         if (mConfig.multiStackEnabled) {
             updateResizeTaskBarIcon(t);
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 9a6a80e..1c46d42 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -91,6 +91,7 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.keyguard.KeyguardHostView.OnDismissAction;
 import com.android.keyguard.ViewMediatorCallback;
@@ -297,7 +298,6 @@
     int mTrackingPosition; // the position of the top of the tracking view.
 
     // Tracking finger for opening/closing.
-    int mEdgeBorder; // corresponds to R.dimen.status_bar_edge_ignore
     boolean mTracking;
     VelocityTracker mVelocityTracker;
 
@@ -691,6 +691,7 @@
         mDismissView.setOnButtonClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
+                MetricsLogger.action(mContext, MetricsLogger.ACTION_DISMISS_ALL_NOTES);
                 clearAllNotifications();
             }
         });
@@ -724,8 +725,6 @@
                         R.id.keyguard_indication_text));
         mKeyguardBottomArea.setKeyguardIndicationController(mKeyguardIndicationController);
 
-        mEdgeBorder = res.getDimensionPixelSize(R.dimen.status_bar_edge_ignore);
-
         // set the inital view visibility
         setAreThereNotifications();
 
@@ -2818,8 +2817,6 @@
         mNaturalBarHeight = res.getDimensionPixelSize(
                 com.android.internal.R.dimen.status_bar_height);
 
-        mEdgeBorder = res.getDimensionPixelSize(R.dimen.status_bar_edge_ignore);
-
         mRowMinHeight =  res.getDimensionPixelSize(R.dimen.notification_min_height);
         mRowMaxHeight =  res.getDimensionPixelSize(R.dimen.notification_max_height);
 
diff --git a/rs/java/android/renderscript/ScriptIntrinsicBLAS.java b/rs/java/android/renderscript/ScriptIntrinsicBLAS.java
index 149c0be..5e28d3f 100644
--- a/rs/java/android/renderscript/ScriptIntrinsicBLAS.java
+++ b/rs/java/android/renderscript/ScriptIntrinsicBLAS.java
@@ -1288,7 +1288,7 @@
         } else {
             K = A.getType().getX();
         }
-        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_ssyr2k, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), K, alpha, A.getID(mRS), B.getID(mRS), beta, C.getID(mRS), 0, 0, 0, 0);
+        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dsyr2k, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), K, alpha, A.getID(mRS), B.getID(mRS), beta, C.getID(mRS), 0, 0, 0, 0);
     }
     public void CSYR2K(@Uplo int Uplo, @Transpose int Trans, Float2 alpha, Allocation A, Allocation B, Float2 beta, Allocation C) {
         validateUplo(Uplo);
@@ -1299,7 +1299,7 @@
         } else {
             K = A.getType().getX();
         }
-        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_ssyr2k, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), K, alpha.x, alpha.y, A.getID(mRS), B.getID(mRS), beta.x, beta.y, C.getID(mRS), 0, 0, 0, 0);
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_csyr2k, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), K, alpha.x, alpha.y, A.getID(mRS), B.getID(mRS), beta.x, beta.y, C.getID(mRS), 0, 0, 0, 0);
     }
     public void ZSYR2K(@Uplo int Uplo, @Transpose int Trans, Double2 alpha, Allocation A, Allocation B, Double2 beta, Allocation C) {
         validateUplo(Uplo);
@@ -1310,7 +1310,7 @@
         } else {
             K = A.getType().getX();
         }
-        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_ssyr2k, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), K, alpha.x, alpha.y, A.getID(mRS), B.getID(mRS), beta.x, beta.y, C.getID(mRS), 0, 0, 0, 0);
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zsyr2k, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), K, alpha.x, alpha.y, A.getID(mRS), B.getID(mRS), beta.x, beta.y, C.getID(mRS), 0, 0, 0, 0);
     }
 
     static void validateTRMM(Element e, @Side int Side, @Transpose int TransA, Allocation A, Allocation B) {
@@ -1351,21 +1351,21 @@
         validateUplo(Uplo);
         validateDiag(Diag);
         validateTRMM(Element.F64(mRS), Side, TransA, A, B);
-        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_strmm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
-                                        alpha, A.getID(mRS), B.getID(mRS), 0.f, 0, 0, 0, 0, 0);
+        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dtrmm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
+                                        alpha, A.getID(mRS), B.getID(mRS), 0, 0, 0, 0, 0, 0);
     }
     public void CTRMM(@Side int Side, @Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Float2 alpha, Allocation A, Allocation B) {
         validateUplo(Uplo);
         validateDiag(Diag);
         validateTRMM(Element.F32_2(mRS), Side, TransA, A, B);
-        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_strmm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_ctrmm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
                                          alpha.x, alpha.y, A.getID(mRS), B.getID(mRS), 0, 0, 0, 0, 0, 0, 0);
     }
     public void ZTRMM(@Side int Side, @Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Double2 alpha, Allocation A, Allocation B) {
         validateUplo(Uplo);
         validateDiag(Diag);
         validateTRMM(Element.F64_2(mRS), Side, TransA, A, B);
-        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_strmm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_ztrmm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
                                    alpha.x, alpha.y, A.getID(mRS), B.getID(mRS), 0, 0, 0, 0, 0, 0, 0);
     }
 
@@ -1409,21 +1409,21 @@
         validateUplo(Uplo);
         validateDiag(Diag);
         validateTRSM(Element.F64(mRS), Side, TransA, A, B);
-        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_strsm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
+        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dtrsm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
                                         alpha, A.getID(mRS), B.getID(mRS), 0, 0, 0, 0, 0, 0);
     }
     public void CTRSM(@Side int Side, @Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Float2 alpha, Allocation A, Allocation B) {
         validateUplo(Uplo);
         validateDiag(Diag);
         validateTRSM(Element.F32_2(mRS), Side, TransA, A, B);
-        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_strsm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_ctrsm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
                                          alpha.x, alpha.y, A.getID(mRS), B.getID(mRS), 0, 0, 0, 0, 0, 0, 0);
     }
     public void ZTRSM(@Side int Side, @Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Double2 alpha, Allocation A, Allocation B) {
         validateUplo(Uplo);
         validateDiag(Diag);
         validateTRSM(Element.F64_2(mRS), Side, TransA, A, B);
-        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_strsm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_ztrsm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
                                    alpha.x, alpha.y, A.getID(mRS), B.getID(mRS), 0, 0, 0, 0, 0, 0, 0);
     }
 
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 17c7e0c..78cbac9 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -63,6 +63,7 @@
 import android.util.AttributeSet;
 import android.util.Pair;
 import android.util.Slog;
+import android.util.SparseArray;
 import android.util.SparseIntArray;
 import android.util.TypedValue;
 import android.util.Xml;
@@ -171,6 +172,8 @@
 
     private final SparseIntArray mLoadedUserIds = new SparseIntArray();
 
+    private final SparseArray<ArraySet<String>> mWidgetPackages = new SparseArray<>();
+
     private final BackupRestoreController mBackupRestoreController;
 
     private final Context mContext;
@@ -572,7 +575,7 @@
             widget.host = host;
 
             host.widgets.add(widget);
-            mWidgets.add(widget);
+            addWidgetLocked(widget);
 
             saveGroupStateAsync(userId);
 
@@ -800,6 +803,8 @@
             widget.provider = provider;
             widget.options = (options != null) ? cloneIfLocalBinder(options) : new Bundle();
 
+            onWidgetProviderAddedOrChangedLocked(widget);
+
             // We need to provide a default value for the widget category if it is not specified
             if (!widget.options.containsKey(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY)) {
                 widget.options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
@@ -1410,7 +1415,7 @@
         host.widgets.remove(widget);
         pruneHostLocked(host);
 
-        mWidgets.remove(widget);
+        removeWidgetLocked(widget);
 
         Provider provider = widget.provider;
         if (provider != null) {
@@ -1874,7 +1879,7 @@
             updateAppWidgetInstanceLocked(widget, null, false);
             // clear out references to this appWidgetId
             widget.host.widgets.remove(widget);
-            mWidgets.remove(widget);
+            removeWidgetLocked(widget);
             widget.provider = null;
             pruneHostLocked(widget.host);
             widget.host = null;
@@ -2277,14 +2282,14 @@
 
         if (version >= 0) {
             // Hooke'm up...
-            bindLoadedWidgets(loadedWidgets);
+            bindLoadedWidgetsLocked(loadedWidgets);
 
             // upgrade the database if needed
             performUpgradeLocked(version);
         } else {
             // failed reading, clean up
             Slog.w(TAG, "Failed to read state, clearing widgets and hosts.");
-            mWidgets.clear();
+            clearWidgetsLocked();
             mHosts.clear();
             final int N = mProviders.size();
             for (int i = 0; i < N; i++) {
@@ -2293,7 +2298,7 @@
         }
     }
 
-    private void bindLoadedWidgets(List<LoadedWidgetState> loadedWidgets) {
+    private void bindLoadedWidgetsLocked(List<LoadedWidgetState> loadedWidgets) {
         final int loadedWidgetCount = loadedWidgets.size();
         for (int i = loadedWidgetCount - 1; i >= 0; i--) {
             LoadedWidgetState loadedWidget = loadedWidgets.remove(i);
@@ -2314,7 +2319,7 @@
 
             widget.provider.widgets.add(widget);
             widget.host.widgets.add(widget);
-            mWidgets.add(widget);
+            addWidgetLocked(widget);
         }
     }
 
@@ -2346,6 +2351,91 @@
         return null;
     }
 
+    /**
+     * Adds the widget to mWidgets and tracks the package name in mWidgetPackages.
+     */
+    void addWidgetLocked(Widget widget) {
+        mWidgets.add(widget);
+
+        onWidgetProviderAddedOrChangedLocked(widget);
+    }
+
+    /**
+     * Checks if the provider is assigned and updates the mWidgetPackages to track packages
+     * that have bound widgets.
+     */
+    void onWidgetProviderAddedOrChangedLocked(Widget widget) {
+        if (widget.provider == null) return;
+
+        int userId = widget.provider.getUserId();
+        ArraySet<String> packages = mWidgetPackages.get(userId);
+        if (packages == null) {
+            mWidgetPackages.put(userId, packages = new ArraySet<String>());
+        }
+        packages.add(widget.provider.info.provider.getPackageName());
+    }
+
+    /**
+     * Removes a widget from mWidgets and updates the cache of bound widget provider packages.
+     * If there are other widgets with the same package, leaves it in the cache, otherwise it
+     * removes the associated package from the cache.
+     */
+    void removeWidgetLocked(Widget widget) {
+        mWidgets.remove(widget);
+
+        onWidgetRemovedLocked(widget);
+    }
+
+    private void onWidgetRemovedLocked(Widget widget) {
+        if (widget.provider == null) return;
+
+        final int userId = widget.provider.getUserId();
+        final String packageName = widget.provider.info.provider.getPackageName();
+        ArraySet<String> packages = mWidgetPackages.get(userId);
+        if (packages == null) {
+            return;
+        }
+        // Check if there is any other widget with the same package name.
+        // Remove packageName if none.
+        final int N = mWidgets.size();
+        for (int i = 0; i < N; i++) {
+            Widget w = mWidgets.get(i);
+            if (w.provider == null) continue;
+            if (w.provider.getUserId() == userId
+                    && packageName.equals(w.provider.info.provider.getPackageName())) {
+                return;
+            }
+        }
+        packages.remove(packageName);
+    }
+
+    /**
+     * Clears all widgets and associated cache of packages with bound widgets.
+     */
+    void clearWidgetsLocked() {
+        mWidgets.clear();
+
+        onWidgetsClearedLocked();
+    }
+
+    private void onWidgetsClearedLocked() {
+        mWidgetPackages.clear();
+    }
+
+    @Override
+    public boolean isBoundWidgetPackage(String packageName, int userId) {
+        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+            throw new SecurityException("Only the system process can call this");
+        }
+        synchronized (mLock) {
+            final ArraySet<String> packages = mWidgetPackages.get(userId);
+            if (packages != null) {
+                return packages.contains(packageName);
+            }
+        }
+        return false;
+    }
+
     private void saveStateLocked(int userId) {
         tagProvidersAndHosts();
 
@@ -2692,7 +2782,7 @@
                 // as we do not want to make host callbacks and provider broadcasts
                 // as the host and the provider will be killed.
                 if (hostInUser && (!hasProvider || providerInUser)) {
-                    mWidgets.remove(i);
+                    removeWidgetLocked(widget);
                     widget.host.widgets.remove(widget);
                     widget.host = null;
                     if (hasProvider) {
@@ -3751,7 +3841,7 @@
                                         Slog.i(TAG, "New restored id " + restoredId
                                                 + " now " + id);
                                     }
-                                    mWidgets.add(id);
+                                    addWidgetLocked(id);
                                 }
                                 if (id.provider.info != null) {
                                     stashProviderRestoreUpdateLocked(id.provider,
@@ -4013,7 +4103,7 @@
                         host.widgets.remove(widget);
                         provider.widgets.remove(widget);
                         unbindAppWidgetRemoteViewsServicesLocked(widget);
-                        mWidgets.remove(i);
+                        removeWidgetLocked(widget);
                     }
                 }
                 mPrunedApps.add(pkg);
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 17b4939..1366149 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -744,6 +744,11 @@
         }
     }
 
+    @Override
+    public int permissionToOpCode(String permission) {
+        return AppOpsManager.permissionToOpCode(permission);
+    }
+
     void finishOperationLocked(Op op) {
         if (op.nesting <= 1) {
             if (op.nesting == 1) {
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index ef82bb7..1019faa 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -48,6 +48,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
 import android.util.Log;
 
 import java.io.FileDescriptor;
@@ -443,6 +444,16 @@
     /** Internal death rec list */
     Map<IBinder, ClientDeathRecipient> mBleApps = new HashMap<IBinder, ClientDeathRecipient>();
 
+    @Override
+    public boolean isBleScanAlwaysAvailable() {
+        try {
+            return (Settings.Global.getInt(mContentResolver,
+                    Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE)) != 0;
+        } catch (SettingNotFoundException e) {
+        }
+        return false;
+    }
+
     public int updateBleAppCount(IBinder token, boolean enable) {
         if (enable) {
             ClientDeathRecipient r = mBleApps.get(token);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 069878e..eea6234 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -47,6 +47,7 @@
 import android.app.usage.UsageEvents;
 import android.app.usage.UsageStatsManagerInternal;
 import android.appwidget.AppWidgetManager;
+import android.content.pm.PermissionInfo;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Point;
@@ -6619,6 +6620,18 @@
             return mActivityManagerService.mContext.getPackageManager()
                     .getPackagesForUid(uid);
         }
+
+        @Override
+        public boolean isRuntimePermission(String permission) {
+            try {
+                PermissionInfo info = mActivityManagerService.mContext.getPackageManager()
+                        .getPermissionInfo(permission, 0);
+                return info.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS;
+            } catch (NameNotFoundException nnfe) {
+                Slog.e(TAG, "No such permission: "+ permission, nnfe);
+            }
+            return false;
+        }
     }
 
     class IntentFirewallInterface implements IntentFirewall.AMSInterface {
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 0f3b4e6..fb98d94 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -264,9 +264,9 @@
         return mInstaller.execute(builder.toString());
     }
 
-    public int moveUserDataDirs(String fromUuid, String toUuid, String packageName, int appId,
-            String seinfo) {
-        StringBuilder builder = new StringBuilder("mvuserdata");
+    public int moveCompleteApp(String fromUuid, String toUuid, String packageName,
+            String dataAppName, int appId, String seinfo) {
+        StringBuilder builder = new StringBuilder("mvcompleteapp");
         builder.append(' ');
         builder.append(escapeNull(fromUuid));
         builder.append(' ');
@@ -274,6 +274,8 @@
         builder.append(' ');
         builder.append(packageName);
         builder.append(' ');
+        builder.append(dataAppName);
+        builder.append(' ');
         builder.append(appId);
         builder.append(' ');
         builder.append(seinfo);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 11ab042..66dd8f1 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -171,6 +171,7 @@
 import android.util.ExceptionUtils;
 import android.util.Log;
 import android.util.LogPrinter;
+import android.util.MathUtils;
 import android.util.PrintStreamPrinter;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -241,6 +242,8 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
@@ -2158,6 +2161,8 @@
                 mSettings.mFingerprint = Build.FINGERPRINT;
             }
 
+            primeDomainVerificationsLPw(false);
+
             // All the changes are done during package scanning.
             mSettings.updateInternalDatabaseVersion();
 
@@ -2175,8 +2180,6 @@
             mIntentFilterVerifier = new IntentVerifierProxy(mContext,
                     mIntentFilterVerifierComponent);
 
-            primeDomainVerificationsLPw(false);
-
         } // synchronized (mPackages)
         } // synchronized (mInstallLock)
 
@@ -2274,9 +2277,9 @@
     }
 
     private void primeDomainVerificationsLPw(boolean logging) {
-        Slog.d(TAG, "Start priming domain verification");
+        Slog.d(TAG, "Start priming domain verifications");
         boolean updated = false;
-        ArrayList<String> allHosts = new ArrayList<>();
+        ArraySet<String> allHostsSet = new ArraySet<>();
         for (PackageParser.Package pkg : mPackages.values()) {
             final String packageName = pkg.packageName;
             if (!hasDomainURLs(pkg)) {
@@ -2296,18 +2299,20 @@
             for (PackageParser.Activity a : pkg.activities) {
                 for (ActivityIntentInfo filter : a.intents) {
                     if (hasValidDomains(filter, false)) {
-                        allHosts.addAll(filter.getHostsList());
+                        allHostsSet.addAll(filter.getHostsList());
                     }
                 }
             }
-            if (allHosts.size() == 0) {
-                allHosts.add("*");
+            if (allHostsSet.size() == 0) {
+                allHostsSet.add("*");
             }
+            ArrayList<String> allHostsList = new ArrayList<>(allHostsSet);
             IntentFilterVerificationInfo ivi =
-                    mSettings.createIntentFilterVerificationIfNeededLPw(packageName, allHosts);
+                    mSettings.createIntentFilterVerificationIfNeededLPw(packageName, allHostsList);
             if (ivi != null) {
                 // We will always log this
-                Slog.d(TAG, "Priming domain verifications for package: " + packageName);
+                Slog.d(TAG, "Priming domain verifications for package: " + packageName +
+                        " with hosts:" + ivi.getDomainsString());
                 ivi.setStatus(INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS);
                 updated = true;
             }
@@ -2316,12 +2321,14 @@
                     Slog.d(TAG, "No priming domain verifications for package: " + packageName);
                 }
             }
-            allHosts.clear();
+            allHostsSet.clear();
         }
         if (updated) {
-            scheduleWriteSettingsLocked();
+            if (logging) {
+                Slog.d(TAG, "Will need to write primed domain verifications");
+            }
         }
-        Slog.d(TAG, "End priming domain verification");
+        Slog.d(TAG, "End priming domain verifications");
     }
 
     @Override
@@ -5049,8 +5056,7 @@
                             + " better than installed " + ps.versionCode);
 
                     InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
-                            ps.codePathString, ps.resourcePathString, ps.legacyNativeLibraryPathString,
-                            getAppDexInstructionSets(ps));
+                            ps.codePathString, ps.resourcePathString, getAppDexInstructionSets(ps));
                     synchronized (mInstallLock) {
                         args.cleanUpResourcesLI();
                     }
@@ -5116,8 +5122,7 @@
                             + " reverting from " + ps.codePathString + ": new version "
                             + pkg.mVersionCode + " better than installed " + ps.versionCode);
                     InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
-                            ps.codePathString, ps.resourcePathString, ps.legacyNativeLibraryPathString,
-                            getAppDexInstructionSets(ps));
+                            ps.codePathString, ps.resourcePathString, getAppDexInstructionSets(ps));
                     synchronized (mInstallLock) {
                         args.cleanUpResourcesLI();
                     }
@@ -8499,46 +8504,53 @@
         }
     };
 
-    static final void sendPackageBroadcast(String action, String pkg,
-            Bundle extras, String targetPkg, IIntentReceiver finishedReceiver,
-            int[] userIds) {
-        IActivityManager am = ActivityManagerNative.getDefault();
-        if (am != null) {
-            try {
-                if (userIds == null) {
-                    userIds = am.getRunningUserIds();
+    final void sendPackageBroadcast(final String action, final String pkg,
+            final Bundle extras, final String targetPkg, final IIntentReceiver finishedReceiver,
+            final int[] userIds) {
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    final IActivityManager am = ActivityManagerNative.getDefault();
+                    if (am == null) return;
+                    final int[] resolvedUserIds;
+                    if (userIds == null) {
+                        resolvedUserIds = am.getRunningUserIds();
+                    } else {
+                        resolvedUserIds = userIds;
+                    }
+                    for (int id : resolvedUserIds) {
+                        final Intent intent = new Intent(action,
+                                pkg != null ? Uri.fromParts("package", pkg, null) : null);
+                        if (extras != null) {
+                            intent.putExtras(extras);
+                        }
+                        if (targetPkg != null) {
+                            intent.setPackage(targetPkg);
+                        }
+                        // Modify the UID when posting to other users
+                        int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
+                        if (uid > 0 && UserHandle.getUserId(uid) != id) {
+                            uid = UserHandle.getUid(id, UserHandle.getAppId(uid));
+                            intent.putExtra(Intent.EXTRA_UID, uid);
+                        }
+                        intent.putExtra(Intent.EXTRA_USER_HANDLE, id);
+                        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+                        if (DEBUG_BROADCASTS) {
+                            RuntimeException here = new RuntimeException("here");
+                            here.fillInStackTrace();
+                            Slog.d(TAG, "Sending to user " + id + ": "
+                                    + intent.toShortString(false, true, false, false)
+                                    + " " + intent.getExtras(), here);
+                        }
+                        am.broadcastIntent(null, intent, null, finishedReceiver,
+                                0, null, null, null, android.app.AppOpsManager.OP_NONE,
+                                finishedReceiver != null, false, id);
+                    }
+                } catch (RemoteException ex) {
                 }
-                for (int id : userIds) {
-                    final Intent intent = new Intent(action,
-                            pkg != null ? Uri.fromParts("package", pkg, null) : null);
-                    if (extras != null) {
-                        intent.putExtras(extras);
-                    }
-                    if (targetPkg != null) {
-                        intent.setPackage(targetPkg);
-                    }
-                    // Modify the UID when posting to other users
-                    int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
-                    if (uid > 0 && UserHandle.getUserId(uid) != id) {
-                        uid = UserHandle.getUid(id, UserHandle.getAppId(uid));
-                        intent.putExtra(Intent.EXTRA_UID, uid);
-                    }
-                    intent.putExtra(Intent.EXTRA_USER_HANDLE, id);
-                    intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-                    if (DEBUG_BROADCASTS) {
-                        RuntimeException here = new RuntimeException("here");
-                        here.fillInStackTrace();
-                        Slog.d(TAG, "Sending to user " + id + ": "
-                                + intent.toShortString(false, true, false, false)
-                                + " " + intent.getExtras(), here);
-                    }
-                    am.broadcastIntent(null, intent, null, finishedReceiver,
-                            0, null, null, null, android.app.AppOpsManager.OP_NONE,
-                            finishedReceiver != null, false, id);
-                }
-            } catch (RemoteException ex) {
             }
-        }
+        });
     }
 
     /**
@@ -8665,8 +8677,8 @@
         final OriginInfo origin = OriginInfo.fromUntrustedFile(originFile);
 
         final Message msg = mHandler.obtainMessage(INIT_COPY);
-        msg.obj = new InstallParams(origin, observer, installFlags,
-                installerPackageName, null, verificationParams, user, packageAbiOverride);
+        msg.obj = new InstallParams(origin, null, observer, installFlags, installerPackageName,
+                null, verificationParams, user, packageAbiOverride);
         mHandler.sendMessage(msg);
     }
 
@@ -8684,7 +8696,7 @@
         }
 
         final Message msg = mHandler.obtainMessage(INIT_COPY);
-        msg.obj = new InstallParams(origin, observer, params.installFlags,
+        msg.obj = new InstallParams(origin, null, observer, params.installFlags,
                 installerPackageName, params.volumeUuid, verifParams, user, params.abiOverride);
         mHandler.sendMessage(msg);
     }
@@ -9517,8 +9529,30 @@
         }
     }
 
+    class MoveInfo {
+        final int moveId;
+        final String fromUuid;
+        final String toUuid;
+        final String packageName;
+        final String dataAppName;
+        final int appId;
+        final String seinfo;
+
+        public MoveInfo(int moveId, String fromUuid, String toUuid, String packageName,
+                String dataAppName, int appId, String seinfo) {
+            this.moveId = moveId;
+            this.fromUuid = fromUuid;
+            this.toUuid = toUuid;
+            this.packageName = packageName;
+            this.dataAppName = dataAppName;
+            this.appId = appId;
+            this.seinfo = seinfo;
+        }
+    }
+
     class InstallParams extends HandlerParams {
         final OriginInfo origin;
+        final MoveInfo move;
         final IPackageInstallObserver2 observer;
         int installFlags;
         final String installerPackageName;
@@ -9528,11 +9562,12 @@
         private int mRet;
         final String packageAbiOverride;
 
-        InstallParams(OriginInfo origin, IPackageInstallObserver2 observer, int installFlags,
-                String installerPackageName, String volumeUuid,
+        InstallParams(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 observer,
+                int installFlags, String installerPackageName, String volumeUuid,
                 VerificationParams verificationParams, UserHandle user, String packageAbiOverride) {
             super(user);
             this.origin = origin;
+            this.move = move;
             this.observer = observer;
             this.installFlags = installFlags;
             this.installerPackageName = installerPackageName;
@@ -9911,7 +9946,9 @@
     }
 
     private InstallArgs createInstallArgs(InstallParams params) {
-        if (installOnExternalAsec(params.installFlags) || params.isForwardLocked()) {
+        if (params.move != null) {
+            return new MoveInstallArgs(params);
+        } else if (installOnExternalAsec(params.installFlags) || params.isForwardLocked()) {
             return new AsecInstallArgs(params);
         } else {
             return new FileInstallArgs(params);
@@ -9923,7 +9960,7 @@
      * when cleaning up old installs, or used as a move source.
      */
     private InstallArgs createInstallArgsForExisting(int installFlags, String codePath,
-            String resourcePath, String nativeLibraryRoot, String[] instructionSets) {
+            String resourcePath, String[] instructionSets) {
         final boolean isInAsec;
         if (installOnExternalAsec(installFlags)) {
             /* Apps on SD card are always in ASEC containers. */
@@ -9943,14 +9980,15 @@
             return new AsecInstallArgs(codePath, instructionSets,
                     installOnExternalAsec(installFlags), installForwardLocked(installFlags));
         } else {
-            return new FileInstallArgs(codePath, resourcePath, nativeLibraryRoot,
-                    instructionSets);
+            return new FileInstallArgs(codePath, resourcePath, instructionSets);
         }
     }
 
     static abstract class InstallArgs {
         /** @see InstallParams#origin */
         final OriginInfo origin;
+        /** @see InstallParams#move */
+        final MoveInfo move;
 
         final IPackageInstallObserver2 observer;
         // Always refers to PackageManager flags only
@@ -9966,10 +10004,12 @@
         // if we move dex files under the common app path.
         /* nullable */ String[] instructionSets;
 
-        InstallArgs(OriginInfo origin, IPackageInstallObserver2 observer, int installFlags,
-                String installerPackageName, String volumeUuid, ManifestDigest manifestDigest,
-                UserHandle user, String[] instructionSets, String abiOverride) {
+        InstallArgs(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 observer,
+                int installFlags, String installerPackageName, String volumeUuid,
+                ManifestDigest manifestDigest, UserHandle user, String[] instructionSets,
+                String abiOverride) {
             this.origin = origin;
+            this.move = move;
             this.installFlags = installFlags;
             this.observer = observer;
             this.installerPackageName = installerPackageName;
@@ -9994,12 +10034,10 @@
         abstract String getCodePath();
         /** @see PackageSettingBase#resourcePathString */
         abstract String getResourcePath();
-        abstract String getLegacyNativeLibraryPath();
 
         // Need installer lock especially for dex file removal.
         abstract void cleanUpResourcesLI();
         abstract boolean doPostDeleteLI(boolean delete);
-        abstract boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException;
 
         /**
          * Called before the source arguments are copied. This is used mostly
@@ -10060,7 +10098,6 @@
     class FileInstallArgs extends InstallArgs {
         private File codeFile;
         private File resourceFile;
-        private File legacyNativeLibraryPath;
 
         // Example topology:
         // /data/app/com.example/base.apk
@@ -10071,7 +10108,7 @@
 
         /** New install */
         FileInstallArgs(InstallParams params) {
-            super(params.origin, params.observer, params.installFlags,
+            super(params.origin, params.move, params.observer, params.installFlags,
                     params.installerPackageName, params.volumeUuid, params.getManifestDigest(),
                     params.getUser(), null /* instruction sets */, params.packageAbiOverride);
             if (isFwdLocked()) {
@@ -10080,21 +10117,11 @@
         }
 
         /** Existing install */
-        FileInstallArgs(String codePath, String resourcePath, String legacyNativeLibraryPath,
-                String[] instructionSets) {
-            super(OriginInfo.fromNothing(), null, 0, null, null, null, null, instructionSets, null);
+        FileInstallArgs(String codePath, String resourcePath, String[] instructionSets) {
+            super(OriginInfo.fromNothing(), null, null, 0, null, null, null, null, instructionSets,
+                    null);
             this.codeFile = (codePath != null) ? new File(codePath) : null;
             this.resourceFile = (resourcePath != null) ? new File(resourcePath) : null;
-            this.legacyNativeLibraryPath = (legacyNativeLibraryPath != null) ?
-                    new File(legacyNativeLibraryPath) : null;
-        }
-
-        boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
-            final long sizeBytes = imcs.calculateInstalledSize(origin.file.getAbsolutePath(),
-                    isFwdLocked(), abiOverride);
-
-            final StorageManager storage = StorageManager.from(mContext);
-            return (sizeBytes <= storage.getStorageBytesUntilLow(Environment.getDataDirectory()));
         }
 
         int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
@@ -10166,46 +10193,46 @@
             if (status != PackageManager.INSTALL_SUCCEEDED) {
                 cleanUp();
                 return false;
-            } else {
-                final File targetDir = codeFile.getParentFile();
-                final File beforeCodeFile = codeFile;
-                final File afterCodeFile = getNextCodePath(targetDir, pkg.packageName);
-
-                Slog.d(TAG, "Renaming " + beforeCodeFile + " to " + afterCodeFile);
-                try {
-                    Os.rename(beforeCodeFile.getAbsolutePath(), afterCodeFile.getAbsolutePath());
-                } catch (ErrnoException e) {
-                    Slog.d(TAG, "Failed to rename", e);
-                    return false;
-                }
-
-                if (!SELinux.restoreconRecursive(afterCodeFile)) {
-                    Slog.d(TAG, "Failed to restorecon");
-                    return false;
-                }
-
-                // Reflect the rename internally
-                codeFile = afterCodeFile;
-                resourceFile = afterCodeFile;
-
-                // Reflect the rename in scanned details
-                pkg.codePath = afterCodeFile.getAbsolutePath();
-                pkg.baseCodePath = FileUtils.rewriteAfterRename(beforeCodeFile, afterCodeFile,
-                        pkg.baseCodePath);
-                pkg.splitCodePaths = FileUtils.rewriteAfterRename(beforeCodeFile, afterCodeFile,
-                        pkg.splitCodePaths);
-
-                // Reflect the rename in app info
-                pkg.applicationInfo.volumeUuid = pkg.volumeUuid;
-                pkg.applicationInfo.setCodePath(pkg.codePath);
-                pkg.applicationInfo.setBaseCodePath(pkg.baseCodePath);
-                pkg.applicationInfo.setSplitCodePaths(pkg.splitCodePaths);
-                pkg.applicationInfo.setResourcePath(pkg.codePath);
-                pkg.applicationInfo.setBaseResourcePath(pkg.baseCodePath);
-                pkg.applicationInfo.setSplitResourcePaths(pkg.splitCodePaths);
-
-                return true;
             }
+
+            final File targetDir = codeFile.getParentFile();
+            final File beforeCodeFile = codeFile;
+            final File afterCodeFile = getNextCodePath(targetDir, pkg.packageName);
+
+            Slog.d(TAG, "Renaming " + beforeCodeFile + " to " + afterCodeFile);
+            try {
+                Os.rename(beforeCodeFile.getAbsolutePath(), afterCodeFile.getAbsolutePath());
+            } catch (ErrnoException e) {
+                Slog.d(TAG, "Failed to rename", e);
+                return false;
+            }
+
+            if (!SELinux.restoreconRecursive(afterCodeFile)) {
+                Slog.d(TAG, "Failed to restorecon");
+                return false;
+            }
+
+            // Reflect the rename internally
+            codeFile = afterCodeFile;
+            resourceFile = afterCodeFile;
+
+            // Reflect the rename in scanned details
+            pkg.codePath = afterCodeFile.getAbsolutePath();
+            pkg.baseCodePath = FileUtils.rewriteAfterRename(beforeCodeFile, afterCodeFile,
+                    pkg.baseCodePath);
+            pkg.splitCodePaths = FileUtils.rewriteAfterRename(beforeCodeFile, afterCodeFile,
+                    pkg.splitCodePaths);
+
+            // Reflect the rename in app info
+            pkg.applicationInfo.volumeUuid = pkg.volumeUuid;
+            pkg.applicationInfo.setCodePath(pkg.codePath);
+            pkg.applicationInfo.setBaseCodePath(pkg.baseCodePath);
+            pkg.applicationInfo.setSplitCodePaths(pkg.splitCodePaths);
+            pkg.applicationInfo.setResourcePath(pkg.codePath);
+            pkg.applicationInfo.setBaseResourcePath(pkg.baseCodePath);
+            pkg.applicationInfo.setSplitResourcePaths(pkg.splitCodePaths);
+
+            return true;
         }
 
         int doPostInstall(int status, int uid) {
@@ -10225,11 +10252,6 @@
             return (resourceFile != null) ? resourceFile.getAbsolutePath() : null;
         }
 
-        @Override
-        String getLegacyNativeLibraryPath() {
-            return (legacyNativeLibraryPath != null) ? legacyNativeLibraryPath.getAbsolutePath() : null;
-        }
-
         private boolean cleanUp() {
             if (codeFile == null || !codeFile.exists()) {
                 return false;
@@ -10245,13 +10267,6 @@
                 resourceFile.delete();
             }
 
-            if (legacyNativeLibraryPath != null && !FileUtils.contains(codeFile, legacyNativeLibraryPath)) {
-                if (!FileUtils.deleteContents(legacyNativeLibraryPath)) {
-                    Slog.w(TAG, "Couldn't delete native library directory " + legacyNativeLibraryPath);
-                }
-                legacyNativeLibraryPath.delete();
-            }
-
             return true;
         }
 
@@ -10315,11 +10330,10 @@
         String cid;
         String packagePath;
         String resourcePath;
-        String legacyNativeLibraryDir;
 
         /** New install */
         AsecInstallArgs(InstallParams params) {
-            super(params.origin, params.observer, params.installFlags,
+            super(params.origin, params.move, params.observer, params.installFlags,
                     params.installerPackageName, params.volumeUuid, params.getManifestDigest(),
                     params.getUser(), null /* instruction sets */, params.packageAbiOverride);
         }
@@ -10327,7 +10341,7 @@
         /** Existing install */
         AsecInstallArgs(String fullCodePath, String[] instructionSets,
                         boolean isExternal, boolean isForwardLocked) {
-            super(OriginInfo.fromNothing(), null, (isExternal ? INSTALL_EXTERNAL : 0)
+            super(OriginInfo.fromNothing(), null, null, (isExternal ? INSTALL_EXTERNAL : 0)
                     | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null, null,
                     instructionSets, null);
             // Hackily pretend we're still looking at a full code path
@@ -10344,7 +10358,7 @@
         }
 
         AsecInstallArgs(String cid, String[] instructionSets, boolean isForwardLocked) {
-            super(OriginInfo.fromNothing(), null, (isAsecExternal(cid) ? INSTALL_EXTERNAL : 0)
+            super(OriginInfo.fromNothing(), null, null, (isAsecExternal(cid) ? INSTALL_EXTERNAL : 0)
                     | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null, null,
                     instructionSets, null);
             this.cid = cid;
@@ -10355,21 +10369,6 @@
             cid = mInstallerService.allocateExternalStageCidLegacy();
         }
 
-        boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
-            final long sizeBytes = imcs.calculateInstalledSize(packagePath, isFwdLocked(),
-                    abiOverride);
-
-            final File target;
-            if (isExternalAsec()) {
-                target = new UserEnvironment(UserHandle.USER_OWNER).getExternalStorageDirectory();
-            } else {
-                target = Environment.getDataDirectory();
-            }
-
-            final StorageManager storage = StorageManager.from(mContext);
-            return (sizeBytes <= storage.getStorageBytesUntilLow(target));
-        }
-
         int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
             if (origin.staged) {
                 Slog.d(TAG, origin.cid + " already staged; skipping copy");
@@ -10410,11 +10409,6 @@
             return resourcePath;
         }
 
-        @Override
-        String getLegacyNativeLibraryPath() {
-            return legacyNativeLibraryDir;
-        }
-
         int doPreInstall(int status) {
             if (status != PackageManager.INSTALL_SUCCEEDED) {
                 // Destroy container
@@ -10513,8 +10507,6 @@
                 packagePath = mountFile.getAbsolutePath();
                 resourcePath = packagePath;
             }
-
-            legacyNativeLibraryDir = new File(mountFile, LIB_DIR_NAME).getAbsolutePath();
         }
 
         int doPostInstall(int status, int uid) {
@@ -10576,8 +10568,6 @@
             removeDexFiles(allCodePaths, instructionSets);
         }
 
-
-
         String getPackageName() {
             return getAsecPackageName(cid);
         }
@@ -10626,6 +10616,108 @@
         }
     }
 
+    /**
+     * Logic to handle movement of existing installed applications.
+     */
+    class MoveInstallArgs extends InstallArgs {
+        private File codeFile;
+        private File resourceFile;
+
+        /** New install */
+        MoveInstallArgs(InstallParams params) {
+            super(params.origin, params.move, params.observer, params.installFlags,
+                    params.installerPackageName, params.volumeUuid, params.getManifestDigest(),
+                    params.getUser(), null /* instruction sets */, params.packageAbiOverride);
+        }
+
+        int copyApk(IMediaContainerService imcs, boolean temp) {
+            Slog.d(TAG, "Moving " + move.packageName + " from " + move.fromUuid + " to "
+                    + move.toUuid);
+            synchronized (mInstaller) {
+                if (mInstaller.moveCompleteApp(move.fromUuid, move.toUuid, move.packageName,
+                        move.dataAppName, move.appId, move.seinfo) != 0) {
+                    return PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+                }
+            }
+
+            codeFile = new File(Environment.getDataAppDirectory(move.toUuid), move.dataAppName);
+            resourceFile = codeFile;
+            Slog.d(TAG, "codeFile after move is " + codeFile);
+
+            return PackageManager.INSTALL_SUCCEEDED;
+        }
+
+        int doPreInstall(int status) {
+            if (status != PackageManager.INSTALL_SUCCEEDED) {
+                cleanUp();
+            }
+            return status;
+        }
+
+        boolean doRename(int status, PackageParser.Package pkg, String oldCodePath) {
+            if (status != PackageManager.INSTALL_SUCCEEDED) {
+                cleanUp();
+                return false;
+            }
+
+            // Reflect the move in app info
+            pkg.applicationInfo.volumeUuid = pkg.volumeUuid;
+            pkg.applicationInfo.setCodePath(pkg.codePath);
+            pkg.applicationInfo.setBaseCodePath(pkg.baseCodePath);
+            pkg.applicationInfo.setSplitCodePaths(pkg.splitCodePaths);
+            pkg.applicationInfo.setResourcePath(pkg.codePath);
+            pkg.applicationInfo.setBaseResourcePath(pkg.baseCodePath);
+            pkg.applicationInfo.setSplitResourcePaths(pkg.splitCodePaths);
+
+            return true;
+        }
+
+        int doPostInstall(int status, int uid) {
+            if (status != PackageManager.INSTALL_SUCCEEDED) {
+                cleanUp();
+            }
+            return status;
+        }
+
+        @Override
+        String getCodePath() {
+            return (codeFile != null) ? codeFile.getAbsolutePath() : null;
+        }
+
+        @Override
+        String getResourcePath() {
+            return (resourceFile != null) ? resourceFile.getAbsolutePath() : null;
+        }
+
+        private boolean cleanUp() {
+            if (codeFile == null || !codeFile.exists()) {
+                return false;
+            }
+
+            if (codeFile.isDirectory()) {
+                mInstaller.rmPackageDir(codeFile.getAbsolutePath());
+            } else {
+                codeFile.delete();
+            }
+
+            if (resourceFile != null && !FileUtils.contains(codeFile, resourceFile)) {
+                resourceFile.delete();
+            }
+
+            return true;
+        }
+
+        void cleanUpResourcesLI() {
+            cleanUp();
+        }
+
+        boolean doPostDeleteLI(boolean delete) {
+            // XXX err, shouldn't we respect the delete flag?
+            cleanUpResourcesLI();
+            return true;
+        }
+    }
+
     static String getAsecPackageName(String packageCid) {
         int idx = packageCid.lastIndexOf("-");
         if (idx == -1) {
@@ -11012,7 +11104,6 @@
                 res.removedInfo.args = createInstallArgsForExisting(0,
                         deletedPackage.applicationInfo.getCodePath(),
                         deletedPackage.applicationInfo.getResourcePath(),
-                        deletedPackage.applicationInfo.nativeLibraryRootDir,
                         getAppDexInstructionSets(deletedPackage.applicationInfo));
             } else {
                 res.removedInfo.args = null;
@@ -11320,8 +11411,10 @@
             return;
         }
 
-        // If app directory is not writable, dexopt will be called after the rename
-        if (!forwardLocked && !pkg.applicationInfo.isExternalAsec()) {
+        if (args.move != null) {
+            // We did an in-place move, so dex is ready to roll
+            scanFlags |= SCAN_NO_DEX;
+        } else if (!forwardLocked && !pkg.applicationInfo.isExternalAsec()) {
             // Enable SCAN_NO_DEX flag to skip dexopt at a later stage
             scanFlags |= SCAN_NO_DEX;
             // Run dexopt before old package gets removed, to minimize time when app is unavailable
@@ -11704,7 +11797,7 @@
         return res ? PackageManager.DELETE_SUCCEEDED : PackageManager.DELETE_FAILED_INTERNAL_ERROR;
     }
 
-    static class PackageRemovedInfo {
+    class PackageRemovedInfo {
         String removedPackage;
         int uid = -1;
         int removedAppId = -1;
@@ -11949,8 +12042,7 @@
         // Delete application code and resources
         if (deleteCodeAndResources && (outInfo != null)) {
             outInfo.args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
-                    ps.codePathString, ps.resourcePathString, ps.legacyNativeLibraryPathString,
-                    getAppDexInstructionSets(ps));
+                    ps.codePathString, ps.resourcePathString, getAppDexInstructionSets(ps));
             if (DEBUG_SD_INSTALL) Slog.i(TAG, "args=" + outInfo.args);
         }
         return true;
@@ -13119,8 +13211,8 @@
         enforceCrossUserPermission(uid, userId, true, true, "stop package");
         // writer
         synchronized (mPackages) {
-            if (mSettings.setPackageStoppedStateLPw(packageName, stopped, allowedByPermission,
-                    uid, userId)) {
+            if (mSettings.setPackageStoppedStateLPw(this, packageName, stopped,
+                    allowedByPermission, uid, userId)) {
                 scheduleWritePackageRestrictionsLocked(userId);
             }
         }
@@ -14180,17 +14272,16 @@
     private void loadPrivatePackages(VolumeInfo vol) {
         final ArrayList<ApplicationInfo> loaded = new ArrayList<>();
         final int parseFlags = mDefParseFlags | PackageParser.PARSE_EXTERNAL_STORAGE;
+        synchronized (mInstallLock) {
         synchronized (mPackages) {
             final List<PackageSetting> packages = mSettings.getVolumePackagesLPr(vol.fsUuid);
             for (PackageSetting ps : packages) {
-                synchronized (mInstallLock) {
-                    final PackageParser.Package pkg;
-                    try {
-                        pkg = scanPackageLI(ps.codePath, parseFlags, 0, 0, null);
-                        loaded.add(pkg.applicationInfo);
-                    } catch (PackageManagerException e) {
-                        Slog.w(TAG, "Failed to scan " + ps.codePath + ": " + e.getMessage());
-                    }
+                final PackageParser.Package pkg;
+                try {
+                    pkg = scanPackageLI(ps.codePath, parseFlags, 0, 0, null);
+                    loaded.add(pkg.applicationInfo);
+                } catch (PackageManagerException e) {
+                    Slog.w(TAG, "Failed to scan " + ps.codePath + ": " + e.getMessage());
                 }
             }
 
@@ -14198,6 +14289,7 @@
 
             mSettings.writeLPr();
         }
+        }
 
         Slog.d(TAG, "Loaded packages " + loaded);
         sendResourcesChangedBroadcast(true, false, loaded, null);
@@ -14205,24 +14297,25 @@
 
     private void unloadPrivatePackages(VolumeInfo vol) {
         final ArrayList<ApplicationInfo> unloaded = new ArrayList<>();
+        synchronized (mInstallLock) {
         synchronized (mPackages) {
             final List<PackageSetting> packages = mSettings.getVolumePackagesLPr(vol.fsUuid);
             for (PackageSetting ps : packages) {
                 if (ps.pkg == null) continue;
-                synchronized (mInstallLock) {
-                    final ApplicationInfo info = ps.pkg.applicationInfo;
-                    final PackageRemovedInfo outInfo = new PackageRemovedInfo();
-                    if (deletePackageLI(ps.name, null, false, null, null,
-                            PackageManager.DELETE_KEEP_DATA, outInfo, false)) {
-                        unloaded.add(info);
-                    } else {
-                        Slog.w(TAG, "Failed to unload " + ps.codePath);
-                    }
+
+                final ApplicationInfo info = ps.pkg.applicationInfo;
+                final PackageRemovedInfo outInfo = new PackageRemovedInfo();
+                if (deletePackageLI(ps.name, null, false, null, null,
+                        PackageManager.DELETE_KEEP_DATA, outInfo, false)) {
+                    unloaded.add(info);
+                } else {
+                    Slog.w(TAG, "Failed to unload " + ps.codePath);
                 }
             }
 
             mSettings.writeLPr();
         }
+        }
 
         Slog.d(TAG, "Unloaded packages " + unloaded);
         sendResourcesChangedBroadcast(false, false, unloaded, null);
@@ -14255,6 +14348,7 @@
     private void movePackageInternal(final String packageName, final String volumeUuid,
             final int moveId) throws PackageManagerException {
         final UserHandle user = new UserHandle(UserHandle.getCallingUserId());
+        final StorageManager storage = mContext.getSystemService(StorageManager.class);
         final PackageManager pm = mContext.getPackageManager();
 
         final boolean currentAsec;
@@ -14284,11 +14378,17 @@
                         "Package already moved to " + volumeUuid);
             }
 
+            final File probe = new File(pkg.codePath);
+            final File probeOat = new File(probe, "oat");
+            if (!probe.isDirectory() || !probeOat.isDirectory()) {
+                throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR,
+                        "Move only supported for modern cluster style installs");
+            }
+
             if (ps.frozen) {
                 throw new PackageManagerException(MOVE_FAILED_OPERATION_PENDING,
                         "Failed to move already frozen package");
             }
-
             ps.frozen = true;
 
             currentAsec = pkg.applicationInfo.isForwardLocked()
@@ -14302,7 +14402,7 @@
             label = String.valueOf(pm.getApplicationLabel(pkg.applicationInfo));
         }
 
-        // Now that we're guarded by frozen state, kill app during upgrade
+        // Now that we're guarded by frozen state, kill app during move
         killApplication(packageName, appId, "move pkg");
 
         final Bundle extras = new Bundle();
@@ -14311,16 +14411,18 @@
         mMoveCallbacks.notifyCreated(moveId, extras);
 
         int installFlags;
-        final boolean moveData;
+        final boolean moveCompleteApp;
+        final File measurePath;
 
         if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) {
             installFlags = INSTALL_INTERNAL;
-            moveData = !currentAsec;
+            moveCompleteApp = !currentAsec;
+            measurePath = Environment.getDataAppDirectory(volumeUuid);
         } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
             installFlags = INSTALL_EXTERNAL;
-            moveData = false;
+            moveCompleteApp = false;
+            measurePath = storage.getPrimaryPhysicalVolume().getPath();
         } else {
-            final StorageManager storage = mContext.getSystemService(StorageManager.class);
             final VolumeInfo volume = storage.findVolumeByUuid(volumeUuid);
             if (volume == null || volume.getType() != VolumeInfo.TYPE_PRIVATE
                     || !volume.isMountedWritable()) {
@@ -14332,26 +14434,38 @@
             Preconditions.checkState(!currentAsec);
 
             installFlags = INSTALL_INTERNAL;
-            moveData = true;
+            moveCompleteApp = true;
+            measurePath = Environment.getDataAppDirectory(volumeUuid);
         }
 
-        Slog.d(TAG, "Moving " + packageName + " from " + currentVolumeUuid + " to " + volumeUuid);
-        mMoveCallbacks.notifyStatusChanged(moveId, 10);
-
-        if (moveData) {
-            synchronized (mInstallLock) {
-                // TODO: split this into separate copy and delete operations
-                if (mInstaller.moveUserDataDirs(currentVolumeUuid, volumeUuid, packageName, appId,
-                        seinfo) != 0) {
-                    unfreezePackage(packageName);
-                    throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR,
-                            "Failed to move private data to " + volumeUuid);
-                }
+        final PackageStats stats = new PackageStats(null, -1);
+        synchronized (mInstaller) {
+            if (!getPackageSizeInfoLI(packageName, -1, stats)) {
+                unfreezePackage(packageName);
+                throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR,
+                        "Failed to measure package size");
             }
         }
 
-        mMoveCallbacks.notifyStatusChanged(moveId, 50);
+        Slog.d(TAG, "Measured code size " + stats.codeSize + ", data size " + stats.dataSize);
 
+        final long startFreeBytes = measurePath.getFreeSpace();
+        final long sizeBytes;
+        if (moveCompleteApp) {
+            sizeBytes = stats.codeSize + stats.dataSize;
+        } else {
+            sizeBytes = stats.codeSize;
+        }
+
+        if (sizeBytes > storage.getStorageBytesUntilLow(measurePath)) {
+            unfreezePackage(packageName);
+            throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR,
+                    "Not enough free space to move");
+        }
+
+        mMoveCallbacks.notifyStatusChanged(moveId, 10);
+
+        final CountDownLatch installedLatch = new CountDownLatch(1);
         final IPackageInstallObserver2 installObserver = new IPackageInstallObserver2.Stub() {
             @Override
             public void onUserActionRequired(Intent intent) throws RemoteException {
@@ -14364,6 +14478,8 @@
                 Slog.d(TAG, "Install result for move: "
                         + PackageManager.installStatusToString(returnCode, msg));
 
+                installedLatch.countDown();
+
                 // Regardless of success or failure of the move operation,
                 // always unfreeze the package
                 unfreezePackage(packageName);
@@ -14386,13 +14502,40 @@
             }
         };
 
-        // Treat a move like reinstalling an existing app, which ensures that we
-        // process everythign uniformly, like unpacking native libraries.
+        final MoveInfo move;
+        if (moveCompleteApp) {
+            // Kick off a thread to report progress estimates
+            new Thread() {
+                @Override
+                public void run() {
+                    while (true) {
+                        try {
+                            if (installedLatch.await(1, TimeUnit.SECONDS)) {
+                                break;
+                            }
+                        } catch (InterruptedException ignored) {
+                        }
+
+                        final long deltaFreeBytes = startFreeBytes - measurePath.getFreeSpace();
+                        final int progress = 10 + (int) MathUtils.constrain(
+                                ((deltaFreeBytes * 80) / sizeBytes), 0, 80);
+                        mMoveCallbacks.notifyStatusChanged(moveId, progress);
+                    }
+                }
+            }.start();
+
+            final String dataAppName = codeFile.getName();
+            move = new MoveInfo(moveId, currentVolumeUuid, volumeUuid, packageName,
+                    dataAppName, appId, seinfo);
+        } else {
+            move = null;
+        }
+
         installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
 
         final Message msg = mHandler.obtainMessage(INIT_COPY);
         final OriginInfo origin = OriginInfo.fromExistingFile(codeFile);
-        msg.obj = new InstallParams(origin, installObserver, installFlags,
+        msg.obj = new InstallParams(origin, move, installObserver, installFlags,
                 installerPackageName, volumeUuid, null, user, packageAbiOverride);
         mHandler.sendMessage(msg);
     }
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index f9c248d..d3bfdeb 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -985,6 +985,13 @@
         if (ivi == null) {
             ivi = new IntentFilterVerificationInfo(packageName, domains);
             ps.setIntentFilterVerificationInfo(ivi);
+            Slog.d(PackageManagerService.TAG,
+                    "Creating new IntentFilterVerificationInfo for packageName: " + packageName);
+        } else {
+            ivi.setDomains(domains);
+            Slog.d(PackageManagerService.TAG,
+                    "Setting domains to existing IntentFilterVerificationInfo for packageName: " +
+                            packageName + " and with domains: " + ivi.getDomainsString());
         }
         return ivi;
     }
@@ -1021,7 +1028,7 @@
 
         // Then, if we set a ALWAYS status, then put NEVER status for Apps whose IntentFilter
         // domains overlap the domains of the current package
-        ArraySet<String> currentDomains = current.getIntentFilterVerificationInfo().getDomainsSet();
+        ArraySet<String> currentDomains = current.getIntentFilterVerificationInfo().getDomains();
         if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS) {
             for (PackageSetting ps : mPackages.values()) {
                 if (ps == null || ps.pkg.packageName.equals(packageName)) continue;
@@ -1029,7 +1036,7 @@
                 if (ivi == null) {
                     continue;
                 }
-                ArraySet<String> set = ivi.getDomainsSet();
+                ArraySet<String> set = ivi.getDomains();
                 set.retainAll(currentDomains);
                 if (set.size() > 0) {
                     ps.setDomainVerificationStatusForUser(
@@ -3603,8 +3610,8 @@
         return pkg.getCurrentEnabledStateLPr(classNameStr, userId);
     }
 
-    boolean setPackageStoppedStateLPw(String packageName, boolean stopped,
-            boolean allowedByPermission, int uid, int userId) {
+    boolean setPackageStoppedStateLPw(PackageManagerService yucky, String packageName,
+            boolean stopped, boolean allowedByPermission, int uid, int userId) {
         int appId = UserHandle.getAppId(uid);
         final PackageSetting pkgSetting = mPackages.get(packageName);
         if (pkgSetting == null) {
@@ -3628,7 +3635,7 @@
             // pkgSetting.pkg.mSetStopped = stopped;
             if (pkgSetting.getNotLaunched(userId)) {
                 if (pkgSetting.installerPackageName != null) {
-                    PackageManagerService.sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_LAUNCH,
+                    yucky.sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_LAUNCH,
                             pkgSetting.name, null,
                             pkgSetting.installerPackageName, null, new int[] {userId});
                 }
diff --git a/services/core/jni/com_android_server_AssetAtlasService.cpp b/services/core/jni/com_android_server_AssetAtlasService.cpp
index 3d8905d..8f4fb51 100644
--- a/services/core/jni/com_android_server_AssetAtlasService.cpp
+++ b/services/core/jni/com_android_server_AssetAtlasService.cpp
@@ -64,7 +64,8 @@
 static jboolean com_android_server_AssetAtlasService_upload(JNIEnv* env, jobject,
         jobject graphicBuffer, jobject bitmapHandle) {
 
-    SkBitmap& bitmap = *GraphicsJNI::getSkBitmapDeprecated(env, bitmapHandle);
+    SkBitmap bitmap;
+    GraphicsJNI::getSkBitmap(env, bitmapHandle, &bitmap);
     SkAutoLockPixels alp(bitmap);
 
     // The goal of this method is to copy the bitmap into the GraphicBuffer
diff --git a/services/core/jni/com_android_server_SystemServer.cpp b/services/core/jni/com_android_server_SystemServer.cpp
index c50d63c..64514a9 100644
--- a/services/core/jni/com_android_server_SystemServer.cpp
+++ b/services/core/jni/com_android_server_SystemServer.cpp
@@ -25,7 +25,7 @@
 
 namespace android {
 
-static void android_server_SystemServer_nativeInit(JNIEnv* /* env */, jobject /* clazz */) {
+static void android_server_SystemServer_startSensorService(JNIEnv* /* env */, jobject /* clazz */) {
     char propBuf[PROPERTY_VALUE_MAX];
     property_get("system_init.startsensorservice", propBuf, "1");
     if (strcmp(propBuf, "1") == 0) {
@@ -39,7 +39,7 @@
  */
 static JNINativeMethod gMethods[] = {
     /* name, signature, funcPtr */
-    { "nativeInit", "()V", (void*) android_server_SystemServer_nativeInit },
+    { "startSensorService", "()V", (void*) android_server_SystemServer_startSensorService },
 };
 
 int register_android_server_SystemServer(JNIEnv* env)
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index f801d2d..c886c4c 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -4065,11 +4065,12 @@
         }
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
         synchronized (this) {
-            if (mDeviceOwner != null) {
-                return mDeviceOwner.getDeviceOwnerName();
+            if (mDeviceOwner == null || !mDeviceOwner.hasDeviceOwner()) {
+                return null;
             }
+            String deviceOwnerPackage = mDeviceOwner.getDeviceOwnerPackageName();
+            return getApplicationLabel(deviceOwnerPackage, UserHandle.USER_OWNER);
         }
-        return null;
     }
 
     // Returns the active device owner or null if there is no device owner.
@@ -4426,7 +4427,6 @@
         if (profileOwner == null) {
             return null;
         }
-
         DevicePolicyData policy = getUserData(userHandle);
         final int n = policy.mAdminList.size();
         for (int i = 0; i < n; i++) {
@@ -4444,13 +4444,37 @@
             return null;
         }
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
-
-        synchronized (this) {
-            if (mDeviceOwner != null) {
-                return mDeviceOwner.getProfileOwnerName(userHandle);
-            }
+        ComponentName profileOwner = getProfileOwner(userHandle);
+        if (profileOwner == null) {
+            return null;
         }
-        return null;
+        return getApplicationLabel(profileOwner.getPackageName(), userHandle);
+    }
+
+    /**
+     * Canonical name for a given package.
+     */
+    private String getApplicationLabel(String packageName, int userHandle) {
+        long token = Binder.clearCallingIdentity();
+        try {
+            final Context userContext;
+            try {
+                UserHandle handle = new UserHandle(userHandle);
+                userContext = mContext.createPackageContextAsUser(packageName, 0, handle);
+            } catch (PackageManager.NameNotFoundException nnfe) {
+                Log.w(LOG_TAG, packageName + " is not installed for user " + userHandle, nnfe);
+                return null;
+            }
+            ApplicationInfo appInfo = userContext.getApplicationInfo();
+            CharSequence result = null;
+            if (appInfo != null) {
+                PackageManager pm = userContext.getPackageManager();
+                result = pm.getApplicationLabel(appInfo);
+            }
+            return result != null ? result.toString() : null;
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     /**
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 2922130..c1153b6 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -156,9 +156,9 @@
     private boolean mFirstBoot;
 
     /**
-     * Called to initialize native system services.
+     * Start the sensor service.
      */
-    private static native void nativeInit();
+    private static native void startSensorService();
 
     /**
      * The main entry point from zygote.
@@ -233,7 +233,6 @@
 
         // Initialize native services.
         System.loadLibrary("android_servers");
-        nativeInit();
 
         // Check whether we failed to shut down last time we tried.
         // This call may not return.
@@ -359,6 +358,10 @@
 
         // Set up the Application instance for the system process and get started.
         mActivityManagerService.setSystemProcess();
+
+        // The sensor service needs access to package manager service, app ops
+        // service, and permissions service, therefore we start it after them.
+        startSensorService();
     }
 
     /**
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index c2e61c6..117cbe4 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -28,6 +28,7 @@
 import android.app.usage.UsageStats;
 import android.app.usage.UsageStatsManagerInternal;
 import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
+import android.appwidget.AppWidgetManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -56,6 +57,7 @@
 import android.util.Slog;
 import android.util.SparseArray;
 
+import com.android.internal.appwidget.IAppWidgetService;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.SystemConfig;
@@ -96,6 +98,7 @@
     Handler mHandler;
     AppOpsManager mAppOps;
     UserManager mUserManager;
+    AppWidgetManager mAppWidgetManager;
 
     private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>();
     private File mUsageStatsDir;
@@ -158,6 +161,7 @@
         if (phase == PHASE_SYSTEM_SERVICES_READY) {
             // Observe changes to the threshold
             new SettingsObserver(mHandler).registerObserver();
+            mAppWidgetManager = getContext().getSystemService(AppWidgetManager.class);
         } else if (phase == PHASE_BOOT_COMPLETED) {
             setAppIdleParoled(getContext().getSystemService(BatteryManager.class).isCharging());
         }
@@ -500,6 +504,11 @@
             return false;
         }
 
+        if (mAppWidgetManager != null
+                && mAppWidgetManager.isBoundWidgetPackage(packageName, userId)) {
+            return false;
+        }
+
         final long lastUsed = getLastPackageAccessTime(packageName, userId);
         return hasPassedIdleDuration(lastUsed);
     }
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 81c5e6a..56b2fa5 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -734,10 +734,10 @@
         }
 
         @Override
-        public boolean activeServiceSupportsAssistGesture() {
+        public boolean activeServiceSupportsAssist() {
             enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
             synchronized (this) {
-                return mImpl != null && mImpl.mInfo.getSupportsAssistGesture();
+                return mImpl != null && mImpl.mInfo.getSupportsAssist();
             }
         }
 
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 9273939..fee6495 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -132,7 +132,7 @@
         /**
          * @hide
          */
-        public static final int CAPABILITY_UNUSED = 0x00000010;
+        public static final int CAPABILITY_UNUSED_1 = 0x00000010;
 
         /** Call supports responding via text option. */
         public static final int CAPABILITY_RESPOND_VIA_TEXT = 0x00000020;
@@ -189,27 +189,6 @@
         public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 0x00002000;
 
         /**
-         * Whether the call is a generic conference, where we do not know the precise state of
-         * participants in the conference (eg. on CDMA).
-         */
-        public static final int CAPABILITY_GENERIC_CONFERENCE = 0x00004000;
-
-        /**
-         * Call is using high definition audio.
-         */
-        public static final int CAPABILITY_HIGH_DEF_AUDIO = 0x00008000;
-
-        /**
-         * Call is using WIFI.
-         */
-        public static final int CAPABILITY_WIFI = 0x00010000;
-
-        /**
-         * Indicates that the current device callback number should be shown.
-         */
-        public static final int CAPABILITY_SHOW_CALLBACK_NUMBER = 0x00020000;
-
-        /**
          * Speed up audio setup for MT call.
          * @hide
          */
@@ -228,7 +207,37 @@
         public static final int CAPABILITY_CAN_PAUSE_VIDEO = 0x00100000;
 
         //******************************************************************************************
-        // Next CAPABILITY value: 0x00200000
+        // Next CAPABILITY value: 0x00004000
+        //******************************************************************************************
+
+        /**
+         * Whether the call is currently a conference.
+         */
+        public static final int PROPERTY_CONFERENCE = 0x00000001;
+
+        /**
+         * Whether the call is a generic conference, where we do not know the precise state of
+         * participants in the conference (eg. on CDMA).
+         */
+        public static final int PROPERTY_GENERIC_CONFERENCE = 0x00000002;
+
+        /**
+         * Whether the call is made while the device is in emergency callback mode.
+         */
+        public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 0x00000004;
+
+        /**
+         * Connection is using WIFI.
+         */
+        public static final int PROPERTY_WIFI = 0x00000008;
+
+        /**
+         * Call is using high definition audio.
+         */
+        public static final int PROPERTY_HIGH_DEF_AUDIO = 0x00000010;
+
+        //******************************************************************************************
+        // Next PROPERTY value: 0x00000020
         //******************************************************************************************
 
         private final Uri mHandle;
@@ -314,18 +323,6 @@
             if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL)) {
                 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL");
             }
-            if (can(capabilities, CAPABILITY_HIGH_DEF_AUDIO)) {
-                builder.append(" CAPABILITY_HIGH_DEF_AUDIO");
-            }
-            if (can(capabilities, CAPABILITY_WIFI)) {
-                builder.append(" CAPABILITY_WIFI");
-            }
-            if (can(capabilities, CAPABILITY_GENERIC_CONFERENCE)) {
-                builder.append(" CAPABILITY_GENERIC_CONFERENCE");
-            }
-            if (can(capabilities, CAPABILITY_SHOW_CALLBACK_NUMBER)) {
-                builder.append(" CAPABILITY_SHOW_CALLBACK_NUMBER");
-            }
             if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) {
                 builder.append(" CAPABILITY_SPEED_UP_MT_AUDIO");
             }
@@ -340,6 +337,55 @@
         }
 
         /**
+         * Whether the supplied properties includes the specified property.
+         *
+         * @param properties A bit field of properties.
+         * @param property The property to check properties for.
+         * @return Whether the specified property is supported.
+         */
+        public static boolean hasProperty(int properties, int property) {
+            return (properties & property) != 0;
+        }
+
+        /**
+         * Whether the properties of this {@code Details} includes the specified property.
+         *
+         * @param property The property to check properties for.
+         * @return Whether the specified property is supported.
+         */
+        public boolean hasProperty(int property) {
+            return hasProperty(mCallProperties, property);
+        }
+
+        /**
+         * Render a set of property bits ({@code PROPERTY_*}) as a human readable string.
+         *
+         * @param properties A property bit field.
+         * @return A human readable string representation.
+         */
+        public static String propertiesToString(int properties) {
+            StringBuilder builder = new StringBuilder();
+            builder.append("[Properties:");
+            if (hasProperty(properties, PROPERTY_CONFERENCE)) {
+                builder.append(" PROPERTY_CONFERENCE");
+            }
+            if (hasProperty(properties, PROPERTY_GENERIC_CONFERENCE)) {
+                builder.append(" PROPERTY_GENERIC_CONFERENCE");
+            }
+            if (hasProperty(properties, PROPERTY_WIFI)) {
+                builder.append(" PROPERTY_WIFI");
+            }
+            if (hasProperty(properties, PROPERTY_HIGH_DEF_AUDIO)) {
+                builder.append(" PROPERTY_HIGH_DEF_AUDIO");
+            }
+            if (hasProperty(properties, PROPERTY_EMERGENCY_CALLBACK_MODE)) {
+                builder.append(" EMERGENCY_CALLBACK_MODE");
+            }
+            builder.append("]");
+            return builder.toString();
+        }
+
+        /**
          * @return The handle (e.g., phone number) to which the {@code Call} is currently
          * connected.
          */
@@ -387,8 +433,8 @@
         }
 
         /**
-         * @return A bitmask of the properties of the {@code Call}, as defined in
-         *         {@link CallProperties}.
+         * @return A bitmask of the properties of the {@code Call}, as defined by the various
+         *         {@code PROPERTY_*} constants in this class.
          */
         public int getCallProperties() {
             return mCallProperties;
diff --git a/telecomm/java/android/telecom/CallProperties.java b/telecomm/java/android/telecom/CallProperties.java
deleted file mode 100644
index 1721a39..0000000
--- a/telecomm/java/android/telecom/CallProperties.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.telecom;
-
-/**
- * Defines properties of a phone call which may be affected by changes to the call.
- */
-public class CallProperties {
-    /** Call is currently in a conference call. */
-    public static final int CONFERENCE                      = 0x00000001;
-}
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index cdecb33..303a492 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -1104,6 +1104,58 @@
                 || radioTechnology == RIL_RADIO_TECHNOLOGY_EHRPD;
     }
 
+    /** @hide */
+    public static boolean hasCdma(int radioTechnologyBitmask) {
+        int cdmaBitmask = (RIL_RADIO_TECHNOLOGY_IS95A
+                | RIL_RADIO_TECHNOLOGY_IS95B
+                | RIL_RADIO_TECHNOLOGY_1xRTT
+                | RIL_RADIO_TECHNOLOGY_EVDO_0
+                | RIL_RADIO_TECHNOLOGY_EVDO_A
+                | RIL_RADIO_TECHNOLOGY_EVDO_B
+                | RIL_RADIO_TECHNOLOGY_EHRPD);
+
+        return ((radioTechnologyBitmask & cdmaBitmask) != 0);
+    }
+
+    /** @hide */
+    public static boolean bitmaskHasTech(int bearerBitmask, int radioTech) {
+        if (bearerBitmask == 0) {
+            return true;
+        } else if (radioTech >= 1) {
+            return ((bearerBitmask & (1 << (radioTech - 1))) != 0);
+        }
+        return false;
+    }
+
+    /** @hide */
+    public static int getBitmaskForTech(int radioTech) {
+        if (radioTech >= 1) {
+            return (1 << (radioTech - 1));
+        }
+        return 0;
+    }
+
+    /** @hide */
+    public static int getBitmaskFromString(String bearerList) {
+        String[] bearers = bearerList.split("\\|");
+        int bearerBitmask = 0;
+        for (String bearer : bearers) {
+            int bearerInt = 0;
+            try {
+                bearerInt = Integer.parseInt(bearer.trim());
+            } catch (NumberFormatException nfe) {
+                return 0;
+            }
+
+            if (bearerInt == 0) {
+                return 0;
+            }
+
+            bearerBitmask |= getBitmaskForTech(bearerInt);
+        }
+        return bearerBitmask;
+    }
+
     /**
      * Returns a merged ServiceState consisting of the base SS with voice settings from the
      * voice SS. The voice SS is only used if it is IN_SERVICE (otherwise the base SS is returned).
diff --git a/tests/Assist/res/xml/interaction_service.xml b/tests/Assist/res/xml/interaction_service.xml
index 2fd50aa..f56156e 100644
--- a/tests/Assist/res/xml/interaction_service.xml
+++ b/tests/Assist/res/xml/interaction_service.xml
@@ -18,4 +18,4 @@
 <voice-interaction-service xmlns:android="http://schemas.android.com/apk/res/android"
     android:sessionService="com.android.test.assist.AssistInteractionSessionService"
     android:recognitionService="com.android.test.assist.AssistRecognitionService"
-    android:supportsAssistGesture="true"/>
+    android:supportsAssist="true"/>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ProjectionActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ProjectionActivity.java
index 5ba3ad9..be5d7f9 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ProjectionActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ProjectionActivity.java
@@ -46,9 +46,9 @@
         }
 
         private void setProject(boolean value) {
-            RenderNode displayList = getDisplayList();
-            if (displayList != null) {
-                displayList.setProjectBackwards(value);
+            RenderNode renderNode = updateDisplayListIfDirty();
+            if (renderNode != null) {
+                renderNode.setProjectBackwards(value);
             }
             // NOTE: we can't invalidate ProjectedView for the redraw because:
             // 1) the view won't preserve displayList properties that it doesn't know about
diff --git a/tests/VoiceInteraction/res/xml/interaction_service.xml b/tests/VoiceInteraction/res/xml/interaction_service.xml
index 789493a..c015ad2 100644
--- a/tests/VoiceInteraction/res/xml/interaction_service.xml
+++ b/tests/VoiceInteraction/res/xml/interaction_service.xml
@@ -21,4 +21,4 @@
     android:sessionService="com.android.test.voiceinteraction.MainInteractionSessionService"
     android:recognitionService="com.android.test.voiceinteraction.MainRecognitionService"
     android:settingsActivity="com.android.test.voiceinteraction.SettingsActivity"
-    android:supportsAssistGesture="true" />
+    android:supportsAssist="true" />
diff --git a/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java
index 30d204f..4098b98 100644
--- a/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java
@@ -57,6 +57,11 @@
                 public String[] getPackagesForUid(int uid) {
                     return new String[0];
                 }
+
+                @Override
+                public boolean isRuntimePermission(String permission) {
+                    return false;
+                }
             };
             ServiceManagerNative.asInterface(BinderInternal.getContextObject())
                     .setPermissionController(pc);
diff --git a/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java b/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java
index 7f1e977..4072302 100644
--- a/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java
@@ -164,10 +164,6 @@
                                 com.android.internal.R.styleable.Include_id, View.NO_ID);
                         final int visibility = a.getInt(
                                 com.android.internal.R.styleable.Include_visibility, -1);
-                        final boolean hasWidth = a.hasValue(
-                                com.android.internal.R.styleable.Include_layout_width);
-                        final boolean hasHeight = a.hasValue(
-                                com.android.internal.R.styleable.Include_layout_height);
                         a.recycle();
 
                         // We try to load the layout params set in the <include /> tag. If
@@ -179,19 +175,17 @@
                         // successfully loaded layout params from the <include /> tag,
                         // false means we need to rely on the included layout params.
                         ViewGroup.LayoutParams params = null;
-                        if (hasWidth && hasHeight) {
-                            try {
-                                // ---- START CHANGES
-                                sIsInInclude = true;
-                                // ---- END CHANGES
+                        try {
+                            // ---- START CHANGES
+                            sIsInInclude = true;
+                            // ---- END CHANGES
 
-                                params = group.generateLayoutParams(attrs);
+                            params = group.generateLayoutParams(attrs);
 
-                            } finally {
-                                // ---- START CHANGES
-                                sIsInInclude = false;
-                                // ---- END CHANGES
-                            }
+                        } finally {
+                            // ---- START CHANGES
+                            sIsInInclude = false;
+                            // ---- END CHANGES
                         }
                         if (params == null) {
                             params = group.generateLayoutParams(childAttrs);