Merge "Loading gps_debug configuration before use" into oc-dev
diff --git a/api/current.txt b/api/current.txt
index b51ea54..40d1d45 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1710,6 +1710,7 @@
     field public static final int ic_notification_clear_all = 17301594; // 0x108005a
     field public static final int ic_notification_overlay = 17301595; // 0x108005b
     field public static final int ic_partial_secure = 17301596; // 0x108005c
+    field public static final int ic_picture_in_picture = 17301685; // 0x10800b5
     field public static final int ic_popup_disk_full = 17301597; // 0x108005d
     field public static final int ic_popup_reminder = 17301598; // 0x108005e
     field public static final int ic_popup_sync = 17301599; // 0x108005f
@@ -4577,6 +4578,7 @@
     method public final android.app.FragmentManager getFragmentManager();
     method public final java.lang.Object getHost();
     method public final int getId();
+    method public final android.view.LayoutInflater getLayoutInflater();
     method public android.app.LoaderManager getLoaderManager();
     method public final android.app.Fragment getParentFragment();
     method public android.transition.Transition getReenterTransition();
@@ -7063,6 +7065,7 @@
     method public static void deleteAllHosts();
     method public void deleteAppWidgetId(int);
     method public void deleteHost();
+    method public int[] getAppWidgetIds();
     method protected android.appwidget.AppWidgetHostView onCreateView(android.content.Context, int, android.appwidget.AppWidgetProviderInfo);
     method protected void onProviderChanged(int, android.appwidget.AppWidgetProviderInfo);
     method protected void onProvidersChanged();
@@ -9381,7 +9384,6 @@
     field public static final java.lang.String ACTION_PACKAGE_ADDED = "android.intent.action.PACKAGE_ADDED";
     field public static final java.lang.String ACTION_PACKAGE_CHANGED = "android.intent.action.PACKAGE_CHANGED";
     field public static final java.lang.String ACTION_PACKAGE_DATA_CLEARED = "android.intent.action.PACKAGE_DATA_CLEARED";
-    field public static final java.lang.String ACTION_PACKAGE_FIRST_ADDED = "android.intent.action.PACKAGE_FIRST_ADDED";
     field public static final java.lang.String ACTION_PACKAGE_FIRST_LAUNCH = "android.intent.action.PACKAGE_FIRST_LAUNCH";
     field public static final java.lang.String ACTION_PACKAGE_FULLY_REMOVED = "android.intent.action.PACKAGE_FULLY_REMOVED";
     field public static final deprecated java.lang.String ACTION_PACKAGE_INSTALL = "android.intent.action.PACKAGE_INSTALL";
@@ -9891,7 +9893,7 @@
   }
 
   public abstract interface ServiceConnection {
-    method public default void onBindingDead(android.content.ComponentName);
+    method public default void onBindingDied(android.content.ComponentName);
     method public abstract void onServiceConnected(android.content.ComponentName, android.os.IBinder);
     method public abstract void onServiceDisconnected(android.content.ComponentName);
   }
@@ -10940,12 +10942,13 @@
     method public android.content.pm.VersionedPackage getDeclaringPackage();
     method public java.util.List<android.content.pm.VersionedPackage> getDependentPackages();
     method public java.lang.String getName();
-    method public int getVersion();
-    method public boolean isBuiltin();
-    method public boolean isDynamic();
-    method public boolean isStatic();
+    method public int getType();
+    method public long getVersion();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.content.pm.SharedLibraryInfo> CREATOR;
+    field public static final int TYPE_BUILTIN = 0; // 0x0
+    field public static final int TYPE_DYNAMIC = 1; // 0x1
+    field public static final int TYPE_STATIC = 2; // 0x2
     field public static final int VERSION_UNDEFINED = -1; // 0xffffffff
   }
 
@@ -12599,7 +12602,6 @@
 
   public class BitmapShader extends android.graphics.Shader {
     ctor public BitmapShader(android.graphics.Bitmap, android.graphics.Shader.TileMode, android.graphics.Shader.TileMode);
-    method public void set(android.graphics.Bitmap, android.graphics.Shader.TileMode, android.graphics.Shader.TileMode);
   }
 
   public class BlurMaskFilter extends android.graphics.MaskFilter {
@@ -12852,8 +12854,6 @@
     ctor public ColorMatrixColorFilter(android.graphics.ColorMatrix);
     ctor public ColorMatrixColorFilter(float[]);
     method public void getColorMatrix(android.graphics.ColorMatrix);
-    method public void setColorMatrix(android.graphics.ColorMatrix);
-    method public void setColorMatrixArray(float[]);
   }
 
   public abstract class ColorSpace {
@@ -12994,8 +12994,6 @@
   public class ComposeShader extends android.graphics.Shader {
     ctor public ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode);
     ctor public ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.PorterDuff.Mode);
-    method public void set(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode);
-    method public void set(android.graphics.Shader, android.graphics.Shader, android.graphics.PorterDuff.Mode);
   }
 
   public class CornerPathEffect extends android.graphics.PathEffect {
@@ -13068,15 +13066,11 @@
     ctor public LightingColorFilter(int, int);
     method public int getColorAdd();
     method public int getColorMultiply();
-    method public void setColorAdd(int);
-    method public void setColorMultiply(int);
   }
 
   public class LinearGradient extends android.graphics.Shader {
     ctor public LinearGradient(float, float, float, float, int[], float[], android.graphics.Shader.TileMode);
     ctor public LinearGradient(float, float, float, float, int, int, android.graphics.Shader.TileMode);
-    method public void set(float, float, float, float, int[], float[], android.graphics.Shader.TileMode);
-    method public void set(float, float, float, float, int, int, android.graphics.Shader.TileMode);
   }
 
   public class MaskFilter {
@@ -13586,10 +13580,6 @@
 
   public class PorterDuffColorFilter extends android.graphics.ColorFilter {
     ctor public PorterDuffColorFilter(int, android.graphics.PorterDuff.Mode);
-    method public int getColor();
-    method public android.graphics.PorterDuff.Mode getMode();
-    method public void setColor(int);
-    method public void setMode(android.graphics.PorterDuff.Mode);
   }
 
   public class PorterDuffXfermode extends android.graphics.Xfermode {
@@ -13599,8 +13589,6 @@
   public class RadialGradient extends android.graphics.Shader {
     ctor public RadialGradient(float, float, float, int[], float[], android.graphics.Shader.TileMode);
     ctor public RadialGradient(float, float, float, int, int, android.graphics.Shader.TileMode);
-    method public void set(float, float, float, int[], float[], android.graphics.Shader.TileMode);
-    method public void set(float, float, float, int, int, android.graphics.Shader.TileMode);
   }
 
   public final class Rect implements android.os.Parcelable {
@@ -13785,8 +13773,6 @@
   public class SweepGradient extends android.graphics.Shader {
     ctor public SweepGradient(float, float, int[], float[]);
     ctor public SweepGradient(float, float, int, int);
-    method public void set(float, float, int[], float[]);
-    method public void set(float, float, int, int);
   }
 
   public class Typeface {
@@ -14832,7 +14818,7 @@
     field public static final java.lang.String STRING_TYPE_HEART_RATE = "android.sensor.heart_rate";
     field public static final java.lang.String STRING_TYPE_LIGHT = "android.sensor.light";
     field public static final java.lang.String STRING_TYPE_LINEAR_ACCELERATION = "android.sensor.linear_acceleration";
-    field public static final java.lang.String STRING_TYPE_LOW_LATENCY_OFFBODY_DETECT = "android.sensor.low_latency_offbody";
+    field public static final java.lang.String STRING_TYPE_LOW_LATENCY_OFFBODY_DETECT = "android.sensor.low_latency_offbody_detect";
     field public static final java.lang.String STRING_TYPE_MAGNETIC_FIELD = "android.sensor.magnetic_field";
     field public static final java.lang.String STRING_TYPE_MAGNETIC_FIELD_UNCALIBRATED = "android.sensor.magnetic_field_uncalibrated";
     field public static final java.lang.String STRING_TYPE_MOTION_DETECT = "android.sensor.motion_detect";
@@ -20800,13 +20786,10 @@
     method public boolean hasSpeedAccuracy();
     method public boolean hasVerticalAccuracy();
     method public boolean isFromMockProvider();
-    method public void removeAccuracy();
-    method public void removeAltitude();
-    method public void removeBearing();
-    method public void removeBearingAccuracy();
-    method public void removeSpeed();
-    method public void removeSpeedAccuracy();
-    method public void removeVerticalAccuracy();
+    method public deprecated void removeAccuracy();
+    method public deprecated void removeAltitude();
+    method public deprecated void removeBearing();
+    method public deprecated void removeSpeed();
     method public void reset();
     method public void set(android.location.Location);
     method public void setAccuracy(float);
@@ -25534,14 +25517,10 @@
   }
 
   public final class IpSecManager {
-    method public void applyTransportModeTransform(java.net.Socket, android.net.IpSecTransform) throws java.io.IOException;
-    method public void applyTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform) throws java.io.IOException;
     method public void applyTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException;
     method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket(int) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
     method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket() throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
-    method public void removeTransportModeTransform(java.net.Socket, android.net.IpSecTransform);
-    method public void removeTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform);
-    method public void removeTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform);
+    method public void removeTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException;
     method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress) throws android.net.IpSecManager.ResourceUnavailableException;
     method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
     field public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; // 0x0
@@ -25560,7 +25539,7 @@
   }
 
   public static final class IpSecManager.UdpEncapsulationSocket implements java.lang.AutoCloseable {
-    method public void close();
+    method public void close() throws java.io.IOException;
     method public int getPort();
     method public java.io.FileDescriptor getSocket();
   }
@@ -37054,6 +37033,7 @@
   public abstract class AutofillService extends android.app.Service {
     ctor public AutofillService();
     method public final deprecated void disableSelf();
+    method public final android.service.autofill.FillEventHistory getFillEventHistory();
     method public final android.os.IBinder onBind(android.content.Intent);
     method public void onConnected();
     method public void onDisconnected();
@@ -37076,6 +37056,7 @@
     ctor public Dataset.Builder();
     method public android.service.autofill.Dataset build();
     method public android.service.autofill.Dataset.Builder setAuthentication(android.content.IntentSender);
+    method public android.service.autofill.Dataset.Builder setId(java.lang.String);
     method public android.service.autofill.Dataset.Builder setValue(android.view.autofill.AutofillId, android.view.autofill.AutofillValue);
     method public android.service.autofill.Dataset.Builder setValue(android.view.autofill.AutofillId, android.view.autofill.AutofillValue, android.widget.RemoteViews);
   }
@@ -37093,6 +37074,23 @@
     field public static final android.os.Parcelable.Creator<android.service.autofill.FillContext> CREATOR;
   }
 
+  public final class FillEventHistory implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.os.Bundle getClientState();
+    method public java.util.List<android.service.autofill.FillEventHistory.Event> getEvents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.FillEventHistory> CREATOR;
+  }
+
+  public static final class FillEventHistory.Event {
+    method public java.lang.String getDatasetId();
+    method public int getType();
+    field public static final int TYPE_AUTHENTICATION_SELECTED = 2; // 0x2
+    field public static final int TYPE_DATASET_AUTHENTICATION_SELECTED = 1; // 0x1
+    field public static final int TYPE_DATASET_SELECTED = 0; // 0x0
+    field public static final int TYPE_SAVE_SHOWN = 3; // 0x3
+  }
+
   public final class FillRequest implements android.os.Parcelable {
     method public int describeContents();
     method public android.os.Bundle getClientState();
@@ -37117,6 +37115,7 @@
     method public android.service.autofill.FillResponse.Builder setAuthentication(android.view.autofill.AutofillId[], android.content.IntentSender, android.widget.RemoteViews);
     method public android.service.autofill.FillResponse.Builder setClientState(android.os.Bundle);
     method public deprecated android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
+    method public android.service.autofill.FillResponse.Builder setIgnoredIds(android.view.autofill.AutofillId...);
     method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo);
   }
 
@@ -37129,6 +37128,7 @@
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.service.autofill.SaveInfo> CREATOR;
+    field public static final int FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE = 1; // 0x1
     field public static final int SAVE_DATA_TYPE_ADDRESS = 2; // 0x2
     field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 4; // 0x4
     field public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 16; // 0x10
@@ -37141,9 +37141,9 @@
     ctor public SaveInfo.Builder(int, android.view.autofill.AutofillId[]);
     method public android.service.autofill.SaveInfo build();
     method public android.service.autofill.SaveInfo.Builder setDescription(java.lang.CharSequence);
+    method public android.service.autofill.SaveInfo.Builder setFlags(int);
     method public android.service.autofill.SaveInfo.Builder setNegativeAction(java.lang.CharSequence, android.content.IntentSender);
     method public android.service.autofill.SaveInfo.Builder setOptionalIds(android.view.autofill.AutofillId[]);
-    method public android.service.autofill.SaveInfo.Builder setSaveOnAllViewsInvisible(boolean);
   }
 
   public final class SaveRequest implements android.os.Parcelable {
@@ -45945,7 +45945,9 @@
     field public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 1; // 0x1
     field public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0; // 0x0
     field public static final int IMPORTANT_FOR_AUTOFILL_NO = 2; // 0x2
+    field public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 8; // 0x8
     field public static final int IMPORTANT_FOR_AUTOFILL_YES = 1; // 0x1
+    field public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 4; // 0x4
     field public static final int INVISIBLE = 4; // 0x4
     field public static final int KEEP_SCREEN_ON = 67108864; // 0x4000000
     field public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
diff --git a/api/removed.txt b/api/removed.txt
index 0f5b81a..b6c2a98 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -63,6 +63,12 @@
     field public static final int REQUESTED_PERMISSION_REQUIRED = 1; // 0x1
   }
 
+  public final class SharedLibraryInfo implements android.os.Parcelable {
+    method public boolean isBuiltin();
+    method public boolean isDynamic();
+    method public boolean isStatic();
+  }
+
 }
 
 package android.database {
@@ -126,6 +132,16 @@
 
 }
 
+package android.location {
+
+  public class Location implements android.os.Parcelable {
+    method public deprecated void removeBearingAccuracy();
+    method public deprecated void removeSpeedAccuracy();
+    method public deprecated void removeVerticalAccuracy();
+  }
+
+}
+
 package android.media {
 
   public final class AudioFormat implements android.os.Parcelable {
diff --git a/api/system-current.txt b/api/system-current.txt
index dc4c21f..e0eb0d2 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1834,6 +1834,7 @@
     field public static final int ic_notification_clear_all = 17301594; // 0x108005a
     field public static final int ic_notification_overlay = 17301595; // 0x108005b
     field public static final int ic_partial_secure = 17301596; // 0x108005c
+    field public static final int ic_picture_in_picture = 17301685; // 0x10800b5
     field public static final int ic_popup_disk_full = 17301597; // 0x108005d
     field public static final int ic_popup_reminder = 17301598; // 0x108005e
     field public static final int ic_popup_sync = 17301599; // 0x108005f
@@ -4744,6 +4745,7 @@
     method public final android.app.FragmentManager getFragmentManager();
     method public final java.lang.Object getHost();
     method public final int getId();
+    method public final android.view.LayoutInflater getLayoutInflater();
     method public android.app.LoaderManager getLoaderManager();
     method public final android.app.Fragment getParentFragment();
     method public android.transition.Transition getReenterTransition();
@@ -7529,6 +7531,7 @@
     method public static void deleteAllHosts();
     method public void deleteAppWidgetId(int);
     method public void deleteHost();
+    method public int[] getAppWidgetIds();
     method protected android.appwidget.AppWidgetHostView onCreateView(android.content.Context, int, android.appwidget.AppWidgetProviderInfo);
     method protected void onProviderChanged(int, android.appwidget.AppWidgetProviderInfo);
     method protected void onProvidersChanged();
@@ -9913,7 +9916,6 @@
     field public static final java.lang.String ACTION_PACKAGE_ADDED = "android.intent.action.PACKAGE_ADDED";
     field public static final java.lang.String ACTION_PACKAGE_CHANGED = "android.intent.action.PACKAGE_CHANGED";
     field public static final java.lang.String ACTION_PACKAGE_DATA_CLEARED = "android.intent.action.PACKAGE_DATA_CLEARED";
-    field public static final java.lang.String ACTION_PACKAGE_FIRST_ADDED = "android.intent.action.PACKAGE_FIRST_ADDED";
     field public static final java.lang.String ACTION_PACKAGE_FIRST_LAUNCH = "android.intent.action.PACKAGE_FIRST_LAUNCH";
     field public static final java.lang.String ACTION_PACKAGE_FULLY_REMOVED = "android.intent.action.PACKAGE_FULLY_REMOVED";
     field public static final deprecated java.lang.String ACTION_PACKAGE_INSTALL = "android.intent.action.PACKAGE_INSTALL";
@@ -10465,7 +10467,7 @@
   }
 
   public abstract interface ServiceConnection {
-    method public default void onBindingDead(android.content.ComponentName);
+    method public default void onBindingDied(android.content.ComponentName);
     method public abstract void onServiceConnected(android.content.ComponentName, android.os.IBinder);
     method public abstract void onServiceDisconnected(android.content.ComponentName);
   }
@@ -11700,12 +11702,13 @@
     method public android.content.pm.VersionedPackage getDeclaringPackage();
     method public java.util.List<android.content.pm.VersionedPackage> getDependentPackages();
     method public java.lang.String getName();
-    method public int getVersion();
-    method public boolean isBuiltin();
-    method public boolean isDynamic();
-    method public boolean isStatic();
+    method public int getType();
+    method public long getVersion();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.content.pm.SharedLibraryInfo> CREATOR;
+    field public static final int TYPE_BUILTIN = 0; // 0x0
+    field public static final int TYPE_DYNAMIC = 1; // 0x1
+    field public static final int TYPE_STATIC = 2; // 0x2
     field public static final int VERSION_UNDEFINED = -1; // 0xffffffff
   }
 
@@ -13373,7 +13376,6 @@
 
   public class BitmapShader extends android.graphics.Shader {
     ctor public BitmapShader(android.graphics.Bitmap, android.graphics.Shader.TileMode, android.graphics.Shader.TileMode);
-    method public void set(android.graphics.Bitmap, android.graphics.Shader.TileMode, android.graphics.Shader.TileMode);
   }
 
   public class BlurMaskFilter extends android.graphics.MaskFilter {
@@ -13626,8 +13628,6 @@
     ctor public ColorMatrixColorFilter(android.graphics.ColorMatrix);
     ctor public ColorMatrixColorFilter(float[]);
     method public void getColorMatrix(android.graphics.ColorMatrix);
-    method public void setColorMatrix(android.graphics.ColorMatrix);
-    method public void setColorMatrixArray(float[]);
   }
 
   public abstract class ColorSpace {
@@ -13768,8 +13768,6 @@
   public class ComposeShader extends android.graphics.Shader {
     ctor public ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode);
     ctor public ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.PorterDuff.Mode);
-    method public void set(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode);
-    method public void set(android.graphics.Shader, android.graphics.Shader, android.graphics.PorterDuff.Mode);
   }
 
   public class CornerPathEffect extends android.graphics.PathEffect {
@@ -13842,15 +13840,11 @@
     ctor public LightingColorFilter(int, int);
     method public int getColorAdd();
     method public int getColorMultiply();
-    method public void setColorAdd(int);
-    method public void setColorMultiply(int);
   }
 
   public class LinearGradient extends android.graphics.Shader {
     ctor public LinearGradient(float, float, float, float, int[], float[], android.graphics.Shader.TileMode);
     ctor public LinearGradient(float, float, float, float, int, int, android.graphics.Shader.TileMode);
-    method public void set(float, float, float, float, int[], float[], android.graphics.Shader.TileMode);
-    method public void set(float, float, float, float, int, int, android.graphics.Shader.TileMode);
   }
 
   public class MaskFilter {
@@ -14360,10 +14354,6 @@
 
   public class PorterDuffColorFilter extends android.graphics.ColorFilter {
     ctor public PorterDuffColorFilter(int, android.graphics.PorterDuff.Mode);
-    method public int getColor();
-    method public android.graphics.PorterDuff.Mode getMode();
-    method public void setColor(int);
-    method public void setMode(android.graphics.PorterDuff.Mode);
   }
 
   public class PorterDuffXfermode extends android.graphics.Xfermode {
@@ -14373,8 +14363,6 @@
   public class RadialGradient extends android.graphics.Shader {
     ctor public RadialGradient(float, float, float, int[], float[], android.graphics.Shader.TileMode);
     ctor public RadialGradient(float, float, float, int, int, android.graphics.Shader.TileMode);
-    method public void set(float, float, float, int[], float[], android.graphics.Shader.TileMode);
-    method public void set(float, float, float, int, int, android.graphics.Shader.TileMode);
   }
 
   public final class Rect implements android.os.Parcelable {
@@ -14559,8 +14547,6 @@
   public class SweepGradient extends android.graphics.Shader {
     ctor public SweepGradient(float, float, int[], float[]);
     ctor public SweepGradient(float, float, int, int);
-    method public void set(float, float, int[], float[]);
-    method public void set(float, float, int, int);
   }
 
   public class Typeface {
@@ -15609,7 +15595,7 @@
     field public static final java.lang.String STRING_TYPE_HEART_RATE = "android.sensor.heart_rate";
     field public static final java.lang.String STRING_TYPE_LIGHT = "android.sensor.light";
     field public static final java.lang.String STRING_TYPE_LINEAR_ACCELERATION = "android.sensor.linear_acceleration";
-    field public static final java.lang.String STRING_TYPE_LOW_LATENCY_OFFBODY_DETECT = "android.sensor.low_latency_offbody";
+    field public static final java.lang.String STRING_TYPE_LOW_LATENCY_OFFBODY_DETECT = "android.sensor.low_latency_offbody_detect";
     field public static final java.lang.String STRING_TYPE_MAGNETIC_FIELD = "android.sensor.magnetic_field";
     field public static final java.lang.String STRING_TYPE_MAGNETIC_FIELD_UNCALIBRATED = "android.sensor.magnetic_field_uncalibrated";
     field public static final java.lang.String STRING_TYPE_MOTION_DETECT = "android.sensor.motion_detect";
@@ -22534,13 +22520,10 @@
     method public boolean isComplete();
     method public boolean isFromMockProvider();
     method public void makeComplete();
-    method public void removeAccuracy();
-    method public void removeAltitude();
-    method public void removeBearing();
-    method public void removeBearingAccuracy();
-    method public void removeSpeed();
-    method public void removeSpeedAccuracy();
-    method public void removeVerticalAccuracy();
+    method public deprecated void removeAccuracy();
+    method public deprecated void removeAltitude();
+    method public deprecated void removeBearing();
+    method public deprecated void removeSpeed();
     method public void reset();
     method public void set(android.location.Location);
     method public void setAccuracy(float);
@@ -27723,14 +27706,10 @@
   }
 
   public final class IpSecManager {
-    method public void applyTransportModeTransform(java.net.Socket, android.net.IpSecTransform) throws java.io.IOException;
-    method public void applyTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform) throws java.io.IOException;
     method public void applyTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException;
     method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket(int) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
     method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket() throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
-    method public void removeTransportModeTransform(java.net.Socket, android.net.IpSecTransform);
-    method public void removeTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform);
-    method public void removeTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform);
+    method public void removeTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException;
     method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress) throws android.net.IpSecManager.ResourceUnavailableException;
     method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
     field public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; // 0x0
@@ -27749,7 +27728,7 @@
   }
 
   public static final class IpSecManager.UdpEncapsulationSocket implements java.lang.AutoCloseable {
-    method public void close();
+    method public void close() throws java.io.IOException;
     method public int getPort();
     method public java.io.FileDescriptor getSocket();
   }
@@ -34383,6 +34362,7 @@
     method public static void rebootWipeUserData(android.content.Context) throws java.io.IOException;
     method public static void scheduleUpdateOnBoot(android.content.Context, java.io.File) throws java.io.IOException;
     method public static void verifyPackage(java.io.File, android.os.RecoverySystem.ProgressListener, java.io.File) throws java.security.GeneralSecurityException, java.io.IOException;
+    method public static boolean verifyPackageCompatibility(java.io.File) throws java.io.IOException;
   }
 
   public static abstract interface RecoverySystem.ProgressListener {
@@ -40166,6 +40146,7 @@
   public abstract class AutofillService extends android.app.Service {
     ctor public AutofillService();
     method public final deprecated void disableSelf();
+    method public final android.service.autofill.FillEventHistory getFillEventHistory();
     method public final android.os.IBinder onBind(android.content.Intent);
     method public void onConnected();
     method public void onDisconnected();
@@ -40188,6 +40169,7 @@
     ctor public Dataset.Builder();
     method public android.service.autofill.Dataset build();
     method public android.service.autofill.Dataset.Builder setAuthentication(android.content.IntentSender);
+    method public android.service.autofill.Dataset.Builder setId(java.lang.String);
     method public android.service.autofill.Dataset.Builder setValue(android.view.autofill.AutofillId, android.view.autofill.AutofillValue);
     method public android.service.autofill.Dataset.Builder setValue(android.view.autofill.AutofillId, android.view.autofill.AutofillValue, android.widget.RemoteViews);
   }
@@ -40205,6 +40187,23 @@
     field public static final android.os.Parcelable.Creator<android.service.autofill.FillContext> CREATOR;
   }
 
+  public final class FillEventHistory implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.os.Bundle getClientState();
+    method public java.util.List<android.service.autofill.FillEventHistory.Event> getEvents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.FillEventHistory> CREATOR;
+  }
+
+  public static final class FillEventHistory.Event {
+    method public java.lang.String getDatasetId();
+    method public int getType();
+    field public static final int TYPE_AUTHENTICATION_SELECTED = 2; // 0x2
+    field public static final int TYPE_DATASET_AUTHENTICATION_SELECTED = 1; // 0x1
+    field public static final int TYPE_DATASET_SELECTED = 0; // 0x0
+    field public static final int TYPE_SAVE_SHOWN = 3; // 0x3
+  }
+
   public final class FillRequest implements android.os.Parcelable {
     method public int describeContents();
     method public android.os.Bundle getClientState();
@@ -40229,6 +40228,7 @@
     method public android.service.autofill.FillResponse.Builder setAuthentication(android.view.autofill.AutofillId[], android.content.IntentSender, android.widget.RemoteViews);
     method public android.service.autofill.FillResponse.Builder setClientState(android.os.Bundle);
     method public deprecated android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
+    method public android.service.autofill.FillResponse.Builder setIgnoredIds(android.view.autofill.AutofillId...);
     method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo);
   }
 
@@ -40241,6 +40241,7 @@
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.service.autofill.SaveInfo> CREATOR;
+    field public static final int FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE = 1; // 0x1
     field public static final int SAVE_DATA_TYPE_ADDRESS = 2; // 0x2
     field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 4; // 0x4
     field public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 16; // 0x10
@@ -40253,9 +40254,9 @@
     ctor public SaveInfo.Builder(int, android.view.autofill.AutofillId[]);
     method public android.service.autofill.SaveInfo build();
     method public android.service.autofill.SaveInfo.Builder setDescription(java.lang.CharSequence);
+    method public android.service.autofill.SaveInfo.Builder setFlags(int);
     method public android.service.autofill.SaveInfo.Builder setNegativeAction(java.lang.CharSequence, android.content.IntentSender);
     method public android.service.autofill.SaveInfo.Builder setOptionalIds(android.view.autofill.AutofillId[]);
-    method public android.service.autofill.SaveInfo.Builder setSaveOnAllViewsInvisible(boolean);
   }
 
   public final class SaveRequest implements android.os.Parcelable {
@@ -49520,7 +49521,9 @@
     field public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 1; // 0x1
     field public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0; // 0x0
     field public static final int IMPORTANT_FOR_AUTOFILL_NO = 2; // 0x2
+    field public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 8; // 0x8
     field public static final int IMPORTANT_FOR_AUTOFILL_YES = 1; // 0x1
+    field public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 4; // 0x4
     field public static final int INVISIBLE = 4; // 0x4
     field public static final int KEEP_SCREEN_ON = 67108864; // 0x4000000
     field public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 823d88f..6d82a49 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -61,6 +61,12 @@
     field public static final int REQUESTED_PERMISSION_REQUIRED = 1; // 0x1
   }
 
+  public final class SharedLibraryInfo implements android.os.Parcelable {
+    method public boolean isBuiltin();
+    method public boolean isDynamic();
+    method public boolean isStatic();
+  }
+
 }
 
 package android.database {
@@ -124,6 +130,16 @@
 
 }
 
+package android.location {
+
+  public class Location implements android.os.Parcelable {
+    method public deprecated void removeBearingAccuracy();
+    method public deprecated void removeSpeedAccuracy();
+    method public deprecated void removeVerticalAccuracy();
+  }
+
+}
+
 package android.media {
 
   public final class AudioFormat implements android.os.Parcelable {
diff --git a/api/test-current.txt b/api/test-current.txt
index 88adb6e..44e1d71 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1710,6 +1710,7 @@
     field public static final int ic_notification_clear_all = 17301594; // 0x108005a
     field public static final int ic_notification_overlay = 17301595; // 0x108005b
     field public static final int ic_partial_secure = 17301596; // 0x108005c
+    field public static final int ic_picture_in_picture = 17301685; // 0x10800b5
     field public static final int ic_popup_disk_full = 17301597; // 0x108005d
     field public static final int ic_popup_reminder = 17301598; // 0x108005e
     field public static final int ic_popup_sync = 17301599; // 0x108005f
@@ -4590,6 +4591,7 @@
     method public final android.app.FragmentManager getFragmentManager();
     method public final java.lang.Object getHost();
     method public final int getId();
+    method public final android.view.LayoutInflater getLayoutInflater();
     method public android.app.LoaderManager getLoaderManager();
     method public final android.app.Fragment getParentFragment();
     method public android.transition.Transition getReenterTransition();
@@ -7094,6 +7096,7 @@
     method public static void deleteAllHosts();
     method public void deleteAppWidgetId(int);
     method public void deleteHost();
+    method public int[] getAppWidgetIds();
     method protected android.appwidget.AppWidgetHostView onCreateView(android.content.Context, int, android.appwidget.AppWidgetProviderInfo);
     method protected void onProviderChanged(int, android.appwidget.AppWidgetProviderInfo);
     method protected void onProvidersChanged();
@@ -9415,7 +9418,6 @@
     field public static final java.lang.String ACTION_PACKAGE_ADDED = "android.intent.action.PACKAGE_ADDED";
     field public static final java.lang.String ACTION_PACKAGE_CHANGED = "android.intent.action.PACKAGE_CHANGED";
     field public static final java.lang.String ACTION_PACKAGE_DATA_CLEARED = "android.intent.action.PACKAGE_DATA_CLEARED";
-    field public static final java.lang.String ACTION_PACKAGE_FIRST_ADDED = "android.intent.action.PACKAGE_FIRST_ADDED";
     field public static final java.lang.String ACTION_PACKAGE_FIRST_LAUNCH = "android.intent.action.PACKAGE_FIRST_LAUNCH";
     field public static final java.lang.String ACTION_PACKAGE_FULLY_REMOVED = "android.intent.action.PACKAGE_FULLY_REMOVED";
     field public static final deprecated java.lang.String ACTION_PACKAGE_INSTALL = "android.intent.action.PACKAGE_INSTALL";
@@ -9925,7 +9927,7 @@
   }
 
   public abstract interface ServiceConnection {
-    method public default void onBindingDead(android.content.ComponentName);
+    method public default void onBindingDied(android.content.ComponentName);
     method public abstract void onServiceConnected(android.content.ComponentName, android.os.IBinder);
     method public abstract void onServiceDisconnected(android.content.ComponentName);
   }
@@ -10981,12 +10983,13 @@
     method public android.content.pm.VersionedPackage getDeclaringPackage();
     method public java.util.List<android.content.pm.VersionedPackage> getDependentPackages();
     method public java.lang.String getName();
-    method public int getVersion();
-    method public boolean isBuiltin();
-    method public boolean isDynamic();
-    method public boolean isStatic();
+    method public int getType();
+    method public long getVersion();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.content.pm.SharedLibraryInfo> CREATOR;
+    field public static final int TYPE_BUILTIN = 0; // 0x0
+    field public static final int TYPE_DYNAMIC = 1; // 0x1
+    field public static final int TYPE_STATIC = 2; // 0x2
     field public static final int VERSION_UNDEFINED = -1; // 0xffffffff
   }
 
@@ -12641,7 +12644,6 @@
 
   public class BitmapShader extends android.graphics.Shader {
     ctor public BitmapShader(android.graphics.Bitmap, android.graphics.Shader.TileMode, android.graphics.Shader.TileMode);
-    method public void set(android.graphics.Bitmap, android.graphics.Shader.TileMode, android.graphics.Shader.TileMode);
   }
 
   public class BlurMaskFilter extends android.graphics.MaskFilter {
@@ -12894,8 +12896,6 @@
     ctor public ColorMatrixColorFilter(android.graphics.ColorMatrix);
     ctor public ColorMatrixColorFilter(float[]);
     method public void getColorMatrix(android.graphics.ColorMatrix);
-    method public void setColorMatrix(android.graphics.ColorMatrix);
-    method public void setColorMatrixArray(float[]);
   }
 
   public abstract class ColorSpace {
@@ -13036,8 +13036,6 @@
   public class ComposeShader extends android.graphics.Shader {
     ctor public ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode);
     ctor public ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.PorterDuff.Mode);
-    method public void set(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode);
-    method public void set(android.graphics.Shader, android.graphics.Shader, android.graphics.PorterDuff.Mode);
   }
 
   public class CornerPathEffect extends android.graphics.PathEffect {
@@ -13110,15 +13108,11 @@
     ctor public LightingColorFilter(int, int);
     method public int getColorAdd();
     method public int getColorMultiply();
-    method public void setColorAdd(int);
-    method public void setColorMultiply(int);
   }
 
   public class LinearGradient extends android.graphics.Shader {
     ctor public LinearGradient(float, float, float, float, int[], float[], android.graphics.Shader.TileMode);
     ctor public LinearGradient(float, float, float, float, int, int, android.graphics.Shader.TileMode);
-    method public void set(float, float, float, float, int[], float[], android.graphics.Shader.TileMode);
-    method public void set(float, float, float, float, int, int, android.graphics.Shader.TileMode);
   }
 
   public class MaskFilter {
@@ -13628,10 +13622,6 @@
 
   public class PorterDuffColorFilter extends android.graphics.ColorFilter {
     ctor public PorterDuffColorFilter(int, android.graphics.PorterDuff.Mode);
-    method public int getColor();
-    method public android.graphics.PorterDuff.Mode getMode();
-    method public void setColor(int);
-    method public void setMode(android.graphics.PorterDuff.Mode);
   }
 
   public class PorterDuffXfermode extends android.graphics.Xfermode {
@@ -13641,8 +13631,6 @@
   public class RadialGradient extends android.graphics.Shader {
     ctor public RadialGradient(float, float, float, int[], float[], android.graphics.Shader.TileMode);
     ctor public RadialGradient(float, float, float, int, int, android.graphics.Shader.TileMode);
-    method public void set(float, float, float, int[], float[], android.graphics.Shader.TileMode);
-    method public void set(float, float, float, int, int, android.graphics.Shader.TileMode);
   }
 
   public final class Rect implements android.os.Parcelable {
@@ -13827,8 +13815,6 @@
   public class SweepGradient extends android.graphics.Shader {
     ctor public SweepGradient(float, float, int[], float[]);
     ctor public SweepGradient(float, float, int, int);
-    method public void set(float, float, int[], float[]);
-    method public void set(float, float, int, int);
   }
 
   public class Typeface {
@@ -14877,7 +14863,7 @@
     field public static final java.lang.String STRING_TYPE_HEART_RATE = "android.sensor.heart_rate";
     field public static final java.lang.String STRING_TYPE_LIGHT = "android.sensor.light";
     field public static final java.lang.String STRING_TYPE_LINEAR_ACCELERATION = "android.sensor.linear_acceleration";
-    field public static final java.lang.String STRING_TYPE_LOW_LATENCY_OFFBODY_DETECT = "android.sensor.low_latency_offbody";
+    field public static final java.lang.String STRING_TYPE_LOW_LATENCY_OFFBODY_DETECT = "android.sensor.low_latency_offbody_detect";
     field public static final java.lang.String STRING_TYPE_MAGNETIC_FIELD = "android.sensor.magnetic_field";
     field public static final java.lang.String STRING_TYPE_MAGNETIC_FIELD_UNCALIBRATED = "android.sensor.magnetic_field_uncalibrated";
     field public static final java.lang.String STRING_TYPE_MOTION_DETECT = "android.sensor.motion_detect";
@@ -20906,13 +20892,10 @@
     method public boolean hasSpeedAccuracy();
     method public boolean hasVerticalAccuracy();
     method public boolean isFromMockProvider();
-    method public void removeAccuracy();
-    method public void removeAltitude();
-    method public void removeBearing();
-    method public void removeBearingAccuracy();
-    method public void removeSpeed();
-    method public void removeSpeedAccuracy();
-    method public void removeVerticalAccuracy();
+    method public deprecated void removeAccuracy();
+    method public deprecated void removeAltitude();
+    method public deprecated void removeBearing();
+    method public deprecated void removeSpeed();
     method public void reset();
     method public void set(android.location.Location);
     method public void setAccuracy(float);
@@ -25641,14 +25624,10 @@
   }
 
   public final class IpSecManager {
-    method public void applyTransportModeTransform(java.net.Socket, android.net.IpSecTransform) throws java.io.IOException;
-    method public void applyTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform) throws java.io.IOException;
     method public void applyTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException;
     method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket(int) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
     method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket() throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
-    method public void removeTransportModeTransform(java.net.Socket, android.net.IpSecTransform);
-    method public void removeTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform);
-    method public void removeTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform);
+    method public void removeTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException;
     method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress) throws android.net.IpSecManager.ResourceUnavailableException;
     method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
     field public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; // 0x0
@@ -25667,7 +25646,7 @@
   }
 
   public static final class IpSecManager.UdpEncapsulationSocket implements java.lang.AutoCloseable {
-    method public void close();
+    method public void close() throws java.io.IOException;
     method public int getPort();
     method public java.io.FileDescriptor getSocket();
   }
@@ -37207,6 +37186,7 @@
   public abstract class AutofillService extends android.app.Service {
     ctor public AutofillService();
     method public final deprecated void disableSelf();
+    method public final android.service.autofill.FillEventHistory getFillEventHistory();
     method public final android.os.IBinder onBind(android.content.Intent);
     method public void onConnected();
     method public void onDisconnected();
@@ -37229,6 +37209,7 @@
     ctor public Dataset.Builder();
     method public android.service.autofill.Dataset build();
     method public android.service.autofill.Dataset.Builder setAuthentication(android.content.IntentSender);
+    method public android.service.autofill.Dataset.Builder setId(java.lang.String);
     method public android.service.autofill.Dataset.Builder setValue(android.view.autofill.AutofillId, android.view.autofill.AutofillValue);
     method public android.service.autofill.Dataset.Builder setValue(android.view.autofill.AutofillId, android.view.autofill.AutofillValue, android.widget.RemoteViews);
   }
@@ -37246,6 +37227,23 @@
     field public static final android.os.Parcelable.Creator<android.service.autofill.FillContext> CREATOR;
   }
 
+  public final class FillEventHistory implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.os.Bundle getClientState();
+    method public java.util.List<android.service.autofill.FillEventHistory.Event> getEvents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.FillEventHistory> CREATOR;
+  }
+
+  public static final class FillEventHistory.Event {
+    method public java.lang.String getDatasetId();
+    method public int getType();
+    field public static final int TYPE_AUTHENTICATION_SELECTED = 2; // 0x2
+    field public static final int TYPE_DATASET_AUTHENTICATION_SELECTED = 1; // 0x1
+    field public static final int TYPE_DATASET_SELECTED = 0; // 0x0
+    field public static final int TYPE_SAVE_SHOWN = 3; // 0x3
+  }
+
   public final class FillRequest implements android.os.Parcelable {
     method public int describeContents();
     method public android.os.Bundle getClientState();
@@ -37270,6 +37268,7 @@
     method public android.service.autofill.FillResponse.Builder setAuthentication(android.view.autofill.AutofillId[], android.content.IntentSender, android.widget.RemoteViews);
     method public android.service.autofill.FillResponse.Builder setClientState(android.os.Bundle);
     method public deprecated android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
+    method public android.service.autofill.FillResponse.Builder setIgnoredIds(android.view.autofill.AutofillId...);
     method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo);
   }
 
@@ -37282,6 +37281,7 @@
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.service.autofill.SaveInfo> CREATOR;
+    field public static final int FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE = 1; // 0x1
     field public static final int SAVE_DATA_TYPE_ADDRESS = 2; // 0x2
     field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 4; // 0x4
     field public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 16; // 0x10
@@ -37294,9 +37294,9 @@
     ctor public SaveInfo.Builder(int, android.view.autofill.AutofillId[]);
     method public android.service.autofill.SaveInfo build();
     method public android.service.autofill.SaveInfo.Builder setDescription(java.lang.CharSequence);
+    method public android.service.autofill.SaveInfo.Builder setFlags(int);
     method public android.service.autofill.SaveInfo.Builder setNegativeAction(java.lang.CharSequence, android.content.IntentSender);
     method public android.service.autofill.SaveInfo.Builder setOptionalIds(android.view.autofill.AutofillId[]);
-    method public android.service.autofill.SaveInfo.Builder setSaveOnAllViewsInvisible(boolean);
   }
 
   public final class SaveRequest implements android.os.Parcelable {
@@ -46315,7 +46315,9 @@
     field public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 1; // 0x1
     field public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0; // 0x0
     field public static final int IMPORTANT_FOR_AUTOFILL_NO = 2; // 0x2
+    field public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 8; // 0x8
     field public static final int IMPORTANT_FOR_AUTOFILL_YES = 1; // 0x1
+    field public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 4; // 0x4
     field public static final int INVISIBLE = 4; // 0x4
     field public static final int KEEP_SCREEN_ON = 67108864; // 0x4000000
     field public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
diff --git a/api/test-removed.txt b/api/test-removed.txt
index 0f5b81a..b6c2a98 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -63,6 +63,12 @@
     field public static final int REQUESTED_PERMISSION_REQUIRED = 1; // 0x1
   }
 
+  public final class SharedLibraryInfo implements android.os.Parcelable {
+    method public boolean isBuiltin();
+    method public boolean isDynamic();
+    method public boolean isStatic();
+  }
+
 }
 
 package android.database {
@@ -126,6 +132,16 @@
 
 }
 
+package android.location {
+
+  public class Location implements android.os.Parcelable {
+    method public deprecated void removeBearingAccuracy();
+    method public deprecated void removeSpeedAccuracy();
+    method public deprecated void removeVerticalAccuracy();
+  }
+
+}
+
 package android.media {
 
   public final class AudioFormat implements android.os.Parcelable {
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 02d1884..63e8cc6 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -1211,9 +1211,6 @@
      * methods that take an options Bundle.
      */
     public Bundle toBundle() {
-        if (mAnimationType == ANIM_DEFAULT) {
-            return null;
-        }
         Bundle b = new Bundle();
         if (mPackageName != null) {
             b.putString(KEY_PACKAGE_NAME, mPackageName);
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index e07b7e4..2ce02df 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -79,6 +79,8 @@
 import android.os.storage.VolumeInfo;
 import android.provider.Settings;
 import android.util.ArrayMap;
+import android.util.IconDrawableFactory;
+import android.util.LauncherIcons;
 import android.util.Log;
 import android.view.Display;
 
@@ -1245,16 +1247,9 @@
         if (!isManagedProfile(user.getIdentifier())) {
             return icon;
         }
-        Drawable badgeShadow = getDrawable("system",
-                com.android.internal.R.drawable.ic_corp_icon_badge_shadow, null);
-        Drawable badgeColor = getDrawable("system",
-                com.android.internal.R.drawable.ic_corp_icon_badge_color, null);
-        badgeColor.setTint(getUserBadgeColor(user));
-        Drawable badgeForeground = getDrawable("system",
-                com.android.internal.R.drawable.ic_corp_icon_badge_case, null);
-
-        Drawable badge = new LayerDrawable(
-                new Drawable[] {badgeShadow, badgeColor, badgeForeground });
+        Drawable badge = new LauncherIcons(mContext).getBadgeDrawable(
+                com.android.internal.R.drawable.ic_corp_icon_badge_case,
+                getUserBadgeColor(user));
         return getBadgedDrawable(icon, badge, null, true);
     }
 
@@ -1268,14 +1263,6 @@
         return getBadgedDrawable(drawable, badgeDrawable, badgeLocation, true);
     }
 
-    // Should have enough colors to cope with UserManagerService.getMaxManagedProfiles()
-    @VisibleForTesting
-    public static final int[] CORP_BADGE_COLORS = new int[] {
-        com.android.internal.R.color.profile_badge_1,
-        com.android.internal.R.color.profile_badge_2,
-        com.android.internal.R.color.profile_badge_3
-    };
-
     @VisibleForTesting
     public static final int[] CORP_BADGE_LABEL_RES_ID = new int[] {
         com.android.internal.R.string.managed_profile_label_badge,
@@ -1284,12 +1271,7 @@
     };
 
     private int getUserBadgeColor(UserHandle user) {
-        int badge = getUserManager().getManagedProfileBadge(user.getIdentifier());
-        if (badge < 0) {
-            badge = 0;
-        }
-        int resourceId = CORP_BADGE_COLORS[badge % CORP_BADGE_COLORS.length];
-        return Resources.getSystem().getColor(resourceId, null);
+        return IconDrawableFactory.getUserBadgeColor(getUserManager(), user.getIdentifier());
     }
 
     @Override
@@ -2648,4 +2630,13 @@
             throw e.rethrowAsRuntimeException();
         }
     }
+
+    @Override
+    public String getInstantAppAndroidId(String packageName, UserHandle user) {
+        try {
+            return mPM.getInstantAppAndroidId(packageName, user.getIdentifier());
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
 }
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index c7bcc54..c5b93cd 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -509,6 +509,10 @@
     // True if mHidden has been changed and the animation should be scheduled.
     boolean mHiddenChanged;
 
+    // The cached value from onGetLayoutInflater(Bundle) that will be returned from
+    // getLayoutInflater()
+    LayoutInflater mLayoutInflater;
+
     /**
      * State information that has been retrieved from a fragment instance
      * through {@link FragmentManager#saveFragmentInstanceState(Fragment)
@@ -1389,6 +1393,38 @@
     }
 
     /**
+     * Returns the cached LayoutInflater used to inflate Views of this Fragment. If
+     * {@link #onGetLayoutInflater(Bundle)} has not been called {@link #onGetLayoutInflater(Bundle)}
+     * will be called with a {@code null} argument and that value will be cached.
+     * <p>
+     * The cached LayoutInflater will be replaced immediately prior to
+     * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)} and cleared immediately after
+     * {@link #onDetach()}.
+     *
+     * @return The LayoutInflater used to inflate Views of this Fragment.
+     */
+    public final LayoutInflater getLayoutInflater() {
+        if (mLayoutInflater == null) {
+            return performGetLayoutInflater(null);
+        }
+        return mLayoutInflater;
+    }
+
+    /**
+     * Calls {@link #onGetLayoutInflater(Bundle)} and caches the result for use by
+     * {@link #getLayoutInflater()}.
+     *
+     * @param savedInstanceState If the fragment is being re-created from
+     * a previous saved state, this is the state.
+     * @return The LayoutInflater used to inflate Views of this Fragment.
+     */
+    LayoutInflater performGetLayoutInflater(Bundle savedInstanceState) {
+        LayoutInflater layoutInflater = onGetLayoutInflater(savedInstanceState);
+        mLayoutInflater = layoutInflater;
+        return mLayoutInflater;
+    }
+
+    /**
      * @deprecated Use {@link #onInflate(Context, AttributeSet, Bundle)} instead.
      */
     @Deprecated
@@ -2835,6 +2871,7 @@
     void performDetach() {
         mCalled = false;
         onDetach();
+        mLayoutInflater = null;
         if (!mCalled) {
             throw new SuperNotCalledException("Fragment " + this
                     + " did not call through to super.onDetach()");
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 91578a2..c1161a2 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -1259,7 +1259,7 @@
                                 }
                             }
                             f.mContainer = container;
-                            f.mView = f.performCreateView(f.onGetLayoutInflater(
+                            f.mView = f.performCreateView(f.performGetLayoutInflater(
                                     f.mSavedFragmentState), container, f.mSavedFragmentState);
                             if (f.mView != null) {
                                 f.mView.setSaveFromParentEnabled(false);
@@ -1431,7 +1431,7 @@
 
     void ensureInflatedFragmentView(Fragment f) {
         if (f.mFromLayout && !f.mPerformedCreateView) {
-            f.mView = f.performCreateView(f.onGetLayoutInflater(
+            f.mView = f.performCreateView(f.performGetLayoutInflater(
                     f.mSavedFragmentState), null, f.mSavedFragmentState);
             if (f.mView != null) {
                 f.mView.setSaveFromParentEnabled(false);
@@ -1462,18 +1462,22 @@
                     if (fragment.isHideReplaced()) {
                         fragment.setHideReplaced(false);
                     } else {
+                        final ViewGroup container = fragment.mContainer;
+                        final View animatingView = fragment.mView;
+                        container.startViewTransition(animatingView);
                         // Delay the actual hide operation until the animation finishes, otherwise
                         // the fragment will just immediately disappear
                         anim.addListener(new AnimatorListenerAdapter() {
                             @Override
                             public void onAnimationEnd(Animator animation) {
+                                container.endViewTransition(animatingView);
                                 animation.removeListener(this);
-                                if (fragment.mView != null) {
-                                    fragment.mView.setVisibility(View.GONE);
-                                }
+                                animatingView.setVisibility(View.GONE);
                             }
                         });
                     }
+                } else {
+                    fragment.mView.setVisibility(View.VISIBLE);
                 }
                 setHWLayerAnimListenerIfAlpha(fragment.mView, anim);
                 anim.start();
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 4205db0..bbcf7ba 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -1598,7 +1598,7 @@
                 mConnection.onServiceDisconnected(name);
             }
             if (dead) {
-                mConnection.onBindingDead(name);
+                mConnection.onBindingDied(name);
             }
             // If there is a new service, it is now connected.
             if (service != null) {
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index cab2114..602cccb 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -3251,7 +3251,6 @@
          * However, for {@link MediaStyle} and {@link DecoratedMediaCustomViewStyle} notifications
          * that have a media session attached there is no such requirement.
          *
-         * @see Builder#setOngoing(boolean)
          * @see Builder#setColor(int)
          * @see MediaStyle#setMediaSession(MediaSession.Token)
          */
@@ -3742,6 +3741,11 @@
             return mActionBarColor;
         }
 
+        private int getActionBarColorDeEmphasized() {
+            int backgroundColor = getBackgroundColor();
+            return NotificationColorUtil.getShiftedColor(backgroundColor, 12);
+        }
+
         private void setTextViewColorSecondary(RemoteViews contentView, int id) {
             ensureColors();
             contentView.setTextColor(id, mSecondaryTextColor);
@@ -4316,8 +4320,13 @@
             // TODO: handle emphasized mode / actions right
             if (emphazisedMode) {
                 // change the background bgColor
-                int bgColor = mContext.getColor(oddAction ? R.color.notification_action_list
-                        : R.color.notification_action_list_dark);
+                int bgColor;
+                if (isColorized()) {
+                    bgColor = oddAction ? getActionBarColor() : getActionBarColorDeEmphasized();
+                } else {
+                    bgColor = mContext.getColor(oddAction ? R.color.notification_action_list
+                            : R.color.notification_action_list_dark);
+                }
                 button.setDrawableParameters(R.id.button_holder, true, -1, bgColor,
                         PorterDuff.Mode.SRC_ATOP, -1);
                 CharSequence title = action.title;
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index 6ba52b7..c1ff580 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -276,8 +276,6 @@
 
     /**
      * Gets a list of all the appWidgetIds that are bound to the current host
-     *
-     * @hide
      */
     public int[] getAppWidgetIds() {
         try {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 0adab1a..46a7042 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -57,6 +57,7 @@
 import android.os.StatFs;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.os.storage.StorageManager;
 import android.provider.MediaStore;
 import android.util.AttributeSet;
 import android.view.Display;
@@ -1146,16 +1147,26 @@
 
     /**
      * Returns the absolute path to the application specific cache directory on
-     * the filesystem. These files will be ones that get deleted first when the
-     * device runs low on storage. There is no guarantee when these files will
-     * be deleted.
+     * the filesystem.
      * <p>
-     * <strong>Note: you should not <em>rely</em> on the system deleting these
-     * files for you; you should always have a reasonable maximum, such as 1 MB,
-     * for the amount of space you consume with cache files, and prune those
-     * files when exceeding that space.</strong> If your app requires a larger
-     * cache (larger than 1 MB), you should use {@link #getExternalCacheDir()}
-     * instead.
+     * The system will automatically delete files in this directory as disk
+     * space is needed elsewhere on the device. The system will always delete
+     * older files first, as reported by {@link File#lastModified()}. If
+     * desired, you can exert more control over how files are deleted using
+     * {@link StorageManager#setCacheBehaviorGroup(File, boolean)} and
+     * {@link StorageManager#setCacheBehaviorTombstone(File, boolean)}.
+     * <p>
+     * Apps are strongly encouraged to keep their usage of cache space below the
+     * quota returned by
+     * {@link StorageManager#getCacheQuotaBytes(java.util.UUID)}. If your app
+     * goes above this quota, your cached files will be some of the first to be
+     * deleted when additional disk space is needed. Conversely, if your app
+     * stays under this quota, your cached files will be some of the last to be
+     * deleted when additional disk space is needed.
+     * <p>
+     * Note that your cache quota will change over time depending on how
+     * frequently the user interacts with your app, and depending on how much
+     * system-wide disk space is used.
      * <p>
      * The returned path may change over time if the calling app is moved to an
      * adopted storage device, so only relative paths should be persisted.
@@ -1173,9 +1184,11 @@
 
     /**
      * Returns the absolute path to the application specific cache directory on
-     * the filesystem designed for storing cached code. The system will delete
-     * any files stored in this location both when your specific application is
-     * upgraded, and when the entire platform is upgraded.
+     * the filesystem designed for storing cached code.
+     * <p>
+     * The system will delete any files stored in this location both when your
+     * specific application is upgraded, and when the entire platform is
+     * upgraded.
      * <p>
      * This location is optimal for storing compiled or optimized code generated
      * by your application at runtime.
@@ -3722,6 +3735,7 @@
     public static final String PRINT_SERVICE = "print";
 
     /**
+     * Use with {@link #getSystemService} to retrieve a
      * {@link android.companion.CompanionDeviceManager} for managing companion devices
      *
      * @see #getSystemService
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 5ca4fa3..3e3f1ee 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1517,7 +1517,7 @@
      * Output: If {@link #EXTRA_RETURN_RESULT}, returns whether the install
      * succeeded.
      * <p>
-     * <strong>Note:</strong>If your app is targeting API level higher than 22 you
+     * <strong>Note:</strong>If your app is targeting API level higher than 25 you
      * need to hold {@link android.Manifest.permission#REQUEST_INSTALL_PACKAGES}
      * in order to launch the application installer.
      * </p>
@@ -1656,6 +1656,8 @@
     /**
      * Used as an int extra field with {@link #ACTION_INSTALL_PACKAGE} and
      * {@link #ACTION_VIEW} to indicate the uid of the package that initiated the install
+     * Currently only a system app that hosts the provider authority "downloads" or holds the
+     * permission {@link android.Manifest.permission.MANAGE_DOCUMENTS} can use this.
      * @hide
      */
     @SystemApi
@@ -2072,13 +2074,13 @@
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_PACKAGE_INSTALL = "android.intent.action.PACKAGE_INSTALL";
     /**
-     * Broadcast Action: An application package has been installed or updated on the
+     * Broadcast Action: A new application package has been installed on the
      * device. The data contains the name of the package.  Note that the
      * newly installed package does <em>not</em> receive this broadcast.
      * <p>May include the following extras:
      * <ul>
-     * <li> {@link #EXTRA_UID} containing the integer uid assigned to this package.
-     * <li> {@link #EXTRA_REPLACING} is set to {@code true} if this is following
+     * <li> {@link #EXTRA_UID} containing the integer uid assigned to the new package.
+     * <li> {@link #EXTRA_REPLACING} is set to true if this is following
      * an {@link #ACTION_PACKAGE_REMOVED} broadcast for the same package.
      * </ul>
      *
@@ -2088,22 +2090,6 @@
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_PACKAGE_ADDED = "android.intent.action.PACKAGE_ADDED";
     /**
-     * Broadcast Action: A new application package has been installed on the
-     * device. The data contains the name of the package.  Note that the
-     * newly installed package does <em>not</em> receive this broadcast.
-     * <p class="note">Unlike {@link #ACTION_PACKAGE_ADDED}, this broadcast is delivered
-     * to manifest receivers as well as those registered at runtime.
-     * <p>May include the following extras:
-     * <ul>
-     * <li> {@link #EXTRA_UID} containing the integer uid assigned to the new package.
-     * </ul>
-     *
-     * <p class="note">This is a protected intent that can only be sent
-     * by the system.
-     */
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_PACKAGE_FIRST_ADDED = "android.intent.action.PACKAGE_FIRST_ADDED";
-    /**
      * Broadcast Action: A new version of an application package has been
      * installed, replacing an existing version that was previously installed.
      * The data contains the name of the package.
@@ -8616,6 +8602,32 @@
      *         a single statement.
      * @see #setFlags(int)
      * @see #removeFlags(int)
+     *
+     * @see #FLAG_GRANT_READ_URI_PERMISSION
+     * @see #FLAG_GRANT_WRITE_URI_PERMISSION
+     * @see #FLAG_GRANT_PERSISTABLE_URI_PERMISSION
+     * @see #FLAG_GRANT_PREFIX_URI_PERMISSION
+     * @see #FLAG_DEBUG_LOG_RESOLUTION
+     * @see #FLAG_FROM_BACKGROUND
+     * @see #FLAG_ACTIVITY_BROUGHT_TO_FRONT
+     * @see #FLAG_ACTIVITY_CLEAR_TASK
+     * @see #FLAG_ACTIVITY_CLEAR_TOP
+     * @see #FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
+     * @see #FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
+     * @see #FLAG_ACTIVITY_FORWARD_RESULT
+     * @see #FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
+     * @see #FLAG_ACTIVITY_MULTIPLE_TASK
+     * @see #FLAG_ACTIVITY_NEW_DOCUMENT
+     * @see #FLAG_ACTIVITY_NEW_TASK
+     * @see #FLAG_ACTIVITY_NO_ANIMATION
+     * @see #FLAG_ACTIVITY_NO_HISTORY
+     * @see #FLAG_ACTIVITY_NO_USER_ACTION
+     * @see #FLAG_ACTIVITY_PREVIOUS_IS_TOP
+     * @see #FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
+     * @see #FLAG_ACTIVITY_REORDER_TO_FRONT
+     * @see #FLAG_ACTIVITY_SINGLE_TOP
+     * @see #FLAG_ACTIVITY_TASK_ON_HOME
+     * @see #FLAG_RECEIVER_REGISTERED_ONLY
      */
     public Intent addFlags(int flags) {
         mFlags |= flags;
@@ -8628,6 +8640,32 @@
      * @param flags The flags to remove.
      * @see #setFlags(int)
      * @see #addFlags(int)
+     *
+     * @see #FLAG_GRANT_READ_URI_PERMISSION
+     * @see #FLAG_GRANT_WRITE_URI_PERMISSION
+     * @see #FLAG_GRANT_PERSISTABLE_URI_PERMISSION
+     * @see #FLAG_GRANT_PREFIX_URI_PERMISSION
+     * @see #FLAG_DEBUG_LOG_RESOLUTION
+     * @see #FLAG_FROM_BACKGROUND
+     * @see #FLAG_ACTIVITY_BROUGHT_TO_FRONT
+     * @see #FLAG_ACTIVITY_CLEAR_TASK
+     * @see #FLAG_ACTIVITY_CLEAR_TOP
+     * @see #FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
+     * @see #FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
+     * @see #FLAG_ACTIVITY_FORWARD_RESULT
+     * @see #FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
+     * @see #FLAG_ACTIVITY_MULTIPLE_TASK
+     * @see #FLAG_ACTIVITY_NEW_DOCUMENT
+     * @see #FLAG_ACTIVITY_NEW_TASK
+     * @see #FLAG_ACTIVITY_NO_ANIMATION
+     * @see #FLAG_ACTIVITY_NO_HISTORY
+     * @see #FLAG_ACTIVITY_NO_USER_ACTION
+     * @see #FLAG_ACTIVITY_PREVIOUS_IS_TOP
+     * @see #FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
+     * @see #FLAG_ACTIVITY_REORDER_TO_FRONT
+     * @see #FLAG_ACTIVITY_SINGLE_TOP
+     * @see #FLAG_ACTIVITY_TASK_ON_HOME
+     * @see #FLAG_RECEIVER_REGISTERED_ONLY
      */
     public void removeFlags(int flags) {
         mFlags &= ~flags;
diff --git a/core/java/android/content/ServiceConnection.java b/core/java/android/content/ServiceConnection.java
index 8e428f9..6ff4900 100644
--- a/core/java/android/content/ServiceConnection.java
+++ b/core/java/android/content/ServiceConnection.java
@@ -61,6 +61,6 @@
      * @param name The concrete component name of the service whose
      * connection is dead.
      */
-    default void onBindingDead(ComponentName name) {
+    default void onBindingDied(ComponentName name) {
     }
 }
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 8b2809a..b0f8aa7 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -1203,7 +1203,12 @@
         dest.writeInt(requiresSmallestWidthDp);
         dest.writeInt(compatibleWidthLimitDp);
         dest.writeInt(largestWidthLimitDp);
-        dest.writeUuid(storageUuid);
+        if (storageUuid != null) {
+            dest.writeInt(1);
+            dest.writeUuid(storageUuid);
+        } else {
+            dest.writeInt(0);
+        }
         dest.writeString(scanSourceDir);
         dest.writeString(scanPublicSourceDir);
         dest.writeString(sourceDir);
@@ -1265,8 +1270,10 @@
         requiresSmallestWidthDp = source.readInt();
         compatibleWidthLimitDp = source.readInt();
         largestWidthLimitDp = source.readInt();
-        storageUuid = source.readUuid();
-        volumeUuid = StorageManager.convert(storageUuid);
+        if (source.readInt() != 0) {
+            storageUuid = source.readUuid();
+            volumeUuid = StorageManager.convert(storageUuid);
+        }
         scanSourceDir = source.readString();
         scanPublicSourceDir = source.readString();
         sourceDir = source.readString();
diff --git a/core/java/android/content/pm/ChangedPackages.java b/core/java/android/content/pm/ChangedPackages.java
index 94b8a5d..78c057d 100644
--- a/core/java/android/content/pm/ChangedPackages.java
+++ b/core/java/android/content/pm/ChangedPackages.java
@@ -17,6 +17,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.TestApi;
 import android.content.Intent;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -26,6 +27,7 @@
 /**
  * Packages that have been changed since the last time they
  * were requested.
+ * @see PackageManager#getChangedPackages(int)
  */
 public final class ChangedPackages implements Parcelable {
     /** The last known sequence number for these changes */
@@ -33,6 +35,7 @@
     /** The names of the packages that have changed */
     private final List<String> mPackageNames;
 
+    @TestApi
     public ChangedPackages(int sequenceNumber, @NonNull List<String> packageNames) {
         this.mSequenceNumber = sequenceNumber;
         this.mPackageNames = packageNames;
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index bbc942a..bc7a612 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -634,4 +634,6 @@
     ComponentName getInstantAppResolverSettingsComponent();
 
     ComponentName getInstantAppInstallerComponent();
+
+    String getInstantAppAndroidId(String packageName, int userId);
 }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 09906be..7cc2334 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -54,6 +54,7 @@
 import android.os.UserManager;
 import android.os.storage.StorageManager;
 import android.os.storage.VolumeInfo;
+import android.provider.Settings;
 import android.util.AndroidException;
 import android.util.Log;
 
@@ -3983,6 +3984,8 @@
      * <p>If no packages have been changed, returns <code>null</code>.
      * <p>The sequence number starts at <code>0</code> and is
      * reset every boot.
+     * @param sequenceNumber The first sequence number for which to retrieve package changes.
+     * @see Settings.Global#BOOT_COUNT
      */
     public abstract @Nullable ChangedPackages getChangedPackages(
             @IntRange(from=0) int sequenceNumber);
@@ -5937,8 +5940,20 @@
      * <p>
      * This hint can only be set by the app which installed this package, as
      * determined by {@link #getInstallerPackageName(String)}.
+     *
+     * @param packageName the package to change the category hint for.
+     * @param categoryHint the category hint to set; one of
+     *            {@link ApplicationInfo#CATEGORY_AUDIO},
+     *            {@link ApplicationInfo#CATEGORY_GAME},
+     *            {@link ApplicationInfo#CATEGORY_IMAGE},
+     *            {@link ApplicationInfo#CATEGORY_MAPS},
+     *            {@link ApplicationInfo#CATEGORY_NEWS},
+     *            {@link ApplicationInfo#CATEGORY_PRODUCTIVITY},
+     *            {@link ApplicationInfo#CATEGORY_SOCIAL},
+     *            {@link ApplicationInfo#CATEGORY_UNDEFINED}, or
+     *            {@link ApplicationInfo#CATEGORY_VIDEO}.
      */
-    public abstract void setApplicationCategoryHint(String packageName,
+    public abstract void setApplicationCategoryHint(@NonNull String packageName,
             @ApplicationInfo.Category int categoryHint);
 
     /** {@hide} */
@@ -6256,18 +6271,18 @@
 
     /**
      * Checks whether the calling package is allowed to request package installs through package
-     * installer. Apps are encouraged to call this api before launching the package installer via
+     * installer. Apps are encouraged to call this API before launching the package installer via
      * intent {@link android.content.Intent#ACTION_INSTALL_PACKAGE}. Starting from Android O, the
      * user can explicitly choose what external sources they trust to install apps on the device.
-     * If this api returns false, the install request will be blocked by the package installer and
+     * If this API returns false, the install request will be blocked by the package installer and
      * a dialog will be shown to the user with an option to launch settings to change their
      * preference. An application must target Android O or higher and declare permission
-     * {@link android.Manifest.permission#REQUEST_INSTALL_PACKAGES} in order to use this api.
+     * {@link android.Manifest.permission#REQUEST_INSTALL_PACKAGES} in order to use this API.
      *
      * @return true if the calling package is trusted by the user to request install packages on
      * the device, false otherwise.
-     * @see {@link android.content.Intent#ACTION_INSTALL_PACKAGE}
-     * @see {@link android.provider.Settings#ACTION_MANAGE_UNKNOWN_APP_SOURCES}
+     * @see android.content.Intent#ACTION_INSTALL_PACKAGE
+     * @see android.provider.Settings#ACTION_MANAGE_UNKNOWN_APP_SOURCES
      */
     public abstract boolean canRequestPackageInstalls();
 
@@ -6290,4 +6305,12 @@
      */
     @SystemApi
     public abstract ComponentName getInstantAppInstallerComponent();
+
+    /**
+     * Return the Android Id for a given Instant App.
+     *
+     * @see {@link android.provider.Settings.Secure#ANDROID_ID}
+     * @hide
+     */
+    public abstract String getInstantAppAndroidId(String packageName, @NonNull UserHandle user);
 }
diff --git a/core/java/android/content/pm/SharedLibraryInfo.java b/core/java/android/content/pm/SharedLibraryInfo.java
index d79deb2..0ad4874 100644
--- a/core/java/android/content/pm/SharedLibraryInfo.java
+++ b/core/java/android/content/pm/SharedLibraryInfo.java
@@ -16,11 +16,14 @@
 
 package android.content.pm;
 
+import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Collections;
 import java.util.List;
 
@@ -31,28 +34,37 @@
  * static - updatable non backwards-compatible emulating static linking.
  */
 public final class SharedLibraryInfo implements Parcelable {
+
+    /** @hide */
+    @IntDef(
+        flag = true,
+        value = {
+                TYPE_BUILTIN,
+                TYPE_DYNAMIC,
+                TYPE_STATIC,
+        })
+    @Retention(RetentionPolicy.SOURCE)
+    @interface Type{}
+
     /**
      * Shared library type: this library is a part of the OS
      * and cannot be updated or uninstalled.
-     * @hide
      */
-    public static final int TYPE_BUILTIN = 0x1<<0;
+    public static final int TYPE_BUILTIN = 0;
 
     /**
      * Shared library type: this library is backwards-compatible, can
      * be updated, and updates can be uninstalled. Clients link against
      * the latest version of the library.
-     * @hide
      */
-    public static final int TYPE_DYNAMIC = 0x1<<1;
+    public static final int TYPE_DYNAMIC = 1;
 
     /**
      * Shared library type: this library is <strong>not</strong> backwards
      * -compatible, can be updated and updates can be uninstalled. Clients
      * link against a specific version of the library.
-     * @hide
      */
-    public static final int TYPE_STATIC = 0x1<<2;
+    public static final int TYPE_STATIC = 2;
 
     /**
      * Constant for referring to an undefined version.
@@ -60,8 +72,10 @@
     public static final int VERSION_UNDEFINED = -1;
 
     private final String mName;
+
+    // TODO: Make long when we change the paltform to use longs
     private final int mVersion;
-    private final int mType;
+    private final @Type int mType;
     private final VersionedPackage mDeclaringPackage;
     private final List<VersionedPackage> mDependentPackages;
 
@@ -90,13 +104,18 @@
                 parcel.readParcelable(null), parcel.readArrayList(null));
     }
 
-    /** @hide */
-    public int getType() {
+    /**
+     * Gets the type of this library.
+     *
+     * @return The library type.
+     */
+    public @Type int getType() {
         return mType;
     }
 
     /**
-     * Gets the library name.
+     * Gets the library name an app defines in its manifest
+     * to depend on the library.
      *
      * @return The name.
      */
@@ -105,40 +124,36 @@
     }
 
     /**
-     * Gets the version of the library. For {@link #isStatic()}  static} libraries
-     * this is the declared version and for {@link #isDynamic()} dynamic} and
-     * {@link #isBuiltin()} builtin} it is {@link #VERSION_UNDEFINED} as these
+     * Gets the version of the library. For {@link #TYPE_STATIC static} libraries
+     * this is the declared version and for {@link #TYPE_DYNAMIC dynamic} and
+     * {@link #TYPE_BUILTIN builtin} it is {@link #VERSION_UNDEFINED} as these
      * are not versioned.
      *
      * @return The version.
      */
-    public @IntRange(from = -1) int getVersion() {
+    public @IntRange(from = -1) long getVersion() {
         return mVersion;
     }
 
     /**
-     * @return whether this library is builtin which means that it
-     * is a part of the OS and cannot be updated or uninstalled.
+     * @hide
+     * @removed
      */
     public boolean isBuiltin() {
         return mType == TYPE_BUILTIN;
     }
 
     /**
-     * @return whether this library is dynamic which means that it
-     * is backwards-compatible, can be updated, and updates can be
-     * uninstalled. Clients link against the latest version of the
-     * library.
+     * @hide
+     * @removed
      */
     public boolean isDynamic() {
         return mType == TYPE_DYNAMIC;
     }
 
     /**
-     * @return whether this library is dynamic which means that it
-     * is <strong>not</strong> backwards-compatible, can be updated
-     * and updates can be uninstalled. Clients link against a specific
-     * version of the library.
+     * @hide
+     * @removed
      */
     public boolean isStatic() {
         return mType == TYPE_STATIC;
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index f48afb5..88bb1a4 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -56,12 +56,13 @@
         // Reset the assets, which may have changed due to configuration changes
         // or further resource loading.
         attrs.mAssets = res.getAssets();
+        attrs.mMetrics = res.getDisplayMetrics();
         attrs.resize(len);
         return attrs;
     }
 
     private final Resources mResources;
-    private final DisplayMetrics mMetrics;
+    private DisplayMetrics mMetrics;
     private AssetManager mAssets;
 
     private boolean mRecycled;
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index a895f82..f02e484 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -664,7 +664,7 @@
      * @see #TYPE_LOW_LATENCY_OFFBODY_DETECT
      */
     public static final String STRING_TYPE_LOW_LATENCY_OFFBODY_DETECT =
-            "android.sensor.low_latency_offbody";
+            "android.sensor.low_latency_offbody_detect";
 
     /**
      * A constant describing an uncalibrated accelerometer sensor.
diff --git a/core/java/android/metrics/LogMaker.java b/core/java/android/metrics/LogMaker.java
index a76a8a0..3c6baa7 100644
--- a/core/java/android/metrics/LogMaker.java
+++ b/core/java/android/metrics/LogMaker.java
@@ -54,7 +54,11 @@
 
     /* Deserialize from the eventlog */
     public LogMaker(Object[] items) {
-      deserialize(items);
+        if (items != null) {
+            deserialize(items);
+        } else {
+            setCategory(MetricsEvent.VIEW_UNKNOWN);
+        }
     }
 
     /** @param category to replace the existing setting. */
@@ -373,13 +377,13 @@
      */
     public void deserialize(Object[] items) {
         int i = 0;
-        while (i < items.length) {
+        while (items != null && i < items.length) {
             Object key = items[i++];
             Object value = i < items.length ? items[i++] : null;
             if (key instanceof Integer) {
                 entries.put((Integer) key, value);
             } else {
-                Log.i(TAG, "Invalid key " + key.toString());
+                Log.i(TAG, "Invalid key " + (key == null ? "null" : key.toString()));
             }
         }
     }
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index f8702e2..375b7ee 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -245,6 +245,7 @@
      *
      * @param socket a stream socket
      * @param transform an {@link IpSecTransform}, which must be an active Transport Mode transform.
+     * @hide
      */
     public void applyTransportModeTransform(Socket socket, IpSecTransform transform)
             throws IOException {
@@ -262,6 +263,7 @@
      *
      * @param socket a datagram socket
      * @param transform an {@link IpSecTransform}, which must be an active Transport Mode transform.
+     * @hide
      */
     public void applyTransportModeTransform(DatagramSocket socket, IpSecTransform transform)
             throws IOException {
@@ -284,7 +286,7 @@
      * address associated with that transform will throw an IOException. In addition, if the
      * IpSecTransform is later deactivated, the socket will throw an IOException on any calls to
      * send() or receive() until the transform is removed from the socket by calling {@link
-     * #removeTransportModeTransform(Socket, IpSecTransform)};
+     * #removeTransportModeTransform(FileDescriptor, IpSecTransform)};
      *
      * @param socket a socket file descriptor
      * @param transform an {@link IpSecTransform}, which must be an active Transport Mode transform.
@@ -316,8 +318,10 @@
      *
      * @param socket a socket that previously had a transform applied to it.
      * @param transform the IPsec Transform that was previously applied to the given socket
+     * @hide
      */
-    public void removeTransportModeTransform(Socket socket, IpSecTransform transform) {
+    public void removeTransportModeTransform(Socket socket, IpSecTransform transform)
+            throws IOException {
         removeTransportModeTransform(ParcelFileDescriptor.fromSocket(socket), transform);
     }
 
@@ -330,8 +334,10 @@
      *
      * @param socket a socket that previously had a transform applied to it.
      * @param transform the IPsec Transform that was previously applied to the given socket
+     * @hide
      */
-    public void removeTransportModeTransform(DatagramSocket socket, IpSecTransform transform) {
+    public void removeTransportModeTransform(DatagramSocket socket, IpSecTransform transform)
+            throws IOException {
         removeTransportModeTransform(ParcelFileDescriptor.fromDatagramSocket(socket), transform);
     }
 
@@ -345,7 +351,8 @@
      * @param socket a socket file descriptor that previously had a transform applied to it.
      * @param transform the IPsec Transform that was previously applied to the given socket
      */
-    public void removeTransportModeTransform(FileDescriptor socket, IpSecTransform transform) {
+    public void removeTransportModeTransform(FileDescriptor socket, IpSecTransform transform)
+            throws IOException {
         removeTransportModeTransform(new ParcelFileDescriptor(socket), transform);
     }
 
@@ -419,7 +426,7 @@
          *
          * @param fd a file descriptor previously returned as a UDP Encapsulation socket.
          */
-        public void close() {
+        public void close() throws IOException {
             // TODO: Go close the socket
             mCloseGuard.close();
         }
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index afca0b0..bf7207c 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -19,6 +19,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.BitUtils;
 
 import java.util.Objects;
@@ -230,7 +231,8 @@
      * Capabilities that suggest that a network is restricted.
      * {@see #maybeMarkCapabilitiesRestricted}.
      */
-    private static final long RESTRICTED_CAPABILITIES =
+    @VisibleForTesting
+    /* package */ static final long RESTRICTED_CAPABILITIES =
             (1 << NET_CAPABILITY_CBS) |
             (1 << NET_CAPABILITY_DUN) |
             (1 << NET_CAPABILITY_EIMS) |
@@ -241,6 +243,17 @@
             (1 << NET_CAPABILITY_XCAP);
 
     /**
+     * Capabilities that suggest that a network is unrestricted.
+     * {@see #maybeMarkCapabilitiesRestricted}.
+     */
+    @VisibleForTesting
+    /* package */ static final long UNRESTRICTED_CAPABILITIES =
+            (1 << NET_CAPABILITY_INTERNET) |
+            (1 << NET_CAPABILITY_MMS) |
+            (1 << NET_CAPABILITY_SUPL) |
+            (1 << NET_CAPABILITY_WIFI_P2P);
+
+    /**
      * Adds the given capability to this {@code NetworkCapability} instance.
      * Multiple capabilities may be applied sequentially.  Note that when searching
      * for a network to satisfy a request, all capabilities requested must be satisfied.
@@ -353,12 +366,16 @@
      * @hide
      */
     public void maybeMarkCapabilitiesRestricted() {
-        // If all the capabilities are typically provided by restricted networks, conclude that this
-        // network is restricted.
-        if ((mNetworkCapabilities & ~(DEFAULT_CAPABILITIES | RESTRICTED_CAPABILITIES)) == 0 &&
-                // Must have at least some restricted capabilities, otherwise a request for an
-                // internet-less network will get marked restricted.
-                (mNetworkCapabilities & RESTRICTED_CAPABILITIES) != 0) {
+        // Verify there aren't any unrestricted capabilities.  If there are we say
+        // the whole thing is unrestricted.
+        final boolean hasUnrestrictedCapabilities =
+                ((mNetworkCapabilities & UNRESTRICTED_CAPABILITIES) != 0);
+
+        // Must have at least some restricted capabilities.
+        final boolean hasRestrictedCapabilities =
+                ((mNetworkCapabilities & RESTRICTED_CAPABILITIES) != 0);
+
+        if (hasRestrictedCapabilities && !hasUnrestrictedCapabilities) {
             removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
         }
     }
diff --git a/core/java/android/os/HwParcel.java b/core/java/android/os/HwParcel.java
index 94fd5b0..4ba1144 100644
--- a/core/java/android/os/HwParcel.java
+++ b/core/java/android/os/HwParcel.java
@@ -209,10 +209,11 @@
     public native final IHwBinder readStrongBinder();
 
     // Handle is stored as part of the blob.
-    public native final HwBlob readBuffer();
+    public native final HwBlob readBuffer(long expectedSize);
 
     public native final HwBlob readEmbeddedBuffer(
-            long parentHandle, long offset, boolean nullable);
+            long expectedSize, long parentHandle, long offset,
+            boolean nullable);
 
     public native final void writeBuffer(HwBlob blob);
 
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 5f66abd..447f280 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -16,6 +16,8 @@
 
 package android.os;
 
+import static java.nio.charset.StandardCharsets.UTF_8;
+
 import android.annotation.SystemApi;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -24,9 +26,12 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import libcore.io.Streams;
+
 import java.io.ByteArrayInputStream;
 import java.io.BufferedReader;
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileReader;
 import java.io.FileWriter;
@@ -39,6 +44,7 @@
 import java.security.SignatureException;
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
+import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -46,6 +52,7 @@
 import java.util.Locale;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
+import java.util.zip.ZipInputStream;
 
 import com.android.internal.logging.MetricsLogger;
 
@@ -317,6 +324,70 @@
         } finally {
             raf.close();
         }
+
+        // Additionally verify the package compatibility.
+        if (!readAndVerifyPackageCompatibilityEntry(packageFile)) {
+            throw new SignatureException("package compatibility verification failed");
+        }
+    }
+
+    /**
+     * Verifies the compatibility entry from an {@link InputStream}.
+     *
+     * @return the verification result.
+     */
+    private static boolean verifyPackageCompatibility(InputStream inputStream) throws IOException {
+        ArrayList<String> list = new ArrayList<>();
+        ZipInputStream zis = new ZipInputStream(inputStream);
+        ZipEntry entry;
+        while ((entry = zis.getNextEntry()) != null) {
+            long entrySize = entry.getSize();
+            if (entrySize > Integer.MAX_VALUE || entrySize < 0) {
+                throw new IOException(
+                        "invalid entry size (" + entrySize + ") in the compatibility file");
+            }
+            byte[] bytes = new byte[(int) entrySize];
+            Streams.readFully(zis, bytes);
+            list.add(new String(bytes, UTF_8));
+        }
+        if (list.isEmpty()) {
+            throw new IOException("no entries found in the compatibility file");
+        }
+        return (VintfObject.verify(list.toArray(new String[list.size()])) == 0);
+    }
+
+    /**
+     * Reads and verifies the compatibility entry in an OTA zip package. The compatibility entry is
+     * a zip file (inside the OTA package zip).
+     *
+     * @return {@code true} if the entry doesn't exist or verification passes.
+     */
+    private static boolean readAndVerifyPackageCompatibilityEntry(File packageFile)
+            throws IOException {
+        try (ZipFile zip = new ZipFile(packageFile)) {
+            ZipEntry entry = zip.getEntry("compatibility.zip");
+            if (entry == null) {
+                return true;
+            }
+            InputStream inputStream = zip.getInputStream(entry);
+            return verifyPackageCompatibility(inputStream);
+        }
+    }
+
+    /**
+     * Verifies the package compatibility info against the current system.
+     *
+     * @param compatibilityFile the {@link File} that contains the package compatibility info.
+     * @throws IOException if there were any errors reading the compatibility file.
+     * @return the compatibility verification result.
+     *
+     * {@hide}
+     */
+    @SystemApi
+    public static boolean verifyPackageCompatibility(File compatibilityFile) throws IOException {
+        try (InputStream inputStream = new FileInputStream(compatibilityFile)) {
+            return verifyPackageCompatibility(inputStream);
+        }
     }
 
     /**
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 3942531..1c15004 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -1518,7 +1518,8 @@
      * last to be deleted when additional disk space is needed.
      * <p>
      * This quota will change over time depending on how frequently the user
-     * interacts with your app, and depending on how much disk space is used.
+     * interacts with your app, and depending on how much system-wide disk space
+     * is used.
      * <p class="note">
      * Note: if your app uses the {@code android:sharedUserId} manifest feature,
      * then cached data for all packages in your shared UID is tracked together
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index c6ea958..22de27f 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5082,6 +5082,10 @@
          * (available on certain devices running Android 4.2 or higher), each user appears as a
          * completely separate device, so the {@code ANDROID_ID} value is unique to each
          * user.</p>
+         *
+         * <p class="note"><strong>Note:</strong> If the caller is an Instant App the id is scoped
+         * to the Instant App, it is generated when the Instant App is first installed and reset if
+         * the user clears the Instant App.
          */
         public static final String ANDROID_ID = "android_id";
 
@@ -7077,6 +7081,7 @@
             CLONE_TO_MANAGED_PROFILE.add(ACCESSIBILITY_ENABLED);
             CLONE_TO_MANAGED_PROFILE.add(ALLOW_MOCK_LOCATION);
             CLONE_TO_MANAGED_PROFILE.add(ALLOWED_GEOLOCATION_ORIGINS);
+            CLONE_TO_MANAGED_PROFILE.add(AUTOFILL_SERVICE);
             CLONE_TO_MANAGED_PROFILE.add(DEFAULT_INPUT_METHOD);
             CLONE_TO_MANAGED_PROFILE.add(ENABLED_ACCESSIBILITY_SERVICES);
             CLONE_TO_MANAGED_PROFILE.add(ENABLED_INPUT_METHODS);
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
index 5e49b8f..813c54f 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -247,7 +247,7 @@
      * @param callback object used to notify the result of the request.
      */
     public void onSaveRequest(@NonNull SaveRequest request, @NonNull SaveCallback callback) {
-        List<FillContext> contexts = request.getFillContexts();
+        final List<FillContext> contexts = request.getFillContexts();
         onSaveRequest(contexts.get(contexts.size() - 1).getStructure(),
                 request.getClientState(), callback);
     }
@@ -285,4 +285,22 @@
         // TODO(b/33197203): Remove when GCore has migrated off this API
         getSystemService(AutofillManager.class).disableOwnedAutofillServices();
     }
+
+    /**
+     * Returns the {@link FillEventHistory.Event events} since the last {@link FillResponse} was
+     * returned.
+     *
+     * <p>The history is not persisted over reboots.
+     *
+     * @return The history or {@code null} if there are not events.
+     */
+    @Nullable public final FillEventHistory getFillEventHistory() {
+        AutofillManager afm = getSystemService(AutofillManager.class);
+
+        if (afm == null) {
+            return null;
+        } else {
+            return afm.getFillEventHistory();
+        }
+    }
 }
diff --git a/core/java/android/service/autofill/Dataset.java b/core/java/android/service/autofill/Dataset.java
index e77bd0d..e04fae7 100644
--- a/core/java/android/service/autofill/Dataset.java
+++ b/core/java/android/service/autofill/Dataset.java
@@ -24,6 +24,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillManager;
 import android.view.autofill.AutofillValue;
 import android.widget.RemoteViews;
 import com.android.internal.util.Preconditions;
@@ -50,6 +51,7 @@
     private final ArrayList<RemoteViews> mFieldPresentations;
     private final RemoteViews mPresentation;
     private final IntentSender mAuthentication;
+    @Nullable String mId;
 
     private Dataset(Builder builder) {
         mFieldIds = builder.mFieldIds;
@@ -57,6 +59,7 @@
         mFieldPresentations = builder.mFieldPresentations;
         mPresentation = builder.mPresentation;
         mAuthentication = builder.mAuthentication;
+        mId = builder.mId;
     }
 
     /** @hide */
@@ -89,7 +92,7 @@
     public String toString() {
         if (!DEBUG) return super.toString();
 
-        return new StringBuilder("Dataset [")
+        return new StringBuilder("Dataset " + mId + " [")
                 .append("fieldIds=").append(mFieldIds)
                 .append(", fieldValues=").append(mFieldValues)
                 .append(", fieldPresentations=")
@@ -100,6 +103,17 @@
     }
 
     /**
+     * Gets the id of this dataset.
+     *
+     * @return The id of this dataset or {@code null} if not set
+     *
+     * @hide
+     */
+    public String getId() {
+        return mId;
+    }
+
+    /**
      * A builder for {@link Dataset} objects. You must to provide at least
      * one value for a field or set an authentication intent.
      */
@@ -110,6 +124,7 @@
         private RemoteViews mPresentation;
         private IntentSender mAuthentication;
         private boolean mDestroyed;
+        @Nullable private String mId;
 
         /**
          * Creates a new builder.
@@ -173,6 +188,25 @@
         }
 
         /**
+         * Sets the id for the dataset.
+         *
+         * <p>The id of the last selected dataset can be read from
+         * {@link AutofillService#getFillEventHistory()}. If the id is not set it will not be clear
+         * if a dataset was selected as {@link AutofillService#getFillEventHistory()} uses
+         * {@code null} to indicate that no dataset was selected.
+         *
+         * @param id id for this dataset or {@code null} to unset.
+
+         * @return This builder.
+         */
+        public @NonNull Builder setId(@Nullable String id) {
+            throwIfDestroyed();
+
+            mId = id;
+            return this;
+        }
+
+        /**
          * Sets the value of a field.
          *
          * @param id id returned by {@link
@@ -269,6 +303,7 @@
         parcel.writeTypedArrayList(mFieldValues, flags);
         parcel.writeParcelableList(mFieldPresentations, flags);
         parcel.writeParcelable(mAuthentication, flags);
+        parcel.writeString(mId);
     }
 
     public static final Creator<Dataset> CREATOR = new Creator<Dataset>() {
@@ -295,6 +330,7 @@
                 builder.setValueAndPresentation(id, value, fieldPresentation);
             }
             builder.setAuthentication(parcel.readParcelable(null));
+            builder.setId(parcel.readString());
             return builder.build();
         }
 
diff --git a/core/java/android/service/autofill/FillCallback.java b/core/java/android/service/autofill/FillCallback.java
index a009be8..7774bdd 100644
--- a/core/java/android/service/autofill/FillCallback.java
+++ b/core/java/android/service/autofill/FillCallback.java
@@ -18,7 +18,6 @@
 
 import android.annotation.Nullable;
 import android.app.Activity;
-import android.os.Bundle;
 import android.os.RemoteException;
 
 /**
@@ -38,8 +37,8 @@
 
     /**
      * Notifies the Android System that an
-     * {@link AutofillService#onFillRequest(android.app.assist.AssistStructure, Bundle,
-     * int, android.os.CancellationSignal, FillCallback)} was successfully fulfilled by the service.
+     * {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal,
+     * FillCallback)} was successfully fulfilled by the service.
      *
      * @param response autofill information for that activity, or {@code null} when the activity
      * cannot be autofilled (for example, if it only contains read-only fields). See
@@ -57,9 +56,8 @@
 
     /**
      * Notifies the Android System that an
-     * {@link AutofillService#onFillRequest(android.app.assist.AssistStructure,
-     * Bundle, int, android.os.CancellationSignal, FillCallback)}
-     * could not be fulfilled by the service.
+     * {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal,
+     * FillCallback)} could not be fulfilled by the service.
      *
      * @param message error message to be displayed to the user.
      */
diff --git a/core/java/android/service/autofill/FillEventHistory.aidl b/core/java/android/service/autofill/FillEventHistory.aidl
new file mode 100644
index 0000000..3c48524
--- /dev/null
+++ b/core/java/android/service/autofill/FillEventHistory.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2017, 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.service.autofill;
+
+parcelable FillEventHistory;
diff --git a/core/java/android/service/autofill/FillEventHistory.java b/core/java/android/service/autofill/FillEventHistory.java
new file mode 100644
index 0000000..3d72fcc
--- /dev/null
+++ b/core/java/android/service/autofill/FillEventHistory.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2017 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.service.autofill;
+
+import android.annotation.IntDef;
+import android.annotation.Nullable;
+import android.content.IntentSender;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.view.autofill.AutofillId;
+import android.widget.RemoteViews;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Describes what happened after the latest call to {@link FillCallback#onSuccess(FillResponse)}.
+ */
+public final class FillEventHistory implements Parcelable {
+    /**
+     * Not in parcel. The UID of the {@link AutofillService} that created the {@link FillResponse}.
+     */
+    private final int mServiceUid;
+
+    @Nullable private final Bundle mClientState;
+    @Nullable List<Event> mEvents;
+
+    /**
+     * Gets the UID of the {@link AutofillService} that created the {@link FillResponse}.
+     *
+     * @return The UID of the {@link AutofillService}
+     *
+     * @hide
+     */
+    public int getServiceUid() {
+        return mServiceUid;
+    }
+
+    /**
+     * Returns the client state of the {@link FillResponse}.
+     *
+     * @return The client state set by the last {@link FillResponse}
+     */
+    @Nullable public Bundle getClientState() {
+        return mClientState;
+    }
+
+    /**
+     * Returns the events occurred after the latest call to
+     * {@link FillCallback#onSuccess(FillResponse)}.
+     *
+     * @return The list of events or {@code null} if non occurred.
+     */
+    @Nullable public List<Event> getEvents() {
+        return mEvents;
+    }
+
+    /**
+     * @hide
+     */
+    public void addEvent(Event event) {
+        if (mEvents == null) {
+            mEvents = new ArrayList<>(1);
+        }
+        mEvents.add(event);
+    }
+
+    /**
+     * @hide
+     */
+    public FillEventHistory(int serviceUid, @Nullable Bundle clientState) {
+        mClientState = clientState;
+        mServiceUid = serviceUid;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeBundle(mClientState);
+
+        if (mEvents == null) {
+            dest.writeInt(0);
+        } else {
+            dest.writeInt(mEvents.size());
+
+            int numEvents = mEvents.size();
+            for (int i = 0; i < numEvents; i++) {
+                Event event = mEvents.get(i);
+                dest.writeInt(event.getType());
+                dest.writeString(event.getDatasetId());
+            }
+        }
+    }
+
+    /**
+     * Description of an event that occured after the latest call to
+     * {@link FillCallback#onSuccess(FillResponse)}.
+     */
+    public static final class Event {
+        /**
+         * A dataset was selected. The dataset selected can be read from {@link #getDatasetId()}.
+         */
+        public static final int TYPE_DATASET_SELECTED = 0;
+
+        /**
+         * A {@link Dataset.Builder#setAuthentication(IntentSender) dataset authentication} was
+         * selected. The dataset authenticated can be read from {@link #getDatasetId()}.
+         */
+        public static final int TYPE_DATASET_AUTHENTICATION_SELECTED = 1;
+
+        /**
+         * A {@link FillResponse.Builder#setAuthentication(AutofillId[], IntentSender, RemoteViews)
+         * fill response authentication} was selected.
+         */
+        public static final int TYPE_AUTHENTICATION_SELECTED = 2;
+
+        /** A save UI was shown. */
+        public static final int TYPE_SAVE_SHOWN = 3;
+
+        /** @hide */
+        @IntDef(
+                value = {TYPE_DATASET_SELECTED,
+                        TYPE_DATASET_AUTHENTICATION_SELECTED,
+                        TYPE_AUTHENTICATION_SELECTED,
+                        TYPE_SAVE_SHOWN})
+        @Retention(RetentionPolicy.SOURCE)
+        @interface EventIds{}
+
+        @EventIds private final int mEventType;
+        @Nullable private final String mDatasetId;
+
+        /**
+         * Returns the type of the event.
+         *
+         * @return The type of the event
+         */
+        public int getType() {
+            return mEventType;
+        }
+
+        /**
+         * Returns the id of dataset the id was on.
+         *
+         * @return The id of dataset, or {@code null} the event is not associated with a dataset.
+         */
+        @Nullable public String getDatasetId() {
+            return mDatasetId;
+        }
+
+        /**
+         * Creates a new event.
+         *
+         * @param eventType The type of the event
+         * @param datasetId The dataset the event was on, or {@code null} if the event was on the
+         *                  whole response.
+         *
+         * @hide
+         */
+        public Event(int eventType, String datasetId) {
+            mEventType = Preconditions.checkArgumentInRange(eventType, 0, TYPE_SAVE_SHOWN,
+                    "eventType");
+            mDatasetId = datasetId;
+        }
+    }
+
+    public static final Parcelable.Creator<FillEventHistory> CREATOR =
+            new Parcelable.Creator<FillEventHistory>() {
+                @Override
+                public FillEventHistory createFromParcel(Parcel parcel) {
+                    FillEventHistory selection = new FillEventHistory(0, parcel.readBundle());
+
+                    int numEvents = parcel.readInt();
+                    for (int i = 0; i < numEvents; i++) {
+                        selection.addEvent(new Event(parcel.readInt(), parcel.readString()));
+                    }
+
+                    return selection;
+                }
+
+                @Override
+                public FillEventHistory[] newArray(int size) {
+                    return new FillEventHistory[size];
+                }
+            };
+}
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index 8c8060a..0025365 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -32,8 +32,7 @@
 
 /**
  * Response for a {@link
- * AutofillService#onFillRequest(android.app.assist.AssistStructure,
- * Bundle, int, android.os.CancellationSignal, FillCallback)}.
+ * AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)}.
  *
  * <p>The response typically contains one or more {@link Dataset}s, each representing a set of
  * fields that can be autofilled together, and the Android system displays a dataset picker UI
@@ -258,6 +257,19 @@
         }
 
         /**
+         * Specifies views that should not trigger new
+         * {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal,
+         * FillCallback)} requests.
+         *
+         * <p>This is typically used when the service cannot autofill the view; for example, an
+         * {@code EditText} representing a captcha.
+         */
+        public Builder setIgnoredIds(AutofillId...ids) {
+            // TODO: implement
+            return this;
+        }
+
+        /**
          * Adds a new {@link Dataset} to this response.
          *
          * @return This builder.
@@ -289,6 +301,9 @@
             return this;
         }
 
+        /**
+         * @deprecated Use {@link #setClientState(Bundle)} instead.
+         */
         @Deprecated
         public Builder setExtras(@Nullable Bundle extras) {
             throwIfDestroyed();
@@ -299,11 +314,9 @@
         /**
          * Sets a {@link Bundle state} that will be passed to subsequent APIs that
          * manipulate this response. For example, they are passed to subsequent
-         * calls to {@link AutofillService#onFillRequest(
-         * android.app.assist.AssistStructure, Bundle, int,
-         * android.os.CancellationSignal, FillCallback)} and {@link AutofillService#onSaveRequest(
-         * android.app.assist.AssistStructure, Bundle, SaveCallback)}. You can use
-         * this to store intermediate state that is persistent across multiple
+         * calls to {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal,
+         * FillCallback)} and {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)}.
+         * You can use this to store intermediate state that is persistent across multiple
          * fill requests and the subsequent save request.
          *
          * <p>If this method is called on multiple {@link FillResponse} objects for the same
diff --git a/core/java/android/service/autofill/SaveCallback.java b/core/java/android/service/autofill/SaveCallback.java
index 2c4ba6c..3a70138 100644
--- a/core/java/android/service/autofill/SaveCallback.java
+++ b/core/java/android/service/autofill/SaveCallback.java
@@ -17,7 +17,6 @@
 package android.service.autofill;
 
 import android.app.Activity;
-import android.os.Bundle;
 import android.os.RemoteException;
 
 /**
@@ -35,8 +34,8 @@
 
     /**
      * Notifies the Android System that an
-     * {@link AutofillService#onSaveRequest (android.app.assist.AssistStructure, Bundle,
-     * SaveCallback)} was successfully fulfilled by the service.
+     * {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)} was successfully fulfilled
+     * by the service.
      *
      * @throws RuntimeException if an error occurred while calling the Android System.
      */
@@ -52,8 +51,8 @@
 
     /**
      * Notifies the Android System that an
-     * {@link AutofillService#onSaveRequest(android.app.assist.AssistStructure, Bundle,
-     * SaveCallback)} could not be fulfilled by the service.
+     * {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)} could not be fulfilled
+     * by the service.
      *
      * @param message error message to be displayed to the user.
      *
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
index 7f960df..f796444 100644
--- a/core/java/android/service/autofill/SaveInfo.java
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -40,7 +40,7 @@
 /**
  * Information used to indicate that an {@link AutofillService} is interested on saving the
  * user-inputed data for future use, through a
- * {@link AutofillService#onSaveRequest(android.app.assist.AssistStructure, Bundle, SaveCallback)}
+ * {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)}
  * call.
  *
  * <p>A {@link SaveInfo} is always associated with a {@link FillResponse}, and it contains at least
@@ -94,7 +94,7 @@
  * </pre>
  *
  * The
- * {@link AutofillService#onSaveRequest(android.app.assist.AssistStructure, Bundle, SaveCallback)}
+ * {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)}
  * is triggered after a call to {@link AutofillManager#commit()}, but only when all conditions
  * below are met:
  *
@@ -153,13 +153,27 @@
     @Retention(RetentionPolicy.SOURCE)
     @interface SaveDataType{}
 
+    /**
+     * Usually {@link AutofillService#onSaveRequest(AssistStructure, Bundle, SaveCallback)}
+     * is called once the activity finishes. If this flag is set it is called once all saved views
+     * become invisible.
+     */
+    public static final int FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE = 0x1;
+
+    /** @hide */
+    @IntDef(
+            flag = true,
+            value = {FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE})
+    @Retention(RetentionPolicy.SOURCE)
+    @interface SaveInfoFlags{}
+
     private final @SaveDataType int mType;
     private final CharSequence mNegativeActionTitle;
     private final IntentSender mNegativeActionListener;
     private final AutofillId[] mRequiredIds;
     private final AutofillId[] mOptionalIds;
     private final CharSequence mDescription;
-    private final boolean mSaveOnAllViewsInvisible;
+    private final int mFlags;
 
     private SaveInfo(Builder builder) {
         mType = builder.mType;
@@ -168,7 +182,7 @@
         mRequiredIds = builder.mRequiredIds;
         mOptionalIds = builder.mOptionalIds;
         mDescription = builder.mDescription;
-        mSaveOnAllViewsInvisible = builder.mSaveOnAllViewsInvisible;
+        mFlags = builder.mFlags;
     }
 
     /** @hide */
@@ -197,8 +211,8 @@
     }
 
     /** @hide */
-    public boolean saveOnAllViewsInvisible() {
-        return mSaveOnAllViewsInvisible;
+    public @SaveInfoFlags int getFlags() {
+        return mFlags;
     }
 
     /** @hide */
@@ -219,7 +233,7 @@
         private AutofillId[] mOptionalIds;
         private CharSequence mDescription;
         private boolean mDestroyed;
-        private boolean mSaveOnAllViewsInvisible;
+        private int mFlags;
 
         /**
          * Creates a new builder.
@@ -268,17 +282,15 @@
         }
 
         /**
-         * Usually {@link AutofillService#onSaveRequest(AssistStructure, Bundle, SaveCallback)}
-         * is called once the activity finishes. If this property is set it is called once all
-         * autofillable or saved views become invisible.
+         * Set flags changing the save behavior.
          *
-         * @param saveOnAllViewsInvisible Set to {@code true} if the data should be saved once
-         *                                all the views become invisible.
+         * @param flags {@link #FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE} or 0.
          * @return This builder.
          */
-        public @NonNull Builder setSaveOnAllViewsInvisible(boolean saveOnAllViewsInvisible) {
+        public @NonNull Builder setFlags(@SaveInfoFlags int flags) {
             throwIfDestroyed();
-            mSaveOnAllViewsInvisible = saveOnAllViewsInvisible;
+
+            mFlags = Preconditions.checkFlagsArgument(flags, FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE);
             return this;
         }
 
@@ -378,7 +390,7 @@
                 .append(", requiredIds=").append(Arrays.toString(mRequiredIds))
                 .append(", optionalIds=").append(Arrays.toString(mOptionalIds))
                 .append(", description=").append(mDescription)
-                .append(", saveOnNoVisibleTrackedViews=").append(mSaveOnAllViewsInvisible)
+                .append(", mFlags=").append(mFlags)
                 .append("]").toString();
     }
 
@@ -399,7 +411,7 @@
         parcel.writeParcelable(mNegativeActionListener, flags);
         parcel.writeParcelableArray(mOptionalIds, flags);
         parcel.writeCharSequence(mDescription);
-        parcel.writeBoolean(mSaveOnAllViewsInvisible);
+        parcel.writeInt(mFlags);
     }
 
     public static final Parcelable.Creator<SaveInfo> CREATOR = new Parcelable.Creator<SaveInfo>() {
@@ -413,7 +425,7 @@
             builder.setNegativeAction(parcel.readCharSequence(), parcel.readParcelable(null));
             builder.setOptionalIds(parcel.readParcelableArray(null, AutofillId.class));
             builder.setDescription(parcel.readCharSequence());
-            builder.setSaveOnAllViewsInvisible(parcel.readBoolean());
+            builder.setFlags(parcel.readInt());
             return builder.build();
         }
 
diff --git a/core/java/android/util/IconDrawableFactory.java b/core/java/android/util/IconDrawableFactory.java
new file mode 100644
index 0000000..b07942f
--- /dev/null
+++ b/core/java/android/util/IconDrawableFactory.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2017 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.util;
+
+import android.annotation.UserIdInt;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageItemInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.os.UserHandle;
+import android.os.UserManager;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Utility class to load app drawables with appropriate badging.
+ *
+ * @hide
+ */
+public class IconDrawableFactory {
+
+    protected final Context mContext;
+    protected final PackageManager mPm;
+    protected final UserManager mUm;
+    protected final LauncherIcons mLauncherIcons;
+    protected final boolean mEmbedShadow;
+
+    private IconDrawableFactory(Context context, boolean embedShadow) {
+        mContext = context;
+        mPm = context.getPackageManager();
+        mUm = context.getSystemService(UserManager.class);
+        mLauncherIcons = new LauncherIcons(context);
+        mEmbedShadow = embedShadow;
+    }
+
+    protected boolean needsBadging(ApplicationInfo appInfo, @UserIdInt int userId) {
+        return appInfo.isInstantApp() || mUm.isManagedProfile(userId);
+    }
+
+    public Drawable getBadgedIcon(ApplicationInfo appInfo) {
+        return getBadgedIcon(appInfo, UserHandle.getUserId(appInfo.uid));
+    }
+
+    public Drawable getBadgedIcon(ApplicationInfo appInfo, @UserIdInt int userId) {
+        return getBadgedIcon(appInfo, appInfo, userId);
+    }
+
+    public Drawable getBadgedIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo,
+            @UserIdInt int userId) {
+        Drawable icon = mPm.loadUnbadgedItemIcon(itemInfo, appInfo);
+        if (!mEmbedShadow && !needsBadging(appInfo, userId)) {
+            return icon;
+        }
+
+        // Before badging, add shadow to adaptive icon if needed.
+        icon = mLauncherIcons.wrapIconDrawableWithShadow(icon);
+        if (appInfo.isInstantApp()) {
+            int badgeColor = Resources.getSystem().getColor(
+                    com.android.internal.R.color.instant_app_badge, null);
+            icon = mLauncherIcons.getBadgedDrawable(icon,
+                    com.android.internal.R.drawable.ic_instant_icon_badge_bolt,
+                    badgeColor);
+        }
+        if (mUm.isManagedProfile(userId)) {
+            icon = mLauncherIcons.getBadgedDrawable(icon,
+                    com.android.internal.R.drawable.ic_corp_icon_badge_case,
+                    getUserBadgeColor(mUm, userId));
+        }
+        return icon;
+    }
+
+    // Should have enough colors to cope with UserManagerService.getMaxManagedProfiles()
+    @VisibleForTesting
+    public static final int[] CORP_BADGE_COLORS = new int[] {
+            com.android.internal.R.color.profile_badge_1,
+            com.android.internal.R.color.profile_badge_2,
+            com.android.internal.R.color.profile_badge_3
+    };
+
+    public static int getUserBadgeColor(UserManager um, @UserIdInt int userId) {
+        int badge = um.getManagedProfileBadge(userId);
+        if (badge < 0) {
+            badge = 0;
+        }
+        int resourceId = CORP_BADGE_COLORS[badge % CORP_BADGE_COLORS.length];
+        return Resources.getSystem().getColor(resourceId, null);
+    }
+
+    public static IconDrawableFactory newInstance(Context context) {
+        return new IconDrawableFactory(context, true);
+    }
+
+    public static IconDrawableFactory newInstance(Context context, boolean embedShadow) {
+        return new IconDrawableFactory(context, embedShadow);
+    }
+}
diff --git a/core/java/android/util/LauncherIcons.java b/core/java/android/util/LauncherIcons.java
index 89b9646..402bef9 100644
--- a/core/java/android/util/LauncherIcons.java
+++ b/core/java/android/util/LauncherIcons.java
@@ -21,10 +21,11 @@
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
-import android.graphics.PaintFlagsDrawFilter;
+import android.graphics.Rect;
 import android.graphics.drawable.AdaptiveIconDrawable;
-import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.DrawableWrapper;
+import android.graphics.drawable.LayerDrawable;
 
 /**
  * Utility class to handle icon treatments (e.g., shadow generation) for the Launcher icons.
@@ -32,78 +33,152 @@
  */
 public final class LauncherIcons {
 
-    private final Paint mPaint = new Paint();
-    private final Canvas mCanvas = new Canvas();
+    // Percent of actual icon size
+    private static final float ICON_SIZE_BLUR_FACTOR = 0.5f/48;
+    // Percent of actual icon size
+    private static final float ICON_SIZE_KEY_SHADOW_DELTA_FACTOR = 1f/48;
 
     private static final int KEY_SHADOW_ALPHA = 61;
     private static final int AMBIENT_SHADOW_ALPHA = 30;
-    private static final float BLUR_FACTOR = 0.5f / 48;
-    private int mShadowInset;
-    private Bitmap mShadowBitmap;
-    private int mIconSize;
-    private Resources mRes;
+
+    private final SparseArray<Bitmap> mShadowCache = new SparseArray<>();
+    private final int mIconSize;
+    private final Resources mRes;
 
     public LauncherIcons(Context context) {
         mRes = context.getResources();
-        DisplayMetrics metrics = mRes.getDisplayMetrics();
-        mShadowInset = (int)(2 * metrics.density);
-        mCanvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG,
-            Paint.FILTER_BITMAP_FLAG));
-        mIconSize = (int) mRes.getDimensionPixelSize(android.R.dimen.app_icon_size);
-    }
-
-    /**
-     * Draw the drawable into a bitmap.
-     */
-    public Bitmap createIconBitmap(Drawable icon) {
-        final Bitmap bitmap = Bitmap.createBitmap(mIconSize, mIconSize, Bitmap.Config.ARGB_8888);
-        mPaint.setAlpha(255);
-        mCanvas.setBitmap(bitmap);
-        int iconInset = 0;
-        if (mShadowBitmap != null) {
-            mCanvas.drawBitmap(mShadowBitmap, 0, 0, mPaint);
-            iconInset = mShadowInset;
-        }
-
-        icon.setBounds(iconInset, iconInset, mIconSize - iconInset,
-            mIconSize - iconInset);
-        icon.draw(mCanvas);
-        mCanvas.setBitmap(null);
-        return bitmap;
+        mIconSize = mRes.getDimensionPixelSize(android.R.dimen.app_icon_size);
     }
 
     public Drawable wrapIconDrawableWithShadow(Drawable drawable) {
         if (!(drawable instanceof AdaptiveIconDrawable)) {
             return drawable;
         }
-        AdaptiveIconDrawable d =
-            (AdaptiveIconDrawable) drawable.getConstantState().newDrawable().mutate();
-        getShadowBitmap(d);
-        Bitmap iconbitmap = createIconBitmap(d);
-        return new BitmapDrawable(mRes, iconbitmap);
+        Bitmap shadow = getShadowBitmap((AdaptiveIconDrawable) drawable);
+        return new ShadowDrawable(shadow, drawable);
     }
 
     private Bitmap getShadowBitmap(AdaptiveIconDrawable d) {
-        if (mShadowBitmap != null) {
-            return mShadowBitmap;
+        int shadowSize = Math.max(mIconSize, d.getIntrinsicHeight());
+        synchronized (mShadowCache) {
+            Bitmap shadow = mShadowCache.get(shadowSize);
+            if (shadow != null) {
+                return shadow;
+            }
         }
 
-        mShadowBitmap = Bitmap.createBitmap(mIconSize, mIconSize, Bitmap.Config.ALPHA_8);
-        mCanvas.setBitmap(mShadowBitmap);
+        d.setBounds(0, 0, shadowSize, shadowSize);
 
-        // Draw key shadow
-        mPaint.setColor(Color.TRANSPARENT);
-        float blur = BLUR_FACTOR * mIconSize;
-        mPaint.setShadowLayer(blur, 0, mShadowInset, KEY_SHADOW_ALPHA << 24);
-        d.setBounds(mShadowInset, mShadowInset, mIconSize - mShadowInset, mIconSize - mShadowInset);
-        mCanvas.drawPath(d.getIconMask(), mPaint);
+        float blur = ICON_SIZE_BLUR_FACTOR * shadowSize;
+        float keyShadowDistance = ICON_SIZE_KEY_SHADOW_DELTA_FACTOR * shadowSize;
+
+        int bitmapSize = (int) (shadowSize + 2 * blur + keyShadowDistance);
+        Bitmap shadow = Bitmap.createBitmap(bitmapSize, bitmapSize, Bitmap.Config.ARGB_8888);
+
+        Canvas canvas = new Canvas(shadow);
+        canvas.translate(blur + keyShadowDistance / 2, blur);
+
+        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        paint.setColor(Color.TRANSPARENT);
 
         // Draw ambient shadow
-        mPaint.setShadowLayer(blur, 0, 0, AMBIENT_SHADOW_ALPHA << 24);
-        d.setBounds(mShadowInset, 2 * mShadowInset, mIconSize - mShadowInset, mIconSize);
-        mCanvas.drawPath(d.getIconMask(), mPaint);
-        mPaint.clearShadowLayer();
+        paint.setShadowLayer(blur, 0, 0, AMBIENT_SHADOW_ALPHA << 24);
+        canvas.drawPath(d.getIconMask(), paint);
 
-        return mShadowBitmap;
+        // Draw key shadow
+        canvas.translate(0, keyShadowDistance);
+        paint.setShadowLayer(blur, 0, 0, KEY_SHADOW_ALPHA << 24);
+        canvas.drawPath(d.getIconMask(), paint);
+
+        canvas.setBitmap(null);
+        synchronized (mShadowCache) {
+            mShadowCache.put(shadowSize, shadow);
+        }
+        return shadow;
+    }
+
+    public Drawable getBadgeDrawable(int foregroundRes, int backgroundColor) {
+        return getBadgedDrawable(null, foregroundRes, backgroundColor);
+    }
+
+    public Drawable getBadgedDrawable(Drawable base, int foregroundRes, int backgroundColor) {
+        Resources sysRes = Resources.getSystem();
+
+        Drawable badgeShadow = sysRes.getDrawable(
+                com.android.internal.R.drawable.ic_corp_icon_badge_shadow);
+
+        Drawable badgeColor = sysRes.getDrawable(
+                com.android.internal.R.drawable.ic_corp_icon_badge_color)
+                .getConstantState().newDrawable().mutate();
+        badgeColor.setTint(backgroundColor);
+
+        Drawable badgeForeground = sysRes.getDrawable(foregroundRes);
+
+        Drawable[] drawables = base == null
+                ? new Drawable[] {badgeShadow, badgeColor, badgeForeground }
+                : new Drawable[] {base, badgeShadow, badgeColor, badgeForeground };
+        return new LayerDrawable(drawables);
+    }
+
+    /**
+     * A drawable which draws a shadow bitmap behind a drawable
+     */
+    private static class ShadowDrawable extends DrawableWrapper {
+
+        final MyConstantState mState;
+
+        public ShadowDrawable(Bitmap shadow, Drawable dr) {
+            super(dr);
+            mState = new MyConstantState(shadow, dr.getConstantState());
+        }
+
+        ShadowDrawable(MyConstantState state) {
+            super(state.mChildState.newDrawable());
+            mState = state;
+        }
+
+        @Override
+        public ConstantState getConstantState() {
+            return mState;
+        }
+
+        @Override
+        public void draw(Canvas canvas) {
+            Rect bounds = getBounds();
+            canvas.drawBitmap(mState.mShadow, null, bounds, mState.mPaint);
+            canvas.save();
+            // Ratio of child drawable size to shadow bitmap size
+            float factor = 1 / (1 + 2 * ICON_SIZE_BLUR_FACTOR + ICON_SIZE_KEY_SHADOW_DELTA_FACTOR);
+
+            canvas.translate(
+                    bounds.width() * factor *
+                            (ICON_SIZE_BLUR_FACTOR + ICON_SIZE_KEY_SHADOW_DELTA_FACTOR / 2),
+                    bounds.height() * factor * ICON_SIZE_BLUR_FACTOR);
+            canvas.scale(factor, factor);
+            super.draw(canvas);
+            canvas.restore();
+        }
+
+        private static class MyConstantState extends ConstantState {
+
+            final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
+            final Bitmap mShadow;
+            final ConstantState mChildState;
+
+            MyConstantState(Bitmap shadow, ConstantState childState) {
+                mShadow = shadow;
+                mChildState = childState;
+            }
+
+            @Override
+            public Drawable newDrawable() {
+                return new ShadowDrawable(this);
+            }
+
+            @Override
+            public int getChangingConfigurations() {
+                return mChildState.getChangingConfigurations();
+            }
+        }
     }
 }
diff --git a/core/java/android/view/FocusFinder.java b/core/java/android/view/FocusFinder.java
index f47c355..1ccf16a 100644
--- a/core/java/android/view/FocusFinder.java
+++ b/core/java/android/view/FocusFinder.java
@@ -127,20 +127,23 @@
         if (focused == null || focused == root) {
             return root;
         }
-        ViewParent effective = focused.getParent();
+        ViewGroup effective = null;
+        ViewParent nextParent = focused.getParent();
         do {
-            if (effective == root) {
-                return root;
+            if (nextParent == root) {
+                return effective != null ? effective : root;
             }
-            ViewGroup vg = (ViewGroup) effective;
+            ViewGroup vg = (ViewGroup) nextParent;
             if (vg.getTouchscreenBlocksFocus()
                     && focused.getContext().getPackageManager().hasSystemFeature(
                             PackageManager.FEATURE_TOUCHSCREEN)
                     && vg.isKeyboardNavigationCluster()) {
-                return vg;
+                // Don't stop and return here because the cluster could be nested and we only
+                // care about the top-most one.
+                effective = vg;
             }
-            effective = effective.getParent();
-        } while (effective != null);
+            nextParent = nextParent.getParent();
+        } while (nextParent instanceof ViewGroup);
         return root;
     }
 
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 1a71679..9d40895 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -295,7 +295,15 @@
 
     @Override
     protected void onDetachedFromWindow() {
-        getViewRootImpl().removeWindowStoppedCallback(this);
+        ViewRootImpl viewRoot = getViewRootImpl();
+        // It's possible to create a SurfaceView using the default constructor and never
+        // attach it to a view hierarchy, this is a common use case when dealing with
+        // OpenGL. A developer will probably create a new GLSurfaceView, and let it manage
+        // the lifecycle. Instead of attaching it to a view, he/she can just pass
+        // the SurfaceHolder forward, most live wallpapers do it.
+        if (viewRoot != null) {
+            viewRoot.removeWindowStoppedCallback(this);
+        }
 
         mAttachedToWindow = false;
         if (mGlobalListenersAdded) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 7d2d77e..9ab6775 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1135,27 +1135,39 @@
     @IntDef({
             IMPORTANT_FOR_AUTOFILL_AUTO,
             IMPORTANT_FOR_AUTOFILL_YES,
-            IMPORTANT_FOR_AUTOFILL_NO
+            IMPORTANT_FOR_AUTOFILL_NO,
+            IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
+            IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface AutofillImportance {}
 
     /**
-     * Automatically determine whether a view is important for auto-fill.
+     * Automatically determine whether a view is important for autofill.
      */
     public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0x0;
 
     /**
-     * The view is important for important for auto-fill.
+     * The view is important for autofill, and its children (if any) will be traversed.
      */
     public static final int IMPORTANT_FOR_AUTOFILL_YES = 0x1;
 
     /**
-     * The view is not important for auto-fill.
+     * The view is not important for autofill, and its children (if any) will be traversed.
      */
     public static final int IMPORTANT_FOR_AUTOFILL_NO = 0x2;
 
     /**
+     * The view is important for autofill, but its children (if any) will not be traversed.
+     */
+    public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 0x4;
+
+    /**
+     * The view is not important for autofill, and its children (if any) will not be traversed.
+     */
+    public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 0x8;
+
+    /**
      * This view is enabled. Interpretation varies by subclass.
      * Use with ENABLED_MASK when calling setFlags.
      * {@hide}
@@ -3875,6 +3887,10 @@
     private Drawable mDefaultFocusHighlight;
     private Drawable mDefaultFocusHighlightCache;
     private boolean mDefaultFocusHighlightSizeChanged;
+    /**
+     * True if the default focus highlight is needed on the target device.
+     */
+    private static boolean sUseDefaultFocusHighlight;
 
     private String mTransitionName;
 
@@ -4452,6 +4468,9 @@
 
             sAutoFocusableOffUIThreadWontNotifyParents = targetSdkVersion < Build.VERSION_CODES.O;
 
+            sUseDefaultFocusHighlight = context.getResources().getBoolean(
+                    com.android.internal.R.bool.config_useDefaultFocusHighlight);
+
             sCompatibilityDone = true;
         }
     }
@@ -7568,7 +7587,7 @@
      * should use {@link #setImportantForAutofill(int)} instead.
      *
      * <p><strong>Note:</strong> returning {@code false} does not guarantee the view will be
-     * excluded from the structure; for example, if the user explicitly requested auto-fill, the
+     * excluded from the structure; for example, if the user explicitly requested autofill, the
      * View might be always included.
      *
      * <p>This decision applies just for the view, not its children - if the view children are not
@@ -9720,7 +9739,7 @@
             @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"),
             @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"),
             @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
-            })
+            }, category = "focus")
     @Focusable
     public int getFocusable() {
         return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE;
@@ -9734,7 +9753,7 @@
      * @return Whether the view is focusable in touch mode.
      * @attr ref android.R.styleable#View_focusableInTouchMode
      */
-    @ViewDebug.ExportedProperty
+    @ViewDebug.ExportedProperty(category = "focus")
     public final boolean isFocusableInTouchMode() {
         return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
     }
@@ -9762,12 +9781,31 @@
      * @return True if this view is a root of a cluster, or false otherwise.
      * @attr ref android.R.styleable#View_keyboardNavigationCluster
      */
-    @ViewDebug.ExportedProperty(category = "keyboardNavigationCluster")
+    @ViewDebug.ExportedProperty(category = "focus")
     public final boolean isKeyboardNavigationCluster() {
         return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
     }
 
     /**
+     * Searches up the view hierarchy to find the top-most cluster. All deeper/nested clusters
+     * will be ignored.
+     *
+     * @return the keyboard navigation cluster that this view is in (can be this view)
+     *         or {@code null} if not in one
+     */
+    View findKeyboardNavigationCluster() {
+        if (mParent instanceof View) {
+            View cluster = ((View) mParent).findKeyboardNavigationCluster();
+            if (cluster != null) {
+                return cluster;
+            } else if (isKeyboardNavigationCluster()) {
+                return this;
+            }
+        }
+        return null;
+    }
+
+    /**
      * Set whether this view is a root of a keyboard navigation cluster.
      *
      * @param isCluster If true, this view is a root of a cluster.
@@ -9789,9 +9827,20 @@
      *
      * @hide
      */
-    public void setFocusedInCluster() {
-        if (mParent instanceof ViewGroup) {
-            ((ViewGroup) mParent).setFocusInCluster(this);
+    public final void setFocusedInCluster() {
+        View top = findKeyboardNavigationCluster();
+        if (top == this) {
+            return;
+        }
+        ViewParent parent = mParent;
+        View child = this;
+        while (parent instanceof ViewGroup) {
+            ((ViewGroup) parent).setFocusedInCluster(child);
+            if (parent == top) {
+                return;
+            }
+            child = (View) parent;
+            parent = parent.getParent();
         }
     }
 
@@ -9807,7 +9856,7 @@
      * @return {@code true} if this view is the default-focus view, {@code false} otherwise
      * @attr ref android.R.styleable#View_focusedByDefault
      */
-    @ViewDebug.ExportedProperty(category = "focusedByDefault")
+    @ViewDebug.ExportedProperty(category = "focus")
     public final boolean isFocusedByDefault() {
         return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0;
     }
@@ -9920,7 +9969,7 @@
      * @return True if this View should use a default focus highlight.
      * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
      */
-    @ViewDebug.ExportedProperty(category = "defaultFocusHighlightEnabled")
+    @ViewDebug.ExportedProperty(category = "focus")
     public final boolean getDefaultFocusHighlightEnabled() {
         return mDefaultFocusHighlightEnabled;
     }
@@ -19635,7 +19684,7 @@
         final boolean hasFocusStateSpecified = background == null || !background.isStateful()
                 || !background.hasFocusStateSpecified();
         return !isInTouchMode() && getDefaultFocusHighlightEnabled() && hasFocusStateSpecified
-                && isAttachedToWindow();
+                && isAttachedToWindow() && sUseDefaultFocusHighlight;
     }
 
     /**
@@ -25743,6 +25792,7 @@
         // focus
         stream.addProperty("focus:hasFocus", hasFocus());
         stream.addProperty("focus:isFocused", isFocused());
+        stream.addProperty("focus:focusable", getFocusable());
         stream.addProperty("focus:isFocusable", isFocusable());
         stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
 
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index f9eb25d..1977ef5 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -807,33 +807,27 @@
         return mDefaultFocus != null || super.hasDefaultFocus();
     }
 
-    void setFocusInCluster(View child) {
-        // Stop at the root of the cluster
-        if (child.isKeyboardNavigationCluster()) {
-            return;
-        }
-
+    void setFocusedInCluster(View child) {
         mFocusedInCluster = child;
-
-        if (mParent instanceof ViewGroup) {
-            ((ViewGroup) mParent).setFocusInCluster(this);
-        }
     }
 
-    void clearFocusInCluster(View child) {
+    /**
+     * Removes {@code child} (and associated focusedInCluster chain) from the cluster containing
+     * it.
+     * <br>
+     * This is intended to be run on {@code child}'s immediate parent. This is necessary because
+     * the chain is sometimes cleared after {@code child} has been detached.
+     */
+    void clearFocusedInCluster(View child) {
         if (mFocusedInCluster != child) {
             return;
         }
-
-        if (child.isKeyboardNavigationCluster()) {
-            return;
-        }
-
-        mFocusedInCluster = null;
-
-        if (mParent instanceof ViewGroup) {
-            ((ViewGroup) mParent).clearFocusInCluster(this);
-        }
+        View top = findKeyboardNavigationCluster();
+        ViewParent parent = this;
+        do {
+            ((ViewGroup) parent).mFocusedInCluster = null;
+            parent = parent.getParent();
+        } while (parent != top && parent instanceof ViewGroup);
     }
 
     @Override
@@ -1281,7 +1275,7 @@
     public void setTouchscreenBlocksFocus(boolean touchscreenBlocksFocus) {
         if (touchscreenBlocksFocus) {
             mGroupFlags |= FLAG_TOUCHSCREEN_BLOCKS_FOCUS;
-            if (hasFocus()) {
+            if (hasFocus() && !isKeyboardNavigationCluster()) {
                 final View focusedChild = getDeepestFocusedChild();
                 if (!focusedChild.isFocusableInTouchMode()) {
                     final View newFocus = focusSearch(FOCUS_FORWARD);
@@ -1306,6 +1300,7 @@
     /**
      * Check whether this ViewGroup should ignore focus requests for itself and its children.
      */
+    @ViewDebug.ExportedProperty(category = "focus")
     public boolean getTouchscreenBlocksFocus() {
         return (mGroupFlags & FLAG_TOUCHSCREEN_BLOCKS_FOCUS) != 0;
     }
@@ -1316,7 +1311,8 @@
         // cluster, focus is free to move around within it.
         return getTouchscreenBlocksFocus() &&
                 mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)
-                && (!hasFocus() || !isKeyboardNavigationCluster());
+                && !(isKeyboardNavigationCluster()
+                        && (hasFocus() || (findKeyboardNavigationCluster() != this)));
     }
 
     @Override
@@ -3217,8 +3213,7 @@
     }
 
     private boolean restoreFocusInClusterInternal(@FocusRealDirection int direction) {
-        if (mFocusedInCluster != null && !mFocusedInCluster.isKeyboardNavigationCluster()
-                && getDescendantFocusability() != FOCUS_BLOCK_DESCENDANTS
+        if (mFocusedInCluster != null && getDescendantFocusability() != FOCUS_BLOCK_DESCENDANTS
                 && (mFocusedInCluster.mViewFlags & VISIBILITY_MASK) == VISIBLE
                 && mFocusedInCluster.restoreFocusInCluster(direction)) {
             return true;
@@ -5182,7 +5177,7 @@
             clearChildFocus = true;
         }
         if (view == mFocusedInCluster) {
-            clearFocusInCluster(view);
+            clearFocusedInCluster(view);
         }
 
         view.clearAccessibilityFocus();
@@ -5302,7 +5297,7 @@
                 clearDefaultFocus = view;
             }
             if (view == mFocusedInCluster) {
-                clearFocusInCluster(view);
+                clearFocusedInCluster(view);
             }
 
             view.clearAccessibilityFocus();
@@ -5458,7 +5453,7 @@
             clearDefaultFocus(child);
         }
         if (child == mFocusedInCluster) {
-            clearFocusInCluster(child);
+            clearFocusedInCluster(child);
         }
 
         child.clearAccessibilityFocus();
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 080ffeb..9ecced6 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -4675,7 +4675,8 @@
             if (focused == null && mView.restoreDefaultFocus()) {
                 return true;
             }
-            View cluster = focused.keyboardNavigationClusterSearch(null, direction);
+            View cluster = focused == null ? keyboardNavigationClusterSearch(null, direction)
+                    : focused.keyboardNavigationClusterSearch(null, direction);
 
             // Since requestFocus only takes "real" focus directions (and therefore also
             // restoreFocusInCluster), convert forward/backward focus into FOCUS_DOWN.
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index b157709..92b0d98 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -326,8 +326,8 @@
     /**
      * Sets whether the data on this node is sensitive; if it is, then its content (text, autofill
      * value, etc..) is striped before calls to {@link
-     * android.service.autofill.AutofillService#onFillRequest(android.app.assist.AssistStructure,
-     * Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback)}.
+     * android.service.autofill.AutofillService#onFillRequest(android.service.autofill.FillRequest,
+     * android.os.CancellationSignal, android.service.autofill.FillCallback)}.
      *
      * <p>By default, all nodes are assumed to be sensitive, and only nodes that does not have PII
      * (Personally Identifiable Information - sensitive data such as email addresses, credit card
@@ -336,8 +336,8 @@
      *
      * <p>Notice that the content of even sensitive nodes are sent to the service (through the
      * {@link
-     * android.service.autofill.AutofillService#onSaveRequest(android.app.assist.AssistStructure,
-     * Bundle, android.service.autofill.SaveCallback)} call) when the user consented to save
+     * android.service.autofill.AutofillService#onSaveRequest(android.service.autofill.SaveRequest,
+     * android.service.autofill.SaveCallback)} call) when the user consented to save
      * thedata, so it is important to set the content of sensitive nodes as well, but mark them as
      * sensitive.
      *
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index f9f400d..8ed0762 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -31,6 +31,8 @@
 import android.os.IBinder;
 import android.os.Parcelable;
 import android.os.RemoteException;
+import android.service.autofill.AutofillService;
+import android.service.autofill.FillEventHistory;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Log;
@@ -105,6 +107,7 @@
      *
      * @deprecated Use {@link android.service.autofill.FillRequest#FLAG_MANUAL_REQUEST}
      */
+    // TODO(b/33197203): remove
     @Deprecated
     public static final int FLAG_MANUAL_REQUEST = 0x1;
 
@@ -334,6 +337,20 @@
     }
 
     /**
+     * Should always be called from {@link AutofillService#getFillEventHistory()}.
+     *
+     * @hide
+     */
+    @Nullable public FillEventHistory getFillEventHistory() {
+        try {
+            return mService.getFillEventHistory();
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+            return null;
+        }
+    }
+
+    /**
      * Explicitly requests a new autofill context.
      *
      * <p>Normally, the autofill context is automatically started when autofillable views are
diff --git a/core/java/android/view/autofill/IAutoFillManager.aidl b/core/java/android/view/autofill/IAutoFillManager.aidl
index 68b3ccabc..df777c4 100644
--- a/core/java/android/view/autofill/IAutoFillManager.aidl
+++ b/core/java/android/view/autofill/IAutoFillManager.aidl
@@ -19,6 +19,7 @@
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.service.autofill.FillEventHistory;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillValue;
 import android.view.autofill.IAutoFillManagerClient;
@@ -33,6 +34,7 @@
     int startSession(IBinder activityToken, IBinder windowToken, in IBinder appCallback,
             in AutofillId autoFillId, in Rect bounds, in AutofillValue value, int userId,
             boolean hasCallback, int flags, String packageName);
+    FillEventHistory getFillEventHistory();
     boolean restoreSession(int sessionId, in IBinder activityToken, in IBinder appCallback);
     void setWindow(int sessionId, in IBinder windowToken);
     void updateSession(int sessionId, in AutofillId id, in Rect bounds,
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index f634a1b..022c157 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -53,7 +53,6 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.Objects;
-import java.util.StringJoiner;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -89,7 +88,7 @@
     @Override
     public TextSelection suggestSelection(
             @NonNull CharSequence text, int selectionStartIndex, int selectionEndIndex,
-            LocaleList defaultLocales) {
+            @Nullable LocaleList defaultLocales) {
         validateInput(text, selectionStartIndex, selectionEndIndex);
         try {
             if (text.length() > 0) {
@@ -128,7 +127,8 @@
 
     @Override
     public TextClassificationResult getTextClassificationResult(
-            @NonNull CharSequence text, int startIndex, int endIndex, LocaleList defaultLocales) {
+            @NonNull CharSequence text, int startIndex, int endIndex,
+            @Nullable LocaleList defaultLocales) {
         validateInput(text, startIndex, endIndex);
         try {
             if (text.length() > 0) {
@@ -156,7 +156,8 @@
     }
 
     @Override
-    public LinksInfo getLinks(CharSequence text, int linkMask, LocaleList defaultLocales) {
+    public LinksInfo getLinks(
+            @NonNull CharSequence text, int linkMask, @Nullable LocaleList defaultLocales) {
         Preconditions.checkArgument(text != null);
         try {
             return LinksInfoFactory.create(
@@ -199,12 +200,11 @@
     @GuardedBy("mSmartSelectionLock") // Do not call outside this lock.
     @Nullable
     private Locale findBestSupportedLocaleLocked(LocaleList localeList) {
-        final List<Locale.LanguageRange> languageRangeList = Locale.LanguageRange.parse(
-                new StringJoiner(",")
-                        // Specified localeList takes priority over the system default
-                        .add(localeList.toLanguageTags())
-                        .add(LocaleList.getDefault().toLanguageTags())
-                        .toString());
+        // Specified localeList takes priority over the system default, so it is listed first.
+        final String languages = localeList.isEmpty()
+                ? LocaleList.getDefault().toLanguageTags()
+                : localeList.toLanguageTags() + "," + LocaleList.getDefault().toLanguageTags();
+        final List<Locale.LanguageRange> languageRangeList = Locale.LanguageRange.parse(languages);
         return Locale.lookup(languageRangeList, loadModelFilePathsLocked().keySet());
     }
 
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 9245134..036b391 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -252,9 +252,7 @@
                 if (mEnterAnimationId != 0) {
                     opts = ActivityOptions.makeCustomAnimation(context, mEnterAnimationId, 0);
                 } else {
-                    opts = ActivityOptions.makeScaleUpAnimation(view,
-                            0, 0,
-                            view.getMeasuredWidth(), view.getMeasuredHeight());
+                    opts = ActivityOptions.makeBasic();
                 }
 
                 if (launchStackId != StackId.INVALID_STACK_ID) {
diff --git a/core/java/android/widget/TextClock.java b/core/java/android/widget/TextClock.java
index a6a9db4..1279040 100644
--- a/core/java/android/widget/TextClock.java
+++ b/core/java/android/widget/TextClock.java
@@ -133,6 +133,7 @@
     private CharSequence mDescFormat;
 
     private boolean mRegistered;
+    private boolean mShouldRunTicker;
 
     private Calendar mTime;
     private String mTimeZone;
@@ -252,8 +253,7 @@
         }
 
         createTime(mTimeZone);
-        // Wait until registering for events to handle the ticker
-        chooseFormat(false);
+        chooseFormat();
     }
 
     private void createTime(String timeZone) {
@@ -461,16 +461,6 @@
     }
 
     /**
-     * Selects either one of {@link #getFormat12Hour()} or {@link #getFormat24Hour()}
-     * depending on whether the user has selected 24-hour format.
-     *
-     * Calling this method does not schedule or unschedule the time ticker.
-     */
-    private void chooseFormat() {
-        chooseFormat(true);
-    }
-
-    /**
      * Returns the current format string. Always valid after constructor has
      * finished, and will never be {@code null}.
      *
@@ -483,11 +473,8 @@
     /**
      * Selects either one of {@link #getFormat12Hour()} or {@link #getFormat24Hour()}
      * depending on whether the user has selected 24-hour format.
-     *
-     * @param handleTicker true if calling this method should schedule/unschedule the
-     *                     time ticker, false otherwise
      */
-    private void chooseFormat(boolean handleTicker) {
+    private void chooseFormat() {
         final boolean format24Requested = is24HourModeEnabled();
 
         LocaleData ld = LocaleData.get(getContext().getResources().getConfiguration().locale);
@@ -503,7 +490,7 @@
         boolean hadSeconds = mHasSeconds;
         mHasSeconds = DateFormat.hasSeconds(mFormat);
 
-        if (handleTicker && mRegistered && hadSeconds != mHasSeconds) {
+        if (mShouldRunTicker && hadSeconds != mHasSeconds) {
             if (hadSeconds) getHandler().removeCallbacks(mTicker);
             else mTicker.run();
         }
@@ -517,26 +504,44 @@
     }
 
     @Override
-    public void onVisibilityAggregated(boolean isVisible) {
-        if (!mRegistered && isVisible) {
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+
+        if (!mRegistered) {
             mRegistered = true;
 
             registerReceiver();
             registerObserver();
 
             createTime(mTimeZone);
+        }
+    }
 
+    @Override
+    public void onVisibilityAggregated(boolean isVisible) {
+        super.onVisibilityAggregated(isVisible);
+
+        if (!mShouldRunTicker && isVisible) {
+            mShouldRunTicker = true;
             if (mHasSeconds) {
                 mTicker.run();
             } else {
                 onTimeChanged();
             }
-        } else if (mRegistered && !isVisible) {
+        } else if (mShouldRunTicker && !isVisible) {
+            mShouldRunTicker = false;
+            getHandler().removeCallbacks(mTicker);
+        }
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+
+        if (mRegistered) {
             unregisterReceiver();
             unregisterObserver();
 
-            getHandler().removeCallbacks(mTicker);
-
             mRegistered = false;
         }
     }
@@ -586,10 +591,16 @@
         }
     }
 
+    /**
+     * Update the displayed time if this view and its ancestors and window is visible
+     */
     private void onTimeChanged() {
-        mTime.setTimeInMillis(System.currentTimeMillis());
-        setText(DateFormat.format(mFormat, mTime));
-        setContentDescription(DateFormat.format(mDescFormat, mTime));
+        // mShouldRunTicker always equals the last value passed into onVisibilityAggregated
+        if (mShouldRunTicker) {
+            mTime.setTimeInMillis(System.currentTimeMillis());
+            setText(DateFormat.format(mFormat, mTime));
+            setContentDescription(DateFormat.format(mDescFormat, mTime));
+        }
     }
 
     /** @hide */
diff --git a/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java b/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java
index 032c775..b9ed963 100644
--- a/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java
+++ b/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java
@@ -34,6 +34,7 @@
 import android.widget.TextView;
 
 import com.android.internal.R;
+import com.android.internal.widget.ResolverDrawerLayout;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -56,6 +57,11 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.accessibility_button_chooser);
 
+        final ResolverDrawerLayout rdl = findViewById(R.id.contentPanel);
+        if (rdl != null) {
+            rdl.setOnDismissedListener(this::finish);
+        }
+
         String component = Settings.Secure.getString(getContentResolver(),
                 Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT);
         if (TextUtils.isEmpty(component)) {
diff --git a/core/java/com/android/internal/content/FileSystemProvider.java b/core/java/com/android/internal/content/FileSystemProvider.java
index 6e9e350..79544df 100644
--- a/core/java/com/android/internal/content/FileSystemProvider.java
+++ b/core/java/com/android/internal/content/FileSystemProvider.java
@@ -17,6 +17,7 @@
 package com.android.internal.content;
 
 import android.annotation.CallSuper;
+import android.annotation.Nullable;
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Intent;
@@ -150,14 +151,17 @@
         return childId;
     }
 
-    private void addFolderToMediaStore(File visibleFolder) {
-        assert(visibleFolder.isDirectory());
+    private void addFolderToMediaStore(@Nullable File visibleFolder) {
+        // visibleFolder is null if we're adding a folder to external thumb drive or SD card.
+        if (visibleFolder != null) {
+            assert (visibleFolder.isDirectory());
 
-        final ContentResolver resolver = getContext().getContentResolver();
-        final Uri uri = MediaStore.Files.getDirectoryUri("external");
-        ContentValues values = new ContentValues();
-        values.put(MediaStore.Files.FileColumns.DATA, visibleFolder.getAbsolutePath());
-        resolver.insert(uri, values);
+            final ContentResolver resolver = getContext().getContentResolver();
+            final Uri uri = MediaStore.Files.getDirectoryUri("external");
+            ContentValues values = new ContentValues();
+            values.put(MediaStore.Files.FileColumns.DATA, visibleFolder.getAbsolutePath());
+            resolver.insert(uri, values);
+        }
     }
 
     @Override
@@ -204,8 +208,12 @@
         return docId;
     }
 
-    private void moveInMediaStore(File oldVisibleFile, File newVisibleFile) {
-        if (newVisibleFile != null) {
+    private void moveInMediaStore(@Nullable File oldVisibleFile, @Nullable File newVisibleFile) {
+        // visibleFolders are null if we're moving a document in external thumb drive or SD card.
+        //
+        // They should be all null or not null at the same time. File#renameTo() doesn't work across
+        // volumes so an exception will be thrown before calling this method.
+        if (oldVisibleFile != null && newVisibleFile != null) {
             final ContentResolver resolver = getContext().getContentResolver();
             final Uri externalUri = newVisibleFile.isDirectory()
                     ? MediaStore.Files.getDirectoryUri("external")
@@ -241,8 +249,9 @@
         removeFromMediaStore(visibleFile, isDirectory);
     }
 
-    private void removeFromMediaStore(File visibleFile, boolean isFolder)
+    private void removeFromMediaStore(@Nullable File visibleFile, boolean isFolder)
             throws FileNotFoundException {
+        // visibleFolder is null if we're removing a document from external thumb drive or SD card.
         if (visibleFile != null) {
             final ContentResolver resolver = getContext().getContentResolver();
             final Uri externalUri = MediaStore.Files.getContentUri("external");
diff --git a/core/java/com/android/internal/graphics/ColorUtils.java b/core/java/com/android/internal/graphics/ColorUtils.java
new file mode 100644
index 0000000..6c1efa4
--- /dev/null
+++ b/core/java/com/android/internal/graphics/ColorUtils.java
@@ -0,0 +1,618 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.internal.graphics;
+
+import android.annotation.ColorInt;
+import android.annotation.FloatRange;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.graphics.Color;
+
+/**
+ * Copied from: frameworks/support/core-utils/java/android/support/v4/graphics/ColorUtils.java
+ *
+ * A set of color-related utility methods, building upon those available in {@code Color}.
+ */
+public final class ColorUtils {
+
+    private static final double XYZ_WHITE_REFERENCE_X = 95.047;
+    private static final double XYZ_WHITE_REFERENCE_Y = 100;
+    private static final double XYZ_WHITE_REFERENCE_Z = 108.883;
+    private static final double XYZ_EPSILON = 0.008856;
+    private static final double XYZ_KAPPA = 903.3;
+
+    private static final int MIN_ALPHA_SEARCH_MAX_ITERATIONS = 10;
+    private static final int MIN_ALPHA_SEARCH_PRECISION = 1;
+
+    private static final ThreadLocal<double[]> TEMP_ARRAY = new ThreadLocal<>();
+
+    private ColorUtils() {}
+
+    /**
+     * Composite two potentially translucent colors over each other and returns the result.
+     */
+    public static int compositeColors(@ColorInt int foreground, @ColorInt int background) {
+        int bgAlpha = Color.alpha(background);
+        int fgAlpha = Color.alpha(foreground);
+        int a = compositeAlpha(fgAlpha, bgAlpha);
+
+        int r = compositeComponent(Color.red(foreground), fgAlpha,
+                Color.red(background), bgAlpha, a);
+        int g = compositeComponent(Color.green(foreground), fgAlpha,
+                Color.green(background), bgAlpha, a);
+        int b = compositeComponent(Color.blue(foreground), fgAlpha,
+                Color.blue(background), bgAlpha, a);
+
+        return Color.argb(a, r, g, b);
+    }
+
+    private static int compositeAlpha(int foregroundAlpha, int backgroundAlpha) {
+        return 0xFF - (((0xFF - backgroundAlpha) * (0xFF - foregroundAlpha)) / 0xFF);
+    }
+
+    private static int compositeComponent(int fgC, int fgA, int bgC, int bgA, int a) {
+        if (a == 0) return 0;
+        return ((0xFF * fgC * fgA) + (bgC * bgA * (0xFF - fgA))) / (a * 0xFF);
+    }
+
+    /**
+     * Returns the luminance of a color as a float between {@code 0.0} and {@code 1.0}.
+     * <p>Defined as the Y component in the XYZ representation of {@code color}.</p>
+     */
+    @FloatRange(from = 0.0, to = 1.0)
+    public static double calculateLuminance(@ColorInt int color) {
+        final double[] result = getTempDouble3Array();
+        colorToXYZ(color, result);
+        // Luminance is the Y component
+        return result[1] / 100;
+    }
+
+    /**
+     * Returns the contrast ratio between {@code foreground} and {@code background}.
+     * {@code background} must be opaque.
+     * <p>
+     * Formula defined
+     * <a href="http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef">here</a>.
+     */
+    public static double calculateContrast(@ColorInt int foreground, @ColorInt int background) {
+        if (Color.alpha(background) != 255) {
+            throw new IllegalArgumentException("background can not be translucent: #"
+                    + Integer.toHexString(background));
+        }
+        if (Color.alpha(foreground) < 255) {
+            // If the foreground is translucent, composite the foreground over the background
+            foreground = compositeColors(foreground, background);
+        }
+
+        final double luminance1 = calculateLuminance(foreground) + 0.05;
+        final double luminance2 = calculateLuminance(background) + 0.05;
+
+        // Now return the lighter luminance divided by the darker luminance
+        return Math.max(luminance1, luminance2) / Math.min(luminance1, luminance2);
+    }
+
+    /**
+     * Calculates the minimum alpha value which can be applied to {@code foreground} so that would
+     * have a contrast value of at least {@code minContrastRatio} when compared to
+     * {@code background}.
+     *
+     * @param foreground       the foreground color
+     * @param background       the opaque background color
+     * @param minContrastRatio the minimum contrast ratio
+     * @return the alpha value in the range 0-255, or -1 if no value could be calculated
+     */
+    public static int calculateMinimumAlpha(@ColorInt int foreground, @ColorInt int background,
+            float minContrastRatio) {
+        if (Color.alpha(background) != 255) {
+            throw new IllegalArgumentException("background can not be translucent: #"
+                    + Integer.toHexString(background));
+        }
+
+        // First lets check that a fully opaque foreground has sufficient contrast
+        int testForeground = setAlphaComponent(foreground, 255);
+        double testRatio = calculateContrast(testForeground, background);
+        if (testRatio < minContrastRatio) {
+            // Fully opaque foreground does not have sufficient contrast, return error
+            return -1;
+        }
+
+        // Binary search to find a value with the minimum value which provides sufficient contrast
+        int numIterations = 0;
+        int minAlpha = 0;
+        int maxAlpha = 255;
+
+        while (numIterations <= MIN_ALPHA_SEARCH_MAX_ITERATIONS &&
+                (maxAlpha - minAlpha) > MIN_ALPHA_SEARCH_PRECISION) {
+            final int testAlpha = (minAlpha + maxAlpha) / 2;
+
+            testForeground = setAlphaComponent(foreground, testAlpha);
+            testRatio = calculateContrast(testForeground, background);
+
+            if (testRatio < minContrastRatio) {
+                minAlpha = testAlpha;
+            } else {
+                maxAlpha = testAlpha;
+            }
+
+            numIterations++;
+        }
+
+        // Conservatively return the max of the range of possible alphas, which is known to pass.
+        return maxAlpha;
+    }
+
+    /**
+     * Convert RGB components to HSL (hue-saturation-lightness).
+     * <ul>
+     * <li>outHsl[0] is Hue [0 .. 360)</li>
+     * <li>outHsl[1] is Saturation [0...1]</li>
+     * <li>outHsl[2] is Lightness [0...1]</li>
+     * </ul>
+     *
+     * @param r      red component value [0..255]
+     * @param g      green component value [0..255]
+     * @param b      blue component value [0..255]
+     * @param outHsl 3-element array which holds the resulting HSL components
+     */
+    public static void RGBToHSL(@IntRange(from = 0x0, to = 0xFF) int r,
+            @IntRange(from = 0x0, to = 0xFF) int g, @IntRange(from = 0x0, to = 0xFF) int b,
+            @NonNull float[] outHsl) {
+        final float rf = r / 255f;
+        final float gf = g / 255f;
+        final float bf = b / 255f;
+
+        final float max = Math.max(rf, Math.max(gf, bf));
+        final float min = Math.min(rf, Math.min(gf, bf));
+        final float deltaMaxMin = max - min;
+
+        float h, s;
+        float l = (max + min) / 2f;
+
+        if (max == min) {
+            // Monochromatic
+            h = s = 0f;
+        } else {
+            if (max == rf) {
+                h = ((gf - bf) / deltaMaxMin) % 6f;
+            } else if (max == gf) {
+                h = ((bf - rf) / deltaMaxMin) + 2f;
+            } else {
+                h = ((rf - gf) / deltaMaxMin) + 4f;
+            }
+
+            s = deltaMaxMin / (1f - Math.abs(2f * l - 1f));
+        }
+
+        h = (h * 60f) % 360f;
+        if (h < 0) {
+            h += 360f;
+        }
+
+        outHsl[0] = constrain(h, 0f, 360f);
+        outHsl[1] = constrain(s, 0f, 1f);
+        outHsl[2] = constrain(l, 0f, 1f);
+    }
+
+    /**
+     * Convert the ARGB color to its HSL (hue-saturation-lightness) components.
+     * <ul>
+     * <li>outHsl[0] is Hue [0 .. 360)</li>
+     * <li>outHsl[1] is Saturation [0...1]</li>
+     * <li>outHsl[2] is Lightness [0...1]</li>
+     * </ul>
+     *
+     * @param color  the ARGB color to convert. The alpha component is ignored
+     * @param outHsl 3-element array which holds the resulting HSL components
+     */
+    public static void colorToHSL(@ColorInt int color, @NonNull float[] outHsl) {
+        RGBToHSL(Color.red(color), Color.green(color), Color.blue(color), outHsl);
+    }
+
+    /**
+     * Convert HSL (hue-saturation-lightness) components to a RGB color.
+     * <ul>
+     * <li>hsl[0] is Hue [0 .. 360)</li>
+     * <li>hsl[1] is Saturation [0...1]</li>
+     * <li>hsl[2] is Lightness [0...1]</li>
+     * </ul>
+     * If hsv values are out of range, they are pinned.
+     *
+     * @param hsl 3-element array which holds the input HSL components
+     * @return the resulting RGB color
+     */
+    @ColorInt
+    public static int HSLToColor(@NonNull float[] hsl) {
+        final float h = hsl[0];
+        final float s = hsl[1];
+        final float l = hsl[2];
+
+        final float c = (1f - Math.abs(2 * l - 1f)) * s;
+        final float m = l - 0.5f * c;
+        final float x = c * (1f - Math.abs((h / 60f % 2f) - 1f));
+
+        final int hueSegment = (int) h / 60;
+
+        int r = 0, g = 0, b = 0;
+
+        switch (hueSegment) {
+            case 0:
+                r = Math.round(255 * (c + m));
+                g = Math.round(255 * (x + m));
+                b = Math.round(255 * m);
+                break;
+            case 1:
+                r = Math.round(255 * (x + m));
+                g = Math.round(255 * (c + m));
+                b = Math.round(255 * m);
+                break;
+            case 2:
+                r = Math.round(255 * m);
+                g = Math.round(255 * (c + m));
+                b = Math.round(255 * (x + m));
+                break;
+            case 3:
+                r = Math.round(255 * m);
+                g = Math.round(255 * (x + m));
+                b = Math.round(255 * (c + m));
+                break;
+            case 4:
+                r = Math.round(255 * (x + m));
+                g = Math.round(255 * m);
+                b = Math.round(255 * (c + m));
+                break;
+            case 5:
+            case 6:
+                r = Math.round(255 * (c + m));
+                g = Math.round(255 * m);
+                b = Math.round(255 * (x + m));
+                break;
+        }
+
+        r = constrain(r, 0, 255);
+        g = constrain(g, 0, 255);
+        b = constrain(b, 0, 255);
+
+        return Color.rgb(r, g, b);
+    }
+
+    /**
+     * Set the alpha component of {@code color} to be {@code alpha}.
+     */
+    @ColorInt
+    public static int setAlphaComponent(@ColorInt int color,
+            @IntRange(from = 0x0, to = 0xFF) int alpha) {
+        if (alpha < 0 || alpha > 255) {
+            throw new IllegalArgumentException("alpha must be between 0 and 255.");
+        }
+        return (color & 0x00ffffff) | (alpha << 24);
+    }
+
+    /**
+     * Convert the ARGB color to its CIE Lab representative components.
+     *
+     * @param color  the ARGB color to convert. The alpha component is ignored
+     * @param outLab 3-element array which holds the resulting LAB components
+     */
+    public static void colorToLAB(@ColorInt int color, @NonNull double[] outLab) {
+        RGBToLAB(Color.red(color), Color.green(color), Color.blue(color), outLab);
+    }
+
+    /**
+     * Convert RGB components to its CIE Lab representative components.
+     *
+     * <ul>
+     * <li>outLab[0] is L [0 ...1)</li>
+     * <li>outLab[1] is a [-128...127)</li>
+     * <li>outLab[2] is b [-128...127)</li>
+     * </ul>
+     *
+     * @param r      red component value [0..255]
+     * @param g      green component value [0..255]
+     * @param b      blue component value [0..255]
+     * @param outLab 3-element array which holds the resulting LAB components
+     */
+    public static void RGBToLAB(@IntRange(from = 0x0, to = 0xFF) int r,
+            @IntRange(from = 0x0, to = 0xFF) int g, @IntRange(from = 0x0, to = 0xFF) int b,
+            @NonNull double[] outLab) {
+        // First we convert RGB to XYZ
+        RGBToXYZ(r, g, b, outLab);
+        // outLab now contains XYZ
+        XYZToLAB(outLab[0], outLab[1], outLab[2], outLab);
+        // outLab now contains LAB representation
+    }
+
+    /**
+     * Convert the ARGB color to its CIE XYZ representative components.
+     *
+     * <p>The resulting XYZ representation will use the D65 illuminant and the CIE
+     * 2° Standard Observer (1931).</p>
+     *
+     * <ul>
+     * <li>outXyz[0] is X [0 ...95.047)</li>
+     * <li>outXyz[1] is Y [0...100)</li>
+     * <li>outXyz[2] is Z [0...108.883)</li>
+     * </ul>
+     *
+     * @param color  the ARGB color to convert. The alpha component is ignored
+     * @param outXyz 3-element array which holds the resulting LAB components
+     */
+    public static void colorToXYZ(@ColorInt int color, @NonNull double[] outXyz) {
+        RGBToXYZ(Color.red(color), Color.green(color), Color.blue(color), outXyz);
+    }
+
+    /**
+     * Convert RGB components to its CIE XYZ representative components.
+     *
+     * <p>The resulting XYZ representation will use the D65 illuminant and the CIE
+     * 2° Standard Observer (1931).</p>
+     *
+     * <ul>
+     * <li>outXyz[0] is X [0 ...95.047)</li>
+     * <li>outXyz[1] is Y [0...100)</li>
+     * <li>outXyz[2] is Z [0...108.883)</li>
+     * </ul>
+     *
+     * @param r      red component value [0..255]
+     * @param g      green component value [0..255]
+     * @param b      blue component value [0..255]
+     * @param outXyz 3-element array which holds the resulting XYZ components
+     */
+    public static void RGBToXYZ(@IntRange(from = 0x0, to = 0xFF) int r,
+            @IntRange(from = 0x0, to = 0xFF) int g, @IntRange(from = 0x0, to = 0xFF) int b,
+            @NonNull double[] outXyz) {
+        if (outXyz.length != 3) {
+            throw new IllegalArgumentException("outXyz must have a length of 3.");
+        }
+
+        double sr = r / 255.0;
+        sr = sr < 0.04045 ? sr / 12.92 : Math.pow((sr + 0.055) / 1.055, 2.4);
+        double sg = g / 255.0;
+        sg = sg < 0.04045 ? sg / 12.92 : Math.pow((sg + 0.055) / 1.055, 2.4);
+        double sb = b / 255.0;
+        sb = sb < 0.04045 ? sb / 12.92 : Math.pow((sb + 0.055) / 1.055, 2.4);
+
+        outXyz[0] = 100 * (sr * 0.4124 + sg * 0.3576 + sb * 0.1805);
+        outXyz[1] = 100 * (sr * 0.2126 + sg * 0.7152 + sb * 0.0722);
+        outXyz[2] = 100 * (sr * 0.0193 + sg * 0.1192 + sb * 0.9505);
+    }
+
+    /**
+     * Converts a color from CIE XYZ to CIE Lab representation.
+     *
+     * <p>This method expects the XYZ representation to use the D65 illuminant and the CIE
+     * 2° Standard Observer (1931).</p>
+     *
+     * <ul>
+     * <li>outLab[0] is L [0 ...1)</li>
+     * <li>outLab[1] is a [-128...127)</li>
+     * <li>outLab[2] is b [-128...127)</li>
+     * </ul>
+     *
+     * @param x      X component value [0...95.047)
+     * @param y      Y component value [0...100)
+     * @param z      Z component value [0...108.883)
+     * @param outLab 3-element array which holds the resulting Lab components
+     */
+    public static void XYZToLAB(@FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_X) double x,
+            @FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_Y) double y,
+            @FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_Z) double z,
+            @NonNull double[] outLab) {
+        if (outLab.length != 3) {
+            throw new IllegalArgumentException("outLab must have a length of 3.");
+        }
+        x = pivotXyzComponent(x / XYZ_WHITE_REFERENCE_X);
+        y = pivotXyzComponent(y / XYZ_WHITE_REFERENCE_Y);
+        z = pivotXyzComponent(z / XYZ_WHITE_REFERENCE_Z);
+        outLab[0] = Math.max(0, 116 * y - 16);
+        outLab[1] = 500 * (x - y);
+        outLab[2] = 200 * (y - z);
+    }
+
+    /**
+     * Converts a color from CIE Lab to CIE XYZ representation.
+     *
+     * <p>The resulting XYZ representation will use the D65 illuminant and the CIE
+     * 2° Standard Observer (1931).</p>
+     *
+     * <ul>
+     * <li>outXyz[0] is X [0 ...95.047)</li>
+     * <li>outXyz[1] is Y [0...100)</li>
+     * <li>outXyz[2] is Z [0...108.883)</li>
+     * </ul>
+     *
+     * @param l      L component value [0...100)
+     * @param a      A component value [-128...127)
+     * @param b      B component value [-128...127)
+     * @param outXyz 3-element array which holds the resulting XYZ components
+     */
+    public static void LABToXYZ(@FloatRange(from = 0f, to = 100) final double l,
+            @FloatRange(from = -128, to = 127) final double a,
+            @FloatRange(from = -128, to = 127) final double b,
+            @NonNull double[] outXyz) {
+        final double fy = (l + 16) / 116;
+        final double fx = a / 500 + fy;
+        final double fz = fy - b / 200;
+
+        double tmp = Math.pow(fx, 3);
+        final double xr = tmp > XYZ_EPSILON ? tmp : (116 * fx - 16) / XYZ_KAPPA;
+        final double yr = l > XYZ_KAPPA * XYZ_EPSILON ? Math.pow(fy, 3) : l / XYZ_KAPPA;
+
+        tmp = Math.pow(fz, 3);
+        final double zr = tmp > XYZ_EPSILON ? tmp : (116 * fz - 16) / XYZ_KAPPA;
+
+        outXyz[0] = xr * XYZ_WHITE_REFERENCE_X;
+        outXyz[1] = yr * XYZ_WHITE_REFERENCE_Y;
+        outXyz[2] = zr * XYZ_WHITE_REFERENCE_Z;
+    }
+
+    /**
+     * Converts a color from CIE XYZ to its RGB representation.
+     *
+     * <p>This method expects the XYZ representation to use the D65 illuminant and the CIE
+     * 2° Standard Observer (1931).</p>
+     *
+     * @param x X component value [0...95.047)
+     * @param y Y component value [0...100)
+     * @param z Z component value [0...108.883)
+     * @return int containing the RGB representation
+     */
+    @ColorInt
+    public static int XYZToColor(@FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_X) double x,
+            @FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_Y) double y,
+            @FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_Z) double z) {
+        double r = (x * 3.2406 + y * -1.5372 + z * -0.4986) / 100;
+        double g = (x * -0.9689 + y * 1.8758 + z * 0.0415) / 100;
+        double b = (x * 0.0557 + y * -0.2040 + z * 1.0570) / 100;
+
+        r = r > 0.0031308 ? 1.055 * Math.pow(r, 1 / 2.4) - 0.055 : 12.92 * r;
+        g = g > 0.0031308 ? 1.055 * Math.pow(g, 1 / 2.4) - 0.055 : 12.92 * g;
+        b = b > 0.0031308 ? 1.055 * Math.pow(b, 1 / 2.4) - 0.055 : 12.92 * b;
+
+        return Color.rgb(
+                constrain((int) Math.round(r * 255), 0, 255),
+                constrain((int) Math.round(g * 255), 0, 255),
+                constrain((int) Math.round(b * 255), 0, 255));
+    }
+
+    /**
+     * Converts a color from CIE Lab to its RGB representation.
+     *
+     * @param l L component value [0...100]
+     * @param a A component value [-128...127]
+     * @param b B component value [-128...127]
+     * @return int containing the RGB representation
+     */
+    @ColorInt
+    public static int LABToColor(@FloatRange(from = 0f, to = 100) final double l,
+            @FloatRange(from = -128, to = 127) final double a,
+            @FloatRange(from = -128, to = 127) final double b) {
+        final double[] result = getTempDouble3Array();
+        LABToXYZ(l, a, b, result);
+        return XYZToColor(result[0], result[1], result[2]);
+    }
+
+    /**
+     * Returns the euclidean distance between two LAB colors.
+     */
+    public static double distanceEuclidean(@NonNull double[] labX, @NonNull double[] labY) {
+        return Math.sqrt(Math.pow(labX[0] - labY[0], 2)
+                + Math.pow(labX[1] - labY[1], 2)
+                + Math.pow(labX[2] - labY[2], 2));
+    }
+
+    private static float constrain(float amount, float low, float high) {
+        return amount < low ? low : (amount > high ? high : amount);
+    }
+
+    private static int constrain(int amount, int low, int high) {
+        return amount < low ? low : (amount > high ? high : amount);
+    }
+
+    private static double pivotXyzComponent(double component) {
+        return component > XYZ_EPSILON
+                ? Math.pow(component, 1 / 3.0)
+                : (XYZ_KAPPA * component + 16) / 116;
+    }
+
+    /**
+     * Blend between two ARGB colors using the given ratio.
+     *
+     * <p>A blend ratio of 0.0 will result in {@code color1}, 0.5 will give an even blend,
+     * 1.0 will result in {@code color2}.</p>
+     *
+     * @param color1 the first ARGB color
+     * @param color2 the second ARGB color
+     * @param ratio  the blend ratio of {@code color1} to {@code color2}
+     */
+    @ColorInt
+    public static int blendARGB(@ColorInt int color1, @ColorInt int color2,
+            @FloatRange(from = 0.0, to = 1.0) float ratio) {
+        final float inverseRatio = 1 - ratio;
+        float a = Color.alpha(color1) * inverseRatio + Color.alpha(color2) * ratio;
+        float r = Color.red(color1) * inverseRatio + Color.red(color2) * ratio;
+        float g = Color.green(color1) * inverseRatio + Color.green(color2) * ratio;
+        float b = Color.blue(color1) * inverseRatio + Color.blue(color2) * ratio;
+        return Color.argb((int) a, (int) r, (int) g, (int) b);
+    }
+
+    /**
+     * Blend between {@code hsl1} and {@code hsl2} using the given ratio. This will interpolate
+     * the hue using the shortest angle.
+     *
+     * <p>A blend ratio of 0.0 will result in {@code hsl1}, 0.5 will give an even blend,
+     * 1.0 will result in {@code hsl2}.</p>
+     *
+     * @param hsl1      3-element array which holds the first HSL color
+     * @param hsl2      3-element array which holds the second HSL color
+     * @param ratio     the blend ratio of {@code hsl1} to {@code hsl2}
+     * @param outResult 3-element array which holds the resulting HSL components
+     */
+    public static void blendHSL(@NonNull float[] hsl1, @NonNull float[] hsl2,
+            @FloatRange(from = 0.0, to = 1.0) float ratio, @NonNull float[] outResult) {
+        if (outResult.length != 3) {
+            throw new IllegalArgumentException("result must have a length of 3.");
+        }
+        final float inverseRatio = 1 - ratio;
+        // Since hue is circular we will need to interpolate carefully
+        outResult[0] = circularInterpolate(hsl1[0], hsl2[0], ratio);
+        outResult[1] = hsl1[1] * inverseRatio + hsl2[1] * ratio;
+        outResult[2] = hsl1[2] * inverseRatio + hsl2[2] * ratio;
+    }
+
+    /**
+     * Blend between two CIE-LAB colors using the given ratio.
+     *
+     * <p>A blend ratio of 0.0 will result in {@code lab1}, 0.5 will give an even blend,
+     * 1.0 will result in {@code lab2}.</p>
+     *
+     * @param lab1      3-element array which holds the first LAB color
+     * @param lab2      3-element array which holds the second LAB color
+     * @param ratio     the blend ratio of {@code lab1} to {@code lab2}
+     * @param outResult 3-element array which holds the resulting LAB components
+     */
+    public static void blendLAB(@NonNull double[] lab1, @NonNull double[] lab2,
+            @FloatRange(from = 0.0, to = 1.0) double ratio, @NonNull double[] outResult) {
+        if (outResult.length != 3) {
+            throw new IllegalArgumentException("outResult must have a length of 3.");
+        }
+        final double inverseRatio = 1 - ratio;
+        outResult[0] = lab1[0] * inverseRatio + lab2[0] * ratio;
+        outResult[1] = lab1[1] * inverseRatio + lab2[1] * ratio;
+        outResult[2] = lab1[2] * inverseRatio + lab2[2] * ratio;
+    }
+
+    static float circularInterpolate(float a, float b, float f) {
+        if (Math.abs(b - a) > 180) {
+            if (b > a) {
+                a += 360;
+            } else {
+                b += 360;
+            }
+        }
+        return (a + ((b - a) * f)) % 360;
+    }
+
+    private static double[] getTempDouble3Array() {
+        double[] result = TEMP_ARRAY.get();
+        if (result == null) {
+            result = new double[3];
+            TEMP_ARRAY.set(result);
+        }
+        return result;
+    }
+
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/graphics/palette/ColorCutQuantizer.java b/core/java/com/android/internal/graphics/palette/ColorCutQuantizer.java
new file mode 100644
index 0000000..2d0ad66
--- /dev/null
+++ b/core/java/com/android/internal/graphics/palette/ColorCutQuantizer.java
@@ -0,0 +1,535 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.internal.graphics.palette;
+
+/*
+ * Copyright 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.
+ */
+
+import android.graphics.Color;
+import android.util.TimingLogger;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.List;
+import java.util.PriorityQueue;
+
+import com.android.internal.graphics.ColorUtils;
+import com.android.internal.graphics.palette.Palette.Swatch;
+
+/**
+ * Copied from: frameworks/support/v7/palette/src/main/java/android/support/v7/
+ * graphics/ColorCutQuantizer.java
+ *
+ * An color quantizer based on the Median-cut algorithm, but optimized for picking out distinct
+ * colors rather than representation colors.
+ *
+ * The color space is represented as a 3-dimensional cube with each dimension being an RGB
+ * component. The cube is then repeatedly divided until we have reduced the color space to the
+ * requested number of colors. An average color is then generated from each cube.
+ *
+ * What makes this different to median-cut is that median-cut divided cubes so that all of the cubes
+ * have roughly the same population, where this quantizer divides boxes based on their color volume.
+ * This means that the color space is divided into distinct colors, rather than representative
+ * colors.
+ */
+final class ColorCutQuantizer {
+
+    private static final String LOG_TAG = "ColorCutQuantizer";
+    private static final boolean LOG_TIMINGS = false;
+
+    static final int COMPONENT_RED = -3;
+    static final int COMPONENT_GREEN = -2;
+    static final int COMPONENT_BLUE = -1;
+
+    private static final int QUANTIZE_WORD_WIDTH = 5;
+    private static final int QUANTIZE_WORD_MASK = (1 << QUANTIZE_WORD_WIDTH) - 1;
+
+    final int[] mColors;
+    final int[] mHistogram;
+    final List<Swatch> mQuantizedColors;
+    final TimingLogger mTimingLogger;
+    final Palette.Filter[] mFilters;
+
+    private final float[] mTempHsl = new float[3];
+
+    /**
+     * Constructor.
+     *
+     * @param pixels histogram representing an image's pixel data
+     * @param maxColors The maximum number of colors that should be in the result palette.
+     * @param filters Set of filters to use in the quantization stage
+     */
+    ColorCutQuantizer(final int[] pixels, final int maxColors, final Palette.Filter[] filters) {
+        mTimingLogger = LOG_TIMINGS ? new TimingLogger(LOG_TAG, "Creation") : null;
+        mFilters = filters;
+
+        final int[] hist = mHistogram = new int[1 << (QUANTIZE_WORD_WIDTH * 3)];
+        for (int i = 0; i < pixels.length; i++) {
+            final int quantizedColor = quantizeFromRgb888(pixels[i]);
+            // Now update the pixel value to the quantized value
+            pixels[i] = quantizedColor;
+            // And update the histogram
+            hist[quantizedColor]++;
+        }
+
+        if (LOG_TIMINGS) {
+            mTimingLogger.addSplit("Histogram created");
+        }
+
+        // Now let's count the number of distinct colors
+        int distinctColorCount = 0;
+        for (int color = 0; color < hist.length; color++) {
+            if (hist[color] > 0 && shouldIgnoreColor(color)) {
+                // If we should ignore the color, set the population to 0
+                hist[color] = 0;
+            }
+            if (hist[color] > 0) {
+                // If the color has population, increase the distinct color count
+                distinctColorCount++;
+            }
+        }
+
+        if (LOG_TIMINGS) {
+            mTimingLogger.addSplit("Filtered colors and distinct colors counted");
+        }
+
+        // Now lets go through create an array consisting of only distinct colors
+        final int[] colors = mColors = new int[distinctColorCount];
+        int distinctColorIndex = 0;
+        for (int color = 0; color < hist.length; color++) {
+            if (hist[color] > 0) {
+                colors[distinctColorIndex++] = color;
+            }
+        }
+
+        if (LOG_TIMINGS) {
+            mTimingLogger.addSplit("Distinct colors copied into array");
+        }
+
+        if (distinctColorCount <= maxColors) {
+            // The image has fewer colors than the maximum requested, so just return the colors
+            mQuantizedColors = new ArrayList<>();
+            for (int color : colors) {
+                mQuantizedColors.add(new Swatch(approximateToRgb888(color), hist[color]));
+            }
+
+            if (LOG_TIMINGS) {
+                mTimingLogger.addSplit("Too few colors present. Copied to Swatches");
+                mTimingLogger.dumpToLog();
+            }
+        } else {
+            // We need use quantization to reduce the number of colors
+            mQuantizedColors = quantizePixels(maxColors);
+
+            if (LOG_TIMINGS) {
+                mTimingLogger.addSplit("Quantized colors computed");
+                mTimingLogger.dumpToLog();
+            }
+        }
+    }
+
+    /**
+     * @return the list of quantized colors
+     */
+    List<Swatch> getQuantizedColors() {
+        return mQuantizedColors;
+    }
+
+    private List<Swatch> quantizePixels(int maxColors) {
+        // Create the priority queue which is sorted by volume descending. This means we always
+        // split the largest box in the queue
+        final PriorityQueue<Vbox> pq = new PriorityQueue<>(maxColors, VBOX_COMPARATOR_VOLUME);
+
+        // To start, offer a box which contains all of the colors
+        pq.offer(new Vbox(0, mColors.length - 1));
+
+        // Now go through the boxes, splitting them until we have reached maxColors or there are no
+        // more boxes to split
+        splitBoxes(pq, maxColors);
+
+        // Finally, return the average colors of the color boxes
+        return generateAverageColors(pq);
+    }
+
+    /**
+     * Iterate through the {@link java.util.Queue}, popping
+     * {@link ColorCutQuantizer.Vbox} objects from the queue
+     * and splitting them. Once split, the new box and the remaining box are offered back to the
+     * queue.
+     *
+     * @param queue {@link java.util.PriorityQueue} to poll for boxes
+     * @param maxSize Maximum amount of boxes to split
+     */
+    private void splitBoxes(final PriorityQueue<Vbox> queue, final int maxSize) {
+        while (queue.size() < maxSize) {
+            final Vbox vbox = queue.poll();
+
+            if (vbox != null && vbox.canSplit()) {
+                // First split the box, and offer the result
+                queue.offer(vbox.splitBox());
+
+                if (LOG_TIMINGS) {
+                    mTimingLogger.addSplit("Box split");
+                }
+                // Then offer the box back
+                queue.offer(vbox);
+            } else {
+                if (LOG_TIMINGS) {
+                    mTimingLogger.addSplit("All boxes split");
+                }
+                // If we get here then there are no more boxes to split, so return
+                return;
+            }
+        }
+    }
+
+    private List<Swatch> generateAverageColors(Collection<Vbox> vboxes) {
+        ArrayList<Swatch> colors = new ArrayList<>(vboxes.size());
+        for (Vbox vbox : vboxes) {
+            Swatch swatch = vbox.getAverageColor();
+            if (!shouldIgnoreColor(swatch)) {
+                // As we're averaging a color box, we can still get colors which we do not want, so
+                // we check again here
+                colors.add(swatch);
+            }
+        }
+        return colors;
+    }
+
+    /**
+     * Represents a tightly fitting box around a color space.
+     */
+    private class Vbox {
+        // lower and upper index are inclusive
+        private int mLowerIndex;
+        private int mUpperIndex;
+        // Population of colors within this box
+        private int mPopulation;
+
+        private int mMinRed, mMaxRed;
+        private int mMinGreen, mMaxGreen;
+        private int mMinBlue, mMaxBlue;
+
+        Vbox(int lowerIndex, int upperIndex) {
+            mLowerIndex = lowerIndex;
+            mUpperIndex = upperIndex;
+            fitBox();
+        }
+
+        final int getVolume() {
+            return (mMaxRed - mMinRed + 1) * (mMaxGreen - mMinGreen + 1) *
+                    (mMaxBlue - mMinBlue + 1);
+        }
+
+        final boolean canSplit() {
+            return getColorCount() > 1;
+        }
+
+        final int getColorCount() {
+            return 1 + mUpperIndex - mLowerIndex;
+        }
+
+        /**
+         * Recomputes the boundaries of this box to tightly fit the colors within the box.
+         */
+        final void fitBox() {
+            final int[] colors = mColors;
+            final int[] hist = mHistogram;
+
+            // Reset the min and max to opposite values
+            int minRed, minGreen, minBlue;
+            minRed = minGreen = minBlue = Integer.MAX_VALUE;
+            int maxRed, maxGreen, maxBlue;
+            maxRed = maxGreen = maxBlue = Integer.MIN_VALUE;
+            int count = 0;
+
+            for (int i = mLowerIndex; i <= mUpperIndex; i++) {
+                final int color = colors[i];
+                count += hist[color];
+
+                final int r = quantizedRed(color);
+                final int g = quantizedGreen(color);
+                final int b = quantizedBlue(color);
+                if (r > maxRed) {
+                    maxRed = r;
+                }
+                if (r < minRed) {
+                    minRed = r;
+                }
+                if (g > maxGreen) {
+                    maxGreen = g;
+                }
+                if (g < minGreen) {
+                    minGreen = g;
+                }
+                if (b > maxBlue) {
+                    maxBlue = b;
+                }
+                if (b < minBlue) {
+                    minBlue = b;
+                }
+            }
+
+            mMinRed = minRed;
+            mMaxRed = maxRed;
+            mMinGreen = minGreen;
+            mMaxGreen = maxGreen;
+            mMinBlue = minBlue;
+            mMaxBlue = maxBlue;
+            mPopulation = count;
+        }
+
+        /**
+         * Split this color box at the mid-point along its longest dimension
+         *
+         * @return the new ColorBox
+         */
+        final Vbox splitBox() {
+            if (!canSplit()) {
+                throw new IllegalStateException("Can not split a box with only 1 color");
+            }
+
+            // find median along the longest dimension
+            final int splitPoint = findSplitPoint();
+
+            Vbox newBox = new Vbox(splitPoint + 1, mUpperIndex);
+
+            // Now change this box's upperIndex and recompute the color boundaries
+            mUpperIndex = splitPoint;
+            fitBox();
+
+            return newBox;
+        }
+
+        /**
+         * @return the dimension which this box is largest in
+         */
+        final int getLongestColorDimension() {
+            final int redLength = mMaxRed - mMinRed;
+            final int greenLength = mMaxGreen - mMinGreen;
+            final int blueLength = mMaxBlue - mMinBlue;
+
+            if (redLength >= greenLength && redLength >= blueLength) {
+                return COMPONENT_RED;
+            } else if (greenLength >= redLength && greenLength >= blueLength) {
+                return COMPONENT_GREEN;
+            } else {
+                return COMPONENT_BLUE;
+            }
+        }
+
+        /**
+         * Finds the point within this box's lowerIndex and upperIndex index of where to split.
+         *
+         * This is calculated by finding the longest color dimension, and then sorting the
+         * sub-array based on that dimension value in each color. The colors are then iterated over
+         * until a color is found with at least the midpoint of the whole box's dimension midpoint.
+         *
+         * @return the index of the colors array to split from
+         */
+        final int findSplitPoint() {
+            final int longestDimension = getLongestColorDimension();
+            final int[] colors = mColors;
+            final int[] hist = mHistogram;
+
+            // We need to sort the colors in this box based on the longest color dimension.
+            // As we can't use a Comparator to define the sort logic, we modify each color so that
+            // its most significant is the desired dimension
+            modifySignificantOctet(colors, longestDimension, mLowerIndex, mUpperIndex);
+
+            // Now sort... Arrays.sort uses a exclusive toIndex so we need to add 1
+            Arrays.sort(colors, mLowerIndex, mUpperIndex + 1);
+
+            // Now revert all of the colors so that they are packed as RGB again
+            modifySignificantOctet(colors, longestDimension, mLowerIndex, mUpperIndex);
+
+            final int midPoint = mPopulation / 2;
+            for (int i = mLowerIndex, count = 0; i <= mUpperIndex; i++)  {
+                count += hist[colors[i]];
+                if (count >= midPoint) {
+                    return i;
+                }
+            }
+
+            return mLowerIndex;
+        }
+
+        /**
+         * @return the average color of this box.
+         */
+        final Swatch getAverageColor() {
+            final int[] colors = mColors;
+            final int[] hist = mHistogram;
+            int redSum = 0;
+            int greenSum = 0;
+            int blueSum = 0;
+            int totalPopulation = 0;
+
+            for (int i = mLowerIndex; i <= mUpperIndex; i++) {
+                final int color = colors[i];
+                final int colorPopulation = hist[color];
+
+                totalPopulation += colorPopulation;
+                redSum += colorPopulation * quantizedRed(color);
+                greenSum += colorPopulation * quantizedGreen(color);
+                blueSum += colorPopulation * quantizedBlue(color);
+            }
+
+            final int redMean = Math.round(redSum / (float) totalPopulation);
+            final int greenMean = Math.round(greenSum / (float) totalPopulation);
+            final int blueMean = Math.round(blueSum / (float) totalPopulation);
+
+            return new Swatch(approximateToRgb888(redMean, greenMean, blueMean), totalPopulation);
+        }
+    }
+
+    /**
+     * Modify the significant octet in a packed color int. Allows sorting based on the value of a
+     * single color component. This relies on all components being the same word size.
+     *
+     * @see Vbox#findSplitPoint()
+     */
+    static void modifySignificantOctet(final int[] a, final int dimension,
+            final int lower, final int upper) {
+        switch (dimension) {
+            case COMPONENT_RED:
+                // Already in RGB, no need to do anything
+                break;
+            case COMPONENT_GREEN:
+                // We need to do a RGB to GRB swap, or vice-versa
+                for (int i = lower; i <= upper; i++) {
+                    final int color = a[i];
+                    a[i] = quantizedGreen(color) << (QUANTIZE_WORD_WIDTH + QUANTIZE_WORD_WIDTH)
+                            | quantizedRed(color) << QUANTIZE_WORD_WIDTH
+                            | quantizedBlue(color);
+                }
+                break;
+            case COMPONENT_BLUE:
+                // We need to do a RGB to BGR swap, or vice-versa
+                for (int i = lower; i <= upper; i++) {
+                    final int color = a[i];
+                    a[i] = quantizedBlue(color) << (QUANTIZE_WORD_WIDTH + QUANTIZE_WORD_WIDTH)
+                            | quantizedGreen(color) << QUANTIZE_WORD_WIDTH
+                            | quantizedRed(color);
+                }
+                break;
+        }
+    }
+
+    private boolean shouldIgnoreColor(int color565) {
+        final int rgb = approximateToRgb888(color565);
+        ColorUtils.colorToHSL(rgb, mTempHsl);
+        return shouldIgnoreColor(rgb, mTempHsl);
+    }
+
+    private boolean shouldIgnoreColor(Swatch color) {
+        return shouldIgnoreColor(color.getRgb(), color.getHsl());
+    }
+
+    private boolean shouldIgnoreColor(int rgb, float[] hsl) {
+        if (mFilters != null && mFilters.length > 0) {
+            for (int i = 0, count = mFilters.length; i < count; i++) {
+                if (!mFilters[i].isAllowed(rgb, hsl)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Comparator which sorts {@link Vbox} instances based on their volume, in descending order
+     */
+    private static final Comparator<Vbox> VBOX_COMPARATOR_VOLUME = new Comparator<Vbox>() {
+        @Override
+        public int compare(Vbox lhs, Vbox rhs) {
+            return rhs.getVolume() - lhs.getVolume();
+        }
+    };
+
+    /**
+     * Quantized a RGB888 value to have a word width of {@value #QUANTIZE_WORD_WIDTH}.
+     */
+    private static int quantizeFromRgb888(int color) {
+        int r = modifyWordWidth(Color.red(color), 8, QUANTIZE_WORD_WIDTH);
+        int g = modifyWordWidth(Color.green(color), 8, QUANTIZE_WORD_WIDTH);
+        int b = modifyWordWidth(Color.blue(color), 8, QUANTIZE_WORD_WIDTH);
+        return r << (QUANTIZE_WORD_WIDTH + QUANTIZE_WORD_WIDTH) | g << QUANTIZE_WORD_WIDTH | b;
+    }
+
+    /**
+     * Quantized RGB888 values to have a word width of {@value #QUANTIZE_WORD_WIDTH}.
+     */
+    static int approximateToRgb888(int r, int g, int b) {
+        return Color.rgb(modifyWordWidth(r, QUANTIZE_WORD_WIDTH, 8),
+                modifyWordWidth(g, QUANTIZE_WORD_WIDTH, 8),
+                modifyWordWidth(b, QUANTIZE_WORD_WIDTH, 8));
+    }
+
+    private static int approximateToRgb888(int color) {
+        return approximateToRgb888(quantizedRed(color), quantizedGreen(color), quantizedBlue(color));
+    }
+
+    /**
+     * @return red component of the quantized color
+     */
+    static int quantizedRed(int color) {
+        return (color >> (QUANTIZE_WORD_WIDTH + QUANTIZE_WORD_WIDTH)) & QUANTIZE_WORD_MASK;
+    }
+
+    /**
+     * @return green component of a quantized color
+     */
+    static int quantizedGreen(int color) {
+        return (color >> QUANTIZE_WORD_WIDTH) & QUANTIZE_WORD_MASK;
+    }
+
+    /**
+     * @return blue component of a quantized color
+     */
+    static int quantizedBlue(int color) {
+        return color & QUANTIZE_WORD_MASK;
+    }
+
+    private static int modifyWordWidth(int value, int currentWidth, int targetWidth) {
+        final int newValue;
+        if (targetWidth > currentWidth) {
+            // If we're approximating up in word width, we'll shift up
+            newValue = value << (targetWidth - currentWidth);
+        } else {
+            // Else, we will just shift and keep the MSB
+            newValue = value >> (currentWidth - targetWidth);
+        }
+        return newValue & ((1 << targetWidth) - 1);
+    }
+
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/graphics/palette/Palette.java b/core/java/com/android/internal/graphics/palette/Palette.java
new file mode 100644
index 0000000..9f1504a
--- /dev/null
+++ b/core/java/com/android/internal/graphics/palette/Palette.java
@@ -0,0 +1,990 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.internal.graphics.palette;
+
+import android.annotation.ColorInt;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.os.AsyncTask;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.util.SparseBooleanArray;
+import android.util.TimingLogger;
+
+import com.android.internal.graphics.ColorUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * Copied from: /frameworks/support/v7/palette/src/main/java/android/support/v7/
+ * graphics/Palette.java
+ *
+ * A helper class to extract prominent colors from an image.
+ * <p>
+ * A number of colors with different profiles are extracted from the image:
+ * <ul>
+ *     <li>Vibrant</li>
+ *     <li>Vibrant Dark</li>
+ *     <li>Vibrant Light</li>
+ *     <li>Muted</li>
+ *     <li>Muted Dark</li>
+ *     <li>Muted Light</li>
+ * </ul>
+ * These can be retrieved from the appropriate getter method.
+ *
+ * <p>
+ * Instances are created with a {@link Palette.Builder} which supports several options to tweak the
+ * generated Palette. See that class' documentation for more information.
+ * <p>
+ * Generation should always be completed on a background thread, ideally the one in
+ * which you load your image on. {@link Palette.Builder} supports both synchronous and asynchronous
+ * generation:
+ *
+ * <pre>
+ * // Synchronous
+ * Palette p = Palette.from(bitmap).generate();
+ *
+ * // Asynchronous
+ * Palette.from(bitmap).generate(new PaletteAsyncListener() {
+ *     public void onGenerated(Palette p) {
+ *         // Use generated instance
+ *     }
+ * });
+ * </pre>
+ */
+public final class Palette {
+
+    /**
+     * Listener to be used with {@link #generateAsync(Bitmap, Palette.PaletteAsyncListener)} or
+     * {@link #generateAsync(Bitmap, int, Palette.PaletteAsyncListener)}
+     */
+    public interface PaletteAsyncListener {
+
+        /**
+         * Called when the {@link Palette} has been generated.
+         */
+        void onGenerated(Palette palette);
+    }
+
+    static final int DEFAULT_RESIZE_BITMAP_AREA = 112 * 112;
+    static final int DEFAULT_CALCULATE_NUMBER_COLORS = 16;
+
+    static final float MIN_CONTRAST_TITLE_TEXT = 3.0f;
+    static final float MIN_CONTRAST_BODY_TEXT = 4.5f;
+
+    static final String LOG_TAG = "Palette";
+    static final boolean LOG_TIMINGS = false;
+
+    /**
+     * Start generating a {@link Palette} with the returned {@link Palette.Builder} instance.
+     */
+    public static Palette.Builder from(Bitmap bitmap) {
+        return new Palette.Builder(bitmap);
+    }
+
+    /**
+     * Generate a {@link Palette} from the pre-generated list of {@link Palette.Swatch} swatches.
+     * This is useful for testing, or if you want to resurrect a {@link Palette} instance from a
+     * list of swatches. Will return null if the {@code swatches} is null.
+     */
+    public static Palette from(List<Palette.Swatch> swatches) {
+        return new Palette.Builder(swatches).generate();
+    }
+
+    /**
+     * @deprecated Use {@link Palette.Builder} to generate the Palette.
+     */
+    @Deprecated
+    public static Palette generate(Bitmap bitmap) {
+        return from(bitmap).generate();
+    }
+
+    /**
+     * @deprecated Use {@link Palette.Builder} to generate the Palette.
+     */
+    @Deprecated
+    public static Palette generate(Bitmap bitmap, int numColors) {
+        return from(bitmap).maximumColorCount(numColors).generate();
+    }
+
+    /**
+     * @deprecated Use {@link Palette.Builder} to generate the Palette.
+     */
+    @Deprecated
+    public static AsyncTask<Bitmap, Void, Palette> generateAsync(
+            Bitmap bitmap, Palette.PaletteAsyncListener listener) {
+        return from(bitmap).generate(listener);
+    }
+
+    /**
+     * @deprecated Use {@link Palette.Builder} to generate the Palette.
+     */
+    @Deprecated
+    public static AsyncTask<Bitmap, Void, Palette> generateAsync(
+            final Bitmap bitmap, final int numColors, final Palette.PaletteAsyncListener listener) {
+        return from(bitmap).maximumColorCount(numColors).generate(listener);
+    }
+
+    private final List<Palette.Swatch> mSwatches;
+    private final List<Target> mTargets;
+
+    private final Map<Target, Palette.Swatch> mSelectedSwatches;
+    private final SparseBooleanArray mUsedColors;
+
+    private final Palette.Swatch mDominantSwatch;
+
+    Palette(List<Palette.Swatch> swatches, List<Target> targets) {
+        mSwatches = swatches;
+        mTargets = targets;
+
+        mUsedColors = new SparseBooleanArray();
+        mSelectedSwatches = new ArrayMap<>();
+
+        mDominantSwatch = findDominantSwatch();
+    }
+
+    /**
+     * Returns all of the swatches which make up the palette.
+     */
+    @NonNull
+    public List<Palette.Swatch> getSwatches() {
+        return Collections.unmodifiableList(mSwatches);
+    }
+
+    /**
+     * Returns the targets used to generate this palette.
+     */
+    @NonNull
+    public List<Target> getTargets() {
+        return Collections.unmodifiableList(mTargets);
+    }
+
+    /**
+     * Returns the most vibrant swatch in the palette. Might be null.
+     *
+     * @see Target#VIBRANT
+     */
+    @Nullable
+    public Palette.Swatch getVibrantSwatch() {
+        return getSwatchForTarget(Target.VIBRANT);
+    }
+
+    /**
+     * Returns a light and vibrant swatch from the palette. Might be null.
+     *
+     * @see Target#LIGHT_VIBRANT
+     */
+    @Nullable
+    public Palette.Swatch getLightVibrantSwatch() {
+        return getSwatchForTarget(Target.LIGHT_VIBRANT);
+    }
+
+    /**
+     * Returns a dark and vibrant swatch from the palette. Might be null.
+     *
+     * @see Target#DARK_VIBRANT
+     */
+    @Nullable
+    public Palette.Swatch getDarkVibrantSwatch() {
+        return getSwatchForTarget(Target.DARK_VIBRANT);
+    }
+
+    /**
+     * Returns a muted swatch from the palette. Might be null.
+     *
+     * @see Target#MUTED
+     */
+    @Nullable
+    public Palette.Swatch getMutedSwatch() {
+        return getSwatchForTarget(Target.MUTED);
+    }
+
+    /**
+     * Returns a muted and light swatch from the palette. Might be null.
+     *
+     * @see Target#LIGHT_MUTED
+     */
+    @Nullable
+    public Palette.Swatch getLightMutedSwatch() {
+        return getSwatchForTarget(Target.LIGHT_MUTED);
+    }
+
+    /**
+     * Returns a muted and dark swatch from the palette. Might be null.
+     *
+     * @see Target#DARK_MUTED
+     */
+    @Nullable
+    public Palette.Swatch getDarkMutedSwatch() {
+        return getSwatchForTarget(Target.DARK_MUTED);
+    }
+
+    /**
+     * Returns the most vibrant color in the palette as an RGB packed int.
+     *
+     * @param defaultColor value to return if the swatch isn't available
+     * @see #getVibrantSwatch()
+     */
+    @ColorInt
+    public int getVibrantColor(@ColorInt final int defaultColor) {
+        return getColorForTarget(Target.VIBRANT, defaultColor);
+    }
+
+    /**
+     * Returns a light and vibrant color from the palette as an RGB packed int.
+     *
+     * @param defaultColor value to return if the swatch isn't available
+     * @see #getLightVibrantSwatch()
+     */
+    @ColorInt
+    public int getLightVibrantColor(@ColorInt final int defaultColor) {
+        return getColorForTarget(Target.LIGHT_VIBRANT, defaultColor);
+    }
+
+    /**
+     * Returns a dark and vibrant color from the palette as an RGB packed int.
+     *
+     * @param defaultColor value to return if the swatch isn't available
+     * @see #getDarkVibrantSwatch()
+     */
+    @ColorInt
+    public int getDarkVibrantColor(@ColorInt final int defaultColor) {
+        return getColorForTarget(Target.DARK_VIBRANT, defaultColor);
+    }
+
+    /**
+     * Returns a muted color from the palette as an RGB packed int.
+     *
+     * @param defaultColor value to return if the swatch isn't available
+     * @see #getMutedSwatch()
+     */
+    @ColorInt
+    public int getMutedColor(@ColorInt final int defaultColor) {
+        return getColorForTarget(Target.MUTED, defaultColor);
+    }
+
+    /**
+     * Returns a muted and light color from the palette as an RGB packed int.
+     *
+     * @param defaultColor value to return if the swatch isn't available
+     * @see #getLightMutedSwatch()
+     */
+    @ColorInt
+    public int getLightMutedColor(@ColorInt final int defaultColor) {
+        return getColorForTarget(Target.LIGHT_MUTED, defaultColor);
+    }
+
+    /**
+     * Returns a muted and dark color from the palette as an RGB packed int.
+     *
+     * @param defaultColor value to return if the swatch isn't available
+     * @see #getDarkMutedSwatch()
+     */
+    @ColorInt
+    public int getDarkMutedColor(@ColorInt final int defaultColor) {
+        return getColorForTarget(Target.DARK_MUTED, defaultColor);
+    }
+
+    /**
+     * Returns the selected swatch for the given target from the palette, or {@code null} if one
+     * could not be found.
+     */
+    @Nullable
+    public Palette.Swatch getSwatchForTarget(@NonNull final Target target) {
+        return mSelectedSwatches.get(target);
+    }
+
+    /**
+     * Returns the selected color for the given target from the palette as an RGB packed int.
+     *
+     * @param defaultColor value to return if the swatch isn't available
+     */
+    @ColorInt
+    public int getColorForTarget(@NonNull final Target target, @ColorInt final int defaultColor) {
+        Palette.Swatch swatch = getSwatchForTarget(target);
+        return swatch != null ? swatch.getRgb() : defaultColor;
+    }
+
+    /**
+     * Returns the dominant swatch from the palette.
+     *
+     * <p>The dominant swatch is defined as the swatch with the greatest population (frequency)
+     * within the palette.</p>
+     */
+    @Nullable
+    public Palette.Swatch getDominantSwatch() {
+        return mDominantSwatch;
+    }
+
+    /**
+     * Returns the color of the dominant swatch from the palette, as an RGB packed int.
+     *
+     * @param defaultColor value to return if the swatch isn't available
+     * @see #getDominantSwatch()
+     */
+    @ColorInt
+    public int getDominantColor(@ColorInt int defaultColor) {
+        return mDominantSwatch != null ? mDominantSwatch.getRgb() : defaultColor;
+    }
+
+    void generate() {
+        // We need to make sure that the scored targets are generated first. This is so that
+        // inherited targets have something to inherit from
+        for (int i = 0, count = mTargets.size(); i < count; i++) {
+            final Target target = mTargets.get(i);
+            target.normalizeWeights();
+            mSelectedSwatches.put(target, generateScoredTarget(target));
+        }
+        // We now clear out the used colors
+        mUsedColors.clear();
+    }
+
+    private Palette.Swatch generateScoredTarget(final Target target) {
+        final Palette.Swatch maxScoreSwatch = getMaxScoredSwatchForTarget(target);
+        if (maxScoreSwatch != null && target.isExclusive()) {
+            // If we have a swatch, and the target is exclusive, add the color to the used list
+            mUsedColors.append(maxScoreSwatch.getRgb(), true);
+        }
+        return maxScoreSwatch;
+    }
+
+    private Palette.Swatch getMaxScoredSwatchForTarget(final Target target) {
+        float maxScore = 0;
+        Palette.Swatch maxScoreSwatch = null;
+        for (int i = 0, count = mSwatches.size(); i < count; i++) {
+            final Palette.Swatch swatch = mSwatches.get(i);
+            if (shouldBeScoredForTarget(swatch, target)) {
+                final float score = generateScore(swatch, target);
+                if (maxScoreSwatch == null || score > maxScore) {
+                    maxScoreSwatch = swatch;
+                    maxScore = score;
+                }
+            }
+        }
+        return maxScoreSwatch;
+    }
+
+    private boolean shouldBeScoredForTarget(final Palette.Swatch swatch, final Target target) {
+        // Check whether the HSL values are within the correct ranges, and this color hasn't
+        // been used yet.
+        final float hsl[] = swatch.getHsl();
+        return hsl[1] >= target.getMinimumSaturation() && hsl[1] <= target.getMaximumSaturation()
+                && hsl[2] >= target.getMinimumLightness() && hsl[2] <= target.getMaximumLightness()
+                && !mUsedColors.get(swatch.getRgb());
+    }
+
+    private float generateScore(Palette.Swatch swatch, Target target) {
+        final float[] hsl = swatch.getHsl();
+
+        float saturationScore = 0;
+        float luminanceScore = 0;
+        float populationScore = 0;
+
+        final int maxPopulation = mDominantSwatch != null ? mDominantSwatch.getPopulation() : 1;
+
+        if (target.getSaturationWeight() > 0) {
+            saturationScore = target.getSaturationWeight()
+                    * (1f - Math.abs(hsl[1] - target.getTargetSaturation()));
+        }
+        if (target.getLightnessWeight() > 0) {
+            luminanceScore = target.getLightnessWeight()
+                    * (1f - Math.abs(hsl[2] - target.getTargetLightness()));
+        }
+        if (target.getPopulationWeight() > 0) {
+            populationScore = target.getPopulationWeight()
+                    * (swatch.getPopulation() / (float) maxPopulation);
+        }
+
+        return saturationScore + luminanceScore + populationScore;
+    }
+
+    private Palette.Swatch findDominantSwatch() {
+        int maxPop = Integer.MIN_VALUE;
+        Palette.Swatch maxSwatch = null;
+        for (int i = 0, count = mSwatches.size(); i < count; i++) {
+            Palette.Swatch swatch = mSwatches.get(i);
+            if (swatch.getPopulation() > maxPop) {
+                maxSwatch = swatch;
+                maxPop = swatch.getPopulation();
+            }
+        }
+        return maxSwatch;
+    }
+
+    private static float[] copyHslValues(Palette.Swatch color) {
+        final float[] newHsl = new float[3];
+        System.arraycopy(color.getHsl(), 0, newHsl, 0, 3);
+        return newHsl;
+    }
+
+    /**
+     * Represents a color swatch generated from an image's palette. The RGB color can be retrieved
+     * by calling {@link #getRgb()}.
+     */
+    public static final class Swatch {
+        private final int mRed, mGreen, mBlue;
+        private final int mRgb;
+        private final int mPopulation;
+
+        private boolean mGeneratedTextColors;
+        private int mTitleTextColor;
+        private int mBodyTextColor;
+
+        private float[] mHsl;
+
+        public Swatch(@ColorInt int color, int population) {
+            mRed = Color.red(color);
+            mGreen = Color.green(color);
+            mBlue = Color.blue(color);
+            mRgb = color;
+            mPopulation = population;
+        }
+
+        Swatch(int red, int green, int blue, int population) {
+            mRed = red;
+            mGreen = green;
+            mBlue = blue;
+            mRgb = Color.rgb(red, green, blue);
+            mPopulation = population;
+        }
+
+        Swatch(float[] hsl, int population) {
+            this(ColorUtils.HSLToColor(hsl), population);
+            mHsl = hsl;
+        }
+
+        /**
+         * @return this swatch's RGB color value
+         */
+        @ColorInt
+        public int getRgb() {
+            return mRgb;
+        }
+
+        /**
+         * Return this swatch's HSL values.
+         *     hsv[0] is Hue [0 .. 360)
+         *     hsv[1] is Saturation [0...1]
+         *     hsv[2] is Lightness [0...1]
+         */
+        public float[] getHsl() {
+            if (mHsl == null) {
+                mHsl = new float[3];
+            }
+            ColorUtils.RGBToHSL(mRed, mGreen, mBlue, mHsl);
+            return mHsl;
+        }
+
+        /**
+         * @return the number of pixels represented by this swatch
+         */
+        public int getPopulation() {
+            return mPopulation;
+        }
+
+        /**
+         * Returns an appropriate color to use for any 'title' text which is displayed over this
+         * {@link Palette.Swatch}'s color. This color is guaranteed to have sufficient contrast.
+         */
+        @ColorInt
+        public int getTitleTextColor() {
+            ensureTextColorsGenerated();
+            return mTitleTextColor;
+        }
+
+        /**
+         * Returns an appropriate color to use for any 'body' text which is displayed over this
+         * {@link Palette.Swatch}'s color. This color is guaranteed to have sufficient contrast.
+         */
+        @ColorInt
+        public int getBodyTextColor() {
+            ensureTextColorsGenerated();
+            return mBodyTextColor;
+        }
+
+        private void ensureTextColorsGenerated() {
+            if (!mGeneratedTextColors) {
+                // First check white, as most colors will be dark
+                final int lightBodyAlpha = ColorUtils.calculateMinimumAlpha(
+                        Color.WHITE, mRgb, MIN_CONTRAST_BODY_TEXT);
+                final int lightTitleAlpha = ColorUtils.calculateMinimumAlpha(
+                        Color.WHITE, mRgb, MIN_CONTRAST_TITLE_TEXT);
+
+                if (lightBodyAlpha != -1 && lightTitleAlpha != -1) {
+                    // If we found valid light values, use them and return
+                    mBodyTextColor = ColorUtils.setAlphaComponent(Color.WHITE, lightBodyAlpha);
+                    mTitleTextColor = ColorUtils.setAlphaComponent(Color.WHITE, lightTitleAlpha);
+                    mGeneratedTextColors = true;
+                    return;
+                }
+
+                final int darkBodyAlpha = ColorUtils.calculateMinimumAlpha(
+                        Color.BLACK, mRgb, MIN_CONTRAST_BODY_TEXT);
+                final int darkTitleAlpha = ColorUtils.calculateMinimumAlpha(
+                        Color.BLACK, mRgb, MIN_CONTRAST_TITLE_TEXT);
+
+                if (darkBodyAlpha != -1 && darkTitleAlpha != -1) {
+                    // If we found valid dark values, use them and return
+                    mBodyTextColor = ColorUtils.setAlphaComponent(Color.BLACK, darkBodyAlpha);
+                    mTitleTextColor = ColorUtils.setAlphaComponent(Color.BLACK, darkTitleAlpha);
+                    mGeneratedTextColors = true;
+                    return;
+                }
+
+                // If we reach here then we can not find title and body values which use the same
+                // lightness, we need to use mismatched values
+                mBodyTextColor = lightBodyAlpha != -1
+                        ? ColorUtils.setAlphaComponent(Color.WHITE, lightBodyAlpha)
+                        : ColorUtils.setAlphaComponent(Color.BLACK, darkBodyAlpha);
+                mTitleTextColor = lightTitleAlpha != -1
+                        ? ColorUtils.setAlphaComponent(Color.WHITE, lightTitleAlpha)
+                        : ColorUtils.setAlphaComponent(Color.BLACK, darkTitleAlpha);
+                mGeneratedTextColors = true;
+            }
+        }
+
+        @Override
+        public String toString() {
+            return new StringBuilder(getClass().getSimpleName())
+                    .append(" [RGB: #").append(Integer.toHexString(getRgb())).append(']')
+                    .append(" [HSL: ").append(Arrays.toString(getHsl())).append(']')
+                    .append(" [Population: ").append(mPopulation).append(']')
+                    .append(" [Title Text: #").append(Integer.toHexString(getTitleTextColor()))
+                    .append(']')
+                    .append(" [Body Text: #").append(Integer.toHexString(getBodyTextColor()))
+                    .append(']').toString();
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass()) {
+                return false;
+            }
+
+            Palette.Swatch
+                    swatch = (Palette.Swatch) o;
+            return mPopulation == swatch.mPopulation && mRgb == swatch.mRgb;
+        }
+
+        @Override
+        public int hashCode() {
+            return 31 * mRgb + mPopulation;
+        }
+    }
+
+    /**
+     * Builder class for generating {@link Palette} instances.
+     */
+    public static final class Builder {
+        private final List<Palette.Swatch> mSwatches;
+        private final Bitmap mBitmap;
+
+        private final List<Target> mTargets = new ArrayList<>();
+
+        private int mMaxColors = DEFAULT_CALCULATE_NUMBER_COLORS;
+        private int mResizeArea = DEFAULT_RESIZE_BITMAP_AREA;
+        private int mResizeMaxDimension = -1;
+
+        private final List<Palette.Filter> mFilters = new ArrayList<>();
+        private Rect mRegion;
+
+        /**
+         * Construct a new {@link Palette.Builder} using a source {@link Bitmap}
+         */
+        public Builder(Bitmap bitmap) {
+            if (bitmap == null || bitmap.isRecycled()) {
+                throw new IllegalArgumentException("Bitmap is not valid");
+            }
+            mFilters.add(DEFAULT_FILTER);
+            mBitmap = bitmap;
+            mSwatches = null;
+
+            // Add the default targets
+            mTargets.add(Target.LIGHT_VIBRANT);
+            mTargets.add(Target.VIBRANT);
+            mTargets.add(Target.DARK_VIBRANT);
+            mTargets.add(Target.LIGHT_MUTED);
+            mTargets.add(Target.MUTED);
+            mTargets.add(Target.DARK_MUTED);
+        }
+
+        /**
+         * Construct a new {@link Palette.Builder} using a list of {@link Palette.Swatch} instances.
+         * Typically only used for testing.
+         */
+        public Builder(List<Palette.Swatch> swatches) {
+            if (swatches == null || swatches.isEmpty()) {
+                throw new IllegalArgumentException("List of Swatches is not valid");
+            }
+            mFilters.add(DEFAULT_FILTER);
+            mSwatches = swatches;
+            mBitmap = null;
+        }
+
+        /**
+         * Set the maximum number of colors to use in the quantization step when using a
+         * {@link android.graphics.Bitmap} as the source.
+         * <p>
+         * Good values for depend on the source image type. For landscapes, good values are in
+         * the range 10-16. For images which are largely made up of people's faces then this
+         * value should be increased to ~24.
+         */
+        @NonNull
+        public Palette.Builder maximumColorCount(int colors) {
+            mMaxColors = colors;
+            return this;
+        }
+
+        /**
+         * Set the resize value when using a {@link android.graphics.Bitmap} as the source.
+         * If the bitmap's largest dimension is greater than the value specified, then the bitmap
+         * will be resized so that its largest dimension matches {@code maxDimension}. If the
+         * bitmap is smaller or equal, the original is used as-is.
+         *
+         * @deprecated Using {@link #resizeBitmapArea(int)} is preferred since it can handle
+         * abnormal aspect ratios more gracefully.
+         *
+         * @param maxDimension the number of pixels that the max dimension should be scaled down to,
+         *                     or any value <= 0 to disable resizing.
+         */
+        @NonNull
+        @Deprecated
+        public Palette.Builder resizeBitmapSize(final int maxDimension) {
+            mResizeMaxDimension = maxDimension;
+            mResizeArea = -1;
+            return this;
+        }
+
+        /**
+         * Set the resize value when using a {@link android.graphics.Bitmap} as the source.
+         * If the bitmap's area is greater than the value specified, then the bitmap
+         * will be resized so that its area matches {@code area}. If the
+         * bitmap is smaller or equal, the original is used as-is.
+         * <p>
+         * This value has a large effect on the processing time. The larger the resized image is,
+         * the greater time it will take to generate the palette. The smaller the image is, the
+         * more detail is lost in the resulting image and thus less precision for color selection.
+         *
+         * @param area the number of pixels that the intermediary scaled down Bitmap should cover,
+         *             or any value <= 0 to disable resizing.
+         */
+        @NonNull
+        public Palette.Builder resizeBitmapArea(final int area) {
+            mResizeArea = area;
+            mResizeMaxDimension = -1;
+            return this;
+        }
+
+        /**
+         * Clear all added filters. This includes any default filters added automatically by
+         * {@link Palette}.
+         */
+        @NonNull
+        public Palette.Builder clearFilters() {
+            mFilters.clear();
+            return this;
+        }
+
+        /**
+         * Add a filter to be able to have fine grained control over which colors are
+         * allowed in the resulting palette.
+         *
+         * @param filter filter to add.
+         */
+        @NonNull
+        public Palette.Builder addFilter(
+                Palette.Filter filter) {
+            if (filter != null) {
+                mFilters.add(filter);
+            }
+            return this;
+        }
+
+        /**
+         * Set a region of the bitmap to be used exclusively when calculating the palette.
+         * <p>This only works when the original input is a {@link Bitmap}.</p>
+         *
+         * @param left The left side of the rectangle used for the region.
+         * @param top The top of the rectangle used for the region.
+         * @param right The right side of the rectangle used for the region.
+         * @param bottom The bottom of the rectangle used for the region.
+         */
+        @NonNull
+        public Palette.Builder setRegion(int left, int top, int right, int bottom) {
+            if (mBitmap != null) {
+                if (mRegion == null) mRegion = new Rect();
+                // Set the Rect to be initially the whole Bitmap
+                mRegion.set(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
+                // Now just get the intersection with the region
+                if (!mRegion.intersect(left, top, right, bottom)) {
+                    throw new IllegalArgumentException("The given region must intersect with "
+                            + "the Bitmap's dimensions.");
+                }
+            }
+            return this;
+        }
+
+        /**
+         * Clear any previously region set via {@link #setRegion(int, int, int, int)}.
+         */
+        @NonNull
+        public Palette.Builder clearRegion() {
+            mRegion = null;
+            return this;
+        }
+
+        /**
+         * Add a target profile to be generated in the palette.
+         *
+         * <p>You can retrieve the result via {@link Palette#getSwatchForTarget(Target)}.</p>
+         */
+        @NonNull
+        public Palette.Builder addTarget(@NonNull final Target target) {
+            if (!mTargets.contains(target)) {
+                mTargets.add(target);
+            }
+            return this;
+        }
+
+        /**
+         * Clear all added targets. This includes any default targets added automatically by
+         * {@link Palette}.
+         */
+        @NonNull
+        public Palette.Builder clearTargets() {
+            if (mTargets != null) {
+                mTargets.clear();
+            }
+            return this;
+        }
+
+        /**
+         * Generate and return the {@link Palette} synchronously.
+         */
+        @NonNull
+        public Palette generate() {
+            final TimingLogger logger = LOG_TIMINGS
+                    ? new TimingLogger(LOG_TAG, "Generation")
+                    : null;
+
+            List<Palette.Swatch> swatches;
+
+            if (mBitmap != null) {
+                // We have a Bitmap so we need to use quantization to reduce the number of colors
+
+                // First we'll scale down the bitmap if needed
+                final Bitmap bitmap = scaleBitmapDown(mBitmap);
+
+                if (logger != null) {
+                    logger.addSplit("Processed Bitmap");
+                }
+
+                final Rect region = mRegion;
+                if (bitmap != mBitmap && region != null) {
+                    // If we have a scaled bitmap and a selected region, we need to scale down the
+                    // region to match the new scale
+                    final double scale = bitmap.getWidth() / (double) mBitmap.getWidth();
+                    region.left = (int) Math.floor(region.left * scale);
+                    region.top = (int) Math.floor(region.top * scale);
+                    region.right = Math.min((int) Math.ceil(region.right * scale),
+                            bitmap.getWidth());
+                    region.bottom = Math.min((int) Math.ceil(region.bottom * scale),
+                            bitmap.getHeight());
+                }
+
+                // Now generate a quantizer from the Bitmap
+                final ColorCutQuantizer quantizer = new ColorCutQuantizer(
+                        getPixelsFromBitmap(bitmap),
+                        mMaxColors,
+                        mFilters.isEmpty() ? null : mFilters.toArray(new Palette.Filter[mFilters.size()]));
+
+                // If created a new bitmap, recycle it
+                if (bitmap != mBitmap) {
+                    bitmap.recycle();
+                }
+
+                swatches = quantizer.getQuantizedColors();
+
+                if (logger != null) {
+                    logger.addSplit("Color quantization completed");
+                }
+            } else {
+                // Else we're using the provided swatches
+                swatches = mSwatches;
+            }
+
+            // Now create a Palette instance
+            final Palette p = new Palette(swatches, mTargets);
+            // And make it generate itself
+            p.generate();
+
+            if (logger != null) {
+                logger.addSplit("Created Palette");
+                logger.dumpToLog();
+            }
+
+            return p;
+        }
+
+        /**
+         * Generate the {@link Palette} asynchronously. The provided listener's
+         * {@link Palette.PaletteAsyncListener#onGenerated} method will be called with the palette when
+         * generated.
+         */
+        @NonNull
+        public AsyncTask<Bitmap, Void, Palette> generate(final Palette.PaletteAsyncListener listener) {
+            if (listener == null) {
+                throw new IllegalArgumentException("listener can not be null");
+            }
+
+            return new AsyncTask<Bitmap, Void, Palette>() {
+                @Override
+                protected Palette doInBackground(Bitmap... params) {
+                    try {
+                        return generate();
+                    } catch (Exception e) {
+                        Log.e(LOG_TAG, "Exception thrown during async generate", e);
+                        return null;
+                    }
+                }
+
+                @Override
+                protected void onPostExecute(Palette colorExtractor) {
+                    listener.onGenerated(colorExtractor);
+                }
+            }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, mBitmap);
+        }
+
+        private int[] getPixelsFromBitmap(Bitmap bitmap) {
+            final int bitmapWidth = bitmap.getWidth();
+            final int bitmapHeight = bitmap.getHeight();
+            final int[] pixels = new int[bitmapWidth * bitmapHeight];
+            bitmap.getPixels(pixels, 0, bitmapWidth, 0, 0, bitmapWidth, bitmapHeight);
+
+            if (mRegion == null) {
+                // If we don't have a region, return all of the pixels
+                return pixels;
+            } else {
+                // If we do have a region, lets create a subset array containing only the region's
+                // pixels
+                final int regionWidth = mRegion.width();
+                final int regionHeight = mRegion.height();
+                // pixels contains all of the pixels, so we need to iterate through each row and
+                // copy the regions pixels into a new smaller array
+                final int[] subsetPixels = new int[regionWidth * regionHeight];
+                for (int row = 0; row < regionHeight; row++) {
+                    System.arraycopy(pixels, ((row + mRegion.top) * bitmapWidth) + mRegion.left,
+                            subsetPixels, row * regionWidth, regionWidth);
+                }
+                return subsetPixels;
+            }
+        }
+
+        /**
+         * Scale the bitmap down as needed.
+         */
+        private Bitmap scaleBitmapDown(final Bitmap bitmap) {
+            double scaleRatio = -1;
+
+            if (mResizeArea > 0) {
+                final int bitmapArea = bitmap.getWidth() * bitmap.getHeight();
+                if (bitmapArea > mResizeArea) {
+                    scaleRatio = Math.sqrt(mResizeArea / (double) bitmapArea);
+                }
+            } else if (mResizeMaxDimension > 0) {
+                final int maxDimension = Math.max(bitmap.getWidth(), bitmap.getHeight());
+                if (maxDimension > mResizeMaxDimension) {
+                    scaleRatio = mResizeMaxDimension / (double) maxDimension;
+                }
+            }
+
+            if (scaleRatio <= 0) {
+                // Scaling has been disabled or not needed so just return the Bitmap
+                return bitmap;
+            }
+
+            return Bitmap.createScaledBitmap(bitmap,
+                    (int) Math.ceil(bitmap.getWidth() * scaleRatio),
+                    (int) Math.ceil(bitmap.getHeight() * scaleRatio),
+                    false);
+        }
+    }
+
+    /**
+     * A Filter provides a mechanism for exercising fine-grained control over which colors
+     * are valid within a resulting {@link Palette}.
+     */
+    public interface Filter {
+        /**
+         * Hook to allow clients to be able filter colors from resulting palette.
+         *
+         * @param rgb the color in RGB888.
+         * @param hsl HSL representation of the color.
+         *
+         * @return true if the color is allowed, false if not.
+         *
+         * @see Palette.Builder#addFilter(Palette.Filter)
+         */
+        boolean isAllowed(int rgb, float[] hsl);
+    }
+
+    /**
+     * The default filter.
+     */
+    static final Palette.Filter
+            DEFAULT_FILTER = new Palette.Filter() {
+        private static final float BLACK_MAX_LIGHTNESS = 0.05f;
+        private static final float WHITE_MIN_LIGHTNESS = 0.95f;
+
+        @Override
+        public boolean isAllowed(int rgb, float[] hsl) {
+            return !isWhite(hsl) && !isBlack(hsl) && !isNearRedILine(hsl);
+        }
+
+        /**
+         * @return true if the color represents a color which is close to black.
+         */
+        private boolean isBlack(float[] hslColor) {
+            return hslColor[2] <= BLACK_MAX_LIGHTNESS;
+        }
+
+        /**
+         * @return true if the color represents a color which is close to white.
+         */
+        private boolean isWhite(float[] hslColor) {
+            return hslColor[2] >= WHITE_MIN_LIGHTNESS;
+        }
+
+        /**
+         * @return true if the color lies close to the red side of the I line.
+         */
+        private boolean isNearRedILine(float[] hslColor) {
+            return hslColor[0] >= 10f && hslColor[0] <= 37f && hslColor[1] <= 0.82f;
+        }
+    };
+}
diff --git a/core/java/com/android/internal/graphics/palette/Target.java b/core/java/com/android/internal/graphics/palette/Target.java
new file mode 100644
index 0000000..0540d80
--- /dev/null
+++ b/core/java/com/android/internal/graphics/palette/Target.java
@@ -0,0 +1,435 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.internal.graphics.palette;
+
+/*
+ * Copyright 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.
+ */
+
+import android.annotation.FloatRange;
+
+/**
+ * Copied from: frameworks/support/v7/palette/src/main/java/android/support/v7/graphics/Target.java
+ *
+ * A class which allows custom selection of colors in a {@link Palette}'s generation. Instances
+ * can be created via the {@link android.support.v7.graphics.Target.Builder} class.
+ *
+ * <p>To use the target, use the {@link Palette.Builder#addTarget(Target)} API when building a
+ * Palette.</p>
+ */
+public final class Target {
+
+    private static final float TARGET_DARK_LUMA = 0.26f;
+    private static final float MAX_DARK_LUMA = 0.45f;
+
+    private static final float MIN_LIGHT_LUMA = 0.55f;
+    private static final float TARGET_LIGHT_LUMA = 0.74f;
+
+    private static final float MIN_NORMAL_LUMA = 0.3f;
+    private static final float TARGET_NORMAL_LUMA = 0.5f;
+    private static final float MAX_NORMAL_LUMA = 0.7f;
+
+    private static final float TARGET_MUTED_SATURATION = 0.3f;
+    private static final float MAX_MUTED_SATURATION = 0.4f;
+
+    private static final float TARGET_VIBRANT_SATURATION = 1f;
+    private static final float MIN_VIBRANT_SATURATION = 0.35f;
+
+    private static final float WEIGHT_SATURATION = 0.24f;
+    private static final float WEIGHT_LUMA = 0.52f;
+    private static final float WEIGHT_POPULATION = 0.24f;
+
+    static final int INDEX_MIN = 0;
+    static final int INDEX_TARGET = 1;
+    static final int INDEX_MAX = 2;
+
+    static final int INDEX_WEIGHT_SAT = 0;
+    static final int INDEX_WEIGHT_LUMA = 1;
+    static final int INDEX_WEIGHT_POP = 2;
+
+    /**
+     * A target which has the characteristics of a vibrant color which is light in luminance.
+     */
+    public static final Target LIGHT_VIBRANT;
+
+    /**
+     * A target which has the characteristics of a vibrant color which is neither light or dark.
+     */
+    public static final Target VIBRANT;
+
+    /**
+     * A target which has the characteristics of a vibrant color which is dark in luminance.
+     */
+    public static final Target DARK_VIBRANT;
+
+    /**
+     * A target which has the characteristics of a muted color which is light in luminance.
+     */
+    public static final Target LIGHT_MUTED;
+
+    /**
+     * A target which has the characteristics of a muted color which is neither light or dark.
+     */
+    public static final Target MUTED;
+
+    /**
+     * A target which has the characteristics of a muted color which is dark in luminance.
+     */
+    public static final Target DARK_MUTED;
+
+    static {
+        LIGHT_VIBRANT = new Target();
+        setDefaultLightLightnessValues(LIGHT_VIBRANT);
+        setDefaultVibrantSaturationValues(LIGHT_VIBRANT);
+
+        VIBRANT = new Target();
+        setDefaultNormalLightnessValues(VIBRANT);
+        setDefaultVibrantSaturationValues(VIBRANT);
+
+        DARK_VIBRANT = new Target();
+        setDefaultDarkLightnessValues(DARK_VIBRANT);
+        setDefaultVibrantSaturationValues(DARK_VIBRANT);
+
+        LIGHT_MUTED = new Target();
+        setDefaultLightLightnessValues(LIGHT_MUTED);
+        setDefaultMutedSaturationValues(LIGHT_MUTED);
+
+        MUTED = new Target();
+        setDefaultNormalLightnessValues(MUTED);
+        setDefaultMutedSaturationValues(MUTED);
+
+        DARK_MUTED = new Target();
+        setDefaultDarkLightnessValues(DARK_MUTED);
+        setDefaultMutedSaturationValues(DARK_MUTED);
+    }
+
+    final float[] mSaturationTargets = new float[3];
+    final float[] mLightnessTargets = new float[3];
+    final float[] mWeights = new float[3];
+    boolean mIsExclusive = true; // default to true
+
+    Target() {
+        setTargetDefaultValues(mSaturationTargets);
+        setTargetDefaultValues(mLightnessTargets);
+        setDefaultWeights();
+    }
+
+    Target(Target from) {
+        System.arraycopy(from.mSaturationTargets, 0, mSaturationTargets, 0,
+                mSaturationTargets.length);
+        System.arraycopy(from.mLightnessTargets, 0, mLightnessTargets, 0,
+                mLightnessTargets.length);
+        System.arraycopy(from.mWeights, 0, mWeights, 0, mWeights.length);
+    }
+
+    /**
+     * The minimum saturation value for this target.
+     */
+    @FloatRange(from = 0, to = 1)
+    public float getMinimumSaturation() {
+        return mSaturationTargets[INDEX_MIN];
+    }
+
+    /**
+     * The target saturation value for this target.
+     */
+    @FloatRange(from = 0, to = 1)
+    public float getTargetSaturation() {
+        return mSaturationTargets[INDEX_TARGET];
+    }
+
+    /**
+     * The maximum saturation value for this target.
+     */
+    @FloatRange(from = 0, to = 1)
+    public float getMaximumSaturation() {
+        return mSaturationTargets[INDEX_MAX];
+    }
+
+    /**
+     * The minimum lightness value for this target.
+     */
+    @FloatRange(from = 0, to = 1)
+    public float getMinimumLightness() {
+        return mLightnessTargets[INDEX_MIN];
+    }
+
+    /**
+     * The target lightness value for this target.
+     */
+    @FloatRange(from = 0, to = 1)
+    public float getTargetLightness() {
+        return mLightnessTargets[INDEX_TARGET];
+    }
+
+    /**
+     * The maximum lightness value for this target.
+     */
+    @FloatRange(from = 0, to = 1)
+    public float getMaximumLightness() {
+        return mLightnessTargets[INDEX_MAX];
+    }
+
+    /**
+     * Returns the weight of importance that this target places on a color's saturation within
+     * the image.
+     *
+     * <p>The larger the weight, relative to the other weights, the more important that a color
+     * being close to the target value has on selection.</p>
+     *
+     * @see #getTargetSaturation()
+     */
+    public float getSaturationWeight() {
+        return mWeights[INDEX_WEIGHT_SAT];
+    }
+
+    /**
+     * Returns the weight of importance that this target places on a color's lightness within
+     * the image.
+     *
+     * <p>The larger the weight, relative to the other weights, the more important that a color
+     * being close to the target value has on selection.</p>
+     *
+     * @see #getTargetLightness()
+     */
+    public float getLightnessWeight() {
+        return mWeights[INDEX_WEIGHT_LUMA];
+    }
+
+    /**
+     * Returns the weight of importance that this target places on a color's population within
+     * the image.
+     *
+     * <p>The larger the weight, relative to the other weights, the more important that a
+     * color's population being close to the most populous has on selection.</p>
+     */
+    public float getPopulationWeight() {
+        return mWeights[INDEX_WEIGHT_POP];
+    }
+
+    /**
+     * Returns whether any color selected for this target is exclusive for this target only.
+     *
+     * <p>If false, then the color can be selected for other targets.</p>
+     */
+    public boolean isExclusive() {
+        return mIsExclusive;
+    }
+
+    private static void setTargetDefaultValues(final float[] values) {
+        values[INDEX_MIN] = 0f;
+        values[INDEX_TARGET] = 0.5f;
+        values[INDEX_MAX] = 1f;
+    }
+
+    private void setDefaultWeights() {
+        mWeights[INDEX_WEIGHT_SAT] = WEIGHT_SATURATION;
+        mWeights[INDEX_WEIGHT_LUMA] = WEIGHT_LUMA;
+        mWeights[INDEX_WEIGHT_POP] = WEIGHT_POPULATION;
+    }
+
+    void normalizeWeights() {
+        float sum = 0;
+        for (int i = 0, z = mWeights.length; i < z; i++) {
+            float weight = mWeights[i];
+            if (weight > 0) {
+                sum += weight;
+            }
+        }
+        if (sum != 0) {
+            for (int i = 0, z = mWeights.length; i < z; i++) {
+                if (mWeights[i] > 0) {
+                    mWeights[i] /= sum;
+                }
+            }
+        }
+    }
+
+    private static void setDefaultDarkLightnessValues(Target target) {
+        target.mLightnessTargets[INDEX_TARGET] = TARGET_DARK_LUMA;
+        target.mLightnessTargets[INDEX_MAX] = MAX_DARK_LUMA;
+    }
+
+    private static void setDefaultNormalLightnessValues(Target target) {
+        target.mLightnessTargets[INDEX_MIN] = MIN_NORMAL_LUMA;
+        target.mLightnessTargets[INDEX_TARGET] = TARGET_NORMAL_LUMA;
+        target.mLightnessTargets[INDEX_MAX] = MAX_NORMAL_LUMA;
+    }
+
+    private static void setDefaultLightLightnessValues(Target target) {
+        target.mLightnessTargets[INDEX_MIN] = MIN_LIGHT_LUMA;
+        target.mLightnessTargets[INDEX_TARGET] = TARGET_LIGHT_LUMA;
+    }
+
+    private static void setDefaultVibrantSaturationValues(Target target) {
+        target.mSaturationTargets[INDEX_MIN] = MIN_VIBRANT_SATURATION;
+        target.mSaturationTargets[INDEX_TARGET] = TARGET_VIBRANT_SATURATION;
+    }
+
+    private static void setDefaultMutedSaturationValues(Target target) {
+        target.mSaturationTargets[INDEX_TARGET] = TARGET_MUTED_SATURATION;
+        target.mSaturationTargets[INDEX_MAX] = MAX_MUTED_SATURATION;
+    }
+
+    /**
+     * Builder class for generating custom {@link Target} instances.
+     */
+    public final static class Builder {
+        private final Target mTarget;
+
+        /**
+         * Create a new {@link Target} builder from scratch.
+         */
+        public Builder() {
+            mTarget = new Target();
+        }
+
+        /**
+         * Create a new builder based on an existing {@link Target}.
+         */
+        public Builder(Target target) {
+            mTarget = new Target(target);
+        }
+
+        /**
+         * Set the minimum saturation value for this target.
+         */
+        public Target.Builder setMinimumSaturation(@FloatRange(from = 0, to = 1) float value) {
+            mTarget.mSaturationTargets[INDEX_MIN] = value;
+            return this;
+        }
+
+        /**
+         * Set the target/ideal saturation value for this target.
+         */
+        public Target.Builder setTargetSaturation(@FloatRange(from = 0, to = 1) float value) {
+            mTarget.mSaturationTargets[INDEX_TARGET] = value;
+            return this;
+        }
+
+        /**
+         * Set the maximum saturation value for this target.
+         */
+        public Target.Builder setMaximumSaturation(@FloatRange(from = 0, to = 1) float value) {
+            mTarget.mSaturationTargets[INDEX_MAX] = value;
+            return this;
+        }
+
+        /**
+         * Set the minimum lightness value for this target.
+         */
+        public Target.Builder setMinimumLightness(@FloatRange(from = 0, to = 1) float value) {
+            mTarget.mLightnessTargets[INDEX_MIN] = value;
+            return this;
+        }
+
+        /**
+         * Set the target/ideal lightness value for this target.
+         */
+        public Target.Builder setTargetLightness(@FloatRange(from = 0, to = 1) float value) {
+            mTarget.mLightnessTargets[INDEX_TARGET] = value;
+            return this;
+        }
+
+        /**
+         * Set the maximum lightness value for this target.
+         */
+        public Target.Builder setMaximumLightness(@FloatRange(from = 0, to = 1) float value) {
+            mTarget.mLightnessTargets[INDEX_MAX] = value;
+            return this;
+        }
+
+        /**
+         * Set the weight of importance that this target will place on saturation values.
+         *
+         * <p>The larger the weight, relative to the other weights, the more important that a color
+         * being close to the target value has on selection.</p>
+         *
+         * <p>A weight of 0 means that it has no weight, and thus has no
+         * bearing on the selection.</p>
+         *
+         * @see #setTargetSaturation(float)
+         */
+        public Target.Builder setSaturationWeight(@FloatRange(from = 0) float weight) {
+            mTarget.mWeights[INDEX_WEIGHT_SAT] = weight;
+            return this;
+        }
+
+        /**
+         * Set the weight of importance that this target will place on lightness values.
+         *
+         * <p>The larger the weight, relative to the other weights, the more important that a color
+         * being close to the target value has on selection.</p>
+         *
+         * <p>A weight of 0 means that it has no weight, and thus has no
+         * bearing on the selection.</p>
+         *
+         * @see #setTargetLightness(float)
+         */
+        public Target.Builder setLightnessWeight(@FloatRange(from = 0) float weight) {
+            mTarget.mWeights[INDEX_WEIGHT_LUMA] = weight;
+            return this;
+        }
+
+        /**
+         * Set the weight of importance that this target will place on a color's population within
+         * the image.
+         *
+         * <p>The larger the weight, relative to the other weights, the more important that a
+         * color's population being close to the most populous has on selection.</p>
+         *
+         * <p>A weight of 0 means that it has no weight, and thus has no
+         * bearing on the selection.</p>
+         */
+        public Target.Builder setPopulationWeight(@FloatRange(from = 0) float weight) {
+            mTarget.mWeights[INDEX_WEIGHT_POP] = weight;
+            return this;
+        }
+
+        /**
+         * Set whether any color selected for this target is exclusive to this target only.
+         * Defaults to true.
+         *
+         * @param exclusive true if any the color is exclusive to this target, or false is the
+         *                  color can be selected for other targets.
+         */
+        public Target.Builder setExclusive(boolean exclusive) {
+            mTarget.mIsExclusive = exclusive;
+            return this;
+        }
+
+        /**
+         * Builds and returns the resulting {@link Target}.
+         */
+        public Target build() {
+            return mTarget;
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/os/WebViewZygoteInit.java b/core/java/com/android/internal/os/WebViewZygoteInit.java
index cc3f58c..e28079f 100644
--- a/core/java/com/android/internal/os/WebViewZygoteInit.java
+++ b/core/java/com/android/internal/os/WebViewZygoteInit.java
@@ -70,6 +70,7 @@
         @Override
         protected boolean handlePreloadPackage(String packagePath, String libsPath,
                                                String cacheKey) {
+            Log.i(TAG, "Beginning package preload");
             // Ask ApplicationLoaders to create and cache a classloader for the WebView APK so that
             // our children will reuse the same classloader instead of creating their own.
             // This enables us to preload Java and native code in the webview zygote process and
@@ -97,6 +98,7 @@
                      IllegalAccessException | InvocationTargetException e) {
                 Log.e(TAG, "Exception while preloading package", e);
             }
+            Log.i(TAG, "Package preload done");
             return false;
         }
     }
diff --git a/core/java/com/android/internal/util/NotificationColorUtil.java b/core/java/com/android/internal/util/NotificationColorUtil.java
index 44b21b4..5cb66e5 100644
--- a/core/java/com/android/internal/util/NotificationColorUtil.java
+++ b/core/java/com/android/internal/util/NotificationColorUtil.java
@@ -460,13 +460,25 @@
         if (backgroundColor == Notification.COLOR_DEFAULT) {
             return context.getColor(com.android.internal.R.color.notification_action_list);
         }
-        boolean useDark = shouldUseDark(backgroundColor);
+        return getShiftedColor(backgroundColor, 7);
+    }
+
+    /**
+     * Get a color that stays in the same tint, but darkens or lightens it by a certain
+     * amount.
+     * This also looks at the lightness of the provided color and shifts it appropriately.
+     *
+     * @param color the base color to use
+     * @param amount the amount from 1 to 100 how much to modify the color
+     * @return the now color that was modified
+     */
+    public static int getShiftedColor(int color, int amount) {
         final double[] result = ColorUtilsFromCompat.getTempDouble3Array();
-        ColorUtilsFromCompat.colorToLAB(backgroundColor, result);
-        if (useDark && result[0] < 97 || !useDark && result[0] < 4) {
-            result[0] = Math.min(100, result[0] + 7);
+        ColorUtilsFromCompat.colorToLAB(color, result);
+        if (result[0] >= 4) {
+            result[0] = Math.max(0, result[0] - amount);
         } else {
-            result[0] = Math.max(0, result[0] - 7);
+            result[0] = Math.min(100, result[0] + amount);
         }
         return ColorUtilsFromCompat.LABToColor(result[0], result[1], result[2]);
     }
diff --git a/core/java/com/android/internal/widget/NotificationExpandButton.java b/core/java/com/android/internal/widget/NotificationExpandButton.java
index c64ace4..b702898 100644
--- a/core/java/com/android/internal/widget/NotificationExpandButton.java
+++ b/core/java/com/android/internal/widget/NotificationExpandButton.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.graphics.Rect;
 import android.util.AttributeSet;
+import android.view.View;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.Button;
 import android.widget.ImageView;
@@ -30,6 +31,8 @@
  */
 @RemoteViews.RemoteView
 public class NotificationExpandButton extends ImageView {
+    private View mLabeledBy;
+
     public NotificationExpandButton(Context context) {
         super(context);
     }
@@ -66,5 +69,12 @@
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(info);
         info.setClassName(Button.class.getName());
+        if (mLabeledBy != null) {
+            info.setLabeledBy(mLabeledBy);
+        }
+    }
+
+    public void setLabeledBy(View labeledBy) {
+        mLabeledBy = labeledBy;
     }
 }
diff --git a/core/java/com/android/server/BootReceiver.java b/core/java/com/android/server/BootReceiver.java
index 4a9a2c5..c1f443f 100644
--- a/core/java/com/android/server/BootReceiver.java
+++ b/core/java/com/android/server/BootReceiver.java
@@ -35,6 +35,7 @@
 import android.util.Slog;
 import android.util.Xml;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastXmlSerializer;
@@ -89,6 +90,11 @@
 
     // example: fs_stat,/dev/block/platform/soc/by-name/userdata,0x5
     private static final String FS_STAT_PATTERN = "fs_stat,[^,]*/([^/,]+),(0x[0-9a-fA-F]+)";
+    private static final int FS_STAT_FS_FIXED = 0x400; // should match with fs_mgr.cpp:FsStatFlags
+    private static final String FSCK_PASS_PATTERN = "Pass ([1-9]E?):";
+    private static final String FSCK_TREE_OPTIMIZATION_PATTERN =
+            "Inode [0-9]+ extent tree.*could be shorter";
+    private static final String FSCK_FS_MODIFIED = "FILE SYSTEM WAS MODIFIED";
     // ro.boottime.init.mount_all. + postfix for mount_all duration
     private static final String[] MOUNT_DURATION_PROPS_POSTFIX =
             new String[] { "early", "default", "late" };
@@ -334,17 +340,22 @@
 
         String log = FileUtils.readTextFile(file, maxSize, "[[TRUNCATED]]\n");
         Pattern pattern = Pattern.compile(FS_STAT_PATTERN);
-        for (String line : log.split("\n")) { // should check all lines
-            if (line.contains("FILE SYSTEM WAS MODIFIED")) {
+        String lines[] = log.split("\n");
+        int lineNumber = 0;
+        int lastFsStatLineNumber = 0;
+        for (String line : lines) { // should check all lines
+            if (line.contains(FSCK_FS_MODIFIED)) {
                 uploadNeeded = true;
             } else if (line.contains("fs_stat")){
                 Matcher matcher = pattern.matcher(line);
                 if (matcher.find()) {
-                    handleFsckFsStat(matcher);
+                    handleFsckFsStat(matcher, lines, lastFsStatLineNumber, lineNumber);
+                    lastFsStatLineNumber = lineNumber;
                 } else {
                     Slog.w(TAG, "cannot parse fs_stat:" + line);
                 }
             }
+            lineNumber++;
         }
 
         if (uploadEnabled && uploadNeeded ) {
@@ -403,7 +414,88 @@
         }
     }
 
-    private static void handleFsckFsStat(Matcher match) {
+    /**
+     * Fix fs_stat from e2fsck.
+     * For now, only handle the case of quota warning caused by tree optimization. Clear fs fix
+     * flag (=0x400) caused by that.
+     *
+     * @param partition partition name
+     * @param statOrg original stat reported from e2fsck log
+     * @param lines e2fsck logs broken down into lines
+     * @param startLineNumber start line to parse
+     * @param endLineNumber end line. exclusive.
+     * @return updated fs_stat. For tree optimization, will clear bit 0x400.
+     */
+    @VisibleForTesting
+    public static int fixFsckFsStat(String partition, int statOrg, String[] lines,
+            int startLineNumber, int endLineNumber) {
+        int stat = statOrg;
+        if ((stat & FS_STAT_FS_FIXED) != 0) {
+            // fs was fixed. should check if quota warning was caused by tree optimization.
+            // This is not a real fix but optimization, so should not be counted as a fs fix.
+            Pattern passPattern = Pattern.compile(FSCK_PASS_PATTERN);
+            Pattern treeOptPattern = Pattern.compile(FSCK_TREE_OPTIMIZATION_PATTERN);
+            String currentPass = "";
+            boolean foundTreeOptimization = false;
+            boolean foundQuotaFix = false;
+            boolean foundOtherFix = false;
+            String otherFixLine = null;
+            for (int i = startLineNumber; i < endLineNumber; i++) {
+                String line = lines[i];
+                if (line.contains(FSCK_FS_MODIFIED)) { // no need to parse above this
+                    break;
+                } else if (line.startsWith("Pass ")) {
+                    Matcher matcher = passPattern.matcher(line);
+                    if (matcher.find()) {
+                        currentPass = matcher.group(1);
+                    }
+                } else if (line.startsWith("Inode ")) {
+                    Matcher matcher = treeOptPattern.matcher(line);
+                    if (matcher.find() && currentPass.equals("1")) {
+                        foundTreeOptimization = true;
+                        Slog.i(TAG, "fs_stat, partition:" + partition + " found tree optimization:"
+                                + line);
+                    } else {
+                        foundOtherFix = true;
+                        otherFixLine = line;
+                        break;
+                    }
+                } else if (line.startsWith("[QUOTA WARNING]") && currentPass.equals("5")) {
+                    Slog.i(TAG, "fs_stat, partition:" + partition + " found quota warning:"
+                            + line);
+                    foundQuotaFix = true;
+                    if (!foundTreeOptimization) { // only quota warning, this is real fix.
+                        otherFixLine = line;
+                        break;
+                    }
+                } else if (line.startsWith("Update quota info") && currentPass.equals("5")) {
+                    // follows "[QUOTA WARNING]", ignore
+                } else {
+                    line = line.trim();
+                    // ignore empty msg or any msg before Pass 1
+                    if (!line.isEmpty() && !currentPass.isEmpty()) {
+                        foundOtherFix = true;
+                        otherFixLine = line;
+                        break;
+                    }
+                }
+            }
+            if (!foundOtherFix && foundTreeOptimization && foundQuotaFix) {
+                // not a real fix, so clear it.
+                Slog.i(TAG, "fs_stat, partition:" + partition +
+                        " quota fix due to tree optimization");
+                stat &= ~FS_STAT_FS_FIXED;
+            } else {
+                if (otherFixLine != null) {
+                    Slog.i(TAG, "fs_stat, partition:" + partition + " fix:" + otherFixLine);
+                }
+            }
+        }
+        return stat;
+    }
+
+    private static void handleFsckFsStat(Matcher match, String[] lines, int startLineNumber,
+            int endLineNumber) {
         String partition = match.group(1);
         int stat;
         try {
@@ -412,9 +504,9 @@
             Slog.w(TAG, "cannot parse fs_stat: partition:" + partition + " stat:" + match.group(2));
             return;
         }
-
+        stat = fixFsckFsStat(partition, stat, lines, startLineNumber, endLineNumber);
         MetricsLogger.histogram(null, "boot_fs_stat_" + partition, stat);
-        Slog.i(TAG, "fs_stat, partition:" + partition + " stat:" + match.group(2));
+        Slog.i(TAG, "fs_stat, partition:" + partition + " stat:0x" + Integer.toHexString(stat));
     }
 
     private static HashMap<String, Long> readTimestamps() {
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index 2c7174d..d046996 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -75,6 +75,12 @@
     jmethodID   add;
 } gListOffsets;
 
+struct StringOffsets {
+    jclass      clazz;
+    jmethodID   intern;
+    jstring     emptyString;
+} gStringOffsets;
+
 /*
  * nativeClassInit is not inteneded to be thread-safe. It should be called before other native...
  * functions (except nativeCreate).
@@ -84,75 +90,55 @@
 {
     //android.hardware.Sensor
     SensorOffsets& sensorOffsets = gSensorOffsets;
-    jclass sensorClass = (jclass) _env->NewGlobalRef(_env->FindClass("android/hardware/Sensor"));
-    sensorOffsets.clazz       = sensorClass;
-    sensorOffsets.name        = _env->GetFieldID(sensorClass, "mName",      "Ljava/lang/String;");
-    sensorOffsets.vendor      = _env->GetFieldID(sensorClass, "mVendor",    "Ljava/lang/String;");
-    sensorOffsets.version     = _env->GetFieldID(sensorClass, "mVersion",   "I");
-    sensorOffsets.handle      = _env->GetFieldID(sensorClass, "mHandle",    "I");
-    sensorOffsets.range       = _env->GetFieldID(sensorClass, "mMaxRange",  "F");
-    sensorOffsets.resolution  = _env->GetFieldID(sensorClass, "mResolution","F");
-    sensorOffsets.power       = _env->GetFieldID(sensorClass, "mPower",     "F");
-    sensorOffsets.minDelay    = _env->GetFieldID(sensorClass, "mMinDelay",  "I");
+    jclass sensorClass = (jclass)
+            MakeGlobalRefOrDie(_env, FindClassOrDie(_env, "android/hardware/Sensor"));
+    sensorOffsets.clazz = sensorClass;
+    sensorOffsets.name = GetFieldIDOrDie(_env, sensorClass, "mName", "Ljava/lang/String;");
+    sensorOffsets.vendor = GetFieldIDOrDie(_env, sensorClass, "mVendor", "Ljava/lang/String;");
+    sensorOffsets.version = GetFieldIDOrDie(_env, sensorClass, "mVersion", "I");
+    sensorOffsets.handle = GetFieldIDOrDie(_env, sensorClass, "mHandle", "I");
+    sensorOffsets.range = GetFieldIDOrDie(_env, sensorClass, "mMaxRange", "F");
+    sensorOffsets.resolution = GetFieldIDOrDie(_env, sensorClass, "mResolution","F");
+    sensorOffsets.power = GetFieldIDOrDie(_env, sensorClass, "mPower", "F");
+    sensorOffsets.minDelay = GetFieldIDOrDie(_env, sensorClass, "mMinDelay", "I");
     sensorOffsets.fifoReservedEventCount =
-            _env->GetFieldID(sensorClass, "mFifoReservedEventCount",  "I");
-    sensorOffsets.fifoMaxEventCount = _env->GetFieldID(sensorClass, "mFifoMaxEventCount",  "I");
-    sensorOffsets.stringType = _env->GetFieldID(sensorClass, "mStringType", "Ljava/lang/String;");
-    sensorOffsets.requiredPermission = _env->GetFieldID(sensorClass, "mRequiredPermission",
-                                                        "Ljava/lang/String;");
-    sensorOffsets.maxDelay    = _env->GetFieldID(sensorClass, "mMaxDelay",  "I");
-    sensorOffsets.flags = _env->GetFieldID(sensorClass, "mFlags",  "I");
+            GetFieldIDOrDie(_env,sensorClass, "mFifoReservedEventCount", "I");
+    sensorOffsets.fifoMaxEventCount = GetFieldIDOrDie(_env,sensorClass, "mFifoMaxEventCount", "I");
+    sensorOffsets.stringType =
+            GetFieldIDOrDie(_env,sensorClass, "mStringType", "Ljava/lang/String;");
+    sensorOffsets.requiredPermission =
+            GetFieldIDOrDie(_env,sensorClass, "mRequiredPermission", "Ljava/lang/String;");
+    sensorOffsets.maxDelay = GetFieldIDOrDie(_env,sensorClass, "mMaxDelay", "I");
+    sensorOffsets.flags = GetFieldIDOrDie(_env,sensorClass, "mFlags", "I");
 
-    sensorOffsets.setType = _env->GetMethodID(sensorClass, "setType", "(I)Z");
-    sensorOffsets.setUuid = _env->GetMethodID(sensorClass, "setUuid", "(JJ)V");
-    sensorOffsets.init = _env->GetMethodID(sensorClass, "<init>", "()V");
+    sensorOffsets.setType = GetMethodIDOrDie(_env,sensorClass, "setType", "(I)Z");
+    sensorOffsets.setUuid = GetMethodIDOrDie(_env,sensorClass, "setUuid", "(JJ)V");
+    sensorOffsets.init = GetMethodIDOrDie(_env,sensorClass, "<init>", "()V");
 
     // java.util.List;
     ListOffsets& listOffsets = gListOffsets;
-    jclass listClass = (jclass) _env->NewGlobalRef(_env->FindClass("java/util/List"));
+    jclass listClass = (jclass) MakeGlobalRefOrDie(_env, FindClassOrDie(_env, "java/util/List"));
     listOffsets.clazz = listClass;
-    listOffsets.add = _env->GetMethodID(listClass, "add", "(Ljava/lang/Object;)Z");
+    listOffsets.add = GetMethodIDOrDie(_env,listClass, "add", "(Ljava/lang/Object;)Z");
+
+    // initialize java.lang.String and empty string intern
+    StringOffsets& stringOffsets = gStringOffsets;
+    stringOffsets.clazz = MakeGlobalRefOrDie(_env, FindClassOrDie(_env, "java/lang/String"));
+    stringOffsets.intern =
+            GetMethodIDOrDie(_env, stringOffsets.clazz, "intern", "()Ljava/lang/String;");
+    ScopedLocalRef<jstring> empty(_env, _env->NewStringUTF(""));
+    stringOffsets.emptyString = (jstring)
+            MakeGlobalRefOrDie(_env, _env->CallObjectMethod(empty.get(), stringOffsets.intern));
 }
 
-/**
- * A key comparator predicate.
- * It is used to intern strings associated with Sensor data.
- * It defines a 'Strict weak ordering' for the interned strings.
- */
-class InternedStringCompare {
-public:
-    bool operator()(const String8* string1, const String8* string2) const {
-        if (string1 == NULL) {
-            return string2 != NULL;
-        }
-        if (string2 == NULL) {
-            return false;
-        }
-        return string1->compare(*string2) < 0;
+static jstring getJavaInternedString(JNIEnv *env, const String8 &string) {
+    if (string == "") {
+        return gStringOffsets.emptyString;
     }
-};
 
-/**
- * A localized interning mechanism for Sensor strings.
- * We implement our own interning to avoid the overhead of using java.lang.String#intern().
- * It is common that Vendor, StringType, and RequirePermission data is common between many of the
- * Sensors, by interning the memory usage to represent Sensors is optimized.
- */
-static jstring
-getInternedString(JNIEnv *env, const String8* string) {
-    static std::map<const String8*, jstring, InternedStringCompare> internedStrings;
-
-    jstring internedString;
-    std::map<const String8*, jstring>::iterator iterator = internedStrings.find(string);
-    if (iterator != internedStrings.end()) {
-        internedString = iterator->second;
-    } else {
-        jstring localString = env->NewStringUTF(string->string());
-        // we are implementing our own interning so expect these strings to be backed by global refs
-        internedString = (jstring) env->NewGlobalRef(localString);
-        internedStrings.insert(std::make_pair(string, internedString));
-        env->DeleteLocalRef(localString);
-    }
+    ScopedLocalRef<jstring> javaString(env, env->NewStringUTF(string.string()));
+    jstring internedString = (jstring)
+            env->CallObjectMethod(javaString.get(), gStringOffsets.intern);
     return internedString;
 }
 
@@ -174,10 +160,10 @@
     }
 
     if (sensor != NULL) {
-        jstring name = env->NewStringUTF(nativeSensor.getName().string());
-        jstring vendor = env->NewStringUTF(nativeSensor.getVendor().string());
+        jstring name = getJavaInternedString(env, nativeSensor.getName());
+        jstring vendor = getJavaInternedString(env, nativeSensor.getVendor());
         jstring requiredPermission =
-                env->NewStringUTF(nativeSensor.getRequiredPermission().string());
+                getJavaInternedString(env, nativeSensor.getRequiredPermission());
 
         env->SetObjectField(sensor, sensorOffsets.name,      name);
         env->SetObjectField(sensor, sensorOffsets.vendor,    vendor);
@@ -198,7 +184,7 @@
 
         if (env->CallBooleanMethod(sensor, sensorOffsets.setType, nativeSensor.getType())
                 == JNI_FALSE) {
-            jstring stringType = getInternedString(env, &nativeSensor.getStringType());
+            jstring stringType = getJavaInternedString(env, nativeSensor.getStringType());
             env->SetObjectField(sensor, sensorOffsets.stringType, stringType);
         }
 
diff --git a/core/jni/android_os_HwParcel.cpp b/core/jni/android_os_HwParcel.cpp
index 678041f..b21ea828 100644
--- a/core/jni/android_os_HwParcel.cpp
+++ b/core/jni/android_os_HwParcel.cpp
@@ -574,7 +574,7 @@
     size_t parentHandle;
 
     const hidl_string *s;
-    status_t err = parcel->readBuffer(&parentHandle,
+    status_t err = parcel->readBuffer(sizeof(*s), &parentHandle,
             reinterpret_cast<const void**>(&s));
 
     if (err != OK) {
@@ -583,7 +583,7 @@
     }
 
     err = ::android::hardware::readEmbeddedFromParcel(
-            const_cast<hidl_string *>(s),
+            const_cast<hidl_string &>(*s),
             *parcel, parentHandle, 0 /* parentOffset */);
 
     if (err != OK) {
@@ -602,7 +602,7 @@
     size_t parentHandle;                                                       \
                                                                                \
     const hidl_vec<Type> *vec;                                                 \
-    status_t err = parcel->readBuffer(&parentHandle,                           \
+    status_t err = parcel->readBuffer(sizeof(*vec), &parentHandle,             \
             reinterpret_cast<const void**>(&vec));                             \
                                                                                \
     if (err != OK) {                                                           \
@@ -613,7 +613,7 @@
     size_t childHandle;                                                        \
                                                                                \
     err = ::android::hardware::readEmbeddedFromParcel(                         \
-                const_cast<hidl_vec<Type> *>(vec),                             \
+                const_cast<hidl_vec<Type> &>(*vec),                            \
                 *parcel,                                                       \
                 parentHandle,                                                  \
                 0 /* parentOffset */,                                          \
@@ -645,7 +645,7 @@
     size_t parentHandle;
 
     const hidl_vec<bool> *vec;
-    status_t err = parcel->readBuffer(&parentHandle,
+    status_t err = parcel->readBuffer(sizeof(*vec), &parentHandle,
             reinterpret_cast<const void**>(&vec));
 
     if (err != OK) {
@@ -656,7 +656,7 @@
     size_t childHandle;
 
     err = ::android::hardware::readEmbeddedFromParcel(
-                const_cast<hidl_vec<bool> *>(vec),
+                const_cast<hidl_vec<bool> &>(*vec),
                 *parcel,
                 parentHandle,
                 0 /* parentOffset */,
@@ -709,7 +709,7 @@
     size_t parentHandle;
 
     const string_vec *vec;
-    status_t err = parcel->readBuffer(&parentHandle,
+    status_t err = parcel->readBuffer(sizeof(*vec), &parentHandle,
             reinterpret_cast<const void **>(&vec));
 
     if (err != OK) {
@@ -719,16 +719,15 @@
 
     size_t childHandle;
     err = ::android::hardware::readEmbeddedFromParcel(
-            const_cast<string_vec *>(vec),
+            const_cast<string_vec &>(*vec),
             *parcel, parentHandle, 0 /* parentOffset */, &childHandle);
 
     for (size_t i = 0; (err == OK) && (i < vec->size()); ++i) {
         err = android::hardware::readEmbeddedFromParcel(
-                    const_cast<hidl_vec<hidl_string> *>(vec),
+                    const_cast<hidl_string &>((*vec)[i]),
                     *parcel,
                     childHandle,
-                    i * sizeof(hidl_string),
-                    nullptr /* childHandle */);
+                    i * sizeof(hidl_string) /* parentOffset */);
     }
 
     if (err != OK) {
@@ -810,13 +809,20 @@
     return JHwRemoteBinder::NewObject(env, binder);
 }
 
-static jobject JHwParcel_native_readBuffer(JNIEnv *env, jobject thiz) {
+static jobject JHwParcel_native_readBuffer(JNIEnv *env, jobject thiz,
+                                           jlong expectedSize) {
     hardware::Parcel *parcel =
         JHwParcel::GetNativeContext(env, thiz)->getParcel();
 
     size_t handle;
     const void *ptr;
-    status_t status = parcel->readBuffer(&handle, &ptr);
+
+    if (expectedSize < 0) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+        return nullptr;
+    }
+
+    status_t status = parcel->readBuffer(expectedSize, &handle, &ptr);
 
     if (status != OK) {
         jniThrowException(env, "java/util/NoSuchElementException", NULL);
@@ -827,8 +833,8 @@
 }
 
 static jobject JHwParcel_native_readEmbeddedBuffer(
-        JNIEnv *env, jobject thiz, jlong parentHandle, jlong offset,
-        jboolean nullable) {
+        JNIEnv *env, jobject thiz, jlong expectedSize,
+        jlong parentHandle, jlong offset, jboolean nullable) {
     hardware::Parcel *parcel =
         JHwParcel::GetNativeContext(env, thiz)->getParcel();
 
@@ -836,8 +842,13 @@
 
     const void *ptr;
     status_t status =
-        parcel->readNullableEmbeddedBuffer(&childHandle, parentHandle, offset,
-                &ptr);
+        parcel->readNullableEmbeddedBuffer(expectedSize,
+                &childHandle, parentHandle, offset, &ptr);
+
+    if (expectedSize < 0) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+        return nullptr;
+    }
 
     if (status != OK) {
         jniThrowException(env, "java/util/NoSuchElementException", NULL);
@@ -952,10 +963,10 @@
 
     { "send", "()V", (void *)JHwParcel_native_send },
 
-    { "readBuffer", "()L" PACKAGE_PATH "/HwBlob;",
+    { "readBuffer", "(J)L" PACKAGE_PATH "/HwBlob;",
         (void *)JHwParcel_native_readBuffer },
 
-    { "readEmbeddedBuffer", "(JJZ)L" PACKAGE_PATH "/HwBlob;",
+    { "readEmbeddedBuffer", "(JJJZ)L" PACKAGE_PATH "/HwBlob;",
         (void *)JHwParcel_native_readEmbeddedBuffer },
 
     { "writeBuffer", "(L" PACKAGE_PATH "/HwBlob;)V",
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 1aed501..de67c50 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -193,10 +193,10 @@
     if (env->IsInstanceOf(excep, gErrorOffsets.mClass)) {
         /*
          * It's an Error: Reraise the exception and ask the runtime to abort.
-         * This will dump the pending exception as well as all thread traces
-         * to the log.
          */
         env->Throw(excep);
+        ALOGE("java.lang.Error thrown during binder transaction (stack trace follows) : ");
+        env->ExceptionDescribe();
         env->FatalError("java.lang.Error thrown during binder transaction.");
     }
 
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index a2f07d9..2042bf62 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -21,10 +21,14 @@
 
 import "frameworks/base/libs/incident/proto/android/privacy.proto";
 import "frameworks/base/core/proto/android/service/appwidget.proto";
+import "frameworks/base/core/proto/android/service/battery.proto";
 import "frameworks/base/core/proto/android/service/graphicsstats.proto";
 import "frameworks/base/core/proto/android/service/fingerprint.proto";
+import "frameworks/base/core/proto/android/service/diskstats.proto";
 import "frameworks/base/core/proto/android/service/netstats.proto";
 import "frameworks/base/core/proto/android/service/notification.proto";
+import "frameworks/base/core/proto/android/service/package.proto";
+import "frameworks/base/core/proto/android/service/power.proto";
 import "frameworks/base/core/proto/android/providers/settings.proto";
 
 package android.os;
@@ -57,6 +61,10 @@
     android.service.NetworkStatsServiceDumpProto netstats = 3001;
     android.providers.settings.SettingsServiceDumpProto settings = 3002;
     android.service.appwidget.AppWidgetServiceDumpProto appwidget = 3003;
+    android.service.battery.BatteryServiceDumpProto battery = 3006;
+    android.service.diskstats.DiskStatsServiceDumpProto diskstats = 3007;
     android.service.notification.NotificationServiceDumpProto notification = 3004;
+    android.service.pm.PackageServiceDumpProto package = 3008;
+    android.service.power.PowerServiceDumpProto power = 3009;
     android.service.GraphicsStatsServiceDumpProto graphicsstats = 3005;
 }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 8869593..128c5cc 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -37,7 +37,6 @@
     <protected-broadcast android:name="android.intent.action.BOOT_COMPLETED" />
     <protected-broadcast android:name="android.intent.action.PACKAGE_INSTALL" />
     <protected-broadcast android:name="android.intent.action.PACKAGE_ADDED" />
-    <protected-broadcast android:name="android.intent.action.PACKAGE_FIRST_ADDED" />
     <protected-broadcast android:name="android.intent.action.PACKAGE_REPLACED" />
     <protected-broadcast android:name="android.intent.action.MY_PACKAGE_REPLACED" />
     <protected-broadcast android:name="android.intent.action.PACKAGE_REMOVED" />
diff --git a/core/res/res/drawable/ic_corp_badge.xml b/core/res/res/drawable/ic_corp_badge.xml
deleted file mode 100644
index 8917431..0000000
--- a/core/res/res/drawable/ic_corp_badge.xml
+++ /dev/null
@@ -1,33 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="20.0dp"
-        android:height="20.0dp"
-        android:viewportWidth="20.0"
-        android:viewportHeight="20.0">
-    <path
-        android:pathData="M10.0,10.0m-10.0,0.0a10.0,10.0 0.0,1.0 1.0,20.0 0.0a10.0,10.0 0.0,1.0 1.0,-20.0 0.0"
-        android:fillColor="#FF5722"/>
-    <path
-        android:pathData="M15.2,6.2L4.8,6.2c-0.5,0.0 -0.9,0.4 -0.9,1.0L3.9,10.0c0.0,0.5 0.4,1.0 0.9,1.0l3.8,0.0l0.0,-1.0l2.9,0.0l0.0,1.0l3.8,0.0c0.5,0.0 1.0,-0.4 1.0,-1.0L16.3,7.1C16.2,6.6 15.8,6.2 15.2,6.2z"
-        android:fillColor="#FFFFFF"/>
-    <path
-        android:pathData="M8.6,12.9l0.0,-1.0L4.3,11.9l0.0,2.4c0.0,0.5 0.4,0.9 0.9,0.9l9.5,0.0c0.5,0.0 0.9,-0.4 0.9,-0.9l0.0,-2.4l-4.3,0.0l0.0,1.0L8.6,12.9z"
-        android:fillColor="#FFFFFF"/>
-    <path
-        android:pathData="M7.1,5.2l0.0,1.0 1.0,0.0 0.0,-1.0 3.799999,0.0 0.0,1.0 1.0,0.0 0.0,-1.0 -1.0,-0.9 -3.799999,0.0z"
-        android:fillColor="#FFFFFF"/>
-</vector>
diff --git a/core/res/res/drawable/ic_instant_icon_badge_bolt.xml b/core/res/res/drawable/ic_instant_icon_badge_bolt.xml
new file mode 100644
index 0000000..08512b7
--- /dev/null
+++ b/core/res/res/drawable/ic_instant_icon_badge_bolt.xml
@@ -0,0 +1,29 @@
+<!--
+Copyright (C) 2017 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="64.0dp"
+        android:height="64.0dp"
+        android:viewportWidth="64.0"
+        android:viewportHeight="64.0">
+
+    <!--
+     The path is similar to ic_corp_icon_badge_case, such that it positions on top of
+     ic_corp_icon_badge_shadow.
+    -->
+    <path
+        android:pathData="M43.9 50.9h4v8l6-12h-4v-8l-6 12z"
+        android:fillColor="#757575"/>
+</vector>
diff --git a/core/res/res/drawable/ic_picture_in_picture.xml b/core/res/res/drawable/ic_picture_in_picture.xml
new file mode 100644
index 0000000..e2dda33
--- /dev/null
+++ b/core/res/res/drawable/ic_picture_in_picture.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M19 11h-8v6h8v-6zm4 8V4.98C23 3.88 22.1 3 21 3H3c-1.1 0-2 .88-2 1.98V19c0 1.1 .9
+2 2 2h18c1.1 0 2-.9 2-2zm-2 .02H3V4.97h18v14.05z" />
+    <path
+        android:pathData="M0 0h24v24H0V0z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/layout/accessibility_button_chooser.xml b/core/res/res/layout/accessibility_button_chooser.xml
index 0ef785f..480defb 100644
--- a/core/res/res/layout/accessibility_button_chooser.xml
+++ b/core/res/res/layout/accessibility_button_chooser.xml
@@ -19,7 +19,7 @@
 <com.android.internal.widget.ResolverDrawerLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
+    android:layout_height="wrap_content"
     android:maxWidth="@dimen/resolver_max_width"
     android:maxCollapsedHeight="256dp"
     android:maxCollapsedHeightSmall="56dp"
@@ -27,11 +27,14 @@
 
     <LinearLayout
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alwaysShow="true"
         android:orientation="vertical"
         android:background="?attr/colorBackground"
         android:paddingTop="8dp"
-        android:paddingBottom="8dp">
+        android:paddingBottom="8dp"
+        android:paddingStart="?attr/dialogPreferredPadding"
+        android:paddingEnd="?attr/dialogPreferredPadding">
 
         <TextView
             android:layout_width="match_parent"
@@ -41,8 +44,6 @@
             android:text="@string/accessibility_button_prompt_text"
             android:gravity="start|center_vertical"
             android:layout_alignParentStart="true"
-            android:paddingStart="?attr/dialogPreferredPadding"
-            android:paddingEnd="?attr/dialogPreferredPadding"
             android:paddingTop="8dp"
             android:paddingBottom="8dp"/>
 
@@ -55,20 +56,15 @@
             android:verticalSpacing="10dp"
             android:horizontalSpacing="10dp"
             android:stretchMode="columnWidth"
-            android:paddingStart="?attr/dialogPreferredPadding"
-            android:paddingEnd="?attr/dialogPreferredPadding"
             android:gravity="center"/>
 
         <TextView
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:id="@+id/accessibility_button_prompt"
-            android:layout_alwaysShow="true"
             android:textAppearance="?attr/textAppearanceMedium"
             android:text="@string/accessibility_button_instructional_text"
             android:gravity="start|center_vertical"
-            android:paddingStart="?attr/dialogPreferredPadding"
-            android:paddingEnd="?attr/dialogPreferredPadding"
             android:paddingTop="8dp"
             android:paddingBottom="8dp"
             android:visibility="gone"/>
diff --git a/core/res/res/values-television/config.xml b/core/res/res/values-television/config.xml
index 78eeee9..d62b93e 100644
--- a/core/res/res/values-television/config.xml
+++ b/core/res/res/values-television/config.xml
@@ -36,4 +36,7 @@
     <!-- The default gravity for the picture-in-picture window.
          Currently, this maps to Gravity.BOTTOM | Gravity.RIGHT -->
     <integer name="config_defaultPictureInPictureGravity">0x55</integer>
+
+    <!-- Whether the device uses the default focus highlight when focus state isn't specified. -->
+    <bool name="config_useDefaultFocusHighlight">false</bool>
 </resources>
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 937fc6f..536906c 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -171,6 +171,9 @@
     <color name="profile_badge_2">#ff000000</color><!-- Black -->
     <color name="profile_badge_3">#ff22f033</color><!-- Green -->
 
+    <!-- Default instant app badge color -->
+    <color name="instant_app_badge">#FFFFFFFF</color><!-- White -->
+
     <!-- Multi-sim sim colors -->
     <color name="Teal_700">#ff00796b</color>
     <color name="Teal_800">#ff00695c</color>
diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml
index e0cc5b5..8c37d4b 100644
--- a/core/res/res/values/colors_material.xml
+++ b/core/res/res/values/colors_material.xml
@@ -74,10 +74,10 @@
 
     <item name="disabled_alpha_material_light" format="float" type="dimen">0.26</item>
     <item name="disabled_alpha_material_dark" format="float" type="dimen">0.30</item>
-    <item name="primary_content_alpha_material_light" format="float" type="dimen">1</item>
-    <item name="primary_content_alpha_material_dark" format="float" type="dimen">0.87</item>
-    <item name="secondary_content_alpha_material_light" format="float" type="dimen">.7</item>
-    <item name="secondary_content_alpha_material_dark" format="float" type="dimen">0.54</item>
+    <item name="primary_content_alpha_material_dark" format="float" type="dimen">1</item>
+    <item name="primary_content_alpha_material_light" format="float" type="dimen">0.87</item>
+    <item name="secondary_content_alpha_material_dark" format="float" type="dimen">.7</item>
+    <item name="secondary_content_alpha_material_light" format="float" type="dimen">0.54</item>
 
     <item name="highlight_alpha_material_light" format="float" type="dimen">0.12</item>
     <item name="highlight_alpha_material_dark" format="float" type="dimen">0.20</item>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 6a31e16..27a4d5c 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2796,7 +2796,7 @@
     <string name="config_defaultCellBroadcastReceiverPkg" translatable="false">com.android.cellbroadcastreceiver</string>
 
     <!-- Specifies the path that is used by AdaptiveIconDrawable class to crop launcher icons. -->
-    <string name="config_icon_mask" translatable="false">"M50,0L92,0 A8,8,0,0 1 100,8 L100,92 A8,8,0,0 1 92,100 L8,100 A8,8,0,0 1 0,92 L 0,8 A8,8,0,0 1 8,0z"</string>
+    <string name="config_icon_mask" translatable="false">"M50,0L92,0C96.42,0 100,4.58 100 8L100,92C100, 96.42 96.42 100 92 100L8 100C4.58, 100 0 96.42 0 92L0 8 C 0 4.42 4.42 0 8 0L50 0Z"</string>
 
     <!-- The component name, flattened to a string, for the default accessibility service to be
          enabled by the accessibility shortcut. This service must be trusted, as it can be activated
@@ -2830,4 +2830,7 @@
           specified name exists on the device, autofill will be disabled by default.
     -->
     <string name="config_defaultAutofillService" translatable="false"></string>
+
+    <!-- Whether the device uses the default focus highlight when focus state isn't specified. -->
+    <bool name="config_useDefaultFocusHighlight">true</bool>
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 9e98efd..89c912fd 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2834,6 +2834,7 @@
 
     <public-group type="drawable" first-id="0x010800b4">
         <public name="autofilled_highlight" />
+        <public name="ic_picture_in_picture" />
     </public-group>
 
     <public-group type="string" first-id="0x01040019">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index f2da845..1dd8227 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -427,6 +427,7 @@
   <java-symbol type="integer" name="config_mdc_initial_max_retry" />
   <java-symbol type="integer" name="config_keepPreloadsMinDays" />
   <java-symbol type="bool" name="config_hasPermanentDpad" />
+  <java-symbol type="bool" name="config_useDefaultFocusHighlight" />
 
   <java-symbol type="color" name="tab_indicator_text_v4" />
 
@@ -1322,6 +1323,7 @@
   <java-symbol type="drawable" name="ic_corp_user_badge" />
   <java-symbol type="drawable" name="ic_corp_badge_no_background" />
   <java-symbol type="drawable" name="ic_corp_statusbar_icon" />
+  <java-symbol type="drawable" name="ic_instant_icon_badge_bolt" />
   <java-symbol type="drawable" name="emulator_circular_window_overlay" />
 
   <java-symbol type="drawable" name="sim_light_blue" />
@@ -1353,6 +1355,7 @@
   <java-symbol type="color" name="profile_badge_1" />
   <java-symbol type="color" name="profile_badge_2" />
   <java-symbol type="color" name="profile_badge_3" />
+  <java-symbol type="color" name="instant_app_badge" />
 
   <java-symbol type="layout" name="action_bar_home" />
   <java-symbol type="layout" name="action_bar_title_item" />
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index e0b4ec5..d80ff1d 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -794,6 +794,8 @@
 
     <!-- Theme used for the intent picker activity. -->
     <style name="Theme.DeviceDefault.Resolver" parent="Theme.Material.Light">
+        <item name="windowEnterTransition">@empty</item>
+        <item name="windowExitTransition">@empty</item>
         <item name="windowIsTranslucent">true</item>
         <item name="windowNoTitle">true</item>
         <item name="windowBackground">@color/transparent</item>
diff --git a/core/tests/coretests/src/android/metrics/LogMakerTest.java b/core/tests/coretests/src/android/metrics/LogMakerTest.java
index bab9f63..63c1f87 100644
--- a/core/tests/coretests/src/android/metrics/LogMakerTest.java
+++ b/core/tests/coretests/src/android/metrics/LogMakerTest.java
@@ -263,4 +263,32 @@
         assertFalse(a.isSubsetOf(b));
         assertFalse(b.isSubsetOf(a));
     }
+
+    public void testConstructFromNull() {
+        new LogMaker(null);
+        // no promises, just don't throw
+    }
+
+    public void testConstructFromNullKey() {
+        Object[] items = new Object[2];
+        items[0] = null;
+        items[1] = "foo";
+        new LogMaker(items);
+        // no promises, just don't throw
+    }
+
+    public void testConstructFromNullField() {
+        Object[] items = new Object[2];
+        items[0] = 10;
+        items[1] = null;
+        new LogMaker(items);
+        // no promises, just don't throw
+    }
+
+    public void testConstructFromTruncatedArray() {
+        Object[] items = new Object[1];
+        items[0] = 10;
+        new LogMaker(items);
+        // no promises, just don't throw
+    }
 }
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
index 0acff9b..39b999d 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
@@ -24,11 +24,6 @@
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
-import android.view.textclassifier.TextClassificationManager;
-import android.view.textclassifier.TextClassificationResult;
-import android.view.textclassifier.TextClassifier;
-import android.view.textclassifier.TextLanguage;
-import android.view.textclassifier.TextSelection;
 
 import org.hamcrest.BaseMatcher;
 import org.hamcrest.Description;
@@ -74,6 +69,23 @@
     }
 
     @Test
+    public void testSmartSelection_nullLocaleList() {
+        if (isTextClassifierDisabled()) return;
+
+        String text = "Contact me at droid@android.com";
+        String selected = "droid";
+        String suggested = "droid@android.com";
+        int startIndex = text.indexOf(selected);
+        int endIndex = startIndex + selected.length();
+        int smartStartIndex = text.indexOf(suggested);
+        int smartEndIndex = smartStartIndex + suggested.length();
+        LocaleList nullLocales = null;
+
+        assertThat(mClassifier.suggestSelection(text, startIndex, endIndex, nullLocales),
+                isTextSelection(smartStartIndex, smartEndIndex, TextClassifier.TYPE_EMAIL));
+    }
+
+    @Test
     public void testSmartSelection_url() {
         if (isTextClassifierDisabled()) return;
 
@@ -114,6 +126,19 @@
     }
 
     @Test
+    public void testTextClassificationResult_nullLocaleList() {
+        if (isTextClassifierDisabled()) return;
+
+        String text = "Contact me at droid@android.com";
+        String classifiedText = "droid@android.com";
+        int startIndex = text.indexOf(classifiedText);
+        int endIndex = startIndex + classifiedText.length();
+        LocaleList nullLocales = null;
+        assertThat(mClassifier.getTextClassificationResult(text, startIndex, endIndex, nullLocales),
+                isTextClassificationResult(classifiedText, TextClassifier.TYPE_EMAIL));
+    }
+
+    @Test
     public void testLanguageDetection() {
         if (isTextClassifierDisabled()) return;
 
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 7a8e487..abdab39 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -916,17 +916,20 @@
      * @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to
      *                 mark the bitmap as opaque. Doing so will clear the bitmap in black
      *                 instead of transparent.
-     * @param colorSpace The color space of the bitmap. If null or if the config is not
-     *                   {@link Config#ARGB_8888}, {@link ColorSpace.Named#SRGB sRGB} is assumed.
+     * @param colorSpace The color space of the bitmap. If the config is {@link Config#RGBA_F16},
+     *                   {@link ColorSpace.Named#EXTENDED_SRGB scRGB} is assumed, and if the
+     *                   config is not {@link Config#ARGB_8888}, {@link ColorSpace.Named#SRGB sRGB}
+     *                   is assumed.
      *
      * @throws IllegalArgumentException if the width or height are <= 0, if
      *         Config is Config.HARDWARE (because hardware bitmaps are always
      *         immutable), if the specified color space is not {@link ColorSpace.Model#RGB RGB},
-     *         or if the specified color space's transfer function is not an
-     *         {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}
+     *         if the specified color space's transfer function is not an
+     *         {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}, or if
+     *         the color space is null
      */
     public static Bitmap createBitmap(int width, int height, @NonNull Config config,
-            boolean hasAlpha, @Nullable ColorSpace colorSpace) {
+            boolean hasAlpha, @NonNull ColorSpace colorSpace) {
         return createBitmap(null, width, height, config, hasAlpha, colorSpace);
     }
 
@@ -950,7 +953,8 @@
      */
     public static Bitmap createBitmap(@Nullable DisplayMetrics display, int width, int height,
             @NonNull Config config, boolean hasAlpha) {
-        return createBitmap(display, width, height, config, hasAlpha, null);
+        return createBitmap(display, width, height, config, hasAlpha,
+                ColorSpace.get(ColorSpace.Named.SRGB));
     }
 
     /**
@@ -967,26 +971,34 @@
      * @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to
      *                 mark the bitmap as opaque. Doing so will clear the bitmap in black
      *                 instead of transparent.
-     * @param colorSpace The color space of the bitmap. If null or if the config is not
-     *                   {@link Config#ARGB_8888}, {@link ColorSpace.Named#SRGB sRGB} is assumed.
+     * @param colorSpace The color space of the bitmap. If the config is {@link Config#RGBA_F16},
+     *                   {@link ColorSpace.Named#EXTENDED_SRGB scRGB} is assumed, and if the
+     *                   config is not {@link Config#ARGB_8888}, {@link ColorSpace.Named#SRGB sRGB}
+     *                   is assumed.
      *
      * @throws IllegalArgumentException if the width or height are <= 0, if
      *         Config is Config.HARDWARE (because hardware bitmaps are always
      *         immutable), if the specified color space is not {@link ColorSpace.Model#RGB RGB},
-     *         or if the specified color space's transfer function is not an
-     *         {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}
+     *         if the specified color space's transfer function is not an
+     *         {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}, or if
+     *         the color space is null
      */
     public static Bitmap createBitmap(@Nullable DisplayMetrics display, int width, int height,
-            @NonNull Config config, boolean hasAlpha, @Nullable ColorSpace colorSpace) {
+            @NonNull Config config, boolean hasAlpha, @NonNull ColorSpace colorSpace) {
         if (width <= 0 || height <= 0) {
             throw new IllegalArgumentException("width and height must be > 0");
         }
         if (config == Config.HARDWARE) {
             throw new IllegalArgumentException("can't create mutable bitmap with Config.HARDWARE");
         }
+        if (colorSpace == null) {
+            throw new IllegalArgumentException("can't create bitmap without a color space");
+        }
 
         Bitmap bm;
-        if (colorSpace == null || config != Config.ARGB_8888) {
+        // nullptr color spaces have a particular meaning in native and are interpreted as sRGB
+        // (we also avoid the unnecessary extra work of the else branch)
+        if (config != Config.ARGB_8888 || colorSpace == ColorSpace.get(ColorSpace.Named.SRGB)) {
             bm = nativeCreate(null, 0, width, width, height, config.nativeInt, true, null, null);
         } else {
             if (!(colorSpace instanceof ColorSpace.Rgb)) {
diff --git a/graphics/java/android/graphics/BitmapShader.java b/graphics/java/android/graphics/BitmapShader.java
index 7e6756e..5577f53 100644
--- a/graphics/java/android/graphics/BitmapShader.java
+++ b/graphics/java/android/graphics/BitmapShader.java
@@ -41,35 +41,16 @@
      * @param tileY The tiling mode for y to draw the bitmap in.
      */
     public BitmapShader(@NonNull Bitmap bitmap, @NonNull TileMode tileX, @NonNull TileMode tileY) {
-        set(bitmap, tileX, tileY);
+        this(bitmap, tileX.nativeInt, tileY.nativeInt);
     }
 
     private BitmapShader(Bitmap bitmap, int tileX, int tileY) {
-        setInternal(bitmap, tileX, tileY);
-    }
-
-    /**
-     * Reinitialize the BitmapShader's Bitmap and tile modes.
-     *
-     * @param bitmap The bitmap to use inside the shader
-     * @param tileX The tiling mode for x to draw the bitmap in.
-     * @param tileY The tiling mode for y to draw the bitmap in.
-     */
-    public void set(@NonNull Bitmap bitmap, @NonNull TileMode tileX, @NonNull TileMode tileY) {
-        if (tileX == null || tileY == null) {
-            throw new IllegalArgumentException();
-        }
-        setInternal(bitmap, tileX.nativeInt, tileY.nativeInt);
-    }
-
-    private void setInternal(Bitmap bitmap, int tileX, int tileY) {
         if (bitmap == null) {
             throw new IllegalArgumentException("Bitmap must be non-null");
         }
         if (bitmap == mBitmap && tileX == mTileX && tileY == mTileY) {
             return;
         }
-        discardNativeInstance();
         mBitmap = bitmap;
         mTileX = tileX;
         mTileY = tileY;
diff --git a/graphics/java/android/graphics/ColorMatrixColorFilter.java b/graphics/java/android/graphics/ColorMatrixColorFilter.java
index 61f6cc5..9201a2e 100644
--- a/graphics/java/android/graphics/ColorMatrixColorFilter.java
+++ b/graphics/java/android/graphics/ColorMatrixColorFilter.java
@@ -73,6 +73,8 @@
      * @see #getColorMatrix(ColorMatrix)
      * @see #setColorMatrixArray(float[])
      * @see ColorMatrix#reset()
+     *
+     * @hide
      */
     public void setColorMatrix(@Nullable ColorMatrix matrix) {
         discardNativeInstance();
@@ -99,6 +101,8 @@
      *
      * @throws ArrayIndexOutOfBoundsException if the specified array's
      *         length is < 20
+     *
+     * @hide
      */
     public void setColorMatrixArray(@Nullable float[] array) {
         // called '...Array' so that passing null isn't ambiguous
diff --git a/graphics/java/android/graphics/ComposeShader.java b/graphics/java/android/graphics/ComposeShader.java
index 8438bf2..0b1141a 100644
--- a/graphics/java/android/graphics/ComposeShader.java
+++ b/graphics/java/android/graphics/ComposeShader.java
@@ -59,43 +59,10 @@
     }
 
     private ComposeShader(Shader shaderA, Shader shaderB, int nativeMode) {
-        setInternal(shaderA, shaderB, nativeMode);
-    }
-
-    /**
-     * Reinitialize the ComposeShader's component Shaders and blend mode.
-     *
-     * @param shaderA  The colors from this shader are seen as the "dst" by the mode
-     * @param shaderB  The colors from this shader are seen as the "src" by the mode
-     * @param mode     The PorterDuff mode that combines the colors from the two shaders.
-     */
-    public void set(@NonNull Shader shaderA, @NonNull Shader shaderB, @NonNull Xfermode mode) {
-        setInternal(shaderA, shaderB, mode.porterDuffMode);
-    }
-
-    /**
-     * Reinitialize the ComposeShader's component Shaders and blend mode.
-     *
-     * @param shaderA  The colors from this shader are seen as the "dst" by the mode
-     * @param shaderB  The colors from this shader are seen as the "src" by the mode
-     * @param mode     The PorterDuff mode that combines the colors from the two shaders.
-     */
-    public void set(@NonNull Shader shaderA, @NonNull Shader shaderB,
-            @NonNull PorterDuff.Mode mode) {
-        setInternal(shaderA, shaderB, mode.nativeInt);
-    }
-
-    private void setInternal(Shader shaderA, Shader shaderB, int nativeMode) {
         if (shaderA == null || shaderB == null) {
             throw new IllegalArgumentException("Shader parameters must not be null");
         }
 
-        if (shaderA == mShaderA && shaderB == mShaderB && mPorterDuffMode == nativeMode) {
-            // no work to do...
-            return;
-        }
-
-        discardNativeInstance();
         mShaderA = shaderA;
         mShaderB = shaderB;
         mPorterDuffMode = nativeMode;
diff --git a/graphics/java/android/graphics/LightingColorFilter.java b/graphics/java/android/graphics/LightingColorFilter.java
index b0c145b..1578ffb 100644
--- a/graphics/java/android/graphics/LightingColorFilter.java
+++ b/graphics/java/android/graphics/LightingColorFilter.java
@@ -57,8 +57,6 @@
     /**
      * Returns the RGB color used to multiply the source color when the
      * color filter is applied.
-     *
-     * @see #setColorMultiply(int)
      */
     @ColorInt
     public int getColorMultiply() {
@@ -71,6 +69,8 @@
      * The alpha channel of this color is ignored.
      *
      * @see #getColorMultiply()
+     *
+     * @hide
      */
     public void setColorMultiply(@ColorInt int mul) {
         if (mMul != mul) {
@@ -82,8 +82,6 @@
     /**
      * Returns the RGB color that will be added to the source color
      * when the color filter is applied.
-     *
-     * @see #setColorAdd(int)
      */
     @ColorInt
     public int getColorAdd() {
@@ -96,6 +94,8 @@
      * The alpha channel of this color is ignored.
      *
      * @see #getColorAdd()
+     *
+     * @hide
      */
     public void setColorAdd(@ColorInt int add) {
         if (mAdd != add) {
diff --git a/graphics/java/android/graphics/LinearGradient.java b/graphics/java/android/graphics/LinearGradient.java
index 0e4cd0a..7139efe 100644
--- a/graphics/java/android/graphics/LinearGradient.java
+++ b/graphics/java/android/graphics/LinearGradient.java
@@ -57,7 +57,20 @@
     */
     public LinearGradient(float x0, float y0, float x1, float y1, @NonNull @ColorInt int colors[],
             @Nullable float positions[], @NonNull TileMode tile) {
-        set(x0, y0, x1, y1, colors, positions, tile);
+        if (colors.length < 2) {
+            throw new IllegalArgumentException("needs >= 2 number of colors");
+        }
+        if (positions != null && colors.length != positions.length) {
+            throw new IllegalArgumentException("color and position arrays must be of equal length");
+        }
+        mType = TYPE_COLORS_AND_POSITIONS;
+        mX0 = x0;
+        mY0 = y0;
+        mX1 = x1;
+        mY1 = y1;
+        mColors = colors.clone();
+        mPositions = positions != null ? positions.clone() : null;
+        mTileMode = tile;
     }
 
     /**
@@ -74,56 +87,6 @@
     public LinearGradient(float x0, float y0, float x1, float y1,
             @ColorInt int color0, @ColorInt int color1,
             @NonNull TileMode tile) {
-        set(x0, y0, x1, y1, color0, color1, tile);
-    }
-
-    /**
-     * Reinitialize the shader.
-     *
-     * @param x0           The x-coordinate for the start of the gradient line
-     * @param y0           The y-coordinate for the start of the gradient line
-     * @param x1           The x-coordinate for the end of the gradient line
-     * @param y1           The y-coordinate for the end of the gradient line
-     * @param colors       The colors to be distributed along the gradient line
-     * @param positions    May be null. The relative positions [0..1] of
-     *                     each corresponding color in the colors array. If this is null,
-     *                     the the colors are distributed evenly along the gradient line.
-     * @param  tile        The Shader tiling mode
-     */
-    public void set(float x0, float y0, float x1, float y1, @NonNull @ColorInt int colors[],
-            @Nullable float positions[], @NonNull TileMode tile) {
-        if (colors.length < 2) {
-            throw new IllegalArgumentException("needs >= 2 number of colors");
-        }
-        if (positions != null && colors.length != positions.length) {
-            throw new IllegalArgumentException("color and position arrays must be of equal length");
-        }
-        discardNativeInstance();
-        mType = TYPE_COLORS_AND_POSITIONS;
-        mX0 = x0;
-        mY0 = y0;
-        mX1 = x1;
-        mY1 = y1;
-        mColors = colors.clone();
-        mPositions = positions != null ? positions.clone() : null;
-        mTileMode = tile;
-    }
-
-    /**
-     * Reinitialize the shader.
-     *
-     * @param x0       The x-coordinate for the start of the gradient line
-     * @param y0       The y-coordinate for the start of the gradient line
-     * @param x1       The x-coordinate for the end of the gradient line
-     * @param y1       The y-coordinate for the end of the gradient line
-     * @param color0   The color at the start of the gradient line.
-     * @param color1   The color at the end of the gradient line.
-     * @param tile     The Shader tiling mode
-    */
-    public void set(float x0, float y0, float x1, float y1,
-            @ColorInt int color0, @ColorInt int color1,
-            @NonNull TileMode tile) {
-        discardNativeInstance();
         mType = TYPE_COLOR_START_AND_COLOR_END;
         mX0 = x0;
         mY0 = y0;
diff --git a/graphics/java/android/graphics/PorterDuffColorFilter.java b/graphics/java/android/graphics/PorterDuffColorFilter.java
index ccc6ead..01d5825 100644
--- a/graphics/java/android/graphics/PorterDuffColorFilter.java
+++ b/graphics/java/android/graphics/PorterDuffColorFilter.java
@@ -49,6 +49,8 @@
      *
      * @see Color
      * @see #setColor(int)
+     *
+     * @hide
      */
     @ColorInt
     public int getColor() {
@@ -64,6 +66,8 @@
      * @see Color
      * @see #getColor()
      * @see #getMode()
+     *
+     * @hide
      */
     public void setColor(@ColorInt int color) {
         if (mColor != color) {
@@ -78,6 +82,8 @@
      *
      * @see PorterDuff
      * @see #setMode(android.graphics.PorterDuff.Mode)
+     *
+     * @hide
      */
     public PorterDuff.Mode getMode() {
         return mMode;
@@ -90,6 +96,8 @@
      * @see PorterDuff
      * @see #getMode()
      * @see #getColor()
+     *
+     * @hide
      */
     public void setMode(@NonNull PorterDuff.Mode mode) {
         if (mode == null) {
diff --git a/graphics/java/android/graphics/RadialGradient.java b/graphics/java/android/graphics/RadialGradient.java
index ae8f7da..f4b1191 100644
--- a/graphics/java/android/graphics/RadialGradient.java
+++ b/graphics/java/android/graphics/RadialGradient.java
@@ -57,7 +57,22 @@
     public RadialGradient(float centerX, float centerY, float radius,
             @NonNull @ColorInt int colors[], @Nullable float stops[],
             @NonNull TileMode tileMode) {
-        set(centerX, centerY, radius, colors, stops, tileMode);
+        if (radius <= 0) {
+            throw new IllegalArgumentException("radius must be > 0");
+        }
+        if (colors.length < 2) {
+            throw new IllegalArgumentException("needs >= 2 number of colors");
+        }
+        if (stops != null && colors.length != stops.length) {
+            throw new IllegalArgumentException("color and position arrays must be of equal length");
+        }
+        mType = TYPE_COLORS_AND_POSITIONS;
+        mX = centerX;
+        mY = centerY;
+        mRadius = radius;
+        mColors = colors.clone();
+        mPositions = stops != null ? stops.clone() : null;
+        mTileMode = tileMode;
     }
 
     /**
@@ -72,59 +87,9 @@
      */
     public RadialGradient(float centerX, float centerY, float radius,
             @ColorInt int centerColor, @ColorInt int edgeColor, @NonNull TileMode tileMode) {
-        set(centerX, centerY, radius, centerColor, edgeColor, tileMode);
-    }
-
-    /**
-     * Reinitialize the shader.
-     *
-     * @param centerX  The x-coordinate of the center of the radius
-     * @param centerY  The y-coordinate of the center of the radius
-     * @param radius   Must be positive. The radius of the circle for this gradient.
-     * @param colors   The colors to be distributed between the center and edge of the circle
-     * @param stops    May be <code>null</code>. Valid values are between <code>0.0f</code> and
-     *                 <code>1.0f</code>. The relative position of each corresponding color in
-     *                 the colors array. If <code>null</code>, colors are distributed evenly
-     *                 between the center and edge of the circle.
-     * @param tileMode The Shader tiling mode
-     */
-    public void set(float centerX, float centerY, float radius,
-            @NonNull @ColorInt int colors[], @Nullable float stops[], @NonNull TileMode tileMode) {
         if (radius <= 0) {
             throw new IllegalArgumentException("radius must be > 0");
         }
-        if (colors.length < 2) {
-            throw new IllegalArgumentException("needs >= 2 number of colors");
-        }
-        if (stops != null && colors.length != stops.length) {
-            throw new IllegalArgumentException("color and position arrays must be of equal length");
-        }
-        discardNativeInstance();
-        mType = TYPE_COLORS_AND_POSITIONS;
-        mX = centerX;
-        mY = centerY;
-        mRadius = radius;
-        mColors = colors.clone();
-        mPositions = stops != null ? stops.clone() : null;
-        mTileMode = tileMode;
-    }
-
-    /**
-     * Reinitialize the shader.
-     *
-     * @param centerX     The x-coordinate of the center of the radius
-     * @param centerY     The y-coordinate of the center of the radius
-     * @param radius      Must be positive. The radius of the circle for this gradient
-     * @param centerColor The color at the center of the circle.
-     * @param edgeColor   The color at the edge of the circle.
-     * @param tileMode    The Shader tiling mode
-     */
-    public void set(float centerX, float centerY, float radius,
-            @ColorInt int centerColor, @ColorInt int edgeColor, @NonNull TileMode tileMode) {
-        if (radius <= 0) {
-            throw new IllegalArgumentException("radius must be > 0");
-        }
-        discardNativeInstance();
         mType = TYPE_COLOR_CENTER_AND_COLOR_EDGE;
         mX = centerX;
         mY = centerY;
diff --git a/graphics/java/android/graphics/SweepGradient.java b/graphics/java/android/graphics/SweepGradient.java
index 0a1aef6..b6b80b4 100644
--- a/graphics/java/android/graphics/SweepGradient.java
+++ b/graphics/java/android/graphics/SweepGradient.java
@@ -54,7 +54,18 @@
      */
     public SweepGradient(float cx, float cy,
             @NonNull @ColorInt int colors[], @Nullable float positions[]) {
-        set(cx, cy, colors, positions);
+        if (colors.length < 2) {
+            throw new IllegalArgumentException("needs >= 2 number of colors");
+        }
+        if (positions != null && colors.length != positions.length) {
+            throw new IllegalArgumentException(
+                    "color and position arrays must be of equal length");
+        }
+        mType = TYPE_COLORS_AND_POSITIONS;
+        mCx = cx;
+        mCy = cy;
+        mColors = colors.clone();
+        mPositions = positions != null ? positions.clone() : null;
     }
 
     /**
@@ -66,50 +77,6 @@
      * @param color1   The color to use at the end of the sweep
      */
     public SweepGradient(float cx, float cy, @ColorInt int color0, @ColorInt int color1) {
-        set(cx, cy, color0, color1);
-    }
-
-    /**
-     * Reinitialize the shader.
-     *
-     * @param cx       The x-coordinate of the center
-     * @param cy       The y-coordinate of the center
-     * @param colors   The colors to be distributed between around the center.
-     *                 There must be at least 2 colors in the array.
-     * @param positions May be NULL. The relative position of
-     *                 each corresponding color in the colors array, beginning
-     *                 with 0 and ending with 1.0. If the values are not
-     *                 monotonic, the drawing may produce unexpected results.
-     *                 If positions is NULL, then the colors are automatically
-     *                 spaced evenly.
-     */
-    public void set(float cx, float cy,
-            @NonNull @ColorInt int colors[], @Nullable float positions[]) {
-        if (colors.length < 2) {
-            throw new IllegalArgumentException("needs >= 2 number of colors");
-        }
-        if (positions != null && colors.length != positions.length) {
-            throw new IllegalArgumentException(
-                    "color and position arrays must be of equal length");
-        }
-        discardNativeInstance();
-        mType = TYPE_COLORS_AND_POSITIONS;
-        mCx = cx;
-        mCy = cy;
-        mColors = colors.clone();
-        mPositions = positions != null ? positions.clone() : null;
-    }
-
-    /**
-     * Reinitialize the shader.
-     *
-     * @param cx       The x-coordinate of the center
-     * @param cy       The y-coordinate of the center
-     * @param color0   The color to use at the start of the sweep
-     * @param color1   The color to use at the end of the sweep
-     */
-    public void set(float cx, float cy, @ColorInt int color0, @ColorInt int color1) {
-        discardNativeInstance();
         mType = TYPE_COLOR_START_AND_COLOR_END;
         mCx = cx;
         mCy = cy;
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 97d3e5e..18dc0dc 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -563,6 +563,9 @@
         /**
          * Constructs a builder with a file descriptor.
          *
+         * Caller is responsible for closing the passed file descriptor after {@link #build} is
+         * called.
+         *
          * @param fd The file descriptor. The passed fd must be mmap-able.
          */
         public Builder(@NonNull FileDescriptor fd) {
diff --git a/libs/hwui/tests/unit/SkiaBehaviorTests.cpp b/libs/hwui/tests/unit/SkiaBehaviorTests.cpp
index 7ae58a6..dafa074 100644
--- a/libs/hwui/tests/unit/SkiaBehaviorTests.cpp
+++ b/libs/hwui/tests/unit/SkiaBehaviorTests.cpp
@@ -20,6 +20,7 @@
 #include <SkColorMatrixFilter.h>
 #include <SkColorSpace.h>
 #include <SkImagePriv.h>
+#include <SkPathOps.h>
 #include <SkShader.h>
 
 using namespace android;
@@ -90,6 +91,16 @@
     ASSERT_EQ(expected, paint.getBlendMode());
 }
 
+TEST(SkiaBehavior, pathIntersection) {
+    SkPath p0, p1, result;
+    p0.addRect(SkRect::MakeXYWH(-5.0f, 0.0f, 1080.0f, 242.0f));
+    p1.addRect(SkRect::MakeXYWH(0.0f, 0.0f, 1080.0f, 242.0f));
+    Op(p0, p1, kIntersect_SkPathOp, &result);
+    SkRect resultRect;
+    ASSERT_TRUE(result.isRect(&resultRect));
+    ASSERT_EQ(SkRect::MakeXYWH(0.0f, 0.0f, 1075.0f, 242.0f), resultRect);
+}
+
 TEST(SkiaBehavior, srgbColorSpaceIsSingleton) {
     sk_sp<SkColorSpace> sRGB1 = SkColorSpace::MakeSRGB();
     sk_sp<SkColorSpace> sRGB2 = SkColorSpace::MakeSRGB();
diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java
index b222a6d..68f46ad 100644
--- a/location/java/android/location/Location.java
+++ b/location/java/android/location/Location.java
@@ -646,7 +646,10 @@
      *
      * <p>Following this call {@link #hasAltitude} will return false,
      * and {@link #getAltitude} will return 0.0.
+     *
+     * @deprecated use a new Location object for location updates.
      */
+    @Deprecated
     public void removeAltitude() {
         mAltitude = 0.0f;
         mFieldsMask &= ~HAS_ALTITUDE_MASK;
@@ -683,7 +686,10 @@
      *
      * <p>Following this call {@link #hasSpeed} will return false,
      * and {@link #getSpeed} will return 0.0.
+     *
+     * @deprecated use a new Location object for location updates.
      */
+    @Deprecated
     public void removeSpeed() {
         mSpeed = 0.0f;
         mFieldsMask &= ~HAS_SPEED_MASK;
@@ -733,7 +739,10 @@
      *
      * <p>Following this call {@link #hasBearing} will return false,
      * and {@link #getBearing} will return 0.0.
+     *
+     * @deprecated use a new Location object for location updates.
      */
+    @Deprecated
     public void removeBearing() {
         mBearing = 0.0f;
         mFieldsMask &= ~HAS_BEARING_MASK;
@@ -790,7 +799,10 @@
      *
      * <p>Following this call {@link #hasAccuracy} will return false, and
      * {@link #getAccuracy} will return 0.0.
+     *
+     * @deprecated use a new Location object for location updates.
      */
+    @Deprecated
     public void removeAccuracy() {
         mHorizontalAccuracyMeters = 0.0f;
         mFieldsMask &= ~HAS_HORIZONTAL_ACCURACY_MASK;
@@ -839,7 +851,11 @@
      *
      * <p>Following this call {@link #hasVerticalAccuracy} will return false, and
      * {@link #getVerticalAccuracyMeters} will return 0.0.
+     *
+     * @deprecated use a new Location object for location updates.
+     * @removed
      */
+    @Deprecated
     public void removeVerticalAccuracy() {
         mVerticalAccuracyMeters = 0.0f;
         mFieldsMask &= ~HAS_VERTICAL_ACCURACY_MASK;
@@ -883,7 +899,11 @@
      *
      * <p>Following this call {@link #hasSpeedAccuracy} will return false, and
      * {@link #getSpeedAccuracyMetersPerSecond} will return 0.0.
+     *
+     * @deprecated use a new Location object for location updates.
+     * @removed
      */
+    @Deprecated
     public void removeSpeedAccuracy() {
         mSpeedAccuracyMetersPerSecond = 0.0f;
         mFieldsMask &= ~HAS_SPEED_ACCURACY_MASK;
@@ -927,7 +947,11 @@
      *
      * <p>Following this call {@link #hasBearingAccuracy} will return false, and
      * {@link #getBearingAccuracyDegrees} will return 0.0.
+     *
+     * @deprecated use a new Location object for location updates.
+     * @removed
      */
+    @Deprecated
     public void removeBearingAccuracy() {
         mBearingAccuracyDegrees = 0.0f;
         mFieldsMask &= ~HAS_BEARING_ACCURACY_MASK;
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
index 246bd2b..5beb412 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
@@ -314,8 +314,8 @@
     }
 
     class DevicesAdapter extends ArrayAdapter<DeviceFilterPair> {
-        //TODO wifi icon
         private Drawable BLUETOOTH_ICON = icon(android.R.drawable.stat_sys_data_bluetooth);
+        private Drawable WIFI_ICON = icon(com.android.internal.R.drawable.ic_wifi_signal_3);
 
         private Drawable icon(int drawableRes) {
             Drawable icon = getResources().getDrawable(drawableRes, null);
@@ -345,6 +345,11 @@
                     device.equals(mSelectedDevice)
                             ? Color.GRAY
                             : Color.TRANSPARENT);
+            textView.setCompoundDrawablesWithIntrinsicBounds(
+                    device.device instanceof android.net.wifi.ScanResult
+                        ? WIFI_ICON
+                        : BLUETOOTH_ICON,
+                    null, null, null);
             textView.setOnClickListener((view) -> {
                 mSelectedDevice = device;
                 notifyDataSetChanged();
@@ -357,8 +362,6 @@
             textView.setTextColor(Color.BLACK);
             final int padding = DeviceChooserActivity.getPadding(getResources());
             textView.setPadding(padding, padding, padding, padding);
-            textView.setCompoundDrawablesWithIntrinsicBounds(
-                    BLUETOOTH_ICON, null, null, null);
             textView.setCompoundDrawablePadding(padding);
             return textView;
         }
diff --git a/packages/SettingsLib/res/layout/usage_view.xml b/packages/SettingsLib/res/layout/usage_view.xml
index 1d56668..151d1ee 100644
--- a/packages/SettingsLib/res/layout/usage_view.xml
+++ b/packages/SettingsLib/res/layout/usage_view.xml
@@ -76,17 +76,23 @@
             android:id="@+id/bottom_label_space"
             android:layout_width="@dimen/usage_graph_labels_width"
             android:layout_height="wrap_content"/>
-        <include android:id="@+id/label_start"
-            layout="@layout/usage_side_label" />
-
-        <Space
+        <LinearLayout
             android:layout_width="0dp"
             android:layout_height="wrap_content"
-            android:layout_weight="1" />
+            android:layout_weight="1"
+            android:orientation="horizontal"
+            android:layoutDirection="ltr">
+            <include android:id="@+id/label_start"
+                     layout="@layout/usage_side_label" />
 
-        <include android:id="@+id/label_end"
-            layout="@layout/usage_side_label" />
+            <Space
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1" />
 
+            <include android:id="@+id/label_end"
+                     layout="@layout/usage_side_label" />
+        </LinearLayout>
     </LinearLayout>
 
 </LinearLayout>
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index 10f3b63..c109704 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -46,6 +46,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.text.format.Formatter;
+import android.util.IconDrawableFactory;
 import android.util.Log;
 import android.util.SparseArray;
 
@@ -95,6 +96,7 @@
 
     final Context mContext;
     final PackageManager mPm;
+    final IconDrawableFactory mDrawableFactory;
     final IPackageManager mIpm;
     final UserManager mUm;
     final StorageStatsManager mStats;
@@ -132,6 +134,7 @@
     private ApplicationsState(Application app) {
         mContext = app;
         mPm = mContext.getPackageManager();
+        mDrawableFactory = IconDrawableFactory.newInstance(mContext);
         mIpm = AppGlobals.getPackageManager();
         mUm = mContext.getSystemService(UserManager.class);
         mStats = mContext.getSystemService(StorageStatsManager.class);
@@ -327,7 +330,7 @@
             return;
         }
         synchronized (entry) {
-            entry.ensureIconLocked(mContext, mPm);
+            entry.ensureIconLocked(mContext, mDrawableFactory);
         }
     }
 
@@ -943,7 +946,7 @@
                             AppEntry entry = mAppEntries.get(i);
                             if (entry.icon == null || !entry.mounted) {
                                 synchronized (entry) {
-                                    if (entry.ensureIconLocked(mContext, mPm)) {
+                                    if (entry.ensureIconLocked(mContext, mDrawableFactory)) {
                                         if (!mRunning) {
                                             mRunning = true;
                                             Message m = mMainHandler.obtainMessage(
@@ -1266,10 +1269,10 @@
             }
         }
 
-        boolean ensureIconLocked(Context context, PackageManager pm) {
+        boolean ensureIconLocked(Context context, IconDrawableFactory drawableFactory) {
             if (this.icon == null) {
                 if (this.apkFile.exists()) {
-                    this.icon = getBadgedIcon(pm);
+                    this.icon = drawableFactory.getBadgedIcon(info);
                     return true;
                 } else {
                     this.mounted = false;
@@ -1281,19 +1284,13 @@
                 // its icon.
                 if (this.apkFile.exists()) {
                     this.mounted = true;
-                    this.icon = getBadgedIcon(pm);
+                    this.icon = drawableFactory.getBadgedIcon(info);
                     return true;
                 }
             }
             return false;
         }
 
-        private Drawable getBadgedIcon(PackageManager pm) {
-            // Do badging ourself so that it comes from the user of the app not the current user.
-            return pm.getUserBadgedIcon(pm.loadUnbadgedItemIcon(info, info),
-                    new UserHandle(UserHandle.getUserId(info.uid)));
-        }
-
         public String getVersion(Context context) {
             try {
                 return context.getPackageManager().getPackageInfo(info.packageName, 0).versionName;
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
index 6bcf256..fb48054 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
@@ -513,7 +513,7 @@
             return null;
         }
         if (!providerMap.containsKey(authority)) {
-            providerMap.put(authority, context.getContentResolver().acquireProvider(uri));
+            providerMap.put(authority, context.getContentResolver().acquireUnstableProvider(uri));
         }
         return providerMap.get(authority);
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java
index 231fc69..3f826cc 100644
--- a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java
+++ b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java
@@ -27,6 +27,7 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.util.IconDrawableFactory;
 import android.util.Log;
 
 import java.util.ArrayList;
@@ -48,10 +49,12 @@
 
     private final PackageManager mPackageManager;
     private final Context mContext;
+    private final IconDrawableFactory mDrawableFactory;
 
     public RecentLocationApps(Context context) {
         mContext = context;
         mPackageManager = context.getPackageManager();
+        mDrawableFactory = IconDrawableFactory.newInstance(context);
     }
 
     /**
@@ -146,8 +149,7 @@
             }
 
             final UserHandle userHandle = new UserHandle(userId);
-            Drawable appIcon = mPackageManager.getApplicationIcon(appInfo);
-            Drawable icon = mPackageManager.getUserBadgedIcon(appIcon, userHandle);
+            Drawable icon = mDrawableFactory.getBadgedIcon(appInfo, userId);
             CharSequence appLabel = mPackageManager.getApplicationLabel(appInfo);
             CharSequence badgedAppLabel = mPackageManager.getUserBadgedLabel(appLabel, userHandle);
             if (appLabel.toString().contentEquals(badgedAppLabel)) {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
index 5310b7a..8415dc5 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
@@ -302,8 +302,10 @@
         when(mIContentProvider.call(anyString(),
                 eq(TileUtils.getMethodFromUri(Uri.parse(URI_GET_SUMMARY))), eq(URI_GET_SUMMARY),
                 any())).thenReturn(bundle);
-        when(mContentResolver.acquireProvider(anyString())).thenReturn(mIContentProvider);
-        when(mContentResolver.acquireProvider(any(Uri.class))).thenReturn(mIContentProvider);
+        when(mContentResolver.acquireUnstableProvider(anyString()))
+                .thenReturn(mIContentProvider);
+        when(mContentResolver.acquireUnstableProvider(any(Uri.class)))
+                .thenReturn(mIContentProvider);
 
         TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
                 null /* defaultCategory */, outTiles, false /* usePriority */,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 169a034..48429e8 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -1109,6 +1109,33 @@
         // Retrieve the ssaid from the table if present.
         final Setting ssaid = mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_SSAID, owningUserId,
                 name);
+        // If the app is an Instant App use its stored SSAID instead of our own.
+        final String instantSsaid;
+        final long token = Binder.clearCallingIdentity();
+        try {
+            instantSsaid = mPackageManager.getInstantAppAndroidId(callingPkg.packageName,
+                    owningUserId);
+        } catch (RemoteException e) {
+            Slog.e(LOG_TAG, "Failed to get Instant App Android ID", e);
+            return null;
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+        if (instantSsaid != null) {
+            // Use the stored value if it is still valid.
+            if (ssaid != null && instantSsaid.equals(ssaid.getValue())) {
+                return ssaid;
+            }
+            // The value has changed, update the stored value.
+            final SettingsState ssaidSettings = mSettingsRegistry.getSettingsLocked(
+                    SETTINGS_TYPE_SSAID, owningUserId);
+            final boolean success = ssaidSettings.insertSettingLocked(name, instantSsaid, null,
+                    true, callingPkg.packageName);
+            if (!success) {
+                throw new IllegalStateException("Failed to update instant app android id");
+            }
+            return mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_SSAID, owningUserId, name);
+        }
 
         // Lazy initialize ssaid if not yet present in ssaid table.
         if (ssaid == null || ssaid.isNull() || ssaid.getValue() == null) {
diff --git a/packages/SystemUI/res/drawable/ic_info_outline.xml b/packages/SystemUI/res/drawable/ic_info_outline.xml
new file mode 100644
index 0000000..a4a3e9a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_info_outline.xml
@@ -0,0 +1,25 @@
+<!--
+  Copyright (C) 2016 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
+  -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="32dp"
+        android:height="32dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M11,17h2v-6h-2v6zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2L13,7h-2v2z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_pause_white_24dp.xml b/packages/SystemUI/res/drawable/ic_pause_white.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_pause_white_24dp.xml
rename to packages/SystemUI/res/drawable/ic_pause_white.xml
diff --git a/packages/SystemUI/res/drawable/ic_play_arrow_white_24dp.xml b/packages/SystemUI/res/drawable/ic_play_arrow_white.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_play_arrow_white_24dp.xml
rename to packages/SystemUI/res/drawable/ic_play_arrow_white.xml
diff --git a/packages/SystemUI/res/drawable/ic_skip_next_white.xml b/packages/SystemUI/res/drawable/ic_skip_next_white.xml
new file mode 100644
index 0000000..040c7e6
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_skip_next_white.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2017 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M6 18l8.5-6L6 6v12zM16 6v12h2V6h-2z" />
+    <path
+        android:pathData="M0 0h24v24H0z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_skip_previous_white.xml b/packages/SystemUI/res/drawable/ic_skip_previous_white.xml
new file mode 100644
index 0000000..b9b94b7
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_skip_previous_white.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2017 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M6 6h2v12H6zm3.5 6l8.5 6V6z" />
+    <path
+        android:pathData="M0 0h24v24H0z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_accessibility.xml b/packages/SystemUI/res/drawable/ic_volume_accessibility.xml
index 657efaa..88fb2d2 100644
--- a/packages/SystemUI/res/drawable/ic_volume_accessibility.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_accessibility.xml
@@ -18,8 +18,9 @@
         android:width="32dp"
         android:height="32dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
+        android:viewportHeight="24.0"
+        android:tint="?android:attr/colorControlNormal">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M20.5,6c-2.61,0.7 -5.67,1 -8.5,1s-5.89,-0.3 -8.5,-1L3,8c1.86,0.5 4,0.83 6,1v13h2v-6h2v6h2V9c2,-0.17 4.14,-0.5 6,-1l-0.5,-2zM12,6c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2z"/>
-</vector>
\ No newline at end of file
+</vector>
diff --git a/packages/SystemUI/res/layout/notification_snooze.xml b/packages/SystemUI/res/layout/notification_snooze.xml
index 5bd64de..b70f24b 100644
--- a/packages/SystemUI/res/layout/notification_snooze.xml
+++ b/packages/SystemUI/res/layout/notification_snooze.xml
@@ -19,47 +19,56 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:minHeight="@dimen/snooze_snackbar_min_height"
-    android:id="@+id/notification_snooze"
-    android:clickable="true"
-    android:gravity="center_vertical"
-    android:orientation="horizontal"
-    android:paddingStart="24dp"
-    android:paddingEnd="24dp"
-    android:background="@color/snooze_snackbar_bg">
-    
-    <TextView
-        android:id="@+id/snooze_option_default"
-        style="@style/TextAppearance.SnoozeSnackBar"
-        android:layout_width="wrap_content"
-       	android:layout_height="match_parent"
-       	android:gravity="center_vertical"
-      	android:drawableTint="@android:color/white"
-       	android:drawableEnd="@drawable/notification_expand_more"/>
-    
-    <android.widget.Space
-        android:layout_width="0dp"
-        android:layout_height="0dp"
-        android:layout_weight="1"
-        />
-    
-    <TextView
-        android:id="@+id/undo"
-        style="@style/TextAppearance.SnoozeSnackBar.Button"
-        android:layout_width="wrap_content"
-        android:layout_height="match_parent"
-        android:layout_marginEnd="8dp"
-        android:layout_marginStart="8dp"
-        android:background="@drawable/btn_borderless_rect"
-        android:layout_gravity="end"
-        android:text="@string/snooze_undo" />
-    
+    android:orientation="vertical"
+    android:background="@color/notification_guts_bg_color"
+    android:theme="@*android:style/Theme.DeviceDefault.Light">
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:id="@+id/notification_snooze"
+        android:layout_height="@dimen/snooze_snackbar_min_height">
+
+        <TextView
+            android:id="@+id/snooze_option_default"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentStart="true"
+            android:layout_centerVertical="true"
+            android:paddingStart="16dp"
+            android:textColor="#DD000000"
+            android:paddingEnd="4dp"/>
+
+        <ImageView
+            android:id="@+id/expand_button"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_toEndOf="@+id/snooze_option_default"
+            android:layout_centerVertical="true"
+            android:paddingTop="1dp"
+            android:tint="#9E9E9E" />
+
+        <TextView
+            android:id="@+id/undo"
+            style="@style/TextAppearance.NotificationInfo.Button"
+            android:layout_width="wrap_content"
+            android:layout_height="36dp"
+            android:layout_marginEnd="8dp"
+            android:layout_alignParentEnd="true"
+            android:layout_centerVertical="true"
+            android:text="@string/snooze_undo" />
+    </RelativeLayout>
+
+    <View
+        android:id="@+id/divider"
+        android:layout_width="match_parent"
+        android:layout_height="0.5dp"
+        android:background="#9E9E9E" />
+
     <LinearLayout
         android:id="@+id/snooze_options"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:paddingTop="8dp"
         android:paddingBottom="8dp"
-        android:orientation="vertical"/>
-    
+        android:orientation="vertical" />
+
 </com.android.systemui.statusbar.NotificationSnooze>
diff --git a/packages/SystemUI/res/layout/notification_snooze_option.xml b/packages/SystemUI/res/layout/notification_snooze_option.xml
new file mode 100644
index 0000000..aaf45f3
--- /dev/null
+++ b/packages/SystemUI/res/layout/notification_snooze_option.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright 2017, 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.
+-->
+<TextView
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="48dp"
+        android:layout_marginStart="@*android:dimen/notification_content_margin_start"
+        android:layout_marginEnd="@*android:dimen/notification_content_margin_end"
+        android:gravity="center_vertical"
+        android:textSize="14sp"
+        android:textColor="#DD000000"/>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/quick_settings_footer.xml b/packages/SystemUI/res/layout/quick_settings_footer.xml
index 8667a5a..bb1b288 100644
--- a/packages/SystemUI/res/layout/quick_settings_footer.xml
+++ b/packages/SystemUI/res/layout/quick_settings_footer.xml
@@ -14,41 +14,31 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:clickable="true"
     android:paddingBottom="@dimen/qs_tile_padding_top"
-    android:paddingTop="@dimen/qs_tile_padding_top" >
+    android:paddingTop="@dimen/qs_tile_padding_top"
+    android:paddingStart="@dimen/qs_footer_padding_start"
+    android:paddingEnd="@dimen/qs_footer_padding_end"
+    android:gravity="center_vertical"
+    android:background="?android:attr/colorPrimaryDark" >
 
     <TextView
         android:id="@+id/footer_text"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_centerHorizontal="true"
-        android:textSize="@dimen/qs_tile_text_size" />
+        android:gravity="start"
+        android:layout_weight="1"
+        android:textAppearance="@style/TextAppearance.QS.TileLabel"
+        android:textColor="?android:attr/textColorSecondary"/>
 
     <ImageView
         android:id="@+id/footer_icon"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_centerVertical="true"
-        android:layout_marginEnd="8dp"
-        android:layout_toStartOf="@id/footer_text"
+        android:layout_width="@dimen/qs_footer_icon_size"
+        android:layout_height="@dimen/qs_footer_icon_size"
         android:contentDescription="@null"
-        android:src="@drawable/ic_qs_vpn"
-        android:visibility="invisible" />
+        android:src="@drawable/ic_info_outline" />
 
-    <!-- Only shown if both images are visible -->
-    <ImageView
-        android:id="@+id/footer_icon2"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_centerVertical="true"
-        android:layout_marginEnd="8dp"
-        android:layout_toStartOf="@id/footer_icon"
-        android:contentDescription="@null"
-        android:src="@drawable/ic_qs_network_logging"
-        android:visibility="invisible" />
-
-</RelativeLayout>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/tv_pip_controls.xml b/packages/SystemUI/res/layout/tv_pip_controls.xml
index c6bcd32..61ac6f6 100644
--- a/packages/SystemUI/res/layout/tv_pip_controls.xml
+++ b/packages/SystemUI/res/layout/tv_pip_controls.xml
@@ -40,7 +40,7 @@
         android:layout_width="100dp"
         android:layout_height="wrap_content"
         android:layout_marginStart="-50dp"
-        android:src="@drawable/ic_pause_white_24dp"
+        android:src="@drawable/ic_pause_white"
         android:text="@string/pip_pause"
         android:visibility="gone" />
 </merge>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index f461bb3..83a0b7b 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -96,10 +96,6 @@
     <!-- The "inside" of a notification, reached via longpress -->
     <color name="notification_guts_bg_color">#eeeeee</color>
 
-    <!-- Colors of the snooze menu reached via snooze icon behind a notification -->
-    <color name="snooze_snackbar_bg">#FF4A4A4A</color>
-	<color name="snooze_snackbar_text">#FFA6BAFF</color>
-
     <color name="assist_orb_color">#ffffff</color>
 
     <color name="keyguard_user_switcher_background_gradient_color">#77000000</color>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 9c7a6a0..4edadea 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -119,7 +119,7 @@
     <dimen name="notification_menu_icon_padding">20dp</dimen>
 
     <!-- The minimum height for the snackbar shown after the snooze option has been chosen. -->
-    <dimen name="snooze_snackbar_min_height">48dp</dimen>
+    <dimen name="snooze_snackbar_min_height">56dp</dimen>
 
     <!-- The text size of options in the snooze menu. -->
     <dimen name="snooze_option_text_size">14sp</dimen>
@@ -263,6 +263,9 @@
     <dimen name="qs_detail_item_icon_size">24dp</dimen>
     <dimen name="qs_detail_item_icon_marginStart">0dp</dimen>
     <dimen name="qs_detail_item_icon_marginEnd">20dp</dimen>
+    <dimen name="qs_footer_padding_start">16dp</dimen>
+    <dimen name="qs_footer_padding_end">24dp</dimen>
+    <dimen name="qs_footer_icon_size">16dp</dimen>
 
     <!-- Desired qs icon overlay size. -->
     <dimen name="qs_detail_icon_overlay_size">24dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 33b1dd4..c9da889 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -376,13 +376,13 @@
     <string name="accessibility_no_sim">No SIM.</string>
 
     <!-- Content description of the cell data. [CHAR LIMIT=NONE] -->
-    <string name="accessibility_cell_data">Cellular Data</string>
+    <string name="accessibility_cell_data">Mobile Data</string>
 
     <!-- Content description of the cell data being enabled. [CHAR LIMIT=NONE] -->
-    <string name="accessibility_cell_data_on">Cellular Data On</string>
+    <string name="accessibility_cell_data_on">Mobile Data On</string>
 
     <!-- Content description of the cell data being disabled. [CHAR LIMIT=NONE] -->
-    <string name="accessibility_cell_data_off">Cellular Data Off</string>
+    <string name="accessibility_cell_data_off">Mobile Data Off</string>
 
     <!-- Content description of the bluetooth tethering icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_bluetooth_tether">Bluetooth tethering.</string>
@@ -574,11 +574,11 @@
     <!-- Title of dialog shown when 4G data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
     <string name="data_usage_disabled_dialog_4g_title">4G data is paused</string>
     <!-- Title of dialog shown when mobile data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
-    <string name="data_usage_disabled_dialog_mobile_title">Cellular data is paused</string>
+    <string name="data_usage_disabled_dialog_mobile_title">Mobile data is paused</string>
     <!-- Title of dialog shown when data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
     <string name="data_usage_disabled_dialog_title">Data is paused</string>
     <!-- Body of dialog shown when data usage has exceeded limit and has been disabled. [CHAR LIMIT=NONE] -->
-    <string name="data_usage_disabled_dialog">The data limit you set has been reached. You are no longer using cellular data.\n\nIf you resume, charges may apply for data usage.</string>
+    <string name="data_usage_disabled_dialog">The data limit you set has been reached. You are no longer using mobile data.\n\nIf you resume, charges may apply for data usage.</string>
     <!-- Dialog button indicating that data connection should be re-enabled. [CHAR LIMIT=28] -->
     <string name="data_usage_disabled_dialog_enable">Resume</string>
 
@@ -749,7 +749,7 @@
     <!-- QuickSettings: Flashlight [CHAR LIMIT=NONE] -->
     <string name="quick_settings_flashlight_label">Flashlight</string>
     <!-- QuickSettings: Cellular detail panel title [CHAR LIMIT=NONE] -->
-    <string name="quick_settings_cellular_detail_title">Cellular data</string>
+    <string name="quick_settings_cellular_detail_title">Mobile data</string>
     <!-- QuickSettings: Cellular detail panel, data usage title [CHAR LIMIT=NONE] -->
     <string name="quick_settings_cellular_detail_data_usage">Data usage</string>
     <!-- QuickSettings: Cellular detail panel, remaining data title [CHAR LIMIT=NONE] -->
@@ -1502,8 +1502,6 @@
     <string name="snooze_option_30_min">30 minutes</string>
     <!-- Notification: Menu row: Snooze options: 1 hour option. [CHAR LIMIT=50]-->
     <string name="snooze_option_1_hour">1 hour</string>
-    <!-- Notification: Menu row: Snooze options: cancel snoozing option. [CHAR LIMIT=50] -->
-    <string name="snooze_option_dont_snooze">Cancel</string>
     <!-- Notification: Menu row: Snooze undo button label. [CHAR LIMIT=50]-->
     <string name="snooze_undo">UNDO</string>
 
@@ -1897,6 +1895,18 @@
     <!-- PiP minimize description. [CHAR LIMIT=NONE] -->
     <string name="pip_minimize_description" translatable="false">Drag or fling the PIP to the edges of the screen to minimize it.</string>
 
+    <!-- Button to play the current media on picture-in-picture (PIP) [CHAR LIMIT=30] -->
+    <string name="pip_play">Play</string>
+
+    <!-- Button to pause the current media on picture-in-picture (PIP) [CHAR LIMIT=30] -->
+    <string name="pip_pause">Pause</string>
+
+    <!-- Button to skip to the next media on picture-in-picture (PIP) [CHAR LIMIT=30] -->
+    <string name="pip_skip_to_next">Skip to next</string>
+
+    <!-- Button to skip to the prev media on picture-in-picture (PIP) [CHAR LIMIT=30] -->
+    <string name="pip_skip_to_prev">Skip to previous</string>
+
     <!-- Tuner string -->
     <string name="change_theme_reboot" translatable="false">Changing the theme requires a restart.</string>
     <!-- Tuner string -->
@@ -1904,11 +1914,11 @@
     <!-- Tuner string -->
     <string name="default_theme" translatable="false">Default</string>
 
-    <!-- Title for notification & dialog that the user's phone last shut down because it got too hot. [CHAR LIMIT=30] -->
+    <!-- Title for notification & dialog that the user's phone last shut down because it got too hot. [CHAR LIMIT=40] -->
     <string name="thermal_shutdown_title">Phone turned off due to heat</string>
     <!-- Message body for notification that user's phone last shut down because it got too hot. [CHAR LIMIT=100] -->
     <string name="thermal_shutdown_message">Your phone is now running normally</string>
-    <!-- Text body for dialog alerting user that their phone last shut down bewcause it got too hot. [CHAR LIMIT=300] -->
+    <!-- Text body for dialog alerting user that their phone last shut down because it got too hot. [CHAR LIMIT=450] -->
     <string name="thermal_shutdown_dialog_message">Your phone was too hot, so it turned off to cool down. Your phone is now running normally.\n\nYour phone may get too hot if you:\n\t&#8226; Use resource-intensive apps (such as gaming, video, or navigation apps)\n\t&#8226; Download or upload large files\n\t&#8226; Use your phone in high temperatures</string>
 
     <!-- Title for notification (and dialog) that user's phone has reached a certain temperature and may start to slow down in order to cool down. [CHAR LIMIT=30] -->
diff --git a/packages/SystemUI/res/values/strings_tv.xml b/packages/SystemUI/res/values/strings_tv.xml
index 41626fc..e578068 100644
--- a/packages/SystemUI/res/values/strings_tv.xml
+++ b/packages/SystemUI/res/values/strings_tv.xml
@@ -23,8 +23,4 @@
     <string name="pip_close">Close PIP</string>
     <!-- Button to move picture-in-picture (PIP) screen to the fullscreen in PIP menu [CHAR LIMIT=30] -->
     <string name="pip_fullscreen">Full screen</string>
-    <!-- Button to play the current media on picture-in-picture (PIP) [CHAR LIMIT=30] -->
-    <string name="pip_play">Play</string>
-    <!-- Button to pause the current media on picture-in-picture (PIP) [CHAR LIMIT=30] -->
-    <string name="pip_pause">Pause</string>
 </resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index e5f04c6..dbdbd1e 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -386,20 +386,6 @@
         <item name="android:paddingEnd">8dp</item>
     </style>
 
-    <style name="TextAppearance.SnoozeSnackBar">
-        <item name="android:textSize">14sp</item>
-        <item name="android:fontFamily">sans-serif</item>
-        <item name="android:textColor">@android:color/white</item>
-    </style>
-
-    <style name="TextAppearance.SnoozeSnackBar.Button">
-        <item name="android:textSize">14sp</item>
-        <item name="android:textAllCaps">true</item>
-        <item name="android:fontFamily">sans-serif-medium</item>
-        <item name="android:gravity">center</item>
-        <item name="android:textColor">@color/snooze_snackbar_text</item>
-    </style>
-
     <style name="edit_theme" parent="@*android:style/Theme.DeviceDefault.QuickSettings">
         <item name="android:colorBackground">?android:attr/colorSecondary</item>
     </style>
diff --git a/packages/SystemUI/src/com/android/systemui/Interpolators.java b/packages/SystemUI/src/com/android/systemui/Interpolators.java
index 9b5577c..b8cfa3e 100644
--- a/packages/SystemUI/src/com/android/systemui/Interpolators.java
+++ b/packages/SystemUI/src/com/android/systemui/Interpolators.java
@@ -41,6 +41,8 @@
     public static final Interpolator CUSTOM_40_40 = new PathInterpolator(0.4f, 0f, 0.6f, 1f);
     public static final Interpolator HEADS_UP_APPEAR = new HeadsUpAppearInterpolator();
     public static final Interpolator ICON_OVERSHOT = new PathInterpolator(0.4f, 0f, 0.2f, 1.4f);
+    public static final Interpolator PANEL_CLOSE_ACCELERATED
+            = new PathInterpolator(0.3f, 0, 0.5f, 1);
 
     /**
      * Interpolator to be used when animating a move based on a click. Pair with enough duration.
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 5a04108d..8c4159a 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -462,11 +462,20 @@
         int duration = SNAP_ANIM_LEN;
         anim.setDuration(duration);
         anim.addListener(new AnimatorListenerAdapter() {
+            boolean wasCancelled = false;
+
+            @Override
+            public void onAnimationCancel(Animator animator) {
+                wasCancelled = true;
+            }
+
             @Override
             public void onAnimationEnd(Animator animator) {
                 mSnappingChild = false;
-                updateSwipeProgressFromOffset(animView, canBeDismissed);
-                mCallback.onChildSnappedBack(animView, targetLeft);
+                if (!wasCancelled) {
+                    updateSwipeProgressFromOffset(animView, canBeDismissed);
+                    mCallback.onChildSnappedBack(animView, targetLeft);
+                }
             }
         });
         prepareSnapBackAnimation(animView, anim);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
index 86bb0de..4b3cdfb 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
@@ -39,7 +39,8 @@
     // This delay controls how long to wait before we show the target when the user first moves
     // the PIP, to prevent the target from animating if the user just wants to fling the PIP
     private static final int SHOW_TARGET_DELAY = 100;
-    private static final int SHOW_TARGET_DURATION = 200;
+    private static final int SHOW_TARGET_DURATION = 350;
+    private static final int HIDE_TARGET_DURATION = 225;
 
     private Context mContext;
     private WindowManager mWindowManager;
@@ -96,7 +97,7 @@
     public void showDismissTarget() {
         mDismissView.animate()
                 .alpha(1f)
-                .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
+                .setInterpolator(Interpolators.LINEAR)
                 .setStartDelay(SHOW_TARGET_DELAY)
                 .setDuration(SHOW_TARGET_DURATION)
                 .start();
@@ -109,9 +110,9 @@
         if (mDismissView != null) {
             mDismissView.animate()
                     .alpha(0f)
-                    .setInterpolator(Interpolators.FAST_OUT_LINEAR_IN)
+                    .setInterpolator(Interpolators.LINEAR)
                     .setStartDelay(0)
-                    .setDuration(SHOW_TARGET_DURATION)
+                    .setDuration(HIDE_TARGET_DURATION)
                     .withEndAction(new Runnable() {
                         @Override
                         public void run() {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java
index 3a4caa9..62ec09b 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java
@@ -48,6 +48,8 @@
 
     private static final String ACTION_PLAY = "com.android.systemui.pip.phone.PLAY";
     private static final String ACTION_PAUSE = "com.android.systemui.pip.phone.PAUSE";
+    private static final String ACTION_NEXT = "com.android.systemui.pip.phone.NEXT";
+    private static final String ACTION_PREV = "com.android.systemui.pip.phone.PREV";
 
     /**
      * A listener interface to receive notification on changes to the media actions.
@@ -67,6 +69,8 @@
 
     private RemoteAction mPauseAction;
     private RemoteAction mPlayAction;
+    private RemoteAction mNextAction;
+    private RemoteAction mPrevAction;
 
     private BroadcastReceiver mPlayPauseActionReceiver = new BroadcastReceiver() {
         @Override
@@ -76,6 +80,10 @@
                 mMediaController.getTransportControls().play();
             } else if (action.equals(ACTION_PAUSE)) {
                 mMediaController.getTransportControls().pause();
+            } else if (action.equals(ACTION_NEXT)) {
+                mMediaController.getTransportControls().skipToNext();
+            } else if (action.equals(ACTION_PREV)) {
+                mMediaController.getTransportControls().skipToPrevious();
             }
         }
     };
@@ -95,6 +103,8 @@
         IntentFilter mediaControlFilter = new IntentFilter();
         mediaControlFilter.addAction(ACTION_PLAY);
         mediaControlFilter.addAction(ACTION_PAUSE);
+        mediaControlFilter.addAction(ACTION_NEXT);
+        mediaControlFilter.addAction(ACTION_PREV);
         mContext.registerReceiver(mPlayPauseActionReceiver, mediaControlFilter);
 
         createMediaActions();
@@ -143,11 +153,21 @@
         int state = mMediaController.getPlaybackState().getState();
         boolean isPlaying = MediaSession.isActiveState(state);
         long actions = mMediaController.getPlaybackState().getActions();
+
+        // Prev action
+        mPrevAction.setEnabled((actions & PlaybackState.ACTION_SKIP_TO_PREVIOUS) != 0);
+        mediaActions.add(mPrevAction);
+
+        // Play/pause action
         if (!isPlaying && ((actions & PlaybackState.ACTION_PLAY) != 0)) {
             mediaActions.add(mPlayAction);
         } else if (isPlaying && ((actions & PlaybackState.ACTION_PAUSE) != 0)) {
             mediaActions.add(mPauseAction);
         }
+
+        // Next action
+        mNextAction.setEnabled((actions & PlaybackState.ACTION_SKIP_TO_NEXT) != 0);
+        mediaActions.add(mNextAction);
         return mediaActions;
     }
 
@@ -157,15 +177,27 @@
     private void createMediaActions() {
         String pauseDescription = mContext.getString(R.string.pip_pause);
         mPauseAction = new RemoteAction(Icon.createWithResource(mContext,
-                R.drawable.ic_pause_white_24dp), pauseDescription, pauseDescription,
+                R.drawable.ic_pause_white), pauseDescription, pauseDescription,
                         PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_PAUSE),
                                 FLAG_UPDATE_CURRENT));
 
         String playDescription = mContext.getString(R.string.pip_play);
         mPlayAction = new RemoteAction(Icon.createWithResource(mContext,
-                R.drawable.ic_play_arrow_white_24dp), playDescription, playDescription,
+                R.drawable.ic_play_arrow_white), playDescription, playDescription,
                         PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_PLAY),
                                 FLAG_UPDATE_CURRENT));
+
+        String nextDescription = mContext.getString(R.string.pip_skip_to_next);
+        mNextAction = new RemoteAction(Icon.createWithResource(mContext,
+                R.drawable.ic_skip_next_white), nextDescription, nextDescription,
+                        PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_NEXT),
+                                FLAG_UPDATE_CURRENT));
+
+        String prevDescription = mContext.getString(R.string.pip_skip_to_prev);
+        mPrevAction = new RemoteAction(Icon.createWithResource(mContext,
+                R.drawable.ic_skip_previous_white), prevDescription, prevDescription,
+                        PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_PREV),
+                                FLAG_UPDATE_CURRENT));
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index 982b808..79ac816 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -412,16 +412,26 @@
         } else {
             actionsContainer.setVisibility(View.VISIBLE);
             if (mActionsGroup != null) {
-                mActionsGroup.removeAllViews();
+                // Hide extra views
+                for (int i = mActions.size(); i < mActionsGroup.getChildCount(); i++) {
+                    mActionsGroup.getChildAt(i).setVisibility(View.GONE);
+                }
+                // Add needed views
+                final LayoutInflater inflater = LayoutInflater.from(this);
+                while (mActionsGroup.getChildCount() < mActions.size()) {
+                    final ImageView actionView = (ImageView) inflater.inflate(
+                            R.layout.pip_menu_action, mActionsGroup, false);
+                    mActionsGroup.addView(actionView);
+                }
 
                 // Recreate the layout
                 final boolean isLandscapePip = stackBounds != null &&
                         (stackBounds.width() > stackBounds.height());
-                final LayoutInflater inflater = LayoutInflater.from(this);
                 for (int i = 0; i < mActions.size(); i++) {
                     final RemoteAction action = mActions.get(i);
-                    final ImageView actionView = (ImageView) inflater.inflate(
-                            R.layout.pip_menu_action, mActionsGroup, false);
+                    final ImageView actionView = (ImageView) mActionsGroup.getChildAt(i);
+
+                    // TODO: Check if the action drawable has changed before we reload it
                     action.getIcon().loadDrawableAsync(this, d -> {
                         d.setTint(Color.WHITE);
                         actionView.setImageDrawable(d);
@@ -439,12 +449,11 @@
                         actionView.setAlpha(DISABLED_ACTION_ALPHA);
                         actionView.setEnabled(false);
                     }
-                    if (isLandscapePip && i > 0) {
-                        LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
-                                actionView.getLayoutParams();
-                        lp.leftMargin = mBetweenActionPaddingLand;
-                    }
-                    mActionsGroup.addView(actionView);
+
+                    // Update the margin between actions
+                    LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
+                            actionView.getLayoutParams();
+                    lp.leftMargin = (isLandscapePip && i > 0) ? mBetweenActionPaddingLand : 0;
                 }
             }
 
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index fbf7ff2..3223f9f 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -63,7 +63,7 @@
     private static final int METRIC_VALUE_DISMISSED_BY_TAP = 0;
     private static final int METRIC_VALUE_DISMISSED_BY_DRAG = 1;
 
-    private static final int SHOW_DISMISS_AFFORDANCE_DELAY = 200;
+    private static final int SHOW_DISMISS_AFFORDANCE_DELAY = 225;
 
     // Allow dragging the PIP to a location to close it
     private static final boolean ENABLE_DISMISS_DRAG_TO_EDGE = true;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java
index 4c81907..acea3b6 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java
@@ -186,10 +186,10 @@
         } else {
             mPlayPauseButtonView.setVisibility(View.VISIBLE);
             if (state == PipManager.PLAYBACK_STATE_PLAYING) {
-                mPlayPauseButtonView.setImageResource(R.drawable.ic_pause_white_24dp);
+                mPlayPauseButtonView.setImageResource(R.drawable.ic_pause_white);
                 mPlayPauseButtonView.setText(R.string.pip_pause);
             } else {
-                mPlayPauseButtonView.setImageResource(R.drawable.ic_play_arrow_white_24dp);
+                mPlayPauseButtonView.setImageResource(R.drawable.ic_play_arrow_white);
                 mPlayPauseButtonView.setText(R.string.pip_play);
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 38485c7..f5e096eb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -98,9 +98,6 @@
 
         setupTileLayout();
 
-        mFooter = new QSSecurityFooter(this, context);
-        addView(mFooter.getView());
-
         mPageIndicator = LayoutInflater.from(context).inflate(
                 R.layout.qs_page_indicator, this, false);
         addView(mPageIndicator);
@@ -110,6 +107,9 @@
 
         addDivider();
 
+        mFooter = new QSSecurityFooter(this, context);
+        addView(mFooter.getView());
+
         updateResources();
 
         mBrightnessController = new BrightnessController(getContext(),
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
index 5b9d95d..51c6ad8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
@@ -1,4 +1,3 @@
-
 /*
  * Copyright (C) 2014 The Android Open Source Project
  *
@@ -51,24 +50,21 @@
     private final View mRootView;
     private final TextView mFooterText;
     private final ImageView mFooterIcon;
-    private final ImageView mFooterIcon2;
     private final Context mContext;
     private final Callback mCallback = new Callback();
     private final SecurityController mSecurityController;
     private final ActivityStarter mActivityStarter;
     private final Handler mMainHandler;
+    private final View mDivider;
 
     private AlertDialog mDialog;
     private QSTileHost mHost;
     protected H mHandler;
 
     private boolean mIsVisible;
-    private boolean mIsIconVisible;
-    private boolean mIsIcon2Visible;
     private CharSequence mFooterTextContent = null;
     private int mFooterTextId;
     private int mFooterIconId;
-    private int mFooterIcon2Id;
 
     public QSSecurityFooter(QSPanel qsPanel, Context context) {
         mRootView = LayoutInflater.from(context)
@@ -76,14 +72,13 @@
         mRootView.setOnClickListener(this);
         mFooterText = (TextView) mRootView.findViewById(R.id.footer_text);
         mFooterIcon = (ImageView) mRootView.findViewById(R.id.footer_icon);
-        mFooterIcon2 = (ImageView) mRootView.findViewById(R.id.footer_icon2);
-        mFooterIconId = R.drawable.ic_qs_vpn;
-        mFooterIcon2Id = R.drawable.ic_qs_network_logging;
+        mFooterIconId = R.drawable.ic_info_outline;
         mContext = context;
         mMainHandler = new Handler(Looper.getMainLooper());
         mActivityStarter = Dependency.get(ActivityStarter.class);
         mSecurityController = Dependency.get(SecurityController.class);
         mHandler = new H(Dependency.get(Dependency.BG_LOOPER));
+        mDivider = qsPanel == null ? null : qsPanel.getDivider();
     }
 
     public void setHostEnvironment(QSTileHost host) {
@@ -130,45 +125,102 @@
     }
 
     private void handleRefreshState() {
-        boolean isVpnEnabled = mSecurityController.isVpnEnabled();
-        boolean isNetworkLoggingEnabled = mSecurityController.isNetworkLoggingEnabled();
-        mIsIconVisible = isVpnEnabled || isNetworkLoggingEnabled;
-        mIsIcon2Visible = isVpnEnabled && isNetworkLoggingEnabled;
-        if (mSecurityController.isDeviceManaged()) {
-            final CharSequence organizationName =
-                    mSecurityController.getDeviceOwnerOrganizationName();
-            if (organizationName != null) {
-                mFooterTextContent = mContext.getResources().getString(
-                        R.string.do_disclosure_with_name, organizationName);
-            } else {
-                mFooterTextContent =
-                        mContext.getResources().getString(R.string.do_disclosure_generic);
-            }
-            mIsVisible = true;
-            int footerIconId = isVpnEnabled
-                    ? R.drawable.ic_qs_vpn
-                    : R.drawable.ic_qs_network_logging;
-            if (mFooterIconId != footerIconId) {
-                mFooterIconId = footerIconId;
-                mMainHandler.post(mUpdateIcon);
-            }
-        } else {
-            boolean isBranded = mSecurityController.isVpnBranded();
-            mFooterTextContent = mContext.getResources().getText(
-                    isBranded ? R.string.branded_vpn_footer : R.string.vpn_footer);
-            // Update the VPN footer icon, if needed.
-            int footerIconId = isVpnEnabled
-                    ? (isBranded ? R.drawable.ic_qs_branded_vpn : R.drawable.ic_qs_vpn)
-                    : R.drawable.ic_qs_network_logging;
-            if (mFooterIconId != footerIconId) {
-                mFooterIconId = footerIconId;
-                mMainHandler.post(mUpdateIcon);
-            }
-            mIsVisible = mIsIconVisible;
+        final boolean isDeviceManaged = mSecurityController.isDeviceManaged();
+        final boolean hasWorkProfile = mSecurityController.hasWorkProfile();
+        final boolean hasCACerts = mSecurityController.hasCACertInCurrentUser();
+        final boolean hasCACertsInWorkProfile = mSecurityController.hasCACertInWorkProfile();
+        final boolean isNetworkLoggingEnabled = mSecurityController.isNetworkLoggingEnabled();
+        final String vpnName = mSecurityController.getPrimaryVpnName();
+        final String vpnNameWorkProfile = mSecurityController.getWorkProfileVpnName();
+        final CharSequence organizationName = mSecurityController.getDeviceOwnerOrganizationName();
+        final CharSequence workProfileName = mSecurityController.getWorkProfileOrganizationName();
+        // Update visibility of footer
+        mIsVisible = isDeviceManaged || hasCACerts || hasCACertsInWorkProfile ||
+            vpnName != null || vpnNameWorkProfile != null;
+        // Update the string
+        mFooterTextContent = getFooterText(isDeviceManaged, hasWorkProfile,
+                hasCACerts, hasCACertsInWorkProfile, isNetworkLoggingEnabled, vpnName,
+                vpnNameWorkProfile, organizationName, workProfileName);
+        // Update the icon
+        int footerIconId = vpnName != null || vpnNameWorkProfile != null
+                ? R.drawable.ic_qs_vpn
+                : R.drawable.ic_info_outline;
+        if (mFooterIconId != footerIconId) {
+            mFooterIconId = footerIconId;
+            mMainHandler.post(mUpdateIcon);
         }
         mMainHandler.post(mUpdateDisplayState);
     }
 
+    protected CharSequence getFooterText(boolean isDeviceManaged, boolean hasWorkProfile,
+            boolean hasCACerts, boolean hasCACertsInWorkProfile, boolean isNetworkLoggingEnabled,
+            String vpnName, String vpnNameWorkProfile, CharSequence organizationName,
+            CharSequence workProfileName) {
+        if (isDeviceManaged) {
+            if (hasCACerts || hasCACertsInWorkProfile || isNetworkLoggingEnabled) {
+                if (organizationName == null) {
+                    return mContext.getString(
+                            R.string.quick_settings_disclosure_management_monitoring);
+                }
+                return mContext.getString(
+                        R.string.quick_settings_disclosure_named_management_monitoring,
+                        organizationName);
+            }
+            if (vpnName != null && vpnNameWorkProfile != null) {
+                if (organizationName == null) {
+                    return mContext.getString(R.string.quick_settings_disclosure_management_vpns);
+                }
+                return mContext.getString(R.string.quick_settings_disclosure_named_management_vpns,
+                        organizationName);
+            }
+            if (vpnName != null || vpnNameWorkProfile != null) {
+                if (organizationName == null) {
+                    return mContext.getString(
+                            R.string.quick_settings_disclosure_management_named_vpn,
+                            vpnName != null ? vpnName : vpnNameWorkProfile);
+                }
+                return mContext.getString(
+                        R.string.quick_settings_disclosure_named_management_named_vpn,
+                        organizationName,
+                        vpnName != null ? vpnName : vpnNameWorkProfile);
+            }
+            if (organizationName == null) {
+                return mContext.getString(R.string.quick_settings_disclosure_management);
+            }
+            return mContext.getString(R.string.quick_settings_disclosure_named_management,
+                    organizationName);
+        } // end if(isDeviceManaged)
+        if (hasCACertsInWorkProfile) {
+            if (workProfileName == null) {
+                return mContext.getString(
+                        R.string.quick_settings_disclosure_managed_profile_monitoring);
+            }
+            return mContext.getString(
+                    R.string.quick_settings_disclosure_named_managed_profile_monitoring,
+                    workProfileName);
+        }
+        if (hasCACerts) {
+            return mContext.getString(R.string.quick_settings_disclosure_monitoring);
+        }
+        if (vpnName != null && vpnNameWorkProfile != null) {
+            return mContext.getString(R.string.quick_settings_disclosure_vpns);
+        }
+        if (vpnNameWorkProfile != null) {
+            return mContext.getString(R.string.quick_settings_disclosure_managed_profile_named_vpn,
+                    vpnNameWorkProfile);
+        }
+        if (vpnName != null) {
+            if (hasWorkProfile) {
+                return mContext.getString(
+                        R.string.quick_settings_disclosure_personal_profile_named_vpn,
+                        vpnName);
+            }
+            return mContext.getString(R.string.quick_settings_disclosure_named_vpn,
+                    vpnName);
+        }
+        return null;
+    }
+
     @Override
     public void onClick(DialogInterface dialog, int which) {
         if (which == DialogInterface.BUTTON_NEGATIVE) {
@@ -182,18 +234,15 @@
         final String profileOwnerPackage = mSecurityController.getProfileOwnerName();
         final boolean isNetworkLoggingEnabled = mSecurityController.isNetworkLoggingEnabled();
         final String primaryVpn = mSecurityController.getPrimaryVpnName();
-        final String profileVpn = mSecurityController.getProfileVpnName();
+        final String profileVpn = mSecurityController.getWorkProfileVpnName();
         final CharSequence deviceOwnerOrganization =
                 mSecurityController.getDeviceOwnerOrganizationName();
         boolean hasProfileOwner = mSecurityController.hasProfileOwner();
-        boolean isBranded = deviceOwnerPackage == null && mSecurityController.isVpnBranded();
 
         mDialog = new SystemUIDialog(mContext);
-        if (!isBranded) {
-            mDialog.setTitle(getTitle(deviceOwnerPackage));
-        }
+        mDialog.setTitle(getTitle(deviceOwnerPackage));
         CharSequence msg = getMessage(deviceOwnerPackage, profileOwnerPackage, primaryVpn,
-                profileVpn, deviceOwnerOrganization, hasProfileOwner, isBranded);
+                profileVpn, deviceOwnerOrganization, hasProfileOwner);
         if (deviceOwnerPackage == null) {
             mDialog.setMessage(msg);
             if (mSecurityController.isVpnEnabled() && !mSecurityController.isVpnRestricted()) {
@@ -235,7 +284,7 @@
             }
         }
 
-        mDialog.setButton(DialogInterface.BUTTON_POSITIVE, getPositiveButton(isBranded), this);
+        mDialog.setButton(DialogInterface.BUTTON_POSITIVE, getPositiveButton(), this);
         mDialog.show();
         mDialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
     }
@@ -244,13 +293,13 @@
         return mContext.getString(R.string.status_bar_settings_settings_button);
     }
 
-    private String getPositiveButton(boolean isBranded) {
-        return mContext.getString(isBranded ? android.R.string.ok : R.string.quick_settings_done);
+    private String getPositiveButton() {
+        return mContext.getString(R.string.quick_settings_done);
     }
 
     protected CharSequence getMessage(String deviceOwnerPackage, String profileOwnerPackage,
             String primaryVpn, String profileVpn, CharSequence deviceOwnerOrganization,
-            boolean hasProfileOwner, boolean isBranded) {
+            boolean hasProfileOwner) {
         if (deviceOwnerPackage != null) {
             final SpannableStringBuilder message = new SpannableStringBuilder();
             if (deviceOwnerOrganization != null) {
@@ -273,13 +322,8 @@
                 return mContext.getString(R.string.monitoring_description_app_personal_work,
                         profileOwnerPackage, profileVpn, primaryVpn);
             } else {
-                if (isBranded) {
-                    return mContext.getString(R.string.branded_monitoring_description_app_personal,
-                            primaryVpn);
-                } else {
-                    return mContext.getString(R.string.monitoring_description_app_personal,
-                            primaryVpn);
-                }
+                return mContext.getString(R.string.monitoring_description_app_personal,
+                        primaryVpn);
             }
         } else if (profileVpn != null) {
             return mContext.getString(R.string.monitoring_description_app_work,
@@ -305,7 +349,6 @@
         @Override
         public void run() {
             mFooterIcon.setImageResource(mFooterIconId);
-            mFooterIcon2.setImageResource(mFooterIcon2Id);
         }
     };
 
@@ -316,8 +359,7 @@
                 mFooterText.setText(mFooterTextContent);
             }
             mRootView.setVisibility(mIsVisible ? View.VISIBLE : View.GONE);
-            mFooterIcon.setVisibility(mIsIconVisible ? View.VISIBLE : View.INVISIBLE);
-            mFooterIcon2.setVisibility(mIsIcon2Visible ? View.VISIBLE : View.INVISIBLE);
+            if (mDivider != null) mDivider.setVisibility(mIsVisible ? View.GONE : View.VISIBLE);
         }
     };
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
index 6781c16..976efb2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -340,12 +340,12 @@
         switch (state) {
             case Tile.STATE_UNAVAILABLE:
                 return Utils.getDisabled(context,
-                        Utils.getColorAttr(context, android.R.attr.textColorTertiary));
+                        Utils.getColorAttr(context, android.R.attr.textColorPrimary));
             case Tile.STATE_INACTIVE:
                 return Utils.getDisabled(context,
-                        Utils.getColorAttr(context, android.R.attr.textColorSecondary));
+                        Utils.getColorAttr(context, android.R.attr.colorForeground));
             case Tile.STATE_ACTIVE:
-                return Utils.getColorAttr(context, attr.textColorSecondary);
+                return Utils.getColorAttr(context, android.R.attr.textColorPrimary);
             default:
                 Log.e("QSTile", "Invalid state " + state);
                 return 0;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index d27bb85..9b20a7a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -259,22 +259,27 @@
             ArrayList<Item> items = new ArrayList<Item>();
             final Collection<CachedBluetoothDevice> devices = mController.getDevices();
             if (devices != null) {
+                int connectedDevices = 0;
                 for (CachedBluetoothDevice device : devices) {
                     if (device.getBondState() == BluetoothDevice.BOND_NONE) continue;
                     final Item item = new Item();
                     item.icon = R.drawable.ic_qs_bluetooth_on;
                     item.line1 = device.getName();
+                    item.tag = device;
                     int state = device.getMaxConnectionState();
                     if (state == BluetoothProfile.STATE_CONNECTED) {
                         item.icon = R.drawable.ic_qs_bluetooth_connected;
                         item.line2 = mContext.getString(R.string.quick_settings_connected);
                         item.canDisconnect = true;
+                        items.add(connectedDevices, item);
+                        connectedDevices++;
                     } else if (state == BluetoothProfile.STATE_CONNECTING) {
                         item.icon = R.drawable.ic_qs_bluetooth_connecting;
                         item.line2 = mContext.getString(R.string.quick_settings_connecting);
+                        items.add(connectedDevices, item);
+                    } else {
+                        items.add(item);
                     }
-                    item.tag = device;
-                    items.add(item);
                 }
             }
             mItems.setItems(items.toArray(new Item[items.size()]));
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 ccebd7c..429ace6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -65,7 +65,7 @@
 import android.os.UserManager;
 import android.provider.Settings;
 import android.util.ArraySet;
-import android.util.LauncherIcons;
+import android.util.IconDrawableFactory;
 import android.util.Log;
 import android.util.MutableBoolean;
 import android.view.Display;
@@ -121,6 +121,7 @@
     ActivityManager mAm;
     IActivityManager mIam;
     PackageManager mPm;
+    IconDrawableFactory mDrawableFactory;
     IPackageManager mIpm;
     AssistUtils mAssistUtils;
     WindowManager mWm;
@@ -139,7 +140,6 @@
     int mDummyThumbnailHeight;
     Paint mBgProtectionPaint;
     Canvas mBgProtectionCanvas;
-    LauncherIcons mLauncherIcons;
 
     private final Handler mHandler = new H();
 
@@ -258,6 +258,7 @@
         mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
         mIam = ActivityManager.getService();
         mPm = context.getPackageManager();
+        mDrawableFactory = IconDrawableFactory.newInstance(context);
         mIpm = AppGlobals.getPackageManager();
         mAssistUtils = new AssistUtils(context);
         mWm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
@@ -296,8 +297,6 @@
 
         Collections.addAll(sRecentsBlacklist,
                 res.getStringArray(R.array.recents_blacklist_array));
-
-        mLauncherIcons = new LauncherIcons(context);
     }
 
     /**
@@ -808,13 +807,19 @@
      * Returns the content description for a given task, badging it if necessary.  The content
      * description joins the app and activity labels.
      */
-    public String getBadgedContentDescription(ActivityInfo info, int userId, Resources res) {
+    public String getBadgedContentDescription(ActivityInfo info, int userId,
+            ActivityManager.TaskDescription td, Resources res) {
         // If we are mocking, then return a mock label
         if (RecentsDebugFlags.Static.EnableMockTasks) {
             return "Recent Task Content Description: " + userId;
         }
 
-        String activityLabel = info.loadLabel(mPm).toString();
+        String activityLabel;
+        if (td != null && td.getLabel() != null) {
+            activityLabel = td.getLabel();
+        } else {
+            activityLabel = info.loadLabel(mPm).toString();
+        }
         String applicationLabel = info.applicationInfo.loadLabel(mPm).toString();
         String badgedApplicationLabel = getBadgedLabel(applicationLabel, userId);
         return applicationLabel.equals(activityLabel) ? badgedApplicationLabel
@@ -834,8 +839,7 @@
             return new ColorDrawable(0xFF666666);
         }
 
-        Drawable icon = mLauncherIcons.wrapIconDrawableWithShadow(info.loadIcon(mPm));
-        return getBadgedIcon(icon, userId);
+        return mDrawableFactory.getBadgedIcon(info, info.applicationInfo, userId);
     }
 
     /**
@@ -850,8 +854,7 @@
             return new ColorDrawable(0xFF666666);
         }
 
-        Drawable icon = mLauncherIcons.wrapIconDrawableWithShadow(appInfo.loadIcon(mPm));
-        return getBadgedIcon(icon, userId);
+        return mDrawableFactory.getBadgedIcon(appInfo, userId);
     }
 
     /**
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 5c25bfd..78c71a1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -182,7 +182,8 @@
             // Load the title, icon, and color
             ActivityInfo info = loader.getAndUpdateActivityInfo(taskKey);
             String title = loader.getAndUpdateActivityTitle(taskKey, t.taskDescription);
-            String titleDescription = loader.getAndUpdateContentDescription(taskKey, res);
+            String titleDescription = loader.getAndUpdateContentDescription(taskKey,
+                    t.taskDescription, res);
             String dismissDescription = String.format(dismissDescFormat, titleDescription);
             String appInfoDescription = String.format(appInfoDescFormat, titleDescription);
             Drawable icon = isStackTask
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 e8ffb91..5e78b61 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -449,7 +449,8 @@
      * Returns the cached task content description if the task key is not expired, updating the
      * cache if it is.
      */
-    String getAndUpdateContentDescription(Task.TaskKey taskKey, Resources res) {
+    String getAndUpdateContentDescription(Task.TaskKey taskKey, ActivityManager.TaskDescription td,
+            Resources res) {
         SystemServicesProxy ssp = Recents.getSystemServices();
 
         // Return the cached content description if it exists
@@ -461,8 +462,15 @@
         // All short paths failed, load the label from the activity info and cache it
         ActivityInfo activityInfo = getAndUpdateActivityInfo(taskKey);
         if (activityInfo != null) {
-            label = ssp.getBadgedContentDescription(activityInfo, taskKey.userId, res);
-            mContentDescriptionCache.put(taskKey, label);
+            label = ssp.getBadgedContentDescription(activityInfo, taskKey.userId, td, res);
+            if (td == null) {
+                // Only add to the cache if the task description is null, otherwise, it is possible
+                // for the task description to change between calls without the last active time
+                // changing (ie. between preloading and Overview starting) which would lead to stale
+                // content descriptions
+                // TODO: Investigate improving this
+                mContentDescriptionCache.put(taskKey, label);
+            }
             return label;
         }
         // If the content description does not exist, return an empty label for now, but do not
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index cc91753..dff09bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -1494,7 +1494,7 @@
             return getActualHeight();
         }
         if (mGuts != null && mGuts.isExposed()) {
-            return mGuts.getHeight();
+            return mGuts.getIntrinsicHeight();
         } else if ((isChildInGroup() && !isGroupExpanded())) {
             return mPrivateLayout.getMinHeight();
         } else if (mShowAmbient) {
@@ -1835,7 +1835,9 @@
 
     @Override
     public int getMinHeight() {
-        if (!mOnKeyguard && mIsHeadsUp && mHeadsUpManager.isTrackingHeadsUp()) {
+        if (mGuts != null && mGuts.isExposed()) {
+            return mGuts.getIntrinsicHeight();
+        } else if (!mOnKeyguard && mIsHeadsUp && mHeadsUpManager.isTrackingHeadsUp()) {
                 return getPinnedHeadsUpHeight(false /* atLeastMinHeight */);
         } else if (mIsSummaryWithChildren && !isGroupExpanded() && !mShowingPublic) {
             return mChildrenContainer.getMinHeight();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
index 0a99ee6..1375310 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
@@ -74,7 +74,8 @@
     private Handler mHandler;
     private Runnable mFalsingCheck;
     private boolean mNeedsFalsingProtection;
-    private OnGutsClosedListener mListener;
+    private OnGutsClosedListener mClosedListener;
+    private OnHeightChangedListener mHeightListener;
 
     private GutsContent mGutsContent;
 
@@ -88,6 +89,11 @@
         public View getContentView();
 
         /**
+         * @return the actual height of the content.
+         */
+        public int getActualHeight();
+
+        /**
          * Called when the guts view have been told to close, typically after an outside
          * interaction. Returning {@code true} here will prevent the guts view to close.
          */
@@ -103,6 +109,10 @@
         public void onGutsClosed(NotificationGuts guts);
     }
 
+    public interface OnHeightChangedListener {
+        public void onHeightChanged(NotificationGuts guts);
+    }
+
     interface OnSettingsClickListener {
         void onClick(View v, int appUid);
     }
@@ -126,7 +136,6 @@
 
     public NotificationGuts(Context context) {
         this(context, null);
-
     }
 
     public void setGutsContent(GutsContent content) {
@@ -190,8 +199,8 @@
 
     public void closeControls(int x, int y, boolean save) {
         if (getWindowToken() == null) {
-            if (mListener != null) {
-                mListener.onGutsClosed(this);
+            if (mClosedListener != null) {
+                mClosedListener.onGutsClosed(this);
             }
             return;
         }
@@ -199,8 +208,8 @@
             animateClose(x, y);
         }
         setExposed(false, mNeedsFalsingProtection);
-        if (mListener != null) {
-            mListener.onGutsClosed(this);
+        if (mClosedListener != null) {
+            mClosedListener.onGutsClosed(this);
         }
     }
 
@@ -235,6 +244,10 @@
         return mActualHeight;
     }
 
+    public int getIntrinsicHeight() {
+        return mGutsContent != null && mExposed ? mGutsContent.getActualHeight() : getHeight();
+    }
+
     public void setClipTopAmount(int clipTopAmount) {
         mClipTopAmount = clipTopAmount;
         invalidate();
@@ -252,7 +265,17 @@
     }
 
     public void setClosedListener(OnGutsClosedListener listener) {
-        mListener = listener;
+        mClosedListener = listener;
+    }
+
+    public void setHeightChangedListener(OnHeightChangedListener listener) {
+        mHeightListener = listener;
+    }
+
+    protected void onHeightChanged() {
+        if (mHeightListener != null) {
+            mHeightListener.onHeightChanged(this);
+        }
     }
 
     public void setExposed(boolean exposed, boolean needsFalsingProtection) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
index 8925189..f3c7b84 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
@@ -403,4 +403,9 @@
         }
         return false;
     }
+
+    @Override
+    public int getActualHeight() {
+        return getHeight();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
index 802925a..7563fd1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
@@ -317,6 +317,10 @@
     }
 
     private void dismiss(View animView, float velocity) {
+        if (mFadeAnimator != null) {
+            mFadeAnimator.cancel();
+        }
+        mHandler.removeCallbacks(mCheckForDrag);
         mMenuSnappedTo = false;
         mDismissing = true;
         mSwipeHelper.dismiss(animView, velocity);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java
index 4a3f112..ccc99c5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java
@@ -21,35 +21,47 @@
 import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
 import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
 
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.content.res.Resources;
-import android.graphics.Color;
+import android.graphics.Typeface;
 import android.service.notification.SnoozeCriterion;
 import android.service.notification.StatusBarNotification;
+import android.text.SpannableString;
+import android.text.style.StyleSpan;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.util.TypedValue;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
+
+import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 
 public class NotificationSnooze extends LinearLayout
         implements NotificationGuts.GutsContent, View.OnClickListener {
 
-    private static final int MAX_ASSISTANT_SUGGESTIONS = 2;
+    private static final int MAX_ASSISTANT_SUGGESTIONS = 1;
     private NotificationGuts mGutsContainer;
     private NotificationSwipeActionHelper mSnoozeListener;
     private StatusBarNotification mSbn;
 
     private TextView mSelectedOptionText;
     private TextView mUndoButton;
-    private ViewGroup mSnoozeOptionView;
+    private ImageView mExpandButton;
+    private View mDivider;
+    private ViewGroup mSnoozeOptionContainer;
     private List<SnoozeOption> mSnoozeOptions;
-    private boolean mSnoozing;
+    private int mCollapsedHeight;
 
     private SnoozeOption mSelectedOption;
+    private boolean mSnoozing;
+    private boolean mExpanded;
+    private AnimatorSet mExpandAnimation;
 
     public NotificationSnooze(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -58,16 +70,21 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
+        mCollapsedHeight = getResources().getDimensionPixelSize(R.dimen.snooze_snackbar_min_height);
+        findViewById(R.id.notification_snooze).setOnClickListener(this);
+        mSelectedOptionText = (TextView) findViewById(R.id.snooze_option_default);
+        mUndoButton = (TextView) findViewById(R.id.undo);
+        mUndoButton.setOnClickListener(this);
+        mExpandButton = (ImageView) findViewById(R.id.expand_button);
+        mDivider = findViewById(R.id.divider);
+        mDivider.setAlpha(0f);
+        mSnoozeOptionContainer = (ViewGroup) findViewById(R.id.snooze_options);
+        mSnoozeOptionContainer.setAlpha(0f);
+
         // Create the different options based on list
         mSnoozeOptions = getDefaultSnoozeOptions();
         createOptionViews();
 
-        // Snackbar
-        mSelectedOptionText = findViewById(R.id.snooze_option_default);
-        mSelectedOptionText.setOnClickListener(this);
-        mUndoButton = findViewById(R.id.undo);
-        mUndoButton.setOnClickListener(this);
-
         // Default to first option in list
         setSelected(mSnoozeOptions.get(0));
     }
@@ -96,52 +113,68 @@
 
     private SnoozeOption createOption(int descriptionResId, int minutes) {
         Resources res = getResources();
-        String resultText = String.format(
-                res.getString(R.string.snoozed_for_time), res.getString(descriptionResId));
-        return new SnoozeOption(null, minutes, res.getString(descriptionResId), resultText);
+        final String description = res.getString(descriptionResId);
+        String resultText = String.format(res.getString(R.string.snoozed_for_time), description);
+        SpannableString string = new SpannableString(resultText);
+        string.setSpan(new StyleSpan(Typeface.BOLD),
+                resultText.length() - description.length(), resultText.length(), 0 /* flags */);
+        return new SnoozeOption(null, minutes, res.getString(descriptionResId), string);
     }
 
     private void createOptionViews() {
-        mSnoozeOptionView = findViewById(R.id.snooze_options);
-        mSnoozeOptionView.removeAllViews();
-        mSnoozeOptionView.setVisibility(View.GONE);
-        final Resources res = getResources();
-        final int textSize = res.getDimensionPixelSize(R.dimen.snooze_option_text_size);
-        final int p = res.getDimensionPixelSize(R.dimen.snooze_option_padding);
-
-        // Add all the options
+        mSnoozeOptionContainer.removeAllViews();
+        LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
+                Context.LAYOUT_INFLATER_SERVICE);
         for (int i = 0; i < mSnoozeOptions.size(); i++) {
             SnoozeOption option = mSnoozeOptions.get(i);
-            TextView tv = new TextView(getContext());
-            tv.setTextColor(Color.WHITE);
-            tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
-            tv.setPadding(p, p, p, p);
-            mSnoozeOptionView.addView(tv);
+            TextView tv = (TextView) inflater.inflate(R.layout.notification_snooze_option,
+                    mSnoozeOptionContainer, false);
+            mSnoozeOptionContainer.addView(tv);
             tv.setText(option.description);
             tv.setTag(option);
             tv.setOnClickListener(this);
         }
+    }
 
-        // Add the undo option as final item
-        TextView tv = new TextView(getContext());
-        tv.setTextColor(Color.WHITE);
-        tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
-        tv.setPadding(p, p, p, p);
-        mSnoozeOptionView.addView(tv);
-        tv.setText(R.string.snooze_option_dont_snooze);
-        tv.setOnClickListener(this);
+    private void hideSelectedOption() {
+        final int childCount = mSnoozeOptionContainer.getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            final View child = mSnoozeOptionContainer.getChildAt(i);
+            child.setVisibility(child.getTag() == mSelectedOption ? View.GONE : View.VISIBLE);
+        }
     }
 
     private void showSnoozeOptions(boolean show) {
-        mSelectedOptionText.setVisibility(show ? View.GONE : View.VISIBLE);
-        mUndoButton.setVisibility(show ? View.GONE : View.VISIBLE);
-        mSnoozeOptionView.setVisibility(show ? View.VISIBLE : View.GONE);
+        mExpanded = show;
+        animateSnoozeOptions(show);
+        int drawableId = show ? com.android.internal.R.drawable.ic_collapse_notification
+                : com.android.internal.R.drawable.ic_expand_notification;
+        mExpandButton.setImageResource(drawableId);
+        if (mGutsContainer != null) {
+            mGutsContainer.onHeightChanged();
+        }
+    }
+
+    private void animateSnoozeOptions(boolean show) {
+        if (mExpandAnimation != null) {
+            mExpandAnimation.cancel();
+        }
+        ObjectAnimator dividerAnim = ObjectAnimator.ofFloat(mDivider, View.ALPHA,
+                mDivider.getAlpha(), show ? 1f : 0f);
+        ObjectAnimator optionAnim = ObjectAnimator.ofFloat(mSnoozeOptionContainer, View.ALPHA,
+                mSnoozeOptionContainer.getAlpha(), show ? 1f : 0f);
+        mExpandAnimation = new AnimatorSet();
+        mExpandAnimation.playTogether(dividerAnim, optionAnim);
+        mExpandAnimation.setDuration(150);
+        mExpandAnimation.setInterpolator(show ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
+        mExpandAnimation.start();
     }
 
     private void setSelected(SnoozeOption option) {
         mSelectedOption = option;
         mSelectedOptionText.setText(option.confirmation);
         showSnoozeOptions(false);
+        hideSelectedOption();
     }
 
     @Override
@@ -153,17 +186,28 @@
         final SnoozeOption tag = (SnoozeOption) v.getTag();
         if (tag != null) {
             setSelected(tag);
-        } else if (id == R.id.snooze_option_default) {
-            // Show more snooze options
-            showSnoozeOptions(true);
+        } else if (id == R.id.notification_snooze) {
+            // Toggle snooze options
+            showSnoozeOptions(!mExpanded);
         } else {
-            undoSnooze();
+            // Undo snooze was selected
+            mSelectedOption = null;
+            int[] parentLoc = new int[2];
+            int[] targetLoc = new int[2];
+            mGutsContainer.getLocationOnScreen(parentLoc);
+            v.getLocationOnScreen(targetLoc);
+            final int centerX = v.getWidth() / 2;
+            final int centerY = v.getHeight() / 2;
+            final int x = targetLoc[0] - parentLoc[0] + centerX;
+            final int y = targetLoc[1] - parentLoc[1] + centerY;
+            showSnoozeOptions(false);
+            mGutsContainer.closeControls(x, y, false /* save */);
         }
     }
 
-    private void undoSnooze() {
-        mSelectedOption = null;
-        mGutsContainer.closeControls(-1 /* x */, -1 /* y */, true /* notify */);
+    @Override
+    public int getActualHeight() {
+        return mExpanded ? getHeight() : mCollapsedHeight;
     }
 
     @Override
@@ -173,6 +217,8 @@
 
     @Override
     public View getContentView() {
+        // Reset the view before use
+        setSelected(mSnoozeOptions.get(0));
         return this;
     }
 
@@ -197,11 +243,8 @@
             mSnoozing = true;
             mSnoozeListener.snooze(mSbn, mSelectedOption);
             return true;
-        } else {
-            // Reset the view once it's closed
-            setSelected(mSnoozeOptions.get(0));
-            showSnoozeOptions(false);
         }
+        // The view should be closed
         return false;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
index 1ffc944..0b9244a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
@@ -29,6 +29,7 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import com.android.internal.widget.NotificationExpandButton;
 import com.android.systemui.Interpolators;
 import com.android.systemui.ViewInvertHelper;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
@@ -54,7 +55,7 @@
     protected int mColor;
     private ImageView mIcon;
 
-    private ImageView mExpandButton;
+    private NotificationExpandButton mExpandButton;
     private NotificationHeaderView mNotificationHeader;
     private TextView mHeaderText;
     private ImageView mWorkProfileImage;
@@ -106,13 +107,13 @@
     }
 
     protected void resolveHeaderViews() {
-        mIcon = (ImageView) mView.findViewById(com.android.internal.R.id.icon);
-        mHeaderText = (TextView) mView.findViewById(com.android.internal.R.id.header_text);
-        mExpandButton = (ImageView) mView.findViewById(com.android.internal.R.id.expand_button);
-        mWorkProfileImage = (ImageView) mView.findViewById(com.android.internal.R.id.profile_badge);
+        mIcon = mView.findViewById(com.android.internal.R.id.icon);
+        mHeaderText = mView.findViewById(com.android.internal.R.id.header_text);
+        mExpandButton = mView.findViewById(com.android.internal.R.id.expand_button);
+        mExpandButton.setLabeledBy(mRow);
+        mWorkProfileImage = mView.findViewById(com.android.internal.R.id.profile_badge);
         mColor = resolveColor(mExpandButton);
-        mNotificationHeader = (NotificationHeaderView) mView.findViewById(
-                com.android.internal.R.id.notification_header);
+        mNotificationHeader = mView.findViewById(com.android.internal.R.id.notification_header);
         getDozer().setColor(mColor);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
index 9206914..f216d6c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
@@ -83,7 +83,7 @@
     /**
      * How much faster we collapse the lockscreen when authenticating with fingerprint.
      */
-    private static final float FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR = 1.3f;
+    private static final float FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR = 1.1f;
 
     private PowerManager mPowerManager;
     private Handler mHandler = new Handler();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index f1b4498..8a97be5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -2022,7 +2022,7 @@
     @Override
     protected boolean shouldUseDismissingAnimation() {
         return mStatusBarState != StatusBarState.SHADE
-                && !mStatusBar.isKeyguardCurrentlySecure();
+                && (!mStatusBar.isKeyguardCurrentlySecure() || !isTracking());
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 48a8329..e86fd48 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -725,8 +725,14 @@
             }
         } else {
             if (shouldUseDismissingAnimation()) {
-                mFlingAnimationUtilsDismissing.apply(animator, mExpandedHeight, target, vel,
-                        getHeight());
+                if (vel == 0) {
+                    animator.setInterpolator(Interpolators.PANEL_CLOSE_ACCELERATED);
+                    long duration = (long) (200 + mExpandedHeight / getHeight() * 100);
+                    animator.setDuration(duration);
+                } else {
+                    mFlingAnimationUtilsDismissing.apply(animator, mExpandedHeight, target, vel,
+                            getHeight());
+                }
             } else {
                 mFlingAnimationUtilsClosing
                         .apply(animator, mExpandedHeight, target, vel, getHeight());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 79191f3..46d6415 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -5774,6 +5774,9 @@
             snoozeGuts.setSnoozeListener(mStackScroller.getSwipeActionHelper());
             snoozeGuts.setStatusBarNotification(sbn);
             snoozeGuts.setSnoozeOptions(row.getEntry().snoozeCriteria);
+            guts.setHeightChangedListener((NotificationGuts g) -> {
+                mStackScroller.onHeightChanged(row, row.isShown() /* needsAnimation */);
+            });
         }
 
         if (gutsView instanceof NotificationInfo) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java
index 3f8e41a..1fb9b69 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java
@@ -23,16 +23,20 @@
     /** Whether the device has device owner, even if not on this user. */
     boolean isDeviceManaged();
     boolean hasProfileOwner();
+    boolean hasWorkProfile();
     String getDeviceOwnerName();
     String getProfileOwnerName();
     CharSequence getDeviceOwnerOrganizationName();
+    CharSequence getWorkProfileOrganizationName();
     boolean isNetworkLoggingEnabled();
     boolean isVpnEnabled();
     boolean isVpnRestricted();
     /** Whether the VPN app should use branded VPN iconography.  */
     boolean isVpnBranded();
     String getPrimaryVpnName();
-    String getProfileVpnName();
+    String getWorkProfileVpnName();
+    boolean hasCACertInCurrentUser();
+    boolean hasCACertInWorkProfile();
     void onUserSwitched(int newUserId);
 
     public interface SecurityControllerCallback {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index 19ced23..fcb7289 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -138,6 +138,13 @@
     }
 
     @Override
+    public CharSequence getWorkProfileOrganizationName() {
+        final int profileId = getWorkProfileUserId(mCurrentUserId);
+        if (profileId == UserHandle.USER_NULL) return null;
+        return mDevicePolicyManager.getOrganizationNameForUser(profileId);
+    }
+
+    @Override
     public String getPrimaryVpnName() {
         VpnConfig cfg = mCurrentVpns.get(mVpnUserId);
         if (cfg != null) {
@@ -147,16 +154,27 @@
         }
     }
 
+    private int getWorkProfileUserId(int userId) {
+        for (final UserInfo userInfo : mUserManager.getProfiles(userId)) {
+            if (userInfo.isManagedProfile()) {
+                return userInfo.id;
+            }
+        }
+        return UserHandle.USER_NULL;
+    }
+
     @Override
-    public String getProfileVpnName() {
-        for (int profileId : mUserManager.getProfileIdsWithDisabled(mVpnUserId)) {
-            if (profileId == mVpnUserId) {
-                continue;
-            }
-            VpnConfig cfg = mCurrentVpns.get(profileId);
-            if (cfg != null) {
-                return getNameForVpnConfig(cfg, UserHandle.of(profileId));
-            }
+    public boolean hasWorkProfile() {
+        return getWorkProfileUserId(mCurrentUserId) != UserHandle.USER_NULL;
+    }
+
+    @Override
+    public String getWorkProfileVpnName() {
+        final int profileId = getWorkProfileUserId(mVpnUserId);
+        if (profileId == UserHandle.USER_NULL) return null;
+        VpnConfig cfg = mCurrentVpns.get(profileId);
+        if (cfg != null) {
+            return getNameForVpnConfig(cfg, UserHandle.of(profileId));
         }
         return null;
     }
@@ -199,6 +217,18 @@
     }
 
     @Override
+    public boolean hasCACertInCurrentUser() {
+        //TODO: implement
+        return false;
+    }
+
+    @Override
+    public boolean hasCACertInWorkProfile() {
+        //TODO: implement
+        return false;
+    }
+
+    @Override
     public void removeCallback(SecurityControllerCallback callback) {
         synchronized (mCallbacks) {
             if (callback == null) return;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 697cac9..b8b046b 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -433,7 +433,7 @@
                 return false;
             }
         });
-        row.icon = (ImageButton) row.view.findViewById(R.id.volume_row_icon);
+        row.icon = row.view.findViewById(R.id.volume_row_icon);
         row.icon.setImageResource(iconRes);
         if (row.stream != AudioSystem.STREAM_ACCESSIBILITY) {
             row.icon.setOnClickListener(new OnClickListener() {
@@ -465,6 +465,8 @@
                     row.userAttempt = 0;  // reset the grace period, slider updates immediately
                 }
             });
+        } else {
+            row.icon.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
         }
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
index 1ff373c..ff644d8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
@@ -40,6 +40,15 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+/*
+ * Compile and run the whole SystemUI test suite:
+   runtest --path frameworks/base/packages/SystemUI/tests
+ *
+ * Compile and run just this class:
+   runtest --path \
+   frameworks/base/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
+*/
+
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class QSSecurityFooterTest extends SysuiTestCase {
@@ -47,11 +56,11 @@
     private final String MANAGING_ORGANIZATION = "organization";
     private final String DEVICE_OWNER_PACKAGE = "TestDPC";
     private final String VPN_PACKAGE = "TestVPN";
+    private final String VPN_PACKAGE_2 = "TestVPN 2";
 
     private ViewGroup mRootView;
     private TextView mFooterText;
     private TestableImageView mFooterIcon;
-    private TestableImageView mFooterIcon2;
     private QSSecurityFooter mFooter;
     private SecurityController mSecurityController = mock(SecurityController.class);
 
@@ -69,15 +78,12 @@
         mRootView = (ViewGroup) mFooter.getView();
         mFooterText = (TextView) mRootView.findViewById(R.id.footer_text);
         mFooterIcon = (TestableImageView) mRootView.findViewById(R.id.footer_icon);
-        mFooterIcon2 = (TestableImageView) mRootView.findViewById(R.id.footer_icon2);
         mFooter.setHostEnvironment(null);
     }
 
     @Test
     public void testUnmanaged() {
         when(mSecurityController.isDeviceManaged()).thenReturn(false);
-        when(mSecurityController.isVpnEnabled()).thenReturn(false);
-        when(mSecurityController.isVpnBranded()).thenReturn(false);
         mFooter.refreshState();
 
         waitForIdleSync(mFooter.mHandler);
@@ -91,8 +97,12 @@
         mFooter.refreshState();
 
         waitForIdleSync(mFooter.mHandler);
-        assertEquals(mContext.getString(R.string.do_disclosure_generic), mFooterText.getText());
+        assertEquals(mContext.getString(R.string.quick_settings_disclosure_management),
+                     mFooterText.getText());
         assertEquals(View.VISIBLE, mRootView.getVisibility());
+        assertEquals(View.VISIBLE, mFooterIcon.getVisibility());
+        // -1 == never set.
+        assertEquals(-1, mFooterIcon.getLastImageResource());
     }
 
     @Test
@@ -103,37 +113,100 @@
         mFooter.refreshState();
 
         waitForIdleSync(mFooter.mHandler);
-        assertEquals(mContext.getString(R.string.do_disclosure_with_name, MANAGING_ORGANIZATION),
+        assertEquals(mContext.getString(R.string.quick_settings_disclosure_named_management,
+                                        MANAGING_ORGANIZATION),
                 mFooterText.getText());
         assertEquals(View.VISIBLE, mRootView.getVisibility());
+        assertEquals(View.VISIBLE, mFooterIcon.getVisibility());
+        // -1 == never set.
+        assertEquals(-1, mFooterIcon.getLastImageResource());
     }
 
     @Test
     public void testNetworkLoggingEnabled() {
         when(mSecurityController.isDeviceManaged()).thenReturn(true);
         when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
-        when(mSecurityController.isVpnEnabled()).thenReturn(false);
         mFooter.refreshState();
 
         waitForIdleSync(mFooter.mHandler);
-        assertEquals(View.VISIBLE, mFooterIcon.getVisibility());
-        assertEquals(R.drawable.ic_qs_network_logging, mFooterIcon.getLastImageResource());
-        assertEquals(View.INVISIBLE, mFooterIcon2.getVisibility());
-    }
-
-    @Test
-    public void testVpnEnabled() {
-        when(mSecurityController.isDeviceManaged()).thenReturn(true);
-        when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(false);
-        when(mSecurityController.isVpnEnabled()).thenReturn(true);
-        when(mSecurityController.isVpnBranded()).thenReturn(false);
-        mFooter.refreshState();
-
-        waitForIdleSync(mFooter.mHandler);
+        assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_monitoring),
+                mFooterText.getText());
         assertEquals(View.VISIBLE, mFooterIcon.getVisibility());
         // -1 == never set.
         assertEquals(-1, mFooterIcon.getLastImageResource());
-        assertEquals(View.INVISIBLE, mFooterIcon2.getVisibility());
+
+        // Same situation, but with organization name set
+        when(mSecurityController.getDeviceOwnerOrganizationName())
+                .thenReturn(MANAGING_ORGANIZATION);
+        mFooter.refreshState();
+
+        waitForIdleSync(mFooter.mHandler);
+        assertEquals(mContext.getString(
+                             R.string.quick_settings_disclosure_named_management_monitoring,
+                             MANAGING_ORGANIZATION),
+                     mFooterText.getText());
+    }
+
+    @Test
+    public void testManagedCACertsInstalled() {
+        when(mSecurityController.isDeviceManaged()).thenReturn(true);
+        when(mSecurityController.hasCACertInCurrentUser()).thenReturn(true);
+        mFooter.refreshState();
+
+        waitForIdleSync(mFooter.mHandler);
+        assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_monitoring),
+                mFooterText.getText());
+    }
+
+    @Test
+    public void testManagedOneVpnEnabled() {
+        when(mSecurityController.isDeviceManaged()).thenReturn(true);
+        when(mSecurityController.isVpnEnabled()).thenReturn(true);
+        when(mSecurityController.getPrimaryVpnName()).thenReturn(VPN_PACKAGE);
+        mFooter.refreshState();
+
+        waitForIdleSync(mFooter.mHandler);
+        assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_named_vpn,
+                                        VPN_PACKAGE),
+                     mFooterText.getText());
+        assertEquals(View.VISIBLE, mFooterIcon.getVisibility());
+        assertEquals(R.drawable.ic_qs_vpn, mFooterIcon.getLastImageResource());
+
+        // Same situation, but with organization name set
+        when(mSecurityController.getDeviceOwnerOrganizationName())
+                .thenReturn(MANAGING_ORGANIZATION);
+        mFooter.refreshState();
+
+        waitForIdleSync(mFooter.mHandler);
+        assertEquals(mContext.getString(
+                              R.string.quick_settings_disclosure_named_management_named_vpn,
+                              MANAGING_ORGANIZATION, VPN_PACKAGE),
+                     mFooterText.getText());
+    }
+
+    @Test
+    public void testManagedTwoVpnsEnabled() {
+        when(mSecurityController.isDeviceManaged()).thenReturn(true);
+        when(mSecurityController.isVpnEnabled()).thenReturn(true);
+        when(mSecurityController.getPrimaryVpnName()).thenReturn(VPN_PACKAGE);
+        when(mSecurityController.getWorkProfileVpnName()).thenReturn(VPN_PACKAGE_2);
+        mFooter.refreshState();
+
+        waitForIdleSync(mFooter.mHandler);
+        assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_vpns),
+                     mFooterText.getText());
+        assertEquals(View.VISIBLE, mFooterIcon.getVisibility());
+        assertEquals(R.drawable.ic_qs_vpn, mFooterIcon.getLastImageResource());
+
+        // Same situation, but with organization name set
+        when(mSecurityController.getDeviceOwnerOrganizationName())
+                .thenReturn(MANAGING_ORGANIZATION);
+        mFooter.refreshState();
+
+        waitForIdleSync(mFooter.mHandler);
+        assertEquals(mContext.getString(R.string.quick_settings_disclosure_named_management_vpns,
+                                        MANAGING_ORGANIZATION),
+                     mFooterText.getText());
     }
 
     @Test
@@ -141,15 +214,101 @@
         when(mSecurityController.isDeviceManaged()).thenReturn(true);
         when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
         when(mSecurityController.isVpnEnabled()).thenReturn(true);
-        when(mSecurityController.isVpnBranded()).thenReturn(false);
+        when(mSecurityController.getPrimaryVpnName()).thenReturn("VPN Test App");
         mFooter.refreshState();
 
         waitForIdleSync(mFooter.mHandler);
         assertEquals(View.VISIBLE, mFooterIcon.getVisibility());
-        assertEquals(View.VISIBLE, mFooterIcon2.getVisibility());
+        assertEquals(R.drawable.ic_qs_vpn, mFooterIcon.getLastImageResource());
+        assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_monitoring),
+                mFooterText.getText());
+    }
+
+    @Test
+    public void testWorkProfileCACertsInstalled() {
+        when(mSecurityController.isDeviceManaged()).thenReturn(false);
+        when(mSecurityController.hasCACertInWorkProfile()).thenReturn(true);
+        mFooter.refreshState();
+
+        waitForIdleSync(mFooter.mHandler);
         // -1 == never set.
         assertEquals(-1, mFooterIcon.getLastImageResource());
-        assertEquals(-1, mFooterIcon2.getLastImageResource());
+        assertEquals(mContext.getString(
+                             R.string.quick_settings_disclosure_managed_profile_monitoring),
+                     mFooterText.getText());
+
+        // Same situation, but with organization name set
+        when(mSecurityController.getWorkProfileOrganizationName())
+                .thenReturn(MANAGING_ORGANIZATION);
+        mFooter.refreshState();
+
+        waitForIdleSync(mFooter.mHandler);
+        assertEquals(mContext.getString(
+                             R.string.quick_settings_disclosure_named_managed_profile_monitoring,
+                             MANAGING_ORGANIZATION),
+                     mFooterText.getText());
+    }
+
+    @Test
+    public void testCACertsInstalled() {
+        when(mSecurityController.isDeviceManaged()).thenReturn(false);
+        when(mSecurityController.hasCACertInCurrentUser()).thenReturn(true);
+        mFooter.refreshState();
+
+        waitForIdleSync(mFooter.mHandler);
+        // -1 == never set.
+        assertEquals(-1, mFooterIcon.getLastImageResource());
+        assertEquals(mContext.getString(R.string.quick_settings_disclosure_monitoring),
+                     mFooterText.getText());
+    }
+
+    @Test
+    public void testTwoVpnsEnabled() {
+        when(mSecurityController.isVpnEnabled()).thenReturn(true);
+        when(mSecurityController.getPrimaryVpnName()).thenReturn(VPN_PACKAGE);
+        when(mSecurityController.getWorkProfileVpnName()).thenReturn(VPN_PACKAGE_2);
+        mFooter.refreshState();
+
+        waitForIdleSync(mFooter.mHandler);
+        assertEquals(R.drawable.ic_qs_vpn, mFooterIcon.getLastImageResource());
+        assertEquals(mContext.getString(R.string.quick_settings_disclosure_vpns),
+                     mFooterText.getText());
+    }
+
+    @Test
+    public void testWorkProfileVpnEnabled() {
+        when(mSecurityController.isVpnEnabled()).thenReturn(true);
+        when(mSecurityController.getWorkProfileVpnName()).thenReturn(VPN_PACKAGE_2);
+        mFooter.refreshState();
+
+        waitForIdleSync(mFooter.mHandler);
+        assertEquals(R.drawable.ic_qs_vpn, mFooterIcon.getLastImageResource());
+        assertEquals(mContext.getString(
+                             R.string.quick_settings_disclosure_managed_profile_named_vpn,
+                             VPN_PACKAGE_2),
+                     mFooterText.getText());
+    }
+
+    @Test
+    public void testVpnEnabled() {
+        when(mSecurityController.isVpnEnabled()).thenReturn(true);
+        when(mSecurityController.getPrimaryVpnName()).thenReturn(VPN_PACKAGE);
+        mFooter.refreshState();
+
+        waitForIdleSync(mFooter.mHandler);
+        assertEquals(R.drawable.ic_qs_vpn, mFooterIcon.getLastImageResource());
+        assertEquals(mContext.getString(R.string.quick_settings_disclosure_named_vpn,
+                                        VPN_PACKAGE),
+                     mFooterText.getText());
+
+        when(mSecurityController.hasWorkProfile()).thenReturn(true);
+        mFooter.refreshState();
+
+        waitForIdleSync(mFooter.mHandler);
+        assertEquals(mContext.getString(
+                             R.string.quick_settings_disclosure_personal_profile_named_vpn,
+                             VPN_PACKAGE),
+                     mFooterText.getText());
     }
 
     @Test
@@ -160,8 +319,7 @@
                         null /* primaryVpn */,
                         null /* profileVpn */,
                         null /* deviceOwnerOrganization */,
-                        false /* hasProfileOwner */,
-                        false /* isBranded */));
+                        false /* hasProfileOwner */));
     }
 
     @Test
@@ -172,8 +330,7 @@
                         VPN_PACKAGE,
                         null /* profileVpn */,
                         null /* deviceOwnerOrganization */,
-                        false /* hasProfileOwner */,
-                        false /* isBranded */));
+                        false /* hasProfileOwner */));
     }
 
     @Test
@@ -184,8 +341,7 @@
                         null /* primaryVpn */,
                         null /* profileVpn */,
                         MANAGING_ORGANIZATION,
-                        false /* hasProfileOwner */,
-                        false /* isBranded */));
+                        false /* hasProfileOwner */));
     }
 
     @Test
@@ -196,8 +352,7 @@
                         VPN_PACKAGE,
                         null /* profileVpn */,
                         MANAGING_ORGANIZATION,
-                        false /* hasProfileOwner */,
-                        false /* isBranded */));
+                        false /* hasProfileOwner */));
     }
 
     private CharSequence getExpectedMessage(boolean hasDeviceOwnerOrganization, boolean hasVPN) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeSecurityController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeSecurityController.java
index 157b8a0..fee5e32 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeSecurityController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeSecurityController.java
@@ -36,6 +36,11 @@
     }
 
     @Override
+    public boolean hasWorkProfile() {
+        return false;
+    }
+
+    @Override
     public String getDeviceOwnerName() {
         return null;
     }
@@ -51,6 +56,11 @@
     }
 
     @Override
+    public CharSequence getWorkProfileOrganizationName() {
+        return null;
+    }
+
+    @Override
     public boolean isNetworkLoggingEnabled() {
         return false;
     }
@@ -76,11 +86,21 @@
     }
 
     @Override
-    public String getProfileVpnName() {
+    public String getWorkProfileVpnName() {
         return null;
     }
 
     @Override
+    public boolean hasCACertInCurrentUser() {
+        return false;
+    }
+
+    @Override
+    public boolean hasCACertInWorkProfile() {
+        return false;
+    }
+
+    @Override
     public void onUserSwitched(int newUserId) {
 
     }
diff --git a/services/Android.mk b/services/Android.mk
index a4c891b..5c863b0 100644
--- a/services/Android.mk
+++ b/services/Android.mk
@@ -27,6 +27,7 @@
     appwidget \
     autofill \
     backup \
+    companion \
     coverage\
     devicepolicy \
     midi \
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index d6f5256..1b5b2c6 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -48,6 +48,7 @@
 import android.os.UserManager;
 import android.os.UserManagerInternal;
 import android.provider.Settings;
+import android.service.autofill.FillEventHistory;
 import android.util.LocalLog;
 import android.util.Log;
 import android.util.Slog;
@@ -184,7 +185,7 @@
     }
 
     @Override
-    public void onStopUser(int userId) {
+    public void onCleanupUser(int userId) {
         synchronized (mLock) {
             removeCachedServiceLocked(userId);
         }
@@ -211,7 +212,7 @@
     /**
      * Peeks the service instance for a user.
      *
-     * @return service instance or null if not already present
+     * @return service instance or {@code null} if not already present
      */
     @Nullable
     AutofillManagerServiceImpl peekServiceForUserLocked(int userId) {
@@ -398,6 +399,21 @@
         }
 
         @Override
+        public FillEventHistory getFillEventHistory() throws RemoteException {
+            UserHandle user = getCallingUserHandle();
+            int uid = getCallingUid();
+
+            synchronized (mLock) {
+                AutofillManagerServiceImpl service = peekServiceForUserLocked(user.getIdentifier());
+                if (service != null) {
+                    return service.getFillEventHistory(uid);
+                }
+            }
+
+            return null;
+        }
+
+        @Override
         public boolean restoreSession(int sessionId, IBinder activityToken, IBinder appCallback)
                 throws RemoteException {
             activityToken = Preconditions.checkNotNull(activityToken, "activityToken");
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 57ef6d0..e274e18 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -48,7 +48,9 @@
 import android.provider.Settings;
 import android.service.autofill.AutofillService;
 import android.service.autofill.AutofillServiceInfo;
+import android.service.autofill.FillEventHistory;
 import android.service.autofill.FillRequest;
+import android.service.autofill.FillResponse;
 import android.service.autofill.IAutoFillService;
 import android.text.TextUtils;
 import android.util.LocalLog;
@@ -122,6 +124,10 @@
     @GuardedBy("mLock")
     private final SparseArray<Session> mSessions = new SparseArray<>();
 
+    /** The last selection */
+    @GuardedBy("mLock")
+    private FillEventHistory mEventHistory;
+
     /**
      * Receiver of assist data from the app's {@link Activity}.
      */
@@ -500,6 +506,72 @@
         return mInfo.getServiceInfo().loadLabel(mContext.getPackageManager());
     }
 
+    /**
+     * Initializes the last fill selection after an autofill service returned a new
+     * {@link FillResponse}.
+     */
+    void setLastResponse(int serviceUid, @NonNull FillResponse response) {
+        synchronized (mLock) {
+            mEventHistory = new FillEventHistory(serviceUid, response.getClientState());
+        }
+    }
+
+    /**
+     * Updates the last fill selection when an authentication was selected.
+     */
+    void setAuthenticationSelected() {
+        synchronized (mLock) {
+            mEventHistory.addEvent(
+                    new FillEventHistory.Event(FillEventHistory.Event.TYPE_AUTHENTICATION_SELECTED, null));
+        }
+    }
+
+    /**
+     * Updates the last fill selection when an dataset authentication was selected.
+     */
+    void setDatasetAuthenticationSelected(@Nullable String selectedDataset) {
+        synchronized (mLock) {
+            mEventHistory.addEvent(new FillEventHistory.Event(
+                    FillEventHistory.Event.TYPE_DATASET_AUTHENTICATION_SELECTED, selectedDataset));
+        }
+    }
+
+    /**
+     * Updates the last fill selection when an save Ui is shown.
+     */
+    void setSaveShown() {
+        synchronized (mLock) {
+            mEventHistory.addEvent(new FillEventHistory.Event(FillEventHistory.Event.TYPE_SAVE_SHOWN, null));
+        }
+    }
+
+    /**
+     * Updates the last fill response when a dataset was selected.
+     */
+    void setDatasetSelected(@Nullable String selectedDataset) {
+        synchronized (mLock) {
+            mEventHistory.addEvent(
+                    new FillEventHistory.Event(FillEventHistory.Event.TYPE_DATASET_SELECTED, selectedDataset));
+        }
+    }
+
+    /**
+     * Gets the fill event history.
+     *
+     * @param callingUid The calling uid
+     *
+     * @return The history or {@code null} if there is none.
+     */
+    FillEventHistory getFillEventHistory(int callingUid) {
+        synchronized (mLock) {
+            if (mEventHistory != null && mEventHistory.getServiceUid() == callingUid) {
+                return mEventHistory;
+            }
+        }
+
+        return null;
+    }
+
     void dumpLocked(String prefix, PrintWriter pw) {
         final String prefix2 = prefix + "  ";
 
@@ -528,6 +600,20 @@
                 mSessions.valueAt(i).dumpLocked(prefix2, pw);
             }
         }
+
+        if (mEventHistory == null || mEventHistory.getEvents().size() == 0) {
+            pw.print(prefix); pw.println("No event on last fill response");
+        } else {
+            pw.print(prefix); pw.println("Events of last fill response:");
+            pw.print(prefix);
+
+            int numEvents = mEventHistory.getEvents().size();
+            for (int i = 0; i < numEvents; i++) {
+                FillEventHistory.Event event = mEventHistory.getEvents().get(i);
+                pw.println("  " + i + ": eventType=" + event.getType() + " datasetId="
+                        + event.getDatasetId());
+            }
+        }
     }
 
     void destroySessionsLocked() {
diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
index 3badcfc..4d0f380 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
@@ -87,7 +87,7 @@
     private PendingRequest mPendingRequest;
 
     public interface FillServiceCallbacks {
-        void onFillRequestSuccess(@Nullable FillResponse response,
+        void onFillRequestSuccess(@Nullable FillResponse response, int serviceUid,
                 @NonNull String servicePackageName, int requestId);
         void onFillRequestFailure(@Nullable CharSequence message,
                 @NonNull String servicePackageName);
@@ -252,11 +252,11 @@
     }
 
     private void dispatchOnFillRequestSuccess(PendingRequest pendingRequest,
-            FillResponse response, int requestId) {
+            int callingUid, FillResponse response, int requestId) {
         mHandler.getHandler().post(() -> {
             if (handleResponseCallbackCommon(pendingRequest)) {
-                mCallbacks.onFillRequestSuccess(response, mComponentName.getPackageName(),
-                        requestId);
+                mCallbacks.onFillRequestSuccess(response, callingUid,
+                        mComponentName.getPackageName(), requestId);
             }
         });
     }
@@ -424,7 +424,7 @@
                     RemoteFillService remoteService = mWeakService.get();
                     if (remoteService != null) {
                         remoteService.dispatchOnFillRequestSuccess(
-                                PendingFillRequest.this, response, requestId);
+                                PendingFillRequest.this, getCallingUid(), response, requestId);
                     }
                 }
 
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 7c3f324..2b99614 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -229,7 +229,7 @@
 
     // FillServiceCallbacks
     @Override
-    public void onFillRequestSuccess(@Nullable FillResponse response,
+    public void onFillRequestSuccess(@Nullable FillResponse response, int serviceUid,
             @NonNull String servicePackageName, int requestId) {
         if (response == null) {
             if ((mFlags & FLAG_MANUAL_REQUEST) != 0) {
@@ -241,6 +241,8 @@
             return;
         }
 
+        mService.setLastResponse(serviceUid, response);
+
         if ((response.getDatasets() == null || response.getDatasets().isEmpty())
                         && response.getAuthentication() == null) {
             // Response is "empty" from an UI point of view, need to notify client.
@@ -314,6 +316,9 @@
         synchronized (mLock) {
             fillInIntent = createAuthFillInIntent(mStructure, extras);
         }
+
+        mService.setAuthenticationSelected();
+
         mHandlerCaller.getHandler().post(() -> startAuthentication(intent, fillInIntent));
     }
 
@@ -442,7 +447,7 @@
      */
     public boolean showSaveLocked() {
         if (mStructure == null) {
-            Slog.wtf(TAG, "showSaveLocked(): no mStructure");
+            Slog.d(TAG, "showSaveLocked(): no mStructure");
             return true;
         }
         if (mResponses == null) {
@@ -542,6 +547,7 @@
                 }
             }
             if (atLeastOneChanged) {
+                mService.setSaveShown();
                 getUiForShowing().showSaveUi(mService.getServiceLabel(), saveInfo, mPackageName);
                 return false;
             }
@@ -764,7 +770,8 @@
         boolean saveOnAllViewsInvisible = false;
         SaveInfo saveInfo = mResponses.valueAt(getLastResponseIndex()).getSaveInfo();
         if (saveInfo != null) {
-            saveOnAllViewsInvisible = saveInfo.saveOnAllViewsInvisible();
+            saveOnAllViewsInvisible =
+                    (saveInfo.getFlags() & SaveInfo.FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE) != 0;
 
             // We only need to track views if we want to save once they become invisible.
             if (saveOnAllViewsInvisible) {
@@ -881,12 +888,15 @@
         synchronized (mLock) {
             // Autofill it directly...
             if (dataset.getAuthentication() == null) {
+                mService.setDatasetSelected(dataset.getId());
+
                 autoFillApp(dataset);
                 return;
             }
 
             // ...or handle authentication.
             // TODO(b/33197203 , b/35707731): make sure it's ignored if there is one already
+            mService.setDatasetAuthenticationSelected(dataset.getId());
             mDatasetWaitingAuth = dataset;
             setViewStatesLocked(null, dataset, ViewState.STATE_WAITING_DATASET_AUTH);
             final Intent fillInIntent = createAuthFillInIntent(mStructure, null);
diff --git a/services/companion/Android.mk b/services/companion/Android.mk
new file mode 100644
index 0000000..be48761
--- /dev/null
+++ b/services/companion/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := services.companion
+
+LOCAL_SRC_FILES += \
+      $(call all-java-files-under,java)
+
+LOCAL_JAVA_LIBRARIES := services.core
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/print/java/com/android/server/print/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
similarity index 99%
rename from services/print/java/com/android/server/print/CompanionDeviceManagerService.java
rename to services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 122a954..41b70a1 100644
--- a/services/print/java/com/android/server/print/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -15,7 +15,7 @@
  */
 
 
-package com.android.server.print;
+package com.android.server.companion;
 
 import static com.android.internal.util.CollectionUtils.size;
 import static com.android.internal.util.Preconditions.checkArgument;
@@ -81,7 +81,6 @@
 import java.util.concurrent.ConcurrentMap;
 import java.util.function.Function;
 
-//TODO move to own package!
 //TODO onStop schedule unbind in 5 seconds
 //TODO make sure APIs are only callable from currently focused app
 //TODO schedule stopScan on activity destroy(except if configuration change)
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 2cd14e9..b91ecf5 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -756,7 +756,7 @@
                 }
             }
             if (r.fgRequired) {
-                if (DEBUG_BACKGROUND_CHECK) {
+                if (DEBUG_SERVICE || DEBUG_BACKGROUND_CHECK) {
                     Slog.i(TAG, "Service called startForeground() as required: " + r);
                 }
                 r.fgRequired = false;
@@ -1334,16 +1334,19 @@
         final ComponentName comp = service.getComponent();
         if (comp != null) {
             r = smap.mServicesByName.get(comp);
+            if (DEBUG_SERVICE && r != null) Slog.v(TAG_SERVICE, "Retrieved by component: " + r);
         }
         if (r == null && !isBindExternal) {
             Intent.FilterComparison filter = new Intent.FilterComparison(service);
             r = smap.mServicesByIntent.get(filter);
+            if (DEBUG_SERVICE && r != null) Slog.v(TAG_SERVICE, "Retrieved by intent: " + r);
         }
         if (r != null && (r.serviceInfo.flags & ServiceInfo.FLAG_EXTERNAL_SERVICE) != 0
                 && !callingPackage.equals(r.packageName)) {
             // If an external service is running within its own package, other packages
             // should not bind to that instance.
             r = null;
+            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Whoops, can't use existing external service");
         }
         if (r == null) {
             try {
@@ -1403,12 +1406,14 @@
                     sInfo.applicationInfo = mAm.getAppInfoForUser(sInfo.applicationInfo, userId);
                 }
                 r = smap.mServicesByName.get(name);
+                if (DEBUG_SERVICE && r != null) Slog.v(TAG_SERVICE,
+                        "Retrieved via pm by intent: " + r);
                 if (r == null && createIfNeeded) {
-                    Intent.FilterComparison filter
+                    final Intent.FilterComparison filter
                             = new Intent.FilterComparison(service.cloneFilter());
-                    ServiceRestarter res = new ServiceRestarter();
-                    BatteryStatsImpl.Uid.Pkg.Serv ss = null;
-                    BatteryStatsImpl stats = mAm.mBatteryStatsService.getActiveStatistics();
+                    final ServiceRestarter res = new ServiceRestarter();
+                    final BatteryStatsImpl.Uid.Pkg.Serv ss;
+                    final BatteryStatsImpl stats = mAm.mBatteryStatsService.getActiveStatistics();
                     synchronized (stats) {
                         ss = stats.getServiceStatsLocked(
                                 sInfo.applicationInfo.uid, sInfo.packageName,
@@ -1421,12 +1426,14 @@
 
                     // Make sure this component isn't in the pending list.
                     for (int i=mPendingServices.size()-1; i>=0; i--) {
-                        ServiceRecord pr = mPendingServices.get(i);
+                        final ServiceRecord pr = mPendingServices.get(i);
                         if (pr.serviceInfo.applicationInfo.uid == sInfo.applicationInfo.uid
                                 && pr.name.equals(name)) {
+                            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Remove pending: " + pr);
                             mPendingServices.remove(i);
                         }
                     }
+                    if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Retrieve created new service: " + r);
                 }
             } catch (RemoteException ex) {
                 // pm is in same process, this will never happen.
@@ -2114,7 +2121,28 @@
             }
         }
 
-        if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bringing down " + r + " " + r.intent);
+        // Check to see if the service had been started as foreground, but being
+        // brought down before actually showing a notification.  That is not allowed.
+        if (r.fgRequired) {
+            Slog.w(TAG_SERVICE, "Bringing down service while still waiting for start foreground: "
+                    + r);
+            r.fgRequired = false;
+            r.fgWaiting = false;
+            mAm.mHandler.removeMessages(
+                    ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG, r);
+            if (r.app != null) {
+                Message msg = mAm.mHandler.obtainMessage(
+                        ActivityManagerService.SERVICE_FOREGROUND_CRASH_MSG);
+                msg.obj = r.app;
+                mAm.mHandler.sendMessage(msg);
+            }
+        }
+
+        if (DEBUG_SERVICE) {
+            RuntimeException here = new RuntimeException();
+            here.fillInStackTrace();
+            Slog.v(TAG_SERVICE, "Bringing down " + r + " " + r.intent, here);
+        }
         r.destroyTime = SystemClock.uptimeMillis();
         if (LOG_SERVICE_START_STOP) {
             EventLogTags.writeAmDestroyService(
@@ -2122,7 +2150,14 @@
         }
 
         final ServiceMap smap = getServiceMapLocked(r.userId);
-        smap.mServicesByName.remove(r.name);
+        ServiceRecord found = smap.mServicesByName.remove(r.name);
+        if (found != r) {
+            // This is not actually the service we think is running...  this should not happen,
+            // but if it does, fail hard.
+            smap.mServicesByName.put(r.name, found);
+            throw new IllegalStateException("Bringing down " + r + " but actually running "
+                    + found);
+        }
         smap.mServicesByIntent.remove(r.intent);
         r.totalRestartCount = 0;
         unscheduleServiceRestartLocked(r, 0, true);
@@ -2962,7 +2997,7 @@
     void serviceForegroundTimeout(ServiceRecord r) {
         ProcessRecord app;
         synchronized (mAm) {
-            if (!r.fgRequired) {
+            if (!r.fgRequired || r.destroying) {
                 return;
             }
 
@@ -2980,6 +3015,11 @@
         }
     }
 
+    void serviceForegroundCrash(ProcessRecord app) {
+        mAm.crashApplication(app.uid, app.pid, app.info.packageName, app.userId,
+                "Context.startForegroundService() did not then call Service.startForeground()");
+    }
+
     void scheduleServiceTimeoutLocked(ProcessRecord proc) {
         if (proc.executingServices.size() == 0 || proc.thread == null) {
             return;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index d43fa01..52fc611 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1703,6 +1703,7 @@
     static final int SERVICE_FOREGROUND_TIMEOUT_MSG = 66;
     static final int DISPATCH_PENDING_INTENT_CANCEL_MSG = 67;
     static final int PUSH_TEMP_WHITELIST_UI_MSG = 68;
+    static final int SERVICE_FOREGROUND_CRASH_MSG = 69;
     static final int START_USER_SWITCH_FG_MSG = 712;
 
     static final int FIRST_ACTIVITY_STACK_MSG = 100;
@@ -1974,6 +1975,9 @@
             case SERVICE_FOREGROUND_TIMEOUT_MSG: {
                 mServices.serviceForegroundTimeout((ServiceRecord)msg.obj);
             } break;
+            case SERVICE_FOREGROUND_CRASH_MSG: {
+                mServices.serviceForegroundCrash((ProcessRecord)msg.obj);
+            } break;
             case DISPATCH_PENDING_INTENT_CANCEL_MSG: {
                 RemoteCallbackList<IResultReceiver> callbacks
                         = (RemoteCallbackList<IResultReceiver>)msg.obj;
@@ -10685,6 +10689,13 @@
             return;
         }
 
+        // When a task is locked, dismiss the pinned stack if it exists
+        final PinnedActivityStack pinnedStack = mStackSupervisor.getStack(
+                PINNED_STACK_ID);
+        if (pinnedStack != null) {
+            mStackSupervisor.removeStackLocked(PINNED_STACK_ID);
+        }
+
         // isSystemInitiated is used to distinguish between locked and pinned mode, as pinned mode
         // is initiated by system after the pinning request was shown and locked mode is initiated
         // by an authorized app directly
@@ -11245,6 +11256,10 @@
                     holder.provider = null;
                     return holder;
                 }
+                // Don't expose instant app providers
+                if (cpr.appInfo.isInstantApp()) {
+                    return null;
+                }
 
                 final long origId = Binder.clearCallingIdentity();
 
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 7cdddc0..fe03c36 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -2130,6 +2130,11 @@
         if (mWindowContainerController == null) {
             return;
         }
+        if (mTaskOverlay) {
+            // We don't show starting window for overlay activities.
+            return;
+        }
+
         final CompatibilityInfo compatInfo =
                 service.compatibilityInfoForPackageLocked(info.applicationInfo);
         final boolean shown = mWindowContainerController.addStartingWindow(packageName, theme,
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 43ae4b2..ab70340 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2397,10 +2397,10 @@
             } else {
                 for (int i = 0; i < size; i++) {
                     final TaskRecord task = tasks.get(i);
-                    final int position = fullscreenStack != null
-                            ? Math.max(fullscreenStack.getAllTasks().size() - 1, 0) : 0;
-                    // Defer resume until all the tasks have been moved to the fullscreen stack
-                    task.reparent(FULLSCREEN_WORKSPACE_STACK_ID, position,
+                    // Position the tasks in the fullscreen stack in order at the bottom of the
+                    // stack. Also defer resume until all the tasks have been moved to the
+                    // fullscreen stack.
+                    task.reparent(FULLSCREEN_WORKSPACE_STACK_ID, i /* position */,
                             REPARENT_LEAVE_STACK_IN_PLACE, !ANIMATE, DEFER_RESUME,
                             schedulePictureInPictureModeChange,
                             "moveTasksToFullscreenStack - NOT_onTop");
@@ -2878,6 +2878,10 @@
 
         mWindowManager.deferSurfaceLayout();
 
+        // This will clear the pinned stack by moving an existing task to the full screen stack,
+        // ensuring only one task is present.
+        moveTasksToFullscreenStackLocked(PINNED_STACK_ID, !ON_TOP);
+
         // Need to make sure the pinned stack exist so we can resize it below...
         final PinnedActivityStack stack = getStack(PINNED_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
 
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index f8a4d4b..d42b6a7 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -48,6 +48,7 @@
 import android.util.DisplayMetrics;
 import android.util.Slog;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.util.XmlUtils;
 
@@ -445,10 +446,23 @@
 
         final Rect bounds = updateOverrideConfigurationFromLaunchBounds();
         final Configuration overrideConfig = getOverrideConfiguration();
-        mWindowContainerController = new TaskWindowContainerController(taskId, this,
+        setWindowContainerController(new TaskWindowContainerController(taskId, this,
                 getStack().getWindowContainerController(), userId, bounds, overrideConfig,
                 mResizeMode, mSupportsPictureInPicture, isHomeTask(), onTop, showForAllUsers,
-                lastTaskDescription);
+                lastTaskDescription));
+    }
+
+    /**
+     * Should only be invoked from {@link #createWindowContainer(boolean, boolean)}.
+     */
+    @VisibleForTesting
+    protected void setWindowContainerController(TaskWindowContainerController controller) {
+        if (mWindowContainerController != null) {
+            throw new IllegalArgumentException("Window container=" + mWindowContainerController
+                    + " already created for task=" + this);
+        }
+
+        mWindowContainerController = controller;
     }
 
     void removeWindowContainer() {
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 5b2e937..91c32e4 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -288,6 +288,9 @@
     // current setting - 4 hours
     private static final long MAX_RETRY_INTERVAL = 4*60*60*1000;
 
+    // Timeout when holding wakelocks for downloading XTRA data.
+    private static final long DOWNLOAD_XTRA_DATA_TIMEOUT_MS = 60 * 1000;
+
     private BackOff mNtpBackOff = new BackOff(RETRY_INTERVAL, MAX_RETRY_INTERVAL);
     private BackOff mXtraBackOff = new BackOff(RETRY_INTERVAL, MAX_RETRY_INTERVAL);
 
@@ -986,7 +989,7 @@
         mDownloadXtraDataPending = STATE_DOWNLOADING;
 
         // hold wake lock while task runs
-        mWakeLock.acquire();
+        mWakeLock.acquire(DOWNLOAD_XTRA_DATA_TIMEOUT_MS);
         Log.i(TAG, "WakeLock acquired by handleDownloadXtraData()");
         AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
             @Override
@@ -1009,7 +1012,11 @@
                 }
 
                 // release wake lock held by task
-                mWakeLock.release();
+                if (mWakeLock.isHeld()) {
+                    mWakeLock.release();
+                } else {
+                    Log.e(TAG, "WakeLock expired before release in handleDownloadXtraData()");
+                }
                 Log.i(TAG, "WakeLock released by handleDownloadXtraData()");
             }
         });
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index ee348cf..a275f49 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -751,7 +751,12 @@
         @Override
         public void setActive(boolean active) {
             mIsActive = active;
-            mService.updateSession(MediaSessionRecord.this);
+            final long token = Binder.clearCallingIdentity();
+            try {
+                mService.updateSession(MediaSessionRecord.this);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
             mHandler.post(MessageHandler.MSG_UPDATE_SESSION_STATE);
         }
 
@@ -862,7 +867,12 @@
                 }
             }
             if (typeChanged) {
-                mService.onSessionPlaybackTypeChanged(MediaSessionRecord.this);
+                final long token = Binder.clearCallingIdentity();
+                try {
+                    mService.onSessionPlaybackTypeChanged(MediaSessionRecord.this);
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                }
                 mHandler.post(MessageHandler.MSG_UPDATE_VOLUME);
             }
         }
@@ -877,7 +887,12 @@
                 mMaxVolume = max;
             }
             if (typeChanged) {
-                mService.onSessionPlaybackTypeChanged(MediaSessionRecord.this);
+                final long token = Binder.clearCallingIdentity();
+                try {
+                    mService.onSessionPlaybackTypeChanged(MediaSessionRecord.this);
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                }
                 mHandler.post(MessageHandler.MSG_UPDATE_VOLUME);
             }
         }
diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java
index 2f82915..0e69bca 100644
--- a/services/core/java/com/android/server/media/MediaSessionStack.java
+++ b/services/core/java/com/android/server/media/MediaSessionStack.java
@@ -121,9 +121,12 @@
     public void removeSession(MediaSessionRecord record) {
         mSessions.remove(record);
         if (mMediaButtonSession == record) {
-            // When the media button session is gone, try to find the alternative media session
-            // in the media button session app.
-            onMediaSessionChangeInMediaButtonSessionApp();
+            // When the media button session is removed, nullify the media button session and do not
+            // search for the alternative media session within the app. It's because the alternative
+            // media session might be a dummy which isn't able to handle the media key events.
+            mOnMediaButtonSessionChangedListener.onMediaButtonSessionChanged(
+                    mMediaButtonSession, null);
+            mMediaButtonSession = null;
         }
         clearCache(record.getUserId());
     }
@@ -157,7 +160,13 @@
         // In that case, we pick the media session whose PlaybackState matches
         // the audio playback configuration.
         if (mMediaButtonSession != null && mMediaButtonSession.getUid() == record.getUid()) {
-            onMediaSessionChangeInMediaButtonSessionApp();
+            MediaSessionRecord newMediaButtonSession =
+                    findMediaButtonSession(mMediaButtonSession.getUid());
+            if (newMediaButtonSession != mMediaButtonSession) {
+                mOnMediaButtonSessionChangedListener.onMediaButtonSessionChanged(
+                        mMediaButtonSession, newMediaButtonSession);
+                mMediaButtonSession = newMediaButtonSession;
+            }
         }
     }
 
@@ -200,22 +209,6 @@
     }
 
     /**
-     * Handle the change in a media session in the media button session app.
-     * <p>If the app has multiple media sessions, change in a media sesion in the app may change
-     * the media button session.
-     * @see #findMediaButtonSession
-     */
-    private void onMediaSessionChangeInMediaButtonSessionApp() {
-        MediaSessionRecord newMediaButtonSession =
-                findMediaButtonSession(mMediaButtonSession.getUid());
-        if (newMediaButtonSession != mMediaButtonSession) {
-            mOnMediaButtonSessionChangedListener.onMediaButtonSessionChanged(mMediaButtonSession,
-                    newMediaButtonSession);
-            mMediaButtonSession = newMediaButtonSession;
-        }
-    }
-
-    /**
      * Find the media button session with the given {@param uid}.
      * If the app has multiple media sessions, the media session matches the audio playback state
      * becomes the media button session.
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 90e9b92..3cb2f35 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -356,7 +356,6 @@
 
     private void rebuildRestoredPackages() {
         mRestoredPackages.clear();
-        mSnoozingForCurrentProfiles.clear();
         String secureSettingName = restoredSettingName(mConfig.secureSettingName);
         String secondarySettingName = mConfig.secondarySettingName == null
                 ? null : restoredSettingName(mConfig.secondarySettingName);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 8a6a940..c289204 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -3203,6 +3203,8 @@
             return;
         } else if (channelId == null && shouldWarnUseChannels(pkg, notificationUid)) {
             // STOPSHIP TODO: remove once default channel is removed for all apps that target O.
+            Log.e(TAG, "Developer Warning for package " + pkg
+                    + ", no channel specified for posted notification: " + notification);
             doDebugOnlyToast("Developer warning for package \"" + pkg + "\"\n" +
                     "Posted notification should specify a channel");
         }
@@ -3611,7 +3613,7 @@
         final boolean aboveThreshold =
                 record.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT;
         final boolean canInterrupt = aboveThreshold && !record.isIntercepted();
-        if (DBG || record.isIntercepted())
+        if (DBG)
             Slog.v(TAG,
                     "pkg=" + record.sbn.getPackageName() + " canInterrupt=" + canInterrupt +
                             " intercept=" + record.isIntercepted()
diff --git a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
index e472928e..21d78ee 100644
--- a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
+++ b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
@@ -231,7 +231,7 @@
         private final IRemoteCallback mCallback;
 
         public GetEphemeralResolveInfoCaller() {
-            super(TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS);
+            super(BIND_SERVICE_TIMEOUT_MS);
             mCallback = new IRemoteCallback.Stub() {
                     @Override
                     public void sendResult(Bundle data) throws RemoteException {
diff --git a/services/core/java/com/android/server/pm/InstantAppRegistry.java b/services/core/java/com/android/server/pm/InstantAppRegistry.java
index 89a303d..46bc69b 100644
--- a/services/core/java/com/android/server/pm/InstantAppRegistry.java
+++ b/services/core/java/com/android/server/pm/InstantAppRegistry.java
@@ -35,6 +35,7 @@
 import android.provider.Settings;
 import android.util.ArrayMap;
 import android.util.AtomicFile;
+import android.util.ByteStringUtils;
 import android.util.PackageUtils;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -56,8 +57,10 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
+import java.security.SecureRandom;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Locale;
 import java.util.Set;
 import java.util.function.Predicate;
 
@@ -81,6 +84,7 @@
     private static final String INSTANT_APP_COOKIE_FILE_PREFIX = "cookie_";
     private static final String INSTANT_APP_COOKIE_FILE_SIFFIX = ".dat";
     private static final String INSTANT_APP_METADATA_FILE = "metadata.xml";
+    private static final String INSTANT_APP_ANDROID_ID_FILE = "android_id";
 
     private static final String TAG_PACKAGE = "package";
     private static final String TAG_PERMISSIONS = "permissions";
@@ -195,6 +199,36 @@
         return null;
     }
 
+    public String getInstantAppAndroidIdLPw(@NonNull String packageName,
+                                            @UserIdInt int userId) {
+        File idFile = new File(getInstantApplicationDir(packageName, userId),
+                INSTANT_APP_ANDROID_ID_FILE);
+        if (idFile.exists()) {
+            try {
+                return IoUtils.readFileAsString(idFile.getAbsolutePath());
+            } catch (IOException e) {
+                Slog.e(LOG_TAG, "Failed to read instant app android id file: " + idFile, e);
+            }
+        }
+        return generateInstantAppAndroidIdLPw(packageName, userId);
+    }
+
+    private String generateInstantAppAndroidIdLPw(@NonNull String packageName,
+                                                @UserIdInt int userId) {
+        byte[] randomBytes = new byte[8];
+        new SecureRandom().nextBytes(randomBytes);
+        String id = ByteStringUtils.toHexString(randomBytes).toLowerCase(Locale.US);
+        File idFile = new File(getInstantApplicationDir(packageName, userId),
+                INSTANT_APP_ANDROID_ID_FILE);
+        try (FileOutputStream fos = new FileOutputStream(idFile)) {
+            fos.write(id.getBytes());
+        } catch (IOException e) {
+            Slog.e(LOG_TAG, "Error writing instant app android id file: " + idFile, e);
+        }
+        return id;
+
+    }
+
     public @Nullable List<InstantAppInfo> getInstantAppsLPr(@UserIdInt int userId) {
         List<InstantAppInfo> installedApps = getInstalledInstantApplicationsLPr(userId);
         List<InstantAppInfo> uninstalledApps = getUninstalledInstantApplicationsLPr(userId);
@@ -462,6 +496,7 @@
         File instantAppDir = getInstantApplicationDir(packageName, userId);
         new File(instantAppDir, INSTANT_APP_METADATA_FILE).delete();
         new File(instantAppDir, INSTANT_APP_ICON_FILE).delete();
+        new File(instantAppDir, INSTANT_APP_ANDROID_ID_FILE).delete();
         File cookie = peekInstantCookieFile(packageName, userId);
         if (cookie != null) {
             cookie.delete();
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 9039647..8413491 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -149,13 +149,14 @@
         final boolean profileUpdated = checkForProfileUpdates &&
                 isProfileUpdated(pkg, sharedGid, compilerFilter);
 
-        // TODO(calin,jeffhao): shared library paths should be adjusted to include previous code
-        // paths (b/34169257).
-        final String sharedLibrariesPath = getSharedLibrariesPath(sharedLibraries);
+        String sharedLibrariesPath = getSharedLibrariesPath(sharedLibraries);
         // Get the dexopt flags after getRealCompilerFilter to make sure we get the correct flags.
         final int dexoptFlags = getDexFlags(pkg, compilerFilter);
 
         int result = DEX_OPT_SKIPPED;
+        // TODO: Iterate based on dependency hierarchy (currently alphabetically by name)
+        // (b/37480811).
+        String basePathCheck = null;
         for (String path : paths) {
             for (String dexCodeIsa : dexCodeInstructionSets) {
                 int newResult = dexOptPath(pkg, path, dexCodeIsa, compilerFilter, profileUpdated,
@@ -167,6 +168,22 @@
                 if ((result != DEX_OPT_FAILED) && (newResult != DEX_OPT_SKIPPED)) {
                     result = newResult;
                 }
+                // Add the relative path of code we just compiled to the shared libraries.
+                int slashIndex = path.lastIndexOf('/') + 1;
+                String relativePath = path.substring(slashIndex);
+                if (sharedLibrariesPath == null) {
+                    sharedLibrariesPath = relativePath;
+                } else {
+                    sharedLibrariesPath += ":" + relativePath;
+                }
+                // Sanity check that the base paths are all the same.
+                String basePath = path.substring(0, slashIndex);
+                if (basePathCheck == null) {
+                    basePathCheck = basePath;
+                } else if (!basePath.equals(basePathCheck)) {
+                    Slog.wtf(TAG, "Split paths have different base paths: " + basePath + " and " +
+                        basePathCheck);
+                }
             }
         }
         return result;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 312c310..4d026e3d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -955,6 +955,11 @@
             verificationIntent.setComponent(mIntentFilterVerifierComponent);
             verificationIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
 
+            DeviceIdleController.LocalService idleController = getDeviceIdleController();
+            idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
+                    mIntentFilterVerifierComponent.getPackageName(), getVerificationTimeout(),
+                    userId, false, "intent filter verifier");
+
             UserHandle user = new UserHandle(userId);
             mContext.sendBroadcastAsUser(verificationIntent, user);
             if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG,
@@ -1834,10 +1839,6 @@
                 extras.putInt(Intent.EXTRA_UID, res.uid);
                 if (update) {
                     extras.putBoolean(Intent.EXTRA_REPLACING, true);
-                } else {
-                    sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_ADDED, packageName,
-                            extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND,
-                            null /*targetPackage*/, null /*finishedReceiver*/, updateUsers);
                 }
                 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
                         extras, 0 /*flags*/, null /*targetPackage*/,
@@ -2805,8 +2806,12 @@
                 mRequiredInstallerPackage = getRequiredInstallerLPr();
                 mRequiredUninstallerPackage = getRequiredUninstallerLPr();
                 mIntentFilterVerifierComponent = getIntentFilterVerifierComponentNameLPr();
-                mIntentFilterVerifier = new IntentVerifierProxy(mContext,
-                        mIntentFilterVerifierComponent);
+                if (mIntentFilterVerifierComponent != null) {
+                    mIntentFilterVerifier = new IntentVerifierProxy(mContext,
+                            mIntentFilterVerifierComponent);
+                } else {
+                    mIntentFilterVerifier = null;
+                }
                 mServicesSystemSharedLibraryPackageName = getRequiredSharedLibraryLPr(
                         PackageManager.SYSTEM_SHARED_LIBRARY_SERVICES,
                         SharedLibraryInfo.VERSION_UNDEFINED);
@@ -3046,9 +3051,9 @@
 
         if (best != null) {
             return best.getComponentInfo().getComponentName();
-        } else {
-            throw new RuntimeException("There must be at least one intent filter verifier");
         }
+        Slog.w(TAG, "Intent filter verifier not found");
+        return null;
     }
 
     private @Nullable Pair<ComponentName, String> getInstantAppResolverLPr() {
@@ -4218,8 +4223,10 @@
                     }
 
                     SharedLibraryInfo resLibInfo = new SharedLibraryInfo(libInfo.getName(),
-                            libInfo.getVersion(), libInfo.getType(), libInfo.getDeclaringPackage(),
-                            getPackagesUsingSharedLibraryLPr(libInfo, flags, userId));
+                            // TODO: Remove cast for lib version once internally we support longs.
+                            (int) libInfo.getVersion(), libInfo.getType(),
+                            libInfo.getDeclaringPackage(), getPackagesUsingSharedLibraryLPr(libInfo,
+                            flags, userId));
 
                     if (result == null) {
                         result = new ArrayList<>();
@@ -13395,10 +13402,8 @@
         // Set to UID of the first user, EXTRA_UID is automatically updated in sendPackageBroadcast
         extras.putInt(Intent.EXTRA_UID, UserHandle.getUid(userIds[0], appId));
 
-        sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_ADDED, packageName,
-                extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, null, null, userIds);
-        sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
-                extras, 0, null, null, userIds);
+        sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
+                packageName, extras, 0, null, null, userIds);
         if (isSystem) {
             mHandler.post(() -> {
                         for (int userId : userIds) {
@@ -13975,7 +13980,8 @@
     }
 
     /**
-     * Get the verification agent timeout.
+     * Get the verification agent timeout.  Used for both the APK verifier and the
+     * intent filter verifier.
      *
      * @return verification timeout in milliseconds
      */
@@ -17593,7 +17599,8 @@
         for (int i = 0; i < versionCount; i++) {
             SharedLibraryEntry libEntry = versionedLib.valueAt(i);
             if (versionsCallerCanSee != null && versionsCallerCanSee.indexOfKey(
-                    libEntry.info.getVersion()) < 0) {
+                    // TODO: Remove cast for lib version once internally we support longs.
+                    (int) libEntry.info.getVersion()) < 0) {
                 continue;
             }
             // TODO: We will change version code to long, so in the new API it is long
@@ -23651,6 +23658,22 @@
         return mInstantAppInstallerActivity == null
                 ? null : mInstantAppInstallerActivity.getComponentName();
     }
+
+    @Override
+    public String getInstantAppAndroidId(String packageName, int userId) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_INSTANT_APPS,
+                "getInstantAppAndroidId");
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+                true /* requireFullPermission */, false /* checkShell */,
+                "getInstantAppAndroidId");
+        // Make sure the target is an Instant App.
+        if (!isInstantApp(packageName, userId)) {
+            return null;
+        }
+        synchronized (mPackages) {
+            return mInstantAppRegistry.getInstantAppAndroidIdLPw(packageName, userId);
+        }
+    }
 }
 
 interface PackageSender {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index bcb4121..5c9f749 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -223,9 +223,8 @@
 import android.view.animation.AnimationSet;
 import android.view.animation.AnimationUtils;
 import android.view.inputmethod.InputMethodManagerInternal;
-import android.widget.ImageView;
+
 import com.android.internal.R;
-import com.android.internal.annotations.GuardedBy;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.policy.IKeyguardDismissCallback;
 import com.android.internal.policy.IShortcutService;
@@ -497,9 +496,6 @@
     WindowState mLastInputMethodWindow = null;
     WindowState mLastInputMethodTargetWindow = null;
 
-    @GuardedBy("mLock")
-    private boolean mDismissImeOnBackKeyPressed;
-
     // FIXME This state is shared between the input reader and handler thread.
     // Technically it's broken and buggy but it has been like this for many years
     // and we have not yet seen any problems.  Someday we'll rewrite this logic
@@ -519,6 +515,7 @@
     volatile boolean mPictureInPictureVisible;
     // Written by vr manager thread, only read in this class
     volatile boolean mPersistentVrModeEnabled;
+    volatile private boolean mDismissImeOnBackKeyPressed;
 
     // Used to hold the last user key used to wake the device.  This helps us prevent up events
     // from being passed to the foregrounded app without a corresponding down event
@@ -1403,13 +1400,7 @@
                     launchHomeFromHotKey(true /* awakenFromDreams */, false /*respectKeyguard*/);
                     break;
                 case SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME: {
-                    final boolean dismissImeOnBackKeyPressed;
-                    // We can be here on both the main thread (via mHandler) and native callback
-                    // thread (from interceptPowerKeyUp via WindowManagerCallbacks).
-                    synchronized (mLock) {
-                        dismissImeOnBackKeyPressed = mDismissImeOnBackKeyPressed;
-                    }
-                    if (dismissImeOnBackKeyPressed) {
+                    if (mDismissImeOnBackKeyPressed) {
                         if (mInputMethodManagerInternal == null) {
                             mInputMethodManagerInternal =
                                     LocalServices.getService(InputMethodManagerInternal.class);
@@ -7983,9 +7974,7 @@
 
     @Override
     public void setDismissImeOnBackKeyPressed(boolean newValue) {
-        synchronized (mLock) {
-            mDismissImeOnBackKeyPressed = newValue;
-        }
+        mDismissImeOnBackKeyPressed = newValue;
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 1fb34eb..7634644 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1280,6 +1280,11 @@
                 // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
                 dc.setLayoutNeeded();
                 mService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
+
+                final TaskStack s = getStack();
+                if (s != null) {
+                    s.onAllWindowsDrawn();
+                }
             }
         }
 
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index e634552..7f3c89c 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -112,6 +112,8 @@
     private final Interpolator mFastOutSlowInInterpolator;
     private boolean mFinishAnimationAfterTransition = false;
 
+    private static final int WAIT_FOR_DRAW_TIMEOUT_MS = 3000;
+
     BoundsAnimationController(Context context, AppTransition transition, Handler handler) {
         mHandler = handler;
         mAppTransition = transition;
@@ -175,6 +177,13 @@
             }
         }
 
+        final Runnable mResumeRunnable = new Runnable() {
+                @Override
+                public void run() {
+                    resume();
+                }
+        };
+
         @Override
         public void onAnimationStart(Animator animation) {
             if (DEBUG) Slog.d(TAG, "onAnimationStart: mTarget=" + mTarget
@@ -196,10 +205,26 @@
             // the starting position so we don't jump at the beginning of the animation.
             if (animatingToLargerSize()) {
                 mTarget.setPinnedStackSize(mFrom, mTmpRect);
+
+                // We pause the animation until the app has drawn at the new size.
+                // The target will notify us via BoundsAnimationController#resume.
+                // We do this here and pause the animation, rather than just defer starting it
+                // so we can enter the animating state and have WindowStateAnimator apply the
+                // correct logic to make this resize seamless.
+                if (mMoveToFullscreen) {
+                    pause();
+                    mHandler.postDelayed(mResumeRunnable, WAIT_FOR_DRAW_TIMEOUT_MS);
+                }
             }
         }
 
         @Override
+        public void resume() {
+            mHandler.removeCallbacks(mResumeRunnable);
+            super.resume();
+        }
+
+        @Override
         public void onAnimationUpdate(ValueAnimator animation) {
             final float value = (Float) animation.getAnimatedValue();
             final float remains = 1 - value;
@@ -371,4 +396,15 @@
         animator.start();
         return animator;
     }
+
+    private void resume() {
+        for (int i = 0; i < mRunningAnimations.size(); i++) {
+            final BoundsAnimator b = mRunningAnimations.valueAt(i);
+            b.resume();
+        }
+    }
+
+    public void onAllWindowsDrawn() {
+        mHandler.post(this::resume);
+    }
 }
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index d141f7c..1feb743 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -52,6 +52,7 @@
 import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
 import com.android.internal.policy.DockedDividerUtils;
 import com.android.server.EventLogTags;
+import com.android.server.UiThread;
 
 import java.io.PrintWriter;
 
@@ -1475,6 +1476,14 @@
         return true;
     }
 
+    void onAllWindowsDrawn() {
+        if (!mBoundsAnimating) {
+            return;
+        }
+
+        mService.mBoundsAnimationController.onAllWindowsDrawn();
+    }
+
     @Override  // AnimatesBounds
     public void onAnimationStart(boolean schedulePipModeChangedCallback) {
         // Hold the lock since this is called from the BoundsAnimator running on the UiThread
@@ -1482,6 +1491,13 @@
             mBoundsAnimatingRequested = false;
             mBoundsAnimating = true;
             mCancelCurrentBoundsAnimation = false;
+
+            // If we are changing UI mode, as in the PiP to fullscreen
+            // transition, then we need to wait for the window to draw.
+            if (schedulePipModeChangedCallback) {
+                forAllWindows((w) -> { w.mWinAnimator.resetDrawState(); },
+                        false /* traverseTopToBottom */);
+            }
         }
 
         if (mStackId == PINNED_STACK_ID) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 9555c8d..b9776a3 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -4329,7 +4329,9 @@
 
     int relayoutVisibleWindow(MergedConfiguration mergedConfiguration, int result, int attrChanges,
             int oldVisibility) {
-        result |= !isVisibleLw() ? RELAYOUT_RES_FIRST_TIME : 0;
+        final boolean wasVisible = isVisibleLw();
+
+        result |= (!wasVisible || !isDrawnLw()) ? RELAYOUT_RES_FIRST_TIME : 0;
         if (mAnimatingExit) {
             Slog.d(TAG, "relayoutVisibleWindow: " + this + " mAnimatingExit=true, mRemoveOnExit="
                     + mRemoveOnExit + ", mDestroying=" + mDestroying);
@@ -4348,7 +4350,7 @@
         mLastVisibleLayoutRotation = getDisplayContent().getRotation();
 
         mWinAnimator.mEnteringAnimation = true;
-        if ((result & RELAYOUT_RES_FIRST_TIME) != 0) {
+        if (!wasVisible) {
             prepareWindowToDisplayDuringRelayout(mergedConfiguration);
         }
         if ((attrChanges & FORMAT_CHANGED) != 0) {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index a2889b1..b945cf1 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -602,6 +602,22 @@
         }
     }
 
+    void resetDrawState() {
+        mDrawState = DRAW_PENDING;
+
+        if (mWin.mAppToken == null) {
+            return;
+        }
+
+        if (mWin.mAppToken.mAppAnimator.animation == null) {
+            mWin.mAppToken.clearAllDrawn();
+        } else {
+            // Currently animating, persist current state of allDrawn until animation
+            // is complete.
+            mWin.mAppToken.deferClearAllDrawn = true;
+        }
+    }
+
     WindowSurfaceController createSurfaceLocked(int windowType, int ownerUid) {
         final WindowState w = mWin;
         if (w.restoreSavedSurface()) {
@@ -619,16 +635,7 @@
         if (DEBUG_ANIM || DEBUG_ORIENTATION) Slog.i(TAG,
                 "createSurface " + this + ": mDrawState=DRAW_PENDING");
 
-        mDrawState = DRAW_PENDING;
-        if (w.mAppToken != null) {
-            if (w.mAppToken.mAppAnimator.animation == null) {
-                w.mAppToken.clearAllDrawn();
-            } else {
-                // Currently animating, persist current state of allDrawn until animation
-                // is complete.
-                w.mAppToken.deferClearAllDrawn = true;
-            }
-        }
+        resetDrawState();
 
         mService.makeWindowFreezingScreenIfNeededLocked(w);
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 42a9232..978803d 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -159,7 +159,7 @@
     private static final String PRINT_MANAGER_SERVICE_CLASS =
             "com.android.server.print.PrintManagerService";
     private static final String COMPANION_DEVICE_MANAGER_SERVICE_CLASS =
-            "com.android.server.print.CompanionDeviceManagerService";
+            "com.android.server.companion.CompanionDeviceManagerService";
     private static final String USB_SERVICE_CLASS =
             "com.android.server.usb.UsbService$Lifecycle";
     private static final String MIDI_SERVICE_CLASS =
diff --git a/services/tests/servicestests/src/com/android/server/BootReceiverFixFsckFsStatTest.java b/services/tests/servicestests/src/com/android/server/BootReceiverFixFsckFsStatTest.java
new file mode 100644
index 0000000..362c47a
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/BootReceiverFixFsckFsStatTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import static junit.framework.Assert.*;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import junit.framework.Assert;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class BootReceiverFixFsckFsStatTest {
+
+    private static final String PARTITION = "userdata";
+
+    @Test
+    public void testTreeOptimization() {
+        final String[] logs = {
+                "e2fsck 1.43.3 (04-Sep-2016)",
+                "Pass 1: Checking inodes, blocks, and sizes",
+                "Inode 877141 extent tree (at level 1) could be shorter.  Fix? yes",
+                " ",
+                "Pass 1E: Optimizing extent trees",
+                "Pass 2: Checking directory structure",
+                "Pass 3: Checking directory connectivity",
+                "Pass 4: Checking reference counts",
+                "Pass 5: Checking group summary information",
+                "[QUOTA WARNING] Usage inconsistent for ID 10038:actual (71667712, 1000) != expected (71671808, 1000)",
+                "Update quota info for quota type 0? yes",
+                " ",
+                "[QUOTA WARNING] Usage inconsistent for ID 10038:actual (59555840, 953) != expected (59559936, 953)",
+                "Update quota info for quota type 1? yes",
+                " ",
+                "/dev/block/platform/soc/624000.ufshc/by-name/userdata: ***** FILE SYSTEM WAS MODIFIED *****"
+        };
+        doTestFsckFsStat(logs, 0x405, 5, 0, logs.length);
+
+        final String[] doubleLogs = new String[logs.length * 2];
+        System.arraycopy(logs, 0, doubleLogs, 0, logs.length);
+        System.arraycopy(logs, 0, doubleLogs, logs.length, logs.length);
+        doTestFsckFsStat(doubleLogs, 0x401, 1, 0, logs.length);
+        doTestFsckFsStat(doubleLogs, 0x402, 2, logs.length, logs.length * 2);
+    }
+
+    @Test
+    public void testQuotaOnly() {
+        final String[] logs = {
+                "e2fsck 1.43.3 (04-Sep-2016)",
+                "Pass 1: Checking inodes, blocks, and sizes",
+                "Pass 1E: Optimizing extent trees",
+                "Pass 2: Checking directory structure",
+                "Pass 3: Checking directory connectivity",
+                "Pass 4: Checking reference counts",
+                "Pass 5: Checking group summary information",
+                "[QUOTA WARNING] Usage inconsistent for ID 10038:actual (71667712, 1000) != expected (71671808, 1000)",
+                "Update quota info for quota type 0? yes",
+                " ",
+                "[QUOTA WARNING] Usage inconsistent for ID 10038:actual (59555840, 953) != expected (59559936, 953)",
+                "Update quota info for quota type 1? yes",
+                " ",
+                "/dev/block/platform/soc/624000.ufshc/by-name/userdata: ***** FILE SYSTEM WAS MODIFIED *****"
+        };
+        doTestFsckFsStat(logs, 0x405, 0x405, 0, logs.length);
+    }
+
+    @Test
+    public void testOrphaned() {
+        final String[] logs = {
+                "e2fsck 1.43.3 (04-Sep-2016)",
+                "Pass 1: Checking inodes, blocks, and sizes",
+                "Inodes that were part of a corrupted orphan linked list found.  Fix? yes",
+                " ",
+                "Inode 589877 was part of the orphaned inode list.  FIXED.",
+                " ",
+                "Inode 589878 was part of the orphaned inode list.  FIXED.",
+                " ",
+                "Pass 2: Checking directory structure",
+                "Pass 3: Checking directory connectivity",
+                "Pass 4: Checking reference counts",
+                "Pass 5: Checking group summary information",
+                " ",
+                "/dev/block/platform/soc/624000.ufshc/by-name/userdata: ***** FILE SYSTEM WAS MODIFIED *****"
+        };
+        doTestFsckFsStat(logs, 0x405, 0x405, 0, logs.length);
+    }
+
+    private void doTestFsckFsStat(String[] lines, int statOrg, int statUpdated, int startLineNumber,
+            int endLineNumber) {
+        assertEquals(statUpdated, BootReceiver.fixFsckFsStat(PARTITION, statOrg, lines,
+                startLineNumber, endLineNumber));
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
index 54ecab3..f75d49c 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
@@ -16,7 +16,8 @@
 
 package com.android.server.am;
 
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
 
 import android.content.ComponentName;
 import android.platform.test.annotations.Presubmit;
@@ -36,50 +37,61 @@
 @Presubmit
 @RunWith(AndroidJUnit4.class)
 public class ActivityRecordTests extends ActivityTestsBase {
+    private static final int TEST_STACK_ID = 100;
+
     private final ComponentName testActivityComponent =
             ComponentName.unflattenFromString("com.foo/.BarActivity");
     @Test
     public void testStackCleanupOnClearingTask() throws Exception {
         final ActivityManagerService service = createActivityManagerService();
-        final TestActivityStack testStack = new ActivityStackBuilder(service).build();
-        final TaskRecord task = createTask(service, testActivityComponent, testStack);
+        final TaskRecord task = createTask(service, testActivityComponent, TEST_STACK_ID);
         final ActivityRecord record = createActivity(service, testActivityComponent, task);
 
         record.setTask(null);
-        assertTrue(testStack.onActivityRemovedFromStackInvocationCount() == 1);
+        assertEquals(getActivityRemovedFromStackCount(service, TEST_STACK_ID), 1);
     }
 
     @Test
     public void testStackCleanupOnActivityRemoval() throws Exception {
         final ActivityManagerService service = createActivityManagerService();
-        final TestActivityStack testStack = new ActivityStackBuilder(service).build();
-        final TaskRecord task = createTask(service, testActivityComponent, testStack);
+        final TaskRecord task = createTask(service, testActivityComponent, TEST_STACK_ID);
         final ActivityRecord record = createActivity(service, testActivityComponent, task);
 
         task.removeActivity(record);
-        assertTrue(testStack.onActivityRemovedFromStackInvocationCount() == 1);
+        assertEquals(getActivityRemovedFromStackCount(service, TEST_STACK_ID),  1);
     }
 
     @Test
     public void testStackCleanupOnTaskRemoval() throws Exception {
         final ActivityManagerService service = createActivityManagerService();
-        final TestActivityStack testStack = new ActivityStackBuilder(service).build();
-        final TaskRecord task = createTask(service, testActivityComponent, testStack);
+        final TaskRecord task = createTask(service, testActivityComponent, TEST_STACK_ID);
         final ActivityRecord record = createActivity(service, testActivityComponent, task);
 
-        testStack.removeTask(task, null /*reason*/, ActivityStack.REMOVE_TASK_MODE_MOVING);
-        assertTrue(testStack.onActivityRemovedFromStackInvocationCount() == 1);
+        service.mStackSupervisor.getStack(TEST_STACK_ID)
+                .removeTask(task, null /*reason*/, ActivityStack.REMOVE_TASK_MODE_MOVING);
+
+        // Stack should be gone on task removal.
+        assertNull(service.mStackSupervisor.getStack(TEST_STACK_ID));
     }
 
     @Test
     public void testNoCleanupMovingActivityInSameStack() throws Exception {
         final ActivityManagerService service = createActivityManagerService();
-        final TestActivityStack testStack = new ActivityStackBuilder(service).build();
-        final TaskRecord oldTask = createTask(service, testActivityComponent, testStack);
+        final TaskRecord oldTask = createTask(service, testActivityComponent, TEST_STACK_ID);
         final ActivityRecord record = createActivity(service, testActivityComponent, oldTask);
-        final TaskRecord newTask = createTask(service, testActivityComponent, testStack);
+        final TaskRecord newTask = createTask(service, testActivityComponent, TEST_STACK_ID);
 
         record.reparent(newTask, 0, null /*reason*/);
-        assertTrue(testStack.onActivityRemovedFromStackInvocationCount() == 0);
+        assertEquals(getActivityRemovedFromStackCount(service, TEST_STACK_ID), 0);
+    }
+
+    private static int getActivityRemovedFromStackCount(ActivityManagerService service,
+            int stackId) {
+        final ActivityStack stack = service.mStackSupervisor.getStack(stackId);
+        if (stack instanceof ActivityStackReporter) {
+            return ((ActivityStackReporter) stack).onActivityRemovedFromStackInvocationCount();
+        }
+
+        return -1;
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
index 8423aff..fc9ab96 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
@@ -16,8 +16,14 @@
 
 package com.android.server.am;
 
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 
+import android.content.ComponentName;
+import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
 import android.support.test.filters.MediumTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -25,6 +31,10 @@
 import org.junit.runner.RunWith;
 import org.junit.Test;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
 import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
 
 /**
@@ -37,6 +47,9 @@
 @Presubmit
 @RunWith(AndroidJUnit4.class)
 public class ActivityStackSupervisorTests extends ActivityTestsBase {
+    private final ComponentName testActivityComponent =
+            ComponentName.unflattenFromString("com.foo/.BarActivity");
+
     /**
      * This test ensures that we do not try to restore a task based off an invalid task id. The
      * stack supervisor is a test version so there will be no tasks present. We should expect
@@ -49,4 +62,59 @@
                 MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, 0 /*stackId*/);
         assertNull(task);
     }
+
+    /**
+     * This test ensures that an existing task in the pinned stack is moved to the fullscreen
+     * activity stack when a new task is added.
+     */
+    @Test
+    public void testReplacingTaskInPinnedStack() throws Exception {
+        final ActivityManagerService service = createActivityManagerService();
+        final TaskRecord firstTask = createTask(service, testActivityComponent,
+                FULLSCREEN_WORKSPACE_STACK_ID);
+        final ActivityRecord firstActivity = createActivity(service, testActivityComponent,
+                firstTask);
+        // Create a new task on the full screen stack
+        final TaskRecord secondTask = createTask(service, testActivityComponent,
+                FULLSCREEN_WORKSPACE_STACK_ID);
+        final ActivityRecord secondActivity = createActivity(service, testActivityComponent,
+                secondTask);
+        service.mStackSupervisor.setFocusStackUnchecked("testReplacingTaskInPinnedStack",
+                service.mStackSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID));
+
+        // Ensure full screen stack has both tasks.
+        ensureStackPlacement(service.mStackSupervisor, FULLSCREEN_WORKSPACE_STACK_ID, firstTask,
+                secondTask);
+
+        // Move first activity to pinned stack.
+        service.mStackSupervisor.moveActivityToPinnedStackLocked(firstActivity,
+                new Rect() /*sourceBounds*/, 0f /*aspectRatio*/, false, "initialMove");
+
+        // Ensure a task has moved over.
+        ensureStackPlacement(service.mStackSupervisor, PINNED_STACK_ID, firstTask);
+        ensureStackPlacement(service.mStackSupervisor, FULLSCREEN_WORKSPACE_STACK_ID, secondTask);
+
+        // Move second activity to pinned stack.
+        service.mStackSupervisor.moveActivityToPinnedStackLocked(secondActivity,
+                new Rect() /*sourceBounds*/, 0f /*aspectRatio*/ /*destBounds*/, false, "secondMove");
+
+        // Ensure stacks have swapped tasks.
+        ensureStackPlacement(service.mStackSupervisor, PINNED_STACK_ID, secondTask);
+        ensureStackPlacement(service.mStackSupervisor, FULLSCREEN_WORKSPACE_STACK_ID, firstTask);
+    }
+
+    private static void ensureStackPlacement(ActivityStackSupervisor supervisor, int stackId,
+            TaskRecord... tasks) {
+        final ActivityStack stack = supervisor.getStack(stackId);
+        final ArrayList<TaskRecord> stackTasks = stack.getAllTasks();
+        assertEquals(stackTasks.size(), tasks != null ? tasks.length : 0);
+
+        if (tasks == null) {
+            return;
+        }
+
+        for (TaskRecord task : tasks) {
+            assertTrue(stackTasks.contains(task));
+        }
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
index 1d80b33..f42abf1 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
@@ -37,28 +37,27 @@
 @Presubmit
 @RunWith(AndroidJUnit4.class)
 public class ActivityStackTests extends ActivityTestsBase {
-    private final ComponentName testActivityComponent =
+    private static final int TEST_STACK_ID = 100;
+    private static final ComponentName testActivityComponent =
             ComponentName.unflattenFromString("com.foo/.BarActivity");
 
     @Test
     public void testEmptyTaskCleanupOnRemove() throws Exception {
         final ActivityManagerService service = createActivityManagerService();
-        final TestActivityStack testStack = new ActivityStackBuilder(service).build();
-        final TaskRecord task = createTask(service, testActivityComponent, testStack);
+        final TaskRecord task = createTask(service, testActivityComponent, TEST_STACK_ID);
         assertNotNull(task.getWindowContainerController());
-        testStack.removeTask(task, "testEmptyTaskCleanupOnRemove",
-                ActivityStack.REMOVE_TASK_MODE_DESTROYING);
+        service.mStackSupervisor.getStack(TEST_STACK_ID).removeTask(task,
+                "testEmptyTaskCleanupOnRemove", ActivityStack.REMOVE_TASK_MODE_DESTROYING);
         assertNull(task.getWindowContainerController());
     }
     @Test
     public void testOccupiedTaskCleanupOnRemove() throws Exception {
         final ActivityManagerService service = createActivityManagerService();
-        final TestActivityStack testStack = new ActivityStackBuilder(service).build();
-        final TaskRecord task = createTask(service, testActivityComponent, testStack);
+        final TaskRecord task = createTask(service, testActivityComponent, TEST_STACK_ID);
         final ActivityRecord activityRecord = createActivity(service, testActivityComponent, task);
         assertNotNull(task.getWindowContainerController());
-        testStack.removeTask(task, "testOccupiedTaskCleanupOnRemove",
-                ActivityStack.REMOVE_TASK_MODE_DESTROYING);
+        service.mStackSupervisor.getStack(TEST_STACK_ID).removeTask(task,
+                "testOccupiedTaskCleanupOnRemove", ActivityStack.REMOVE_TASK_MODE_DESTROYING);
         assertNotNull(task.getWindowContainerController());
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
index 3bf0e5f..0827084 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -17,6 +17,11 @@
 package com.android.server.am;
 
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doAnswer;
+
+import org.mockito.invocation.InvocationOnMock;
 
 import android.app.ActivityManager;
 import android.content.ComponentName;
@@ -33,6 +38,7 @@
 import com.android.server.wm.AppWindowContainerController;
 import com.android.server.wm.StackWindowController;
 
+import com.android.server.wm.TaskWindowContainerController;
 import com.android.server.wm.WindowManagerService;
 import com.android.server.wm.WindowTestUtils;
 import org.junit.After;
@@ -64,16 +70,15 @@
 
     protected ActivityManagerService createActivityManagerService() {
         final ActivityManagerService service = new TestActivityManagerService(mContext);
-        service.mWindowManager = WindowTestUtils.getWindowManagerService(mContext);
+        service.mWindowManager = WindowTestUtils.getMockWindowManagerService();
         return service;
     }
 
-    protected static TestActivityStack createActivityStack(ActivityManagerService service,
+    protected static ActivityStack createActivityStack(ActivityManagerService service,
             int stackId, int displayId, boolean onTop) {
         if (service.mStackSupervisor instanceof TestActivityStackSupervisor) {
-            final TestActivityStack stack = ((TestActivityStackSupervisor) service.mStackSupervisor)
+            return ((TestActivityStackSupervisor) service.mStackSupervisor)
                     .createTestStack(service, stackId, onTop);
-            return stack;
         }
 
         return null;
@@ -103,7 +108,7 @@
     }
 
     protected static TaskRecord createTask(ActivityManagerService service,
-            ComponentName component, ActivityStack stack) {
+            ComponentName component, int stackId) {
         final ActivityInfo aInfo = new ActivityInfo();
         aInfo.applicationInfo = new ApplicationInfo();
         aInfo.applicationInfo.packageName = component.getPackageName();
@@ -113,13 +118,16 @@
 
         final TaskRecord task = new TaskRecord(service, 0, aInfo, intent /*intent*/,
                 null /*_taskDescription*/, new ActivityManager.TaskThumbnailInfo());
+        final ActivityStack stack = service.mStackSupervisor.getStack(stackId,
+                true /*createStaticStackIfNeeded*/, true /*onTop*/);
         stack.addTask(task, true, "creating test task");
         task.setStack(stack);
-        task.createWindowContainer(true, true);
+        task.setWindowContainerController(mock(TaskWindowContainerController.class));
 
         return task;
     }
 
+
     /**
      * An {@link ActivityManagerService} subclass which provides a test
      * {@link ActivityStackSupervisor}.
@@ -127,6 +135,9 @@
     protected static class TestActivityManagerService extends ActivityManagerService {
         public TestActivityManagerService(Context context) {
             super(context);
+            mSupportsMultiWindow = true;
+            mSupportsMultiDisplay = true;
+            mWindowManager = WindowTestUtils.getWindowManagerService(context);
         }
 
         @Override
@@ -142,6 +153,12 @@
     protected static class TestActivityStackSupervisor extends ActivityStackSupervisor {
         public TestActivityStackSupervisor(ActivityManagerService service, Looper looper) {
             super(service, looper);
+            mWindowManager = prepareMockWindowManager();
+        }
+
+        // No home stack is set.
+        @Override
+        void moveHomeStackToFront(String reason) {
         }
 
         // Invoked during {@link ActivityStack} creation.
@@ -149,18 +166,45 @@
         void updateUIDsPresentOnDisplay() {
         }
 
-        public TestActivityStack createTestStack(ActivityManagerService service, int stackId,
-                boolean onTop) {
+        // Just return the current front task.
+        @Override
+        ActivityStack getNextFocusableStackLocked(ActivityStack currentFocus) {
+            return mFocusedStack;
+        }
+
+        // Called when moving activity to pinned stack.
+        @Override
+        void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
+                boolean preserveWindows) {
+        }
+
+        public <T extends ActivityStack> T createTestStack(ActivityManagerService service,
+                int stackId, boolean onTop) {
             final ActivityDisplay display = new ActivityDisplay();
             final TestActivityContainer container =
                     new TestActivityContainer(service, stackId, display, onTop);
-            return container.getStack();
+            mActivityContainers.put(stackId, container);
+            return (T) container.getStack();
+        }
+
+        @Override
+        protected <T extends ActivityStack> T getStack(int stackId,
+                boolean createStaticStackIfNeeded, boolean createOnTop) {
+            final T stack = super.getStack(stackId, createStaticStackIfNeeded, createOnTop);
+
+            if (stack != null || !createStaticStackIfNeeded) {
+                return stack;
+            }
+
+            return createTestStack(mService, stackId, createOnTop);
         }
 
         private class TestActivityContainer extends ActivityContainer {
-            private ActivityManagerService mService;
-            private TestActivityStack mStack;
+            private final ActivityManagerService mService;
+
             private boolean mOnTop;
+            private int mStackId;
+            private ActivityStack mStack;
 
             TestActivityContainer(ActivityManagerService service, int stackId,
                     ActivityDisplay activityDisplay, boolean onTop) {
@@ -174,12 +218,16 @@
                 // we cannot set {@link mService} by the time the super constructor calling this
                 // method is invoked.
                 mOnTop = onTop;
+                mStackId = stackId;
             }
 
-            public TestActivityStack getStack() {
+            public ActivityStack getStack() {
                 if (mStack == null) {
-                    mStack = new TestActivityStack(this,
-                            new RecentTasks(mService, mService.mStackSupervisor), mOnTop);
+                    final RecentTasks recents =
+                            new RecentTasks(mService, mService.mStackSupervisor);
+                    mStack = mStackId == ActivityManager.StackId.PINNED_STACK_ID
+                    ? new PinnedActivityStack(this, recents, mOnTop)
+                    : new TestActivityStack(this, recents, mOnTop);
                 }
 
                 return mStack;
@@ -187,13 +235,31 @@
         }
     }
 
+    private static WindowManagerService prepareMockWindowManager() {
+        final WindowManagerService service = mock(WindowManagerService.class);
+
+        doAnswer((InvocationOnMock invocationOnMock) -> {
+            final Runnable runnable = invocationOnMock.<Runnable>getArgument(0);
+            if (runnable != null) {
+                runnable.run();
+            }
+            return null;
+        }).when(service).inSurfaceTransaction(any());
+
+        return service;
+    }
+
+    protected interface ActivityStackReporter {
+        int onActivityRemovedFromStackInvocationCount();
+    }
+
     /**
      * Override of {@link ActivityStack} that tracks test metrics, such as the number of times a
      * method is called. Note that its functionality depends on the implementations of the
      * construction arguments.
      */
     protected static class TestActivityStack<T extends StackWindowController>
-            extends ActivityStack<T> {
+            extends ActivityStack<T> implements ActivityStackReporter {
         private int mOnActivityRemovedFromStackCount = 0;
         private T mContainerController;
         TestActivityStack(ActivityStackSupervisor.ActivityContainer activityContainer,
@@ -208,6 +274,7 @@
         }
 
         // Returns the number of times {@link #onActivityRemovedFromStack} has been called
+        @Override
         public int onActivityRemovedFromStackInvocationCount() {
             return mOnActivityRemovedFromStackCount;
         }
@@ -225,6 +292,7 @@
         }
     }
 
+
     protected static class ActivityStackBuilder {
         private boolean mOnTop = true;
         private int mStackId = 0;
@@ -251,7 +319,7 @@
             return this;
         }
 
-        public TestActivityStack build() {
+        public ActivityStack build() {
             return createActivityStack(mService, mStackId, mDisplayId, mOnTop);
         }
     }
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceCreateProfileTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceCreateProfileTest.java
index 929a73d..c314de4 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceCreateProfileTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceCreateProfileTest.java
@@ -27,6 +27,7 @@
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
 import android.support.test.runner.AndroidJUnit4;
+import android.util.IconDrawableFactory;
 
 import com.android.server.LocalServices;
 
@@ -155,9 +156,9 @@
     public void testNumberOfBadges() {
         assertTrue("Max profiles greater than number of badges",
                 UserManagerService.MAX_MANAGED_PROFILES
-                <= ApplicationPackageManager.CORP_BADGE_COLORS.length);
+                <= IconDrawableFactory.CORP_BADGE_COLORS.length);
         assertEquals("Num colors doesn't match number of badge labels",
-                ApplicationPackageManager.CORP_BADGE_COLORS.length,
+                IconDrawableFactory.CORP_BADGE_COLORS.length,
                 ApplicationPackageManager.CORP_BADGE_LABEL_RES_ID.length);
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java
index 7f150a2..cd7a7c7 100644
--- a/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java
@@ -152,6 +152,8 @@
             mAwaitingAnimationStart = false;
             mAnimationStarted = true;
             mSchedulePipModeChangedOnStart = schedulePipModeChangedCallback;
+
+            mController.onAllWindowsDrawn();
         }
 
         @Override
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index fbeda0a..9392e8e 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -90,6 +90,7 @@
                     return null;
                 }).when(am).notifyKeyguardFlagsChanged(any());
             }
+
             sWm = WindowManagerService.main(context, mock(InputManagerService.class), true, false,
                     false, new TestWindowManagerPolicy());
         }
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
index 3a44357..ae3eb52 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
@@ -48,6 +48,13 @@
     }
 
     /**
+     * Retrieves an instance of a mock {@link WindowManagerService}.
+     */
+    public static WindowManagerService getMockWindowManagerService() {
+        return mock(WindowManagerService.class);
+    }
+
+    /**
      * Creates a mock instance of {@link StackWindowController}.
      */
     public static StackWindowController createMockStackWindowContainerController() {
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 80b73d3..31595a6 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -857,13 +857,16 @@
                     break;
                 case MSG_UPDATE_HOST_STATE:
                     SomeArgs args = (SomeArgs) msg.obj;
+                    boolean prevHostConnected = mHostConnected;
                     mHostConnected = (args.argi1 == 1);
                     mSourcePower = (args.argi2 == 1);
                     mSinkPower = (args.argi3 == 1);
                     args.recycle();
                     updateUsbNotification();
                     if (mBootCompleted) {
-                        updateUsbStateBroadcastIfNeeded(false);
+                        if (mHostConnected || prevHostConnected) {
+                            updateUsbStateBroadcastIfNeeded(false);
+                        }
                     } else {
                         mPendingBootBroadcast = true;
                     }
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 3d51c4c..8ee6454 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -911,7 +911,7 @@
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
     public String getDeviceSoftwareVersion() {
-        return getDeviceSoftwareVersion(getDefaultSim());
+        return getDeviceSoftwareVersion(getSlotIndex());
     }
 
     /**
@@ -997,7 +997,7 @@
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
     public String getImei() {
-        return getImei(getDefaultSim());
+        return getImei(getSlotIndex());
     }
 
     /**
@@ -1029,7 +1029,7 @@
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
     public String getMeid() {
-        return getMeid(getDefaultSim());
+        return getMeid(getSlotIndex());
     }
 
     /**
@@ -1059,7 +1059,7 @@
      */
     /** {@hide}*/
     public String getNai() {
-        return getNai(getDefaultSim());
+        return getNai(getSlotIndex());
     }
 
     /**
@@ -1303,7 +1303,7 @@
     }
 
     private int getPhoneTypeFromProperty() {
-        return getPhoneTypeFromProperty(getDefaultPhone());
+        return getPhoneTypeFromProperty(getPhoneId());
     }
 
     /** {@hide} */
@@ -1317,7 +1317,7 @@
     }
 
     private int getPhoneTypeFromNetworkType() {
-        return getPhoneTypeFromNetworkType(getDefaultPhone());
+        return getPhoneTypeFromNetworkType(getPhoneId());
     }
 
     /** {@hide} */
@@ -1500,7 +1500,7 @@
      * on a CDMA network).
      */
     public String getNetworkOperator() {
-        return getNetworkOperatorForPhone(getDefaultPhone());
+        return getNetworkOperatorForPhone(getPhoneId());
     }
 
     /**
@@ -1546,7 +1546,7 @@
      * @see #createForPhoneAccountHandle(PhoneAccountHandle)
      */
     public String getNetworkSpecifier() {
-        return String.valueOf(mSubId);
+        return String.valueOf(getSubId());
     }
 
     /**
@@ -1565,7 +1565,7 @@
     public PersistableBundle getCarrierConfig() {
         CarrierConfigManager carrierConfigManager = mContext
                 .getSystemService(CarrierConfigManager.class);
-        return carrierConfigManager.getConfigForSubId(mSubId);
+        return carrierConfigManager.getConfigForSubId(getSubId());
     }
 
     /**
@@ -1602,7 +1602,7 @@
      * on a CDMA network).
      */
     public String getNetworkCountryIso() {
-        return getNetworkCountryIsoForPhone(getDefaultPhone());
+        return getNetworkCountryIsoForPhone(getPhoneId());
     }
 
     /**
@@ -1748,6 +1748,9 @@
      * Returns a constant indicating the radio technology (network type)
      * currently in use on the device for data transmission.
      *
+     * If this object has been created with {@link #createForSubscriptionId}, applies to the given
+     * subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
+     *
      * <p>
      * Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
@@ -1772,7 +1775,7 @@
      * @see #NETWORK_TYPE_HSPAP
      */
     public int getDataNetworkType() {
-        return getDataNetworkType(getSubId());
+        return getDataNetworkType(getSubId(SubscriptionManager.getDefaultDataSubscriptionId()));
     }
 
     /**
@@ -1996,7 +1999,7 @@
      * @return true if a ICC card is present
      */
     public boolean hasIccCard() {
-        return hasIccCard(getDefaultSim());
+        return hasIccCard(getSlotIndex());
     }
 
     /**
@@ -2037,7 +2040,7 @@
      * @see #SIM_STATE_CARD_RESTRICTED
      */
     public int getSimState() {
-        int slotIndex = getDefaultSim();
+        int slotIndex = getSlotIndex();
         // slotIndex may be invalid due to sim being absent. In that case query all slots to get
         // sim state
         if (slotIndex < 0) {
@@ -2166,7 +2169,7 @@
      * @see #getSimState
      */
     public String getSimOperatorName() {
-        return getSimOperatorNameForPhone(getDefaultPhone());
+        return getSimOperatorNameForPhone(getPhoneId());
     }
 
     /**
@@ -2198,7 +2201,7 @@
      * Returns the ISO country code equivalent for the SIM provider's country code.
      */
     public String getSimCountryIso() {
-        return getSimCountryIsoForPhone(getDefaultPhone());
+        return getSimCountryIsoForPhone(getPhoneId());
     }
 
     /**
@@ -2754,7 +2757,7 @@
             ITelephony telephony = getITelephony();
             if (telephony != null) {
                 return telephony
-                        .getVisualVoicemailPackageName(mContext.getOpPackageName(), mSubId);
+                        .getVisualVoicemailPackageName(mContext.getOpPackageName(), getSubId());
             }
         } catch (RemoteException ex) {
         } catch (NullPointerException ex) {
@@ -4057,35 +4060,67 @@
      * subId is returned. Otherwise, the default subId will be returned.
      */
     private int getSubId() {
-      if (mSubId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
-        return getDefaultSubscription();
+      if (SubscriptionManager.isUsableSubIdValue(mSubId)) {
+        return mSubId;
       }
-      return mSubId;
+      return SubscriptionManager.getDefaultSubscriptionId();
     }
 
     /**
-     * Returns Default subscription.
+     * Return an appropriate subscription ID for any situation.
+     *
+     * If this object has been created with {@link #createForSubscriptionId}, then the provided
+     * subId is returned. Otherwise, the preferred subId which is based on caller's context is
+     * returned.
+     * {@see SubscriptionManager#getDefaultDataSubscriptionId()}
+     * {@see SubscriptionManager#getDefaultVoiceSubscriptionId()}
+     * {@see SubscriptionManager#getDefaultSmsSubscriptionId()}
      */
-    private static int getDefaultSubscription() {
-        return SubscriptionManager.getDefaultSubscriptionId();
+    private int getSubId(int preferredSubId) {
+        if (SubscriptionManager.isUsableSubIdValue(mSubId)) {
+            return mSubId;
+        }
+        return preferredSubId;
     }
 
     /**
-     * Returns Default phone.
+     * Return an appropriate phone ID for any situation.
+     *
+     * If this object has been created with {@link #createForSubscriptionId}, then the phoneId
+     * associated with the provided subId is returned. Otherwise, the default phoneId associated
+     * with the default subId will be returned.
      */
-    private static int getDefaultPhone() {
-        return SubscriptionManager.getPhoneId(SubscriptionManager.getDefaultSubscriptionId());
+    private int getPhoneId() {
+        return SubscriptionManager.getPhoneId(getSubId());
     }
 
     /**
-     *  @return default SIM's slot index. If SIM is not inserted, return default SIM slot index.
+     * Return an appropriate phone ID for any situation.
+     *
+     * If this object has been created with {@link #createForSubscriptionId}, then the phoneId
+     * associated with the provided subId is returned. Otherwise, return the phoneId associated
+     * with the preferred subId based on caller's context.
+     * {@see SubscriptionManager#getDefaultDataSubscriptionId()}
+     * {@see SubscriptionManager#getDefaultVoiceSubscriptionId()}
+     * {@see SubscriptionManager#getDefaultSmsSubscriptionId()}
+     */
+    private int getPhoneId(int preferredSubId) {
+        return SubscriptionManager.getPhoneId(getSubId(preferredSubId));
+    }
+
+    /**
+     * Return an appropriate slot index for any situation.
+     *
+     * if this object has been created with {@link #createForSubscriptionId}, then the slot index
+     * associated with the provided subId is returned. Otherwise, return the slot index associated
+     * with the default subId.
+     * If SIM is not inserted, return default SIM slot index.
      *
      * {@hide}
      */
     @VisibleForTesting
-    public int getDefaultSim() {
-        int slotIndex = SubscriptionManager.getSlotIndex(
-                SubscriptionManager.getDefaultSubscriptionId());
+    public int getSlotIndex() {
+        int slotIndex = SubscriptionManager.getSlotIndex(getSubId());
         if (slotIndex == SubscriptionManager.SIM_NOT_INSERTED) {
             slotIndex = SubscriptionManager.DEFAULT_SIM_SLOT_INDEX;
         }
@@ -4902,7 +4937,7 @@
     /** @hide */
     @SystemApi
     public List<String> getCarrierPackageNamesForIntent(Intent intent) {
-        return getCarrierPackageNamesForIntentAndPhone(intent, getDefaultPhone());
+        return getCarrierPackageNamesForIntentAndPhone(intent, getPhoneId());
     }
 
     /** @hide */
@@ -5164,7 +5199,7 @@
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
-                telephony.handleUssdRequest(mSubId, ussdRequest, wrappedCallback);
+                telephony.handleUssdRequest(getSubId(), ussdRequest, wrappedCallback);
             }
         } catch (RemoteException e) {
             Log.e(TAG, "Error calling ITelephony#sendUSSDCode", e);
@@ -5184,7 +5219,8 @@
     public boolean isConcurrentVoiceAndDataSupported() {
         try {
             ITelephony telephony = getITelephony();
-            return (telephony == null ? false : telephony.isConcurrentVoiceAndDataAllowed(mSubId));
+            return (telephony == null ? false : telephony.isConcurrentVoiceAndDataAllowed(
+                    getSubId()));
         } catch (RemoteException e) {
             Log.e(TAG, "Error calling ITelephony#isConcurrentVoiceAndDataAllowed", e);
         }
@@ -5321,6 +5357,8 @@
 
     /**
      * Turns mobile data on or off.
+     * If this object has been created with {@link #createForSubscriptionId}, applies to the given
+     * subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
      *
      * <p>Requires Permission:
      *     {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the
@@ -5331,7 +5369,7 @@
      * @see #hasCarrierPrivileges
      */
     public void setDataEnabled(boolean enable) {
-        setDataEnabled(getSubId(), enable);
+        setDataEnabled(getSubId(SubscriptionManager.getDefaultDataSubscriptionId()), enable);
     }
 
     /** @hide */
@@ -5361,6 +5399,9 @@
     /**
      * Returns whether mobile data is enabled or not.
      *
+     * If this object has been created with {@link #createForSubscriptionId}, applies to the given
+     * subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
+     *
      * <p>Requires one of the following permissions:
      * {@link android.Manifest.permission#ACCESS_NETWORK_STATE ACCESS_NETWORK_STATE},
      * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}, or that the
@@ -5376,7 +5417,7 @@
      */
     @SuppressWarnings("deprecation")
     public boolean isDataEnabled() {
-        return getDataEnabled(getSubId());
+        return getDataEnabled(getSubId(SubscriptionManager.getDefaultDataSubscriptionId()));
     }
 
     /**
@@ -5626,7 +5667,7 @@
     * @hide
     */
     public void setSimOperatorNumeric(String numeric) {
-        int phoneId = getDefaultPhone();
+        int phoneId = getPhoneId();
         setSimOperatorNumericForPhone(phoneId, numeric);
     }
 
@@ -5646,7 +5687,7 @@
      * @hide
      */
     public void setSimOperatorName(String name) {
-        int phoneId = getDefaultPhone();
+        int phoneId = getPhoneId();
         setSimOperatorNameForPhone(phoneId, name);
     }
 
@@ -5666,7 +5707,7 @@
     * @hide
     */
     public void setSimCountryIso(String iso) {
-        int phoneId = getDefaultPhone();
+        int phoneId = getPhoneId();
         setSimCountryIsoForPhone(phoneId, iso);
     }
 
@@ -5686,7 +5727,7 @@
      * @hide
      */
     public void setSimState(String state) {
-        int phoneId = getDefaultPhone();
+        int phoneId = getPhoneId();
         setSimStateForPhone(phoneId, state);
     }
 
@@ -5711,7 +5752,7 @@
      * @hide
      **/
     public void setSimPowerState(boolean powerUp) {
-        setSimPowerStateForSlot(getDefaultSim(), powerUp);
+        setSimPowerStateForSlot(getSlotIndex(), powerUp);
     }
 
     /**
@@ -5745,7 +5786,7 @@
      * @hide
      */
     public void setBasebandVersion(String version) {
-        int phoneId = getDefaultPhone();
+        int phoneId = getPhoneId();
         setBasebandVersionForPhone(phoneId, version);
     }
 
@@ -5772,7 +5813,7 @@
      * @hide
      */
     public void setPhoneType(int type) {
-        int phoneId = getDefaultPhone();
+        int phoneId = getPhoneId();
         setPhoneType(phoneId, type);
     }
 
@@ -5800,7 +5841,7 @@
      * @hide
      */
     public String getOtaSpNumberSchema(String defaultValue) {
-        int phoneId = getDefaultPhone();
+        int phoneId = getPhoneId();
         return getOtaSpNumberSchemaForPhone(phoneId, defaultValue);
     }
 
@@ -5831,7 +5872,7 @@
      * @hide
      */
     public boolean getSmsReceiveCapable(boolean defaultValue) {
-        int phoneId = getDefaultPhone();
+        int phoneId = getPhoneId();
         return getSmsReceiveCapableForPhone(phoneId, defaultValue);
     }
 
@@ -5862,7 +5903,7 @@
      * @hide
      */
     public boolean getSmsSendCapable(boolean defaultValue) {
-        int phoneId = getDefaultPhone();
+        int phoneId = getPhoneId();
         return getSmsSendCapableForPhone(phoneId, defaultValue);
     }
 
@@ -5890,7 +5931,7 @@
      * @hide
      */
     public void setNetworkOperatorName(String name) {
-        int phoneId = getDefaultPhone();
+        int phoneId = getPhoneId();
         setNetworkOperatorNameForPhone(phoneId, name);
     }
 
@@ -5912,7 +5953,7 @@
      * @hide
      */
     public void setNetworkOperatorNumeric(String numeric) {
-        int phoneId = getDefaultPhone();
+        int phoneId = getPhoneId();
         setNetworkOperatorNumericForPhone(phoneId, numeric);
     }
 
@@ -5932,7 +5973,7 @@
      * @hide
      */
     public void setNetworkRoaming(boolean isRoaming) {
-        int phoneId = getDefaultPhone();
+        int phoneId = getPhoneId();
         setNetworkRoamingForPhone(phoneId, isRoaming);
     }
 
@@ -5956,7 +5997,7 @@
      * @hide
      */
     public void setNetworkCountryIso(String iso) {
-        int phoneId = getDefaultPhone();
+        int phoneId = getPhoneId();
         setNetworkCountryIsoForPhone(phoneId, iso);
     }
 
@@ -5976,11 +6017,15 @@
 
     /**
      * Set the network type currently in use on the device for data transmission.
+     *
+     * If this object has been created with {@link #createForSubscriptionId}, applies to the
+     * phoneId associated with the given subId. Otherwise, applies to the phoneId associated with
+     * {@link SubscriptionManager#getDefaultDataSubscriptionId()}
      * @param type the network type currently in use on the device for data transmission
      * @hide
      */
     public void setDataNetworkType(int type) {
-        int phoneId = getDefaultPhone();
+        int phoneId = getPhoneId(SubscriptionManager.getDefaultDataSubscriptionId());
         setDataNetworkTypeForPhone(phoneId, type);
     }
 
@@ -6200,7 +6245,7 @@
      * @hide
      */
     public String getAidForAppType(int appType) {
-        return getAidForAppType(getDefaultSubscription(), appType);
+        return getAidForAppType(getSubId(), appType);
     }
 
     /**
@@ -6234,7 +6279,7 @@
      * @hide
      */
     public String getEsn() {
-        return getEsn(getDefaultSubscription());
+        return getEsn(getSubId());
     }
 
     /**
@@ -6267,7 +6312,7 @@
      * @hide
      */
     public String getCdmaPrlVersion() {
-        return getCdmaPrlVersion(getDefaultSubscription());
+        return getCdmaPrlVersion(getSubId());
     }
 
     /**
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 20392e7..589dd0c 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -1134,4 +1134,11 @@
     public ComponentName getInstantAppInstallerComponent() {
         throw new UnsupportedOperationException();
     }
+
+    /**
+     * @hide
+     */
+    public String getInstantAppAndroidId(String packageName, UserHandle user) {
+        throw new UnsupportedOperationException();
+    }
 }
diff --git a/tests/net/java/android/net/NetworkCapabilitiesTest.java b/tests/net/java/android/net/NetworkCapabilitiesTest.java
new file mode 100644
index 0000000..e3b06c8
--- /dev/null
+++ b/tests/net/java/android/net/NetworkCapabilitiesTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2017 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.net;
+
+import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
+import static android.net.NetworkCapabilities.RESTRICTED_CAPABILITIES;
+import static android.net.NetworkCapabilities.UNRESTRICTED_CAPABILITIES;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+
+import android.net.NetworkCapabilities;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class NetworkCapabilitiesTest {
+    @Test
+    public void testMaybeMarkCapabilitiesRestricted() {
+        // verify EIMS is restricted
+        assertEquals((1 << NET_CAPABILITY_EIMS) & RESTRICTED_CAPABILITIES,
+                (1 << NET_CAPABILITY_EIMS));
+
+        // verify CBS is also restricted
+        assertEquals((1 << NET_CAPABILITY_CBS) & RESTRICTED_CAPABILITIES,
+                (1 << NET_CAPABILITY_CBS));
+
+        // verify default is not restricted
+        assertEquals((1 << NET_CAPABILITY_INTERNET) & RESTRICTED_CAPABILITIES, 0);
+
+        // just to see
+        assertEquals(RESTRICTED_CAPABILITIES & UNRESTRICTED_CAPABILITIES, 0);
+
+        // check that internet does not get restricted
+        NetworkCapabilities netCap = new NetworkCapabilities();
+        netCap.addCapability(NET_CAPABILITY_INTERNET);
+        netCap.maybeMarkCapabilitiesRestricted();
+        assertTrue(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
+
+        // metered-ness shouldn't matter
+        netCap = new NetworkCapabilities();
+        netCap.addCapability(NET_CAPABILITY_INTERNET);
+        netCap.addCapability(NET_CAPABILITY_NOT_METERED);
+        netCap.maybeMarkCapabilitiesRestricted();
+        assertTrue(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
+        netCap = new NetworkCapabilities();
+        netCap.addCapability(NET_CAPABILITY_INTERNET);
+        netCap.removeCapability(NET_CAPABILITY_NOT_METERED);
+        netCap.maybeMarkCapabilitiesRestricted();
+        assertTrue(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
+
+        // add EIMS - bundled with unrestricted means it's unrestricted
+        netCap = new NetworkCapabilities();
+        netCap.addCapability(NET_CAPABILITY_INTERNET);
+        netCap.addCapability(NET_CAPABILITY_EIMS);
+        netCap.addCapability(NET_CAPABILITY_NOT_METERED);
+        netCap.maybeMarkCapabilitiesRestricted();
+        assertTrue(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
+        netCap = new NetworkCapabilities();
+        netCap.addCapability(NET_CAPABILITY_INTERNET);
+        netCap.addCapability(NET_CAPABILITY_EIMS);
+        netCap.removeCapability(NET_CAPABILITY_NOT_METERED);
+        netCap.maybeMarkCapabilitiesRestricted();
+        assertTrue(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
+
+        // just a restricted cap should be restricted regardless of meteredness
+        netCap = new NetworkCapabilities();
+        netCap.addCapability(NET_CAPABILITY_EIMS);
+        netCap.addCapability(NET_CAPABILITY_NOT_METERED);
+        netCap.maybeMarkCapabilitiesRestricted();
+        assertFalse(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
+        netCap = new NetworkCapabilities();
+        netCap.addCapability(NET_CAPABILITY_EIMS);
+        netCap.removeCapability(NET_CAPABILITY_NOT_METERED);
+        netCap.maybeMarkCapabilitiesRestricted();
+        assertFalse(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
+
+        // try 2 restricted caps
+        netCap = new NetworkCapabilities();
+        netCap.addCapability(NET_CAPABILITY_CBS);
+        netCap.addCapability(NET_CAPABILITY_EIMS);
+        netCap.addCapability(NET_CAPABILITY_NOT_METERED);
+        netCap.maybeMarkCapabilitiesRestricted();
+        assertFalse(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
+        netCap = new NetworkCapabilities();
+        netCap.addCapability(NET_CAPABILITY_CBS);
+        netCap.addCapability(NET_CAPABILITY_EIMS);
+        netCap.removeCapability(NET_CAPABILITY_NOT_METERED);
+        netCap.maybeMarkCapabilitiesRestricted();
+        assertFalse(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
+    }
+
+}
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 2bf5206..bd2b2a36 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -782,7 +782,79 @@
     }
 }
 
-status_t massageManifest(Bundle* bundle, sp<XMLNode> root)
+static sp<ResourceTable::ConfigList> findEntry(const String16& packageStr, const String16& typeStr,
+                                               const String16& nameStr, ResourceTable* table) {
+  sp<ResourceTable::Package> pkg = table->getPackage(packageStr);
+  if (pkg != NULL) {
+      sp<ResourceTable::Type> type = pkg->getTypes().valueFor(typeStr);
+      if (type != NULL) {
+          return type->getConfigs().valueFor(nameStr);
+      }
+  }
+  return NULL;
+}
+
+static uint16_t getMaxSdkVersion(const sp<ResourceTable::ConfigList>& configList) {
+  const DefaultKeyedVector<ConfigDescription, sp<ResourceTable::Entry>>& entries =
+          configList->getEntries();
+  uint16_t maxSdkVersion = 0u;
+  for (size_t i = 0; i < entries.size(); i++) {
+    maxSdkVersion = std::max(maxSdkVersion, entries.keyAt(i).sdkVersion);
+  }
+  return maxSdkVersion;
+}
+
+static void massageRoundIconSupport(const String16& iconRef, const String16& roundIconRef,
+                                    ResourceTable* table) {
+  bool publicOnly = false;
+  const char* err;
+
+  String16 iconPackage, iconType, iconName;
+  if (!ResTable::expandResourceRef(iconRef.string(), iconRef.size(), &iconPackage, &iconType,
+                                   &iconName, NULL, &table->getAssetsPackage(), &err,
+                                   &publicOnly)) {
+      // Errors will be raised in later XML compilation.
+      return;
+  }
+
+  sp<ResourceTable::ConfigList> iconEntry = findEntry(iconPackage, iconType, iconName, table);
+  if (iconEntry == NULL || getMaxSdkVersion(iconEntry) < SDK_O) {
+      // The icon is not adaptive, so nothing to massage.
+      return;
+  }
+
+  String16 roundIconPackage, roundIconType, roundIconName;
+  if (!ResTable::expandResourceRef(roundIconRef.string(), roundIconRef.size(), &roundIconPackage,
+                                   &roundIconType, &roundIconName, NULL, &table->getAssetsPackage(),
+                                   &err, &publicOnly)) {
+      // Errors will be raised in later XML compilation.
+      return;
+  }
+
+  sp<ResourceTable::ConfigList> roundIconEntry = findEntry(roundIconPackage, roundIconType,
+                                                           roundIconName, table);
+  if (roundIconEntry == NULL || getMaxSdkVersion(roundIconEntry) >= SDK_O) {
+      // The developer explicitly used a v26 compatible drawable as the roundIcon, meaning we should
+      // not generate an alias to the icon drawable.
+      return;
+  }
+
+  String16 aliasValue = String16(String8::format("@%s:%s/%s", String8(iconPackage).string(),
+                                                 String8(iconType).string(),
+                                                 String8(iconName).string()));
+
+  // Add an equivalent v26 entry to the roundIcon for each v26 variant of the regular icon.
+  const DefaultKeyedVector<ConfigDescription, sp<ResourceTable::Entry>>& configList =
+          iconEntry->getEntries();
+  for (size_t i = 0; i < configList.size(); i++) {
+      if (configList.keyAt(i).sdkVersion >= SDK_O) {
+          table->addEntry(SourcePos(), roundIconPackage, roundIconType, roundIconName, aliasValue,
+                          NULL, &configList.keyAt(i));
+      }
+  }
+}
+
+status_t massageManifest(Bundle* bundle, ResourceTable* table, sp<XMLNode> root)
 {
     root = root->searchElement(String16(), String16("manifest"));
     if (root == NULL) {
@@ -916,7 +988,7 @@
             String8 tag(child->getElementName());
             if (tag == "instrumentation") {
                 XMLNode::attribute_entry* attr = child->editAttribute(
-                        String16("http://schemas.android.com/apk/res/android"), String16("targetPackage"));
+                        String16(RESOURCES_ANDROID_NAMESPACE), String16("targetPackage"));
                 if (attr != NULL) {
                     attr->string.setTo(String16(instrumentationPackageNameOverride));
                 }
@@ -924,6 +996,19 @@
         }
     }
     
+    sp<XMLNode> application = root->getChildElement(String16(), String16("application"));
+    if (application != NULL) {
+        XMLNode::attribute_entry* icon_attr = application->editAttribute(
+                String16(RESOURCES_ANDROID_NAMESPACE), String16("icon"));
+        if (icon_attr != NULL) {
+            XMLNode::attribute_entry* round_icon_attr = application->editAttribute(
+                    String16(RESOURCES_ANDROID_NAMESPACE), String16("roundIcon"));
+            if (round_icon_attr != NULL) {
+                massageRoundIconSupport(icon_attr->string, round_icon_attr->string, table);
+            }
+        }
+    }
+
     // Generate split name if feature is present.
     const XMLNode::attribute_entry* attr = root->getAttribute(String16(), String16("featureName"));
     if (attr != NULL) {
@@ -1638,7 +1723,7 @@
     if (manifestTree == NULL) {
         return UNKNOWN_ERROR;
     }
-    err = massageManifest(bundle, manifestTree);
+    err = massageManifest(bundle, &table, manifestTree);
     if (err < NO_ERROR) {
         return err;
     }
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 221f3c2..52b93a9 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -4832,8 +4832,7 @@
     item.resPath = resPath;
     item.file = newFile;
     item.xmlRoot = root->clone();
-    item.needsCompiling = false;    // This step occurs after we parse/assign, so we don't need
-                                    // to do it again.
+    item.needsCompiling = true;
     mWorkQueue.push(item);
 
     // Now mark the old entry as deleted.
diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h
index aff22d4..b340fc5 100644
--- a/tools/aapt/ResourceTable.h
+++ b/tools/aapt/ResourceTable.h
@@ -590,9 +590,10 @@
                        const String16& comment,
                        bool appendComment);
 
+    sp<Package> getPackage(const String16& package);
+
 private:
     void writePublicDefinitions(const String16& package, FILE* fp, bool pub);
-    sp<Package> getPackage(const String16& package);
     sp<Type> getType(const String16& package,
                      const String16& type,
                      const SourcePos& pos,
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
index ad26bc8..93319a3 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
@@ -928,4 +928,9 @@
     public ComponentName getInstantAppInstallerComponent() {
         return null;
     }
+
+    @Override
+    public String getInstantAppAndroidId(String packageName, UserHandle user) {
+        return null;
+    }
 }