Merge "Add app bounds to configuration." into oc-dev
diff --git a/api/current.txt b/api/current.txt
index d890cdb..392b60d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6595,6 +6595,7 @@
     method public android.os.Bundle getExtras();
     method public int getHeight();
     method public java.lang.String getHint();
+    method public android.view.ViewStructure.HtmlInfo getHtmlInfo();
     method public int getId();
     method public java.lang.String getIdEntry();
     method public java.lang.String getIdPackage();
@@ -7147,7 +7148,6 @@
     method public static synchronized android.bluetooth.BluetoothAdapter getDefaultAdapter();
     method public int getLeMaximumAdvertisingDataLength();
     method public java.lang.String getName();
-    method public android.bluetooth.le.PeriodicAdvertisingManager getPeriodicAdvertisingManager();
     method public int getProfileConnectionState(int);
     method public boolean getProfileProxy(android.content.Context, android.bluetooth.BluetoothProfile.ServiceListener, int);
     method public android.bluetooth.BluetoothDevice getRemoteDevice(java.lang.String);
@@ -7947,7 +7947,7 @@
   }
 
   public final class AdvertisingSet {
-    method public void enableAdvertising(boolean, int);
+    method public void enableAdvertising(boolean, int, int);
     method public void setAdvertisingData(android.bluetooth.le.AdvertiseData);
     method public void setAdvertisingParameters(android.bluetooth.le.AdvertisingSetParameters);
     method public void setPeriodicAdvertisingData(android.bluetooth.le.AdvertiseData);
@@ -8023,8 +8023,8 @@
     method public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback);
     method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback);
     method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
-    method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, android.bluetooth.le.AdvertisingSetCallback);
-    method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
+    method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, int, android.bluetooth.le.AdvertisingSetCallback);
+    method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, int, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
     method public void stopAdvertising(android.bluetooth.le.AdvertiseCallback);
     method public void stopAdvertisingSet(android.bluetooth.le.AdvertisingSetCallback);
   }
@@ -8036,21 +8036,6 @@
     method public void stopScan(android.bluetooth.le.ScanCallback);
   }
 
-  public abstract class PeriodicAdvertisingCallback {
-    ctor public PeriodicAdvertisingCallback();
-    method public void onPeriodicAdvertisingReport(android.bluetooth.le.PeriodicAdvertisingReport);
-    method public void onSyncEstablished(int, android.bluetooth.BluetoothDevice, int, int, int, int);
-    method public void onSyncLost(int);
-    field public static final int SYNC_NO_RESOURCES = 2; // 0x2
-    field public static final int SYNC_NO_RESPONSE = 1; // 0x1
-  }
-
-  public final class PeriodicAdvertisingManager {
-    method public void registerSync(android.bluetooth.le.ScanResult, int, int, android.bluetooth.le.PeriodicAdvertisingCallback);
-    method public void registerSync(android.bluetooth.le.ScanResult, int, int, android.bluetooth.le.PeriodicAdvertisingCallback, android.os.Handler);
-    method public void unregisterSync(android.bluetooth.le.PeriodicAdvertisingCallback);
-  }
-
   public final class PeriodicAdvertisingParameters implements android.os.Parcelable {
     method public int describeContents();
     method public boolean getEnable();
@@ -8068,21 +8053,6 @@
     method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setInterval(int);
   }
 
-  public final class PeriodicAdvertisingReport implements android.os.Parcelable {
-    ctor public PeriodicAdvertisingReport(int, int, int, int, android.bluetooth.le.ScanRecord);
-    method public int describeContents();
-    method public android.bluetooth.le.ScanRecord getData();
-    method public int getDataStatus();
-    method public int getRssi();
-    method public int getSyncHandle();
-    method public long getTimestampNanos();
-    method public int getTxPower();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.bluetooth.le.PeriodicAdvertisingReport> CREATOR;
-    field public static final int DATA_COMPLETE = 0; // 0x0
-    field public static final int DATA_INCOMPLETE_TRUNCATED = 2; // 0x2
-  }
-
   public abstract class ScanCallback {
     ctor public ScanCallback();
     method public void onBatchScanResults(java.util.List<android.bluetooth.le.ScanResult>);
@@ -12540,6 +12510,7 @@
     field public int inTargetDensity;
     field public byte[] inTempStorage;
     field public deprecated boolean mCancel;
+    field public android.graphics.ColorSpace outColorSpace;
     field public android.graphics.Bitmap.Config outConfig;
     field public int outHeight;
     field public java.lang.String outMimeType;
@@ -46410,6 +46381,7 @@
     method public abstract int getTextSelectionStart();
     method public abstract boolean hasExtras();
     method public abstract android.view.ViewStructure newChild(int);
+    method public abstract android.view.ViewStructure.HtmlInfo.Builder newHtmlInfoBuilder(java.lang.String);
     method public abstract void setAccessibilityFocused(boolean);
     method public abstract void setActivated(boolean);
     method public abstract void setAlpha(float);
@@ -46432,8 +46404,8 @@
     method public abstract void setFocusable(boolean);
     method public abstract void setFocused(boolean);
     method public abstract void setHint(java.lang.CharSequence);
+    method public abstract void setHtmlInfo(android.view.ViewStructure.HtmlInfo);
     method public abstract void setId(int, java.lang.String, java.lang.String, java.lang.String);
-    method public abstract void setIdEntry(java.lang.String);
     method public abstract void setInputType(int);
     method public abstract void setLocaleList(android.os.LocaleList);
     method public abstract void setLongClickable(boolean);
@@ -46448,6 +46420,18 @@
     method public abstract void setVisibility(int);
   }
 
+  public static abstract class ViewStructure.HtmlInfo {
+    ctor public ViewStructure.HtmlInfo();
+    method public abstract java.util.ArrayList<android.util.Pair<java.lang.String, java.lang.String>> getAttributes();
+    method public abstract java.lang.String getTag();
+  }
+
+  public static abstract class ViewStructure.HtmlInfo.Builder {
+    ctor public ViewStructure.HtmlInfo.Builder();
+    method public abstract android.view.ViewStructure.HtmlInfo.Builder addAttribute(java.lang.String, java.lang.String);
+    method public abstract android.view.ViewStructure.HtmlInfo build();
+  }
+
   public final class ViewStub extends android.view.View {
     ctor public ViewStub(android.content.Context);
     ctor public ViewStub(android.content.Context, int);
diff --git a/api/system-current.txt b/api/system-current.txt
index 3e739d9..ac1597f 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -6832,6 +6832,7 @@
     method public android.os.Bundle getExtras();
     method public int getHeight();
     method public java.lang.String getHint();
+    method public android.view.ViewStructure.HtmlInfo getHtmlInfo();
     method public int getId();
     method public java.lang.String getIdEntry();
     method public java.lang.String getIdPackage();
@@ -7607,7 +7608,6 @@
     method public static synchronized android.bluetooth.BluetoothAdapter getDefaultAdapter();
     method public int getLeMaximumAdvertisingDataLength();
     method public java.lang.String getName();
-    method public android.bluetooth.le.PeriodicAdvertisingManager getPeriodicAdvertisingManager();
     method public int getProfileConnectionState(int);
     method public boolean getProfileProxy(android.content.Context, android.bluetooth.BluetoothProfile.ServiceListener, int);
     method public android.bluetooth.BluetoothDevice getRemoteDevice(java.lang.String);
@@ -8413,7 +8413,7 @@
   }
 
   public final class AdvertisingSet {
-    method public void enableAdvertising(boolean, int);
+    method public void enableAdvertising(boolean, int, int);
     method public void setAdvertisingData(android.bluetooth.le.AdvertiseData);
     method public void setAdvertisingParameters(android.bluetooth.le.AdvertisingSetParameters);
     method public void setPeriodicAdvertisingData(android.bluetooth.le.AdvertiseData);
@@ -8489,8 +8489,8 @@
     method public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback);
     method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback);
     method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
-    method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, android.bluetooth.le.AdvertisingSetCallback);
-    method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
+    method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, int, android.bluetooth.le.AdvertisingSetCallback);
+    method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, int, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
     method public void stopAdvertising(android.bluetooth.le.AdvertiseCallback);
     method public void stopAdvertisingSet(android.bluetooth.le.AdvertisingSetCallback);
   }
@@ -8505,21 +8505,6 @@
     method public void stopScan(android.bluetooth.le.ScanCallback);
   }
 
-  public abstract class PeriodicAdvertisingCallback {
-    ctor public PeriodicAdvertisingCallback();
-    method public void onPeriodicAdvertisingReport(android.bluetooth.le.PeriodicAdvertisingReport);
-    method public void onSyncEstablished(int, android.bluetooth.BluetoothDevice, int, int, int, int);
-    method public void onSyncLost(int);
-    field public static final int SYNC_NO_RESOURCES = 2; // 0x2
-    field public static final int SYNC_NO_RESPONSE = 1; // 0x1
-  }
-
-  public final class PeriodicAdvertisingManager {
-    method public void registerSync(android.bluetooth.le.ScanResult, int, int, android.bluetooth.le.PeriodicAdvertisingCallback);
-    method public void registerSync(android.bluetooth.le.ScanResult, int, int, android.bluetooth.le.PeriodicAdvertisingCallback, android.os.Handler);
-    method public void unregisterSync(android.bluetooth.le.PeriodicAdvertisingCallback);
-  }
-
   public final class PeriodicAdvertisingParameters implements android.os.Parcelable {
     method public int describeContents();
     method public boolean getEnable();
@@ -8537,21 +8522,6 @@
     method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setInterval(int);
   }
 
-  public final class PeriodicAdvertisingReport implements android.os.Parcelable {
-    ctor public PeriodicAdvertisingReport(int, int, int, int, android.bluetooth.le.ScanRecord);
-    method public int describeContents();
-    method public android.bluetooth.le.ScanRecord getData();
-    method public int getDataStatus();
-    method public int getRssi();
-    method public int getSyncHandle();
-    method public long getTimestampNanos();
-    method public int getTxPower();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.bluetooth.le.PeriodicAdvertisingReport> CREATOR;
-    field public static final int DATA_COMPLETE = 0; // 0x0
-    field public static final int DATA_INCOMPLETE_TRUNCATED = 2; // 0x2
-  }
-
   public final class ResultStorageDescriptor implements android.os.Parcelable {
     ctor public ResultStorageDescriptor(int, int, int);
     method public int describeContents();
@@ -13270,6 +13240,7 @@
     field public int inTargetDensity;
     field public byte[] inTempStorage;
     field public deprecated boolean mCancel;
+    field public android.graphics.ColorSpace outColorSpace;
     field public android.graphics.Bitmap.Config outConfig;
     field public int outHeight;
     field public java.lang.String outMimeType;
@@ -49867,6 +49838,7 @@
     method public abstract int getTextSelectionStart();
     method public abstract boolean hasExtras();
     method public abstract android.view.ViewStructure newChild(int);
+    method public abstract android.view.ViewStructure.HtmlInfo.Builder newHtmlInfoBuilder(java.lang.String);
     method public abstract void setAccessibilityFocused(boolean);
     method public abstract void setActivated(boolean);
     method public abstract void setAlpha(float);
@@ -49889,8 +49861,8 @@
     method public abstract void setFocusable(boolean);
     method public abstract void setFocused(boolean);
     method public abstract void setHint(java.lang.CharSequence);
+    method public abstract void setHtmlInfo(android.view.ViewStructure.HtmlInfo);
     method public abstract void setId(int, java.lang.String, java.lang.String, java.lang.String);
-    method public abstract void setIdEntry(java.lang.String);
     method public abstract void setInputType(int);
     method public abstract void setLocaleList(android.os.LocaleList);
     method public abstract void setLongClickable(boolean);
@@ -49905,6 +49877,18 @@
     method public abstract void setVisibility(int);
   }
 
+  public static abstract class ViewStructure.HtmlInfo {
+    ctor public ViewStructure.HtmlInfo();
+    method public abstract java.util.ArrayList<android.util.Pair<java.lang.String, java.lang.String>> getAttributes();
+    method public abstract java.lang.String getTag();
+  }
+
+  public static abstract class ViewStructure.HtmlInfo.Builder {
+    ctor public ViewStructure.HtmlInfo.Builder();
+    method public abstract android.view.ViewStructure.HtmlInfo.Builder addAttribute(java.lang.String, java.lang.String);
+    method public abstract android.view.ViewStructure.HtmlInfo build();
+  }
+
   public final class ViewStub extends android.view.View {
     ctor public ViewStub(android.content.Context);
     ctor public ViewStub(android.content.Context, int);
diff --git a/api/test-current.txt b/api/test-current.txt
index 6fba51a..fc3c9e7 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -6624,6 +6624,7 @@
     method public android.os.Bundle getExtras();
     method public int getHeight();
     method public java.lang.String getHint();
+    method public android.view.ViewStructure.HtmlInfo getHtmlInfo();
     method public int getId();
     method public java.lang.String getIdEntry();
     method public java.lang.String getIdPackage();
@@ -7177,7 +7178,6 @@
     method public static synchronized android.bluetooth.BluetoothAdapter getDefaultAdapter();
     method public int getLeMaximumAdvertisingDataLength();
     method public java.lang.String getName();
-    method public android.bluetooth.le.PeriodicAdvertisingManager getPeriodicAdvertisingManager();
     method public int getProfileConnectionState(int);
     method public boolean getProfileProxy(android.content.Context, android.bluetooth.BluetoothProfile.ServiceListener, int);
     method public android.bluetooth.BluetoothDevice getRemoteDevice(java.lang.String);
@@ -7977,7 +7977,7 @@
   }
 
   public final class AdvertisingSet {
-    method public void enableAdvertising(boolean, int);
+    method public void enableAdvertising(boolean, int, int);
     method public void setAdvertisingData(android.bluetooth.le.AdvertiseData);
     method public void setAdvertisingParameters(android.bluetooth.le.AdvertisingSetParameters);
     method public void setPeriodicAdvertisingData(android.bluetooth.le.AdvertiseData);
@@ -8053,8 +8053,8 @@
     method public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback);
     method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback);
     method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
-    method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, android.bluetooth.le.AdvertisingSetCallback);
-    method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
+    method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, int, android.bluetooth.le.AdvertisingSetCallback);
+    method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, int, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
     method public void stopAdvertising(android.bluetooth.le.AdvertiseCallback);
     method public void stopAdvertisingSet(android.bluetooth.le.AdvertisingSetCallback);
   }
@@ -8066,21 +8066,6 @@
     method public void stopScan(android.bluetooth.le.ScanCallback);
   }
 
-  public abstract class PeriodicAdvertisingCallback {
-    ctor public PeriodicAdvertisingCallback();
-    method public void onPeriodicAdvertisingReport(android.bluetooth.le.PeriodicAdvertisingReport);
-    method public void onSyncEstablished(int, android.bluetooth.BluetoothDevice, int, int, int, int);
-    method public void onSyncLost(int);
-    field public static final int SYNC_NO_RESOURCES = 2; // 0x2
-    field public static final int SYNC_NO_RESPONSE = 1; // 0x1
-  }
-
-  public final class PeriodicAdvertisingManager {
-    method public void registerSync(android.bluetooth.le.ScanResult, int, int, android.bluetooth.le.PeriodicAdvertisingCallback);
-    method public void registerSync(android.bluetooth.le.ScanResult, int, int, android.bluetooth.le.PeriodicAdvertisingCallback, android.os.Handler);
-    method public void unregisterSync(android.bluetooth.le.PeriodicAdvertisingCallback);
-  }
-
   public final class PeriodicAdvertisingParameters implements android.os.Parcelable {
     method public int describeContents();
     method public boolean getEnable();
@@ -8098,21 +8083,6 @@
     method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setInterval(int);
   }
 
-  public final class PeriodicAdvertisingReport implements android.os.Parcelable {
-    ctor public PeriodicAdvertisingReport(int, int, int, int, android.bluetooth.le.ScanRecord);
-    method public int describeContents();
-    method public android.bluetooth.le.ScanRecord getData();
-    method public int getDataStatus();
-    method public int getRssi();
-    method public int getSyncHandle();
-    method public long getTimestampNanos();
-    method public int getTxPower();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.bluetooth.le.PeriodicAdvertisingReport> CREATOR;
-    field public static final int DATA_COMPLETE = 0; // 0x0
-    field public static final int DATA_INCOMPLETE_TRUNCATED = 2; // 0x2
-  }
-
   public abstract class ScanCallback {
     ctor public ScanCallback();
     method public void onBatchScanResults(java.util.List<android.bluetooth.le.ScanResult>);
@@ -12590,6 +12560,7 @@
     field public int inTargetDensity;
     field public byte[] inTempStorage;
     field public deprecated boolean mCancel;
+    field public android.graphics.ColorSpace outColorSpace;
     field public android.graphics.Bitmap.Config outConfig;
     field public int outHeight;
     field public java.lang.String outMimeType;
@@ -46791,6 +46762,7 @@
     method public abstract int getTextSelectionStart();
     method public abstract boolean hasExtras();
     method public abstract android.view.ViewStructure newChild(int);
+    method public abstract android.view.ViewStructure.HtmlInfo.Builder newHtmlInfoBuilder(java.lang.String);
     method public abstract void setAccessibilityFocused(boolean);
     method public abstract void setActivated(boolean);
     method public abstract void setAlpha(float);
@@ -46813,8 +46785,8 @@
     method public abstract void setFocusable(boolean);
     method public abstract void setFocused(boolean);
     method public abstract void setHint(java.lang.CharSequence);
+    method public abstract void setHtmlInfo(android.view.ViewStructure.HtmlInfo);
     method public abstract void setId(int, java.lang.String, java.lang.String, java.lang.String);
-    method public abstract void setIdEntry(java.lang.String);
     method public abstract void setInputType(int);
     method public abstract void setLocaleList(android.os.LocaleList);
     method public abstract void setLongClickable(boolean);
@@ -46829,6 +46801,18 @@
     method public abstract void setVisibility(int);
   }
 
+  public static abstract class ViewStructure.HtmlInfo {
+    ctor public ViewStructure.HtmlInfo();
+    method public abstract java.util.ArrayList<android.util.Pair<java.lang.String, java.lang.String>> getAttributes();
+    method public abstract java.lang.String getTag();
+  }
+
+  public static abstract class ViewStructure.HtmlInfo.Builder {
+    ctor public ViewStructure.HtmlInfo.Builder();
+    method public abstract android.view.ViewStructure.HtmlInfo.Builder addAttribute(java.lang.String, java.lang.String);
+    method public abstract android.view.ViewStructure.HtmlInfo build();
+  }
+
   public final class ViewStub extends android.view.View {
     ctor public ViewStub(android.content.Context);
     ctor public ViewStub(android.content.Context, int);
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 124267b..7d2db5c 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -19,9 +19,12 @@
 import android.os.SystemClock;
 import android.text.TextUtils;
 import android.util.Log;
+import android.util.Pair;
 import android.view.View;
 import android.view.ViewRootImpl;
 import android.view.ViewStructure;
+import android.view.ViewStructure.HtmlInfo;
+import android.view.ViewStructure.HtmlInfo.Builder;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 import android.view.autofill.AutoFillId;
@@ -597,6 +600,7 @@
         AutofillValue mAutofillValue;
         String[] mAutofillOptions;
         boolean mSanitized;
+        HtmlInfo mHtmlInfo;
 
         int mX;
         int mY;
@@ -641,7 +645,6 @@
         static final int FLAGS_HAS_CHILDREN = 0x00100000;
         static final int FLAGS_HAS_URL = 0x00080000;
         static final int FLAGS_HAS_INPUT_TYPE = 0x00040000;
-        static final int FLAGS_HAS_ENTRY_ID = 0x00020000;
         static final int FLAGS_HAS_LOCALE_LIST = 0x00010000;
         static final int FLAGS_ALL_CONTROL = 0xfff00000;
 
@@ -677,8 +680,6 @@
                         mIdPackage = preader.readString();
                     }
                 }
-            } else if ((flags&FLAGS_HAS_ENTRY_ID) != 0) {
-                mIdEntry = preader.readString();
             }
 
             if ((flags&FLAGS_HAS_AUTOFILL_DATA) != 0) {
@@ -688,6 +689,10 @@
                 mAutofillHints = in.readStringArray();
                 mAutofillValue = in.readParcelable(null);
                 mAutofillOptions = in.readStringArray();
+                final Parcelable p = in.readParcelable(null);
+                if (p instanceof HtmlInfo) {
+                    mHtmlInfo = (HtmlInfo) p;
+                }
             }
             if ((flags&FLAGS_HAS_LARGE_COORDS) != 0) {
                 mX = in.readInt();
@@ -756,8 +761,6 @@
             int flags = mFlags & ~FLAGS_ALL_CONTROL;
             if (mId != View.NO_ID) {
                 flags |= FLAGS_HAS_ID;
-            } else if (mIdEntry != null ){
-                flags |= FLAGS_HAS_ENTRY_ID;
             }
             if (mAutofillId != null) {
                 flags |= FLAGS_HAS_AUTOFILL_DATA;
@@ -821,8 +824,6 @@
                         pwriter.writeString(mIdPackage);
                     }
                 }
-            } else if ((flags&FLAGS_HAS_ENTRY_ID) != 0) {
-                pwriter.writeString(mIdEntry);
             }
 
             if ((flags&FLAGS_HAS_AUTOFILL_DATA) != 0) {
@@ -834,6 +835,11 @@
                 final AutofillValue sanitizedValue = writeSensitive ? mAutofillValue : null;
                 out.writeParcelable(sanitizedValue,  0);
                 out.writeStringArray(mAutofillOptions);
+                if (mHtmlInfo instanceof Parcelable) {
+                    out.writeParcelable((Parcelable) mHtmlInfo, 0);
+                } else {
+                    out.writeParcelable(null, 0);
+                }
             }
             if ((flags&FLAGS_HAS_LARGE_COORDS) != 0) {
                 out.writeInt(mX);
@@ -908,10 +914,6 @@
          * If {@link #getId()} is a resource identifier, this is the entry name of that
          * identifier.  See {@link android.view.ViewStructure#setId ViewStructure.setId}
          * for more information.
-         *
-         * <p>If the node represents a virtual view, it could also represent the entry id set by
-         *  {@link android.view.ViewStructure#setIdEntry ViewStructure.setIdEntry}
-         *
          */
         public String getIdEntry() {
             return mIdEntry;
@@ -1233,12 +1235,8 @@
         /**
          * Returns the URL represented by this node.
          *
-         * <p>Typically used in 2 categories of nodes:
-         *
-         * <ol>
-         * <li>Root node (containing the URL of the HTML page)
-         * <li>Child nodes that represent hyperlinks (contains the hyperlink URL).
-         * </ol>
+         * <p>Typically used when the view associated with the node is a container for an HTML
+         * document.
          *
          * <strong>WARNING:</strong> a {@link android.service.autofill.AutofillService} should only
          * use this URL for autofill purposes when it trusts the app generating it (i.e., the app
@@ -1249,6 +1247,16 @@
         }
 
         /**
+         * Returns the HTML properties associated with this node.
+         *
+         * <p>It's only set when the {@link AssistStructure} is used for autofilling purposes, not
+         * for assist.
+         */
+        public HtmlInfo getHtmlInfo() {
+            return mHtmlInfo;
+        }
+
+        /**
          * Returns the the list of locales associated with this node.
          */
         public LocaleList getLocaleList() {
@@ -1393,11 +1401,6 @@
         }
 
         @Override
-        public void setIdEntry(String entryName) {
-            mNode.mIdEntry = entryName;
-        }
-
-        @Override
         public void setDimens(int left, int top, int scrollX, int scrollY, int width, int height) {
             mNode.mX = left;
             mNode.mY = top;
@@ -1711,6 +1714,123 @@
         public void setLocaleList(LocaleList localeList) {
             mNode.mLocaleList = localeList;
         }
+
+        @Override
+        public HtmlInfo.Builder newHtmlInfoBuilder(@NonNull String tagName) {
+            return new HtmlInfoNodeBuilder(tagName);
+        }
+
+        @Override
+        public void setHtmlInfo(@NonNull HtmlInfo htmlInfo) {
+            mNode.mHtmlInfo = htmlInfo;
+        }
+    }
+
+    private static final class HtmlInfoNode extends HtmlInfo implements Parcelable {
+        private final String mTag;
+        private final String[] mNames;
+        private final String[] mValues;
+
+        // Not parcelable
+        private ArrayList<Pair<String, String>> mAttributes;
+
+        private HtmlInfoNode(HtmlInfoNodeBuilder builder) {
+            mTag = builder.mTag;
+            if (builder.mNames == null) {
+                mNames = null;
+                mValues = null;
+            } else {
+                mNames = new String[builder.mNames.size()];
+                mValues = new String[builder.mValues.size()];
+                builder.mNames.toArray(mNames);
+                builder.mValues.toArray(mValues);
+            }
+        }
+
+        @Override
+        public String getTag() {
+            return mTag;
+        }
+
+        @Override
+        public ArrayList<Pair<String, String>> getAttributes() {
+            if (mAttributes == null && mNames != null) {
+                mAttributes = new ArrayList<>(mNames.length);
+                for (int i = 0; i < mNames.length; i++) {
+                    final Pair<String, String> pair = new Pair<>(mNames[i], mValues[i]);
+                    mAttributes.add(i, pair);
+                }
+            }
+            return mAttributes;
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel parcel, int flags) {
+            parcel.writeString(mTag);
+            parcel.writeStringArray(mNames);
+            parcel.writeStringArray(mValues);
+        }
+
+        @SuppressWarnings("hiding")
+        public static final Creator<HtmlInfoNode> CREATOR = new Creator<HtmlInfoNode>() {
+            @Override
+            public HtmlInfoNode createFromParcel(Parcel parcel) {
+                // Always go through the builder to ensure the data ingested by
+                // the system obeys the contract of the builder to avoid attacks
+                // using specially crafted parcels.
+                final String tag = parcel.readString();
+                final HtmlInfoNodeBuilder builder = new HtmlInfoNodeBuilder(tag);
+                final String[] names = parcel.readStringArray();
+                final String[] values = parcel.readStringArray();
+                if (names != null && values != null) {
+                    if (names.length != values.length) {
+                        Log.w(TAG, "HtmlInfo attributes mismatch: names=" + names.length
+                                + ", values=" + values.length);
+                    } else {
+                        for (int i = 0; i < names.length; i++) {
+                            builder.addAttribute(names[i], values[i]);
+                        }
+                    }
+                }
+                return builder.build();
+            }
+
+            @Override
+            public HtmlInfoNode[] newArray(int size) {
+                return new HtmlInfoNode[size];
+            }
+        };
+    }
+
+    private static final class HtmlInfoNodeBuilder extends HtmlInfo.Builder {
+        private final String mTag;
+        private ArrayList<String> mNames;
+        private ArrayList<String> mValues;
+
+        HtmlInfoNodeBuilder(String tag) {
+            mTag = tag;
+        }
+
+        @Override
+        public Builder addAttribute(String name, String value) {
+            if (mNames == null) {
+                mNames = new ArrayList<>();
+                mValues = new ArrayList<>();
+            }
+            mNames.add(name);
+            mValues.add(value);
+            return this;
+        }
+
+        @Override
+        public HtmlInfoNode build() {
+            return new HtmlInfoNode(this);
+        }
     }
 
     /** @hide */
@@ -1813,6 +1933,12 @@
         if (url != null) {
             Log.i(TAG, prefix + "  URL: " + url);
         }
+        HtmlInfo htmlInfo = node.getHtmlInfo();
+        if (htmlInfo != null) {
+            Log.i(TAG, prefix + "  HtmlInfo: tag=" + htmlInfo.getTag()
+                    + ", attr="+ htmlInfo.getAttributes());
+        }
+
         LocaleList localeList = node.getLocaleList();
         if (localeList != null) {
             Log.i(TAG, prefix + "  LocaleList: " + localeList);
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 4e1e42d..845a47d 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -638,6 +638,7 @@
      * <p>
      * Use {@link #isLePeriodicAdvertisingSupported()} to check whether LE Periodic Advertising is
      * supported on this device before calling this method.
+     * @hide
      */
     public PeriodicAdvertisingManager getPeriodicAdvertisingManager() {
       if (!getLeAccess())
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index aa61ce2..5d1e8ec 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -778,7 +778,7 @@
 
     /**
      * Set the preferred connection PHY for this app. Please note that this is just a
-     * recommendation, wether the PHY change will happen depends on other applications peferences,
+     * recommendation, whether the PHY change will happen depends on other applications peferences,
      * local and remote controller capabilities. Controller can override these settings.
      * <p>
      * {@link BluetoothGattCallback#onPhyUpdate} will be triggered as a result of this call, even
diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java
index b35a593..2df2ed8 100644
--- a/core/java/android/bluetooth/BluetoothGattServer.java
+++ b/core/java/android/bluetooth/BluetoothGattServer.java
@@ -550,7 +550,7 @@
 
     /**
      * Set the preferred connection PHY for this app. Please note that this is just a
-     * recommendation, wether the PHY change will happen depends on other applications peferences,
+     * recommendation, whether the PHY change will happen depends on other applications peferences,
      * local and remote controller capabilities. Controller can override these settings.
      * <p>
      * {@link BluetoothGattServerCallback#onPhyUpdate} will be triggered as a result of this call, even
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index 98a5341..6bf6aa0 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -416,6 +416,11 @@
                 if(mSocketState != SocketState.INIT) return EBADFD;
                 if(mPfd == null) return -1;
                 FileDescriptor fd = mPfd.getFileDescriptor();
+                if (fd == null) {
+                    Log.e(TAG, "bindListen(), null file descriptor");
+                    return -1;
+                }
+
                 if (DBG) Log.d(TAG, "bindListen(), Create LocalSocket");
                 mSocket = LocalSocket.createConnectedLocalSocket(fd);
                 if (DBG) Log.d(TAG, "bindListen(), new LocalSocket.getInputStream()");
@@ -556,8 +561,9 @@
 
     @Override
     public void close() throws IOException {
-        if (DBG) Log.d(TAG, "close() in, this: " + this + ", channel: " + mPort + ", state: "
-                + mSocketState);
+        Log.d(TAG, "close() this: " + this + ", channel: " + mPort +
+            ", mSocketIS: " + mSocketIS + ", mSocketOS: " + mSocketOS +
+            "mSocket: " + mSocket + ", mSocketState: " + mSocketState);
         if(mSocketState == SocketState.CLOSED)
             return;
         else
@@ -567,9 +573,6 @@
                  if(mSocketState == SocketState.CLOSED)
                     return;
                  mSocketState = SocketState.CLOSED;
-                 if (DBG) Log.d(TAG, "close() this: " + this + ", channel: " + mPort +
-                         ", mSocketIS: " + mSocketIS + ", mSocketOS: " + mSocketOS +
-                         "mSocket: " + mSocket);
                  if(mSocket != null) {
                     if (DBG) Log.d(TAG, "Closing mSocket: " + mSocket);
                     mSocket.shutdownInput();
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index 0825ee8..334e88b 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -52,10 +52,11 @@
 
     void startAdvertisingSet(in AdvertisingSetParameters parameters, in AdvertiseData advertiseData,
                                 in AdvertiseData scanResponse, in PeriodicAdvertisingParameters periodicParameters,
-                                in AdvertiseData periodicData, in int timeout, in IAdvertisingSetCallback callback);
+                                in AdvertiseData periodicData, in int duration, in int maxExtAdvEvents,
+                                in IAdvertisingSetCallback callback);
     void stopAdvertisingSet(in IAdvertisingSetCallback callback);
 
-    void enableAdvertisingSet(in int advertiserId, in boolean enable, in int timeout);
+    void enableAdvertisingSet(in int advertiserId, in boolean enable, in int duration, in int maxExtAdvEvents);
     void setAdvertisingData(in int advertiserId, in AdvertiseData data);
     void setScanResponseData(in int advertiserId, in AdvertiseData data);
     void setAdvertisingParameters(in int advertiserId, in AdvertisingSetParameters parameters);
diff --git a/core/java/android/bluetooth/le/AdvertisingSet.java b/core/java/android/bluetooth/le/AdvertisingSet.java
index 7355b0d..51571b2 100644
--- a/core/java/android/bluetooth/le/AdvertisingSet.java
+++ b/core/java/android/bluetooth/le/AdvertisingSet.java
@@ -16,6 +16,7 @@
 
 package android.bluetooth.le;
 
+import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.IBluetoothGatt;
 import android.bluetooth.IBluetoothManager;
 import android.bluetooth.le.IAdvertisingSetCallback;
@@ -57,15 +58,23 @@
 
     /**
      * Enables Advertising. This method returns immediately, the operation status is
-     * delivered
-     * through {@code callback.onAdvertisingEnabled()}.
+     * delivered through {@code callback.onAdvertisingEnabled()}.
      * <p>
      * Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
      *
+     * @param enable whether the advertising should be enabled (true), or disabled (false)
+     * @param duration advertising duration, in 10ms unit. Valid range is from 1 (10ms) to
+     *                     65535 (655,350 ms)
+     * @param maxExtendedAdvertisingEvents maximum number of extended advertising events the
+     *                     controller shall attempt to send prior to terminating the extended
+     *                     advertising, even if the duration has not expired. Valid range is
+     *                     from 1 to 255.
      */
-    public void enableAdvertising(boolean enable, int timeout) {
+    public void enableAdvertising(boolean enable, int duration,
+            int maxExtendedAdvertisingEvents) {
         try {
-            gatt.enableAdvertisingSet(this.advertiserId, enable, timeout);
+            gatt.enableAdvertisingSet(this.advertiserId, enable, duration,
+                                      maxExtendedAdvertisingEvents);
         } catch (RemoteException e) {
             Log.e(TAG, "remote exception - ", e);
         }
@@ -77,10 +86,16 @@
      * delivered through {@code callback.onAdvertisingDataSet()}.
      * <p>
      * Advertising data must be empty if non-legacy scannable advertising is used.
+     *
+     * @param advertiseData Advertisement data to be broadcasted. Size must not exceed
+     *                     {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the
+     *                     advertisement is connectable, three bytes will be added for flags. If the
+     *                     update takes place when the advertising set is enabled, the data can be
+     *                     maximum 251 bytes long.
      */
-    public void setAdvertisingData(AdvertiseData data) {
+    public void setAdvertisingData(AdvertiseData advertiseData) {
         try {
-            gatt.setAdvertisingData(this.advertiserId, data);
+            gatt.setAdvertisingData(this.advertiserId, advertiseData);
         } catch (RemoteException e) {
             Log.e(TAG, "remote exception - ", e);
         }
@@ -90,10 +105,15 @@
      * Set/update scan response data. Make sure that data doesn't exceed the size limit for
      * specified AdvertisingSetParameters. This method returns immediately, the operation status
      * is delivered through {@code callback.onScanResponseDataSet()}.
+     *
+     * @param scanResponse Scan response associated with the advertisement data. Size must not
+     *                     exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the
+     *                     update takes place when the advertising set is enabled, the data can be
+     *                     maximum 251 bytes long.
      */
-    public void setScanResponseData(AdvertiseData data) {
+    public void setScanResponseData(AdvertiseData scanResponse) {
         try {
-            gatt.setScanResponseData(this.advertiserId, data);
+            gatt.setScanResponseData(this.advertiserId, scanResponse);
         } catch (RemoteException e) {
             Log.e(TAG, "remote exception - ", e);
         }
@@ -103,6 +123,8 @@
      * Update advertising parameters associated with this AdvertisingSet. Must be called when
      * advertising is not active. This method returns immediately, the operation status is delivered
      * through {@code callback.onAdvertisingParametersUpdated}.
+     *
+     * @param parameters advertising set parameters.
      */
     public void setAdvertisingParameters(AdvertisingSetParameters parameters) {
         try {
@@ -130,10 +152,15 @@
      * or after advertising was started with periodic advertising data set. This method returns
      * immediately, the operation status is delivered through
      * {@code callback.onPeriodicAdvertisingDataSet()}.
+     *
+     * @param periodicData Periodic advertising data. Size must not exceed
+     *                     {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the
+     *                     update takes place when the periodic advertising is enabled for this set,
+     *                     the data can be maximum 251 bytes long.
      */
-    public void setPeriodicAdvertisingData(AdvertiseData data) {
+    public void setPeriodicAdvertisingData(AdvertiseData periodicData) {
         try {
-            gatt.setPeriodicAdvertisingData(this.advertiserId, data);
+            gatt.setPeriodicAdvertisingData(this.advertiserId, periodicData);
         } catch (RemoteException e) {
             Log.e(TAG, "remote exception - ", e);
         }
@@ -142,6 +169,8 @@
     /**
      * Used to enable/disable periodic advertising. This method returns immediately, the operation
      * status is delivered through {@code callback.onPeriodicAdvertisingEnable()}.
+     *
+     * @param enable whether the periodic advertising should be enabled (true), or disabled (false).
      */
     public void setPeriodicAdvertisingEnable(boolean enable) {
         try {
diff --git a/core/java/android/bluetooth/le/AdvertisingSetParameters.java b/core/java/android/bluetooth/le/AdvertisingSetParameters.java
index fe1f425..f5c1f08 100644
--- a/core/java/android/bluetooth/le/AdvertisingSetParameters.java
+++ b/core/java/android/bluetooth/le/AdvertisingSetParameters.java
@@ -16,6 +16,7 @@
 
 package android.bluetooth.le;
 
+import android.bluetooth.BluetoothAdapter;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -279,7 +280,7 @@
          * When set to true, advertising set will advertise 4.x Spec compliant
          * advertisements.
          *
-         * @param isLegacy wether legacy advertising mode should be used.
+         * @param isLegacy whether legacy advertising mode should be used.
          */
         public Builder setLegacyMode(boolean isLegacy) {
             this.isLegacy = isLegacy;
@@ -287,12 +288,12 @@
         }
 
         /**
-         * Set wether advertiser address should be ommited from all packets. If this
+         * Set whether advertiser address should be ommited from all packets. If this
          * mode is used, periodic advertising can't be enabled for this set.
          *
          * This is used only if legacy mode is not used.
          *
-         * @param isAnonymous wether anonymous advertising should be used.
+         * @param isAnonymous whether anonymous advertising should be used.
          */
         public Builder setAnonymous(boolean isAnonymous) {
             this.isAnonymous = isAnonymous;
@@ -300,12 +301,12 @@
         }
 
         /**
-         * Set wether TX power should be included in the extended header.
+         * Set whether TX power should be included in the extended header.
          *
          * This is used only if legacy mode is not used.
          *
-         * @param includeTxPower wether TX power should be included in extended
-         * header
+         * @param includeTxPower whether TX power should be included in extended
+         *            header
          */
         public Builder setIncludeTxPower(boolean includeTxPower) {
             this.includeTxPower = includeTxPower;
@@ -317,6 +318,8 @@
          *
          * This is used only if legacy mode is not used.
          *
+         * Use {@link BluetoothAdapter#isLeCodedPhySupported} to determine if LE Coded PHY is
+         * supported on this device.
          * @param primaryPhy Primary advertising physical channel, can only be
          *            {@link AdvertisingSetParameters#PHY_LE_1M} or
          *            {@link AdvertisingSetParameters#PHY_LE_CODED}.
@@ -335,6 +338,10 @@
          *
          * This is used only if legacy mode is not used.
          *
+         * Use {@link BluetoothAdapter#isLeCodedPhySupported} and
+         * {@link BluetoothAdapter#isLe2MPhySupported} to determine if LE Coded PHY or 2M PHY is
+         * supported on this device.
+         *
          * @param secondaryPhy Secondary advertising physical channel, can only be
          *            one of {@link AdvertisingSetParameters#PHY_LE_1M},
          *            {@link AdvertisingSetParameters#PHY_LE_2M} or
@@ -393,6 +400,32 @@
          * Build the {@link AdvertisingSetParameters} object.
          */
         public AdvertisingSetParameters build() {
+            if (isLegacy) {
+                if (isAnonymous) {
+                    throw new IllegalArgumentException("Legacy advertising can't be anonymous");
+                }
+
+                if (connectable == true && scannable == false) {
+                    throw new IllegalArgumentException(
+                        "Legacy advertisement can't be connectable and non-scannable");
+                }
+
+                if (includeTxPower) {
+                    throw new IllegalArgumentException(
+                        "Legacy advertising can't include TX power level in header");
+                }
+            } else {
+                if (connectable && scannable) {
+                    throw new IllegalArgumentException(
+                        "Advertising can't be both connectable and scannable");
+                }
+
+                if (isAnonymous && connectable) {
+                    throw new IllegalArgumentException(
+                        "Advertising can't be both connectable and anonymous");
+                }
+            }
+
             return new AdvertisingSetParameters(connectable, scannable, isLegacy, isAnonymous,
                                                 includeTxPower, primaryPhy,
                                                 secondaryPhy, interval, txPowerLevel);
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
index 242ee77..a9deb75 100644
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
@@ -50,13 +50,13 @@
 
     private static final String TAG = "BluetoothLeAdvertiser";
 
-    private static final int MAX_ADVERTISING_DATA_BYTES = 31;
+    private static final int MAX_ADVERTISING_DATA_BYTES = 1650;
+    private static final int MAX_LEGACY_ADVERTISING_DATA_BYTES = 31;
     // Each fields need one byte for field length and another byte for field type.
     private static final int OVERHEAD_BYTES_PER_FIELD = 2;
     // Flags field will be set by system.
     private static final int FLAGS_FIELD_BYTES = 3;
     private static final int MANUFACTURER_SPECIFIC_DATA_LENGTH = 2;
-    private static final int SERVICE_DATA_UUID_LENGTH = 2;
 
     private final IBluetoothManager mBluetoothManager;
     private final Handler mHandler;
@@ -117,8 +117,8 @@
                 throw new IllegalArgumentException("callback cannot be null");
             }
             boolean isConnectable = settings.isConnectable();
-            if (totalBytes(advertiseData, isConnectable) > MAX_ADVERTISING_DATA_BYTES ||
-                    totalBytes(scanResponse, false) > MAX_ADVERTISING_DATA_BYTES) {
+            if (totalBytes(advertiseData, isConnectable) > MAX_LEGACY_ADVERTISING_DATA_BYTES ||
+                    totalBytes(scanResponse, false) > MAX_LEGACY_ADVERTISING_DATA_BYTES) {
                 postStartFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE);
                 return;
             }
@@ -149,10 +149,16 @@
                 parameters.setTxPowerLevel(1);
             }
 
+            int duration = 0;
+            int timeoutMillis = settings.getTimeout();
+            if (timeoutMillis > 0) {
+                duration = (timeoutMillis < 10) ? 1 : timeoutMillis/10;
+            }
+
             AdvertisingSetCallback wrapped = wrapOldCallback(callback, settings);
             mLegacyAdvertisers.put(callback, wrapped);
             startAdvertisingSet(parameters.build(), advertiseData, scanResponse, null, null,
-                                settings.getTimeout(), wrapped);
+                                duration, 0, wrapped);
         }
     }
 
@@ -206,90 +212,202 @@
     }
 
     /**
-    * Creates a new advertising set. If operation succeed, device will start advertising. This
-    * method returns immediately, the operation status is delivered through
-    * {@code callback.onAdvertisingSetStarted()}.
-    * <p>
-    * @param parameters advertising set parameters.
-    * @param advertiseData Advertisement data to be broadcasted.
-    * @param scanResponse Scan response associated with the advertisement data.
-    * @param periodicData Periodic advertising data.
-    * @param callback Callback for advertising set.
-    */
+     * Creates a new advertising set. If operation succeed, device will start advertising. This
+     * method returns immediately, the operation status is delivered through
+     * {@code callback.onAdvertisingSetStarted()}.
+     * <p>
+     * @param parameters advertising set parameters.
+     * @param advertiseData Advertisement data to be broadcasted. Size must not exceed
+     *                     {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the
+     *                     advertisement is connectable, three bytes will be added for flags.
+     * @param scanResponse Scan response associated with the advertisement data. Size must not
+     *                     exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
+     * @param periodicParameters periodic advertisng parameters. If null, periodic advertising will
+     *                     not be started.
+     * @param periodicData Periodic advertising data. Size must not exceed
+     *                     {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
+     * @param callback Callback for advertising set.
+     * @throws IllegalArgumentException when any of the data parameter exceed the maximum allowable
+     *                     size, or unsupported advertising PHY is selected, or when attempt to use
+     *                     Periodic Advertising feature is made when it's not supported by the
+     *                     controller.
+     */
     public void startAdvertisingSet(AdvertisingSetParameters parameters,
                                     AdvertiseData advertiseData, AdvertiseData scanResponse,
                                     PeriodicAdvertisingParameters periodicParameters,
                                     AdvertiseData periodicData, AdvertisingSetCallback callback) {
             startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
-                            periodicData, 0, callback, new Handler(Looper.getMainLooper()));
+                            periodicData, 0, 0, callback, new Handler(Looper.getMainLooper()));
     }
 
     /**
-    * Creates a new advertising set. If operation succeed, device will start advertising. This
-    * method returns immediately, the operation status is delivered through
-    * {@code callback.onAdvertisingSetStarted()}.
-    * <p>
-    * @param parameters advertising set parameters.
-    * @param advertiseData Advertisement data to be broadcasted.
-    * @param scanResponse Scan response associated with the advertisement data.
-    * @param periodicData Periodic advertising data.
-    * @param callback Callback for advertising set.
-    * @param handler thread upon which the callbacks will be invoked.
-    */
+     * Creates a new advertising set. If operation succeed, device will start advertising. This
+     * method returns immediately, the operation status is delivered through
+     * {@code callback.onAdvertisingSetStarted()}.
+     * <p>
+     * @param parameters advertising set parameters.
+     * @param advertiseData Advertisement data to be broadcasted. Size must not exceed
+     *                     {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the
+     *                     advertisement is connectable, three bytes will be added for flags.
+     * @param scanResponse Scan response associated with the advertisement data. Size must not
+     *                     exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
+     * @param periodicParameters periodic advertisng parameters. If null, periodic advertising will
+     *                     not be started.
+     * @param periodicData Periodic advertising data. Size must not exceed
+     *                     {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
+     * @param callback Callback for advertising set.
+     * @param handler thread upon which the callbacks will be invoked.
+     * @throws IllegalArgumentException when any of the data parameter exceed the maximum allowable
+     *                     size, or unsupported advertising PHY is selected, or when attempt to use
+     *                     Periodic Advertising feature is made when it's not supported by the
+     *                     controller.
+     */
     public void startAdvertisingSet(AdvertisingSetParameters parameters,
                                     AdvertiseData advertiseData, AdvertiseData scanResponse,
                                     PeriodicAdvertisingParameters periodicParameters,
                                     AdvertiseData periodicData, AdvertisingSetCallback callback,
                                     Handler handler) {
         startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
-                            periodicData, 0, callback, handler);
+                            periodicData, 0, 0, callback, handler);
     }
 
     /**
-    * Creates a new advertising set. If operation succeed, device will start advertising. This
-    * method returns immediately, the operation status is delivered through
-    * {@code callback.onAdvertisingSetStarted()}.
-    * <p>
-    * @param parameters advertising set parameters.
-    * @param advertiseData Advertisement data to be broadcasted.
-    * @param scanResponse Scan response associated with the advertisement data.
-    * @param periodicData Periodic advertising data.
-    * @param timeoutMillis Advertising time limit. May not exceed 180000
-    * @param callback Callback for advertising set.
-    */
+     * Creates a new advertising set. If operation succeed, device will start advertising. This
+     * method returns immediately, the operation status is delivered through
+     * {@code callback.onAdvertisingSetStarted()}.
+     * <p>
+     * @param parameters advertising set parameters.
+     * @param advertiseData Advertisement data to be broadcasted. Size must not exceed
+     *                     {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the
+     *                     advertisement is connectable, three bytes will be added for flags.
+     * @param scanResponse Scan response associated with the advertisement data. Size must not
+     *                     exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
+     * @param periodicParameters periodic advertisng parameters. If null, periodic advertising will
+     *                     not be started.
+     * @param periodicData Periodic advertising data. Size must not exceed
+     *                     {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
+     * @param duration advertising duration, in 10ms unit. Valid range is from 1 (10ms) to
+     *                     65535 (655,350 ms). 0 means advertising should continue until stopped.
+     * @param maxExtendedAdvertisingEvents maximum number of extended advertising events the
+     *                     controller shall attempt to send prior to terminating the extended
+     *                     advertising, even if the duration has not expired. Valid range is
+     *                     from 1 to 255. 0 means no maximum.
+     * @param callback Callback for advertising set.
+     * @throws IllegalArgumentException when any of the data parameter exceed the maximum allowable
+     *                     size, or unsupported advertising PHY is selected, or when attempt to use
+     *                     Periodic Advertising feature is made when it's not supported by the
+     *                     controller.
+     */
     public void startAdvertisingSet(AdvertisingSetParameters parameters,
                                     AdvertiseData advertiseData, AdvertiseData scanResponse,
                                     PeriodicAdvertisingParameters periodicParameters,
-                                    AdvertiseData periodicData, int timeoutMillis,
+                                    AdvertiseData periodicData, int duration,
+                                    int maxExtendedAdvertisingEvents,
                                     AdvertisingSetCallback callback) {
         startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
-                            periodicData, timeoutMillis, callback, new Handler(Looper.getMainLooper()));
+                            periodicData, duration, maxExtendedAdvertisingEvents, callback,
+                            new Handler(Looper.getMainLooper()));
     }
 
     /**
-    * Creates a new advertising set. If operation succeed, device will start advertising. This
-    * method returns immediately, the operation status is delivered through
-    * {@code callback.onAdvertisingSetStarted()}.
-    * <p>
-    * @param parameters advertising set parameters.
-    * @param advertiseData Advertisement data to be broadcasted.
-    * @param scanResponse Scan response associated with the advertisement data.
-    * @param periodicData Periodic advertising data.
-    * @param timeoutMillis Advertising time limit. May not exceed 180000
-    * @param callback Callback for advertising set.
-    * @param handler thread upon which the callbacks will be invoked.
-    */
+     * Creates a new advertising set. If operation succeed, device will start advertising. This
+     * method returns immediately, the operation status is delivered through
+     * {@code callback.onAdvertisingSetStarted()}.
+     * <p>
+     * @param parameters Advertising set parameters.
+     * @param advertiseData Advertisement data to be broadcasted. Size must not exceed
+     *                     {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the
+     *                     advertisement is connectable, three bytes will be added for flags.
+     * @param scanResponse Scan response associated with the advertisement data. Size must not
+     *                     exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}
+     * @param periodicParameters Periodic advertisng parameters. If null, periodic advertising will
+     *                     not be started.
+     * @param periodicData Periodic advertising data. Size must not exceed
+     *                     {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}
+     * @param duration advertising duration, in 10ms unit. Valid range is from 1 (10ms) to
+     *                     65535 (655,350 ms). 0 means advertising should continue until stopped.
+     * @param maxExtendedAdvertisingEvents maximum number of extended advertising events the
+     *                     controller shall attempt to send prior to terminating the extended
+     *                     advertising, even if the duration has not expired. Valid range is
+     *                     from 1 to 255. 0 means no maximum.
+     * @param callback Callback for advertising set.
+     * @param handler Thread upon which the callbacks will be invoked.
+     * @throws IllegalArgumentException When any of the data parameter exceed the maximum allowable
+     *                     size, or unsupported advertising PHY is selected, or when attempt to use
+     *                     Periodic Advertising feature is made when it's not supported by the
+     *                     controller, or when maxExtendedAdvertisingEvents is used on a controller
+     *                     that doesn't support the LE Extended Advertising
+     */
     public void startAdvertisingSet(AdvertisingSetParameters parameters,
                                     AdvertiseData advertiseData, AdvertiseData scanResponse,
                                     PeriodicAdvertisingParameters periodicParameters,
-                                    AdvertiseData periodicData, int timeoutMillis,
-                                    AdvertisingSetCallback callback, Handler handler) {
+                                    AdvertiseData periodicData, int duration,
+                                    int maxExtendedAdvertisingEvents, AdvertisingSetCallback callback,
+                                    Handler handler) {
         BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
-
         if (callback == null) {
           throw new IllegalArgumentException("callback cannot be null");
         }
 
+        boolean isConnectable = parameters.isConnectable();
+        if (parameters.isLegacy()) {
+            if (totalBytes(advertiseData, isConnectable) > MAX_LEGACY_ADVERTISING_DATA_BYTES) {
+                throw new IllegalArgumentException("Legacy advertising data too big");
+            }
+
+            if (totalBytes(scanResponse, false) > MAX_LEGACY_ADVERTISING_DATA_BYTES) {
+                throw new IllegalArgumentException("Legacy scan response data too big");
+            }
+        } else {
+            boolean supportCodedPhy = mBluetoothAdapter.isLeCodedPhySupported();
+            boolean support2MPhy = mBluetoothAdapter.isLe2MPhySupported();
+            int pphy = parameters.getPrimaryPhy();
+            int sphy = parameters.getSecondaryPhy();
+            if (pphy == AdvertisingSetParameters.PHY_LE_CODED && !supportCodedPhy) {
+                throw new IllegalArgumentException("Unsupported primary PHY selected");
+            }
+
+            if ((sphy == AdvertisingSetParameters.PHY_LE_CODED && !supportCodedPhy)
+                || (sphy == AdvertisingSetParameters.PHY_LE_2M && !support2MPhy)) {
+                throw new IllegalArgumentException("Unsupported secondary PHY selected");
+            }
+
+            int maxData = mBluetoothAdapter.getLeMaximumAdvertisingDataLength();
+            if (totalBytes(advertiseData, isConnectable) > maxData) {
+                throw new IllegalArgumentException("Advertising data too big");
+            }
+
+            if (totalBytes(scanResponse, false) > maxData) {
+                throw new IllegalArgumentException("Scan response data too big");
+            }
+
+            if (totalBytes(periodicData, false) > maxData) {
+                throw new IllegalArgumentException("Periodic advertising data too big");
+            }
+
+            boolean supportPeriodic = mBluetoothAdapter.isLePeriodicAdvertisingSupported();
+            if (periodicParameters != null && periodicParameters.getEnable() && !supportPeriodic) {
+                throw new IllegalArgumentException(
+                    "Controller does not support LE Periodic Advertising");
+            }
+        }
+
+        if (maxExtendedAdvertisingEvents < 0 || maxExtendedAdvertisingEvents > 255) {
+            throw new IllegalArgumentException(
+                "maxExtendedAdvertisingEvents out of range: " + maxExtendedAdvertisingEvents);
+        }
+
+        if (maxExtendedAdvertisingEvents != 0 &&
+            !mBluetoothAdapter.isLePeriodicAdvertisingSupported()) {
+            throw new IllegalArgumentException(
+                "Can't use maxExtendedAdvertisingEvents with controller that don't support " +
+                "LE Extended Advertising");
+        }
+
+        if (duration < 0 || duration > 65535) {
+            throw new IllegalArgumentException("duration out of range: " + duration);
+        }
+
         IBluetoothGatt gatt;
         try {
           gatt = mBluetoothManager.getBluetoothGatt();
@@ -306,7 +424,7 @@
 
         try {
             gatt.startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
-                                     periodicData, timeoutMillis, wrapped);
+                                     periodicData, duration, maxExtendedAdvertisingEvents, wrapped);
         } catch (RemoteException e) {
           Log.e(TAG, "Failed to start advertising set - ", e);
           throw new IllegalStateException("Failed to start advertising set");
@@ -383,7 +501,8 @@
             }
         }
         for (ParcelUuid uuid : data.getServiceData().keySet()) {
-            size += OVERHEAD_BYTES_PER_FIELD + SERVICE_DATA_UUID_LENGTH
+            int uuidLen = BluetoothUuid.uuidToBytes(uuid).length;
+            size += OVERHEAD_BYTES_PER_FIELD + uuidLen
                     + byteLength(data.getServiceData().get(uuid));
         }
         for (int i = 0; i < data.getManufacturerSpecificData().size(); ++i) {
diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java b/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java
index 6616231..364b575 100644
--- a/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java
+++ b/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java
@@ -23,6 +23,7 @@
  * advertising operation status.
  *
  * @see PeriodicAdvertisingManager#createSync
+ * @hide
  */
 public abstract class PeriodicAdvertisingCallback {
 
diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java b/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java
index 12c8a8c..d9c2d88 100644
--- a/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java
+++ b/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java
@@ -37,6 +37,7 @@
  * <p>
  * <b>Note:</b> Most of the methods here require
  * {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
+ * @hide
  */
 public final class PeriodicAdvertisingManager {
 
diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java b/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java
index ebc92bd..149540c 100644
--- a/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java
+++ b/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java
@@ -93,7 +93,7 @@
         private int interval = INTERVAL_MAX;
 
         /**
-         * Set wether the Periodic Advertising should be enabled for this set.
+         * Set whether the Periodic Advertising should be enabled for this set.
          */
         public Builder setEnable(boolean enable) {
             this.enable = enable;
diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java b/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java
index 3ff4ca5..51b93cb 100644
--- a/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java
+++ b/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java
@@ -24,6 +24,7 @@
 
 /**
  * PeriodicAdvertisingReport for Bluetooth LE synchronized advertising.
+ * @hide
  */
 public final class PeriodicAdvertisingReport implements Parcelable {
 
diff --git a/core/java/android/os/StatFs.java b/core/java/android/os/StatFs.java
index 13e9a15..d9e516c 100644
--- a/core/java/android/os/StatFs.java
+++ b/core/java/android/os/StatFs.java
@@ -61,15 +61,15 @@
      */
     @Deprecated
     public int getBlockSize() {
-        return (int) mStat.f_bsize;
+        return (int) mStat.f_frsize;
     }
 
     /**
      * The size, in bytes, of a block on the file system. This corresponds to
-     * the Unix {@code statvfs.f_bsize} field.
+     * the Unix {@code statvfs.f_frsize} field.
      */
     public long getBlockSizeLong() {
-        return mStat.f_bsize;
+        return mStat.f_frsize;
     }
 
     /**
@@ -112,7 +112,7 @@
      * will want to use {@link #getAvailableBytes()} instead.
      */
     public long getFreeBytes() {
-        return mStat.f_bfree * mStat.f_bsize;
+        return mStat.f_bfree * mStat.f_frsize;
     }
 
     /**
@@ -136,13 +136,13 @@
      * applications.
      */
     public long getAvailableBytes() {
-        return mStat.f_bavail * mStat.f_bsize;
+        return mStat.f_bavail * mStat.f_frsize;
     }
 
     /**
      * The total number of bytes supported by the file system.
      */
     public long getTotalBytes() {
-        return mStat.f_blocks * mStat.f_bsize;
+        return mStat.f_blocks * mStat.f_frsize;
     }
 }
diff --git a/core/java/android/provider/AlarmClock.java b/core/java/android/provider/AlarmClock.java
index 23134cd..d921ed4 100644
--- a/core/java/android/provider/AlarmClock.java
+++ b/core/java/android/provider/AlarmClock.java
@@ -29,6 +29,8 @@
  * new alarm or timer should use
  * {@link android.content.Context#startActivity Context.startActivity()} so that
  * the user has the option of choosing which alarm clock application to use.
+ *
+ * Android TV devices may not support the alarm intents.
  */
 public final class AlarmClock {
     /**
diff --git a/core/java/android/text/BidiFormatter.java b/core/java/android/text/BidiFormatter.java
index d84502f..f65f397 100644
--- a/core/java/android/text/BidiFormatter.java
+++ b/core/java/android/text/BidiFormatter.java
@@ -592,10 +592,21 @@
         static {
             DIR_TYPE_CACHE = new byte[DIR_TYPE_CACHE_SIZE];
             for (int i = 0; i < DIR_TYPE_CACHE_SIZE; i++) {
+                // Calling Character.getDirectionality() is OK here, since new emojis start after
+                // the end of our cache.
                 DIR_TYPE_CACHE[i] = Character.getDirectionality(i);
             }
         }
 
+        private static byte getDirectionality(int codePoint) {
+            if (Emoji.isNewEmoji(codePoint)) {
+                // TODO: Fix or remove once emoji-data.text 5.0 is in ICU or update to 6.0.
+                return Character.DIRECTIONALITY_OTHER_NEUTRALS;
+            } else {
+                return Character.getDirectionality(codePoint);
+            }
+        }
+
         // Internal instance variables.
 
         /**
@@ -809,7 +820,7 @@
          * cache.
          */
         private static byte getCachedDirectionality(char c) {
-            return c < DIR_TYPE_CACHE_SIZE ? DIR_TYPE_CACHE[c] : Character.getDirectionality(c);
+            return c < DIR_TYPE_CACHE_SIZE ? DIR_TYPE_CACHE[c] : getDirectionality(c);
         }
 
         /**
@@ -826,7 +837,7 @@
             if (Character.isHighSurrogate(lastChar)) {
                 int codePoint = Character.codePointAt(text, charIndex);
                 charIndex += Character.charCount(codePoint);
-                return Character.getDirectionality(codePoint);
+                return getDirectionality(codePoint);
             }
             charIndex++;
             byte dirType = getCachedDirectionality(lastChar);
@@ -856,7 +867,7 @@
             if (Character.isLowSurrogate(lastChar)) {
                 int codePoint = Character.codePointBefore(text, charIndex);
                 charIndex -= Character.charCount(codePoint);
-                return Character.getDirectionality(codePoint);
+                return getDirectionality(codePoint);
             }
             charIndex--;
             byte dirType = getCachedDirectionality(lastChar);
diff --git a/core/java/android/text/Emoji.java b/core/java/android/text/Emoji.java
index ee016c1..d33aad9 100644
--- a/core/java/android/text/Emoji.java
+++ b/core/java/android/text/Emoji.java
@@ -65,22 +65,32 @@
         return UCharacter.hasBinaryProperty(codePoint, UProperty.EMOJI_MODIFIER_BASE);
     }
 
-    // Returns true if the character has Emoji property.
-    public static boolean isEmoji(int codePoint) {
+    /**
+     * Returns true if the character is a new emoji still not supported in our version of ICU.
+     */
+    public static boolean isNewEmoji(int codePoint) {
         // Emoji characters new in Unicode emoji 5.0.
         // From http://www.unicode.org/Public/emoji/5.0/emoji-data.txt
         // TODO: Remove once emoji-data.text 5.0 is in ICU or update to 6.0.
-        if ((0x1F6F7 <= codePoint && codePoint <= 0x1F6F8)
+        if (codePoint < 0x1F6F7 || codePoint > 0x1F9E6) {
+            // Optimization for characters outside the new emoji range.
+            return false;
+        }
+        return (0x1F6F7 <= codePoint && codePoint <= 0x1F6F8)
                 || codePoint == 0x1F91F
                 || (0x1F928 <= codePoint && codePoint <= 0x1F92F)
                 || (0x1F931 <= codePoint && codePoint <= 0x1F932)
                 || codePoint == 0x1F94C
                 || (0x1F95F <= codePoint && codePoint <= 0x1F96B)
                 || (0x1F992 <= codePoint && codePoint <= 0x1F997)
-                || (0x1F9D0 <= codePoint && codePoint <= 0x1F9E6)) {
-            return true;
-        }
-        return UCharacter.hasBinaryProperty(codePoint, UProperty.EMOJI);
+                || (0x1F9D0 <= codePoint && codePoint <= 0x1F9E6);
+    }
+
+    /**
+     * Returns true if the character has Emoji property.
+     */
+    public static boolean isEmoji(int codePoint) {
+        return isNewEmoji(codePoint) || UCharacter.hasBinaryProperty(codePoint, UProperty.EMOJI);
     }
 
     // Returns true if the character can be a base character of COMBINING ENCLOSING KEYCAP.
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index 65f3c90..b157709 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -22,9 +22,12 @@
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.LocaleList;
+import android.util.Pair;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillValue;
 
+import java.util.ArrayList;
+
 /**
  * Container for storing additional per-view data generated by {@link View#onProvideStructure
  * View.onProvideStructure} and {@link View#onProvideAutofillStructure
@@ -43,17 +46,6 @@
     public abstract void setId(int id, String packageName, String typeName, String entryName);
 
     /**
-     * Sets the name of the identifier for this view.
-     *
-     * <p>Typically used when adding virtual children (through
-     * {@link #asyncNewChild(int)}) that does not map to Android {@link View}
-     * - otherwise, it's better to call {@link #setId(int, String, String, String)}.
-     *
-     * @param entryName The entry name of the view's identifier, or {@code null} if there is none.
-     */
-    public abstract void setIdEntry(String entryName);
-
-    /**
      * Set the basic dimensions of this view.
      *
      * @param left The view's left position, in pixels relative to its parent's left edge.
@@ -372,13 +364,7 @@
     /**
      * Sets the URL represented by this node.
      *
-     * <p>Typically used in the following situations:
-     *
-     * <ol>
-     * <li>In a {@link android.app.assist.AssistStructure.WindowNode#getRootViewNode()}, to set up
-     * the main URL of an HTML page.
-     * <li>On child nodes represening hyperlinks.
-     * </ol>
+     * <p>Typically used when the view is a container for an HTML document.
      */
     public abstract void setUrl(String url);
 
@@ -386,4 +372,64 @@
      * Sets the the list of locales associated with this node.
      */
     public abstract void setLocaleList(LocaleList localeList);
+
+    /**
+     * Creates a new {@link HtmlInfo.Builder} for the given HTML tag.
+     *
+     * @param tagName name of the HTML tag.
+     * @return a new builder.
+     */
+    public abstract HtmlInfo.Builder newHtmlInfoBuilder(@NonNull String tagName);
+
+    /**
+     * Sets the HTML properties of this node when it represents an HTML element.
+     *
+     * <p>Should only be set when the node is used for autofill purposes - it will be ignored
+     * when used for assist.
+     *
+     * @param htmlInfo HTML properties.
+     */
+    public abstract void setHtmlInfo(@NonNull HtmlInfo htmlInfo);
+
+    /**
+     * Simplified representation of the HTML properties of a node that represents an HTML element.
+     */
+    public abstract static class HtmlInfo {
+
+        /**
+         * Gets the HTML tag.
+         */
+        @NonNull
+        public abstract String getTag();
+
+        /**
+         * Gets the list of HTML attributes.
+         *
+         * @return list of key/value pairs; could contain pairs with the same keys.
+         */
+        @Nullable
+        public abstract ArrayList<Pair<String, String>> getAttributes();
+
+        /**
+         * Builder for {@link HtmlInfo} objects.
+         */
+        public abstract static class Builder {
+
+            /**
+             * Adds an HTML attribute.
+             *
+             * @param name name of the attribute.
+             * @param value value of the attribute.
+             * @return same builder, for chaining.
+             */
+            public abstract Builder addAttribute(@NonNull String name, @NonNull String value);
+
+            /**
+             * Builds the {@link HtmlInfo} object.
+             *
+             * @return a new {@link HtmlInfo} instance.
+             */
+            public abstract HtmlInfo build();
+        }
+    }
 }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 9582b72..3f72fde 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -42,7 +42,6 @@
 import android.os.RemoteException;
 import android.print.PrintDocumentAdapter;
 import android.security.KeyChain;
-import android.text.InputType;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.SparseArray;
@@ -2641,49 +2640,55 @@
      * understood by the {@link android.service.autofill.AutofillService} implementations:
      *
      * <ol>
-     *   <li>{@link ViewStructure#setClassName(String)} should be use to describe the type of node:
-     *   <ol>
-     *       <li>If the Android SDK provides a similar View, the full-qualified class name of that
-     *           view should be used.
-     *       <li>Otherwise, the class name should be {@code HTML.iframe}.
-     *   </ol>
+     *   <li>If the Android SDK provides a similar View, then should be set with the
+     *   fully-qualified class name of such view.
      *   <li>The W3C autofill field ({@code autocomplete} tag attribute) maps to
      *       {@link ViewStructure#setAutofillHints(String[])}.
      *   <li>The {@code type} attribute of {@code INPUT} tags maps to
      *       {@link ViewStructure#setInputType(int)}.
-     *   <li>The {@code name} attribute maps to {@link ViewStructure#setIdEntry(String)}.
      *   <li>The {@code value} attribute maps to {@link ViewStructure#setText(CharSequence)}.
      *   <li>The {@code placeholder} attribute maps to {@link ViewStructure#setHint(CharSequence)}.
      *   <li>{@link ViewStructure#setDataIsSensitive(boolean)} whould only be called with
      *       {@code true} for form fields whose {@code value} attribute was not pre-loaded.
+     *   <li>Other HTML attributes can be represented through
+     *   {@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}.
      * </ol>
      *
      * <p>Example1: an HTML form with 2 fields for username and password.
      *
      * <pre class="prettyprint">
-     *    <input type="text" name="username" value="mr.sparkle" autocomplete="username" placeholder="Email or username">
-     *    <input type="password" name="password" autocomplete="current-password" placeholder="Password">
+     *    <input type="text" name="username" id="user" value="mr.sparkle" autocomplete="username" placeholder="Email or username">
+     *    <input type="password" name="password" id="pass" autocomplete="current-password" placeholder="Password">
      * </pre>
      *
      * <p>Would map to:
      *
      * <pre class="prettyprint">
-     *     ViewStructure username = //structure.newChildForAutofill(...);
+     *     int index = structure.addChildCount(2);
+     *     ViewStructure username = structure.newChild(index);
+     *     username.setAutofillId(structure, 1); // id 1 - first child
      *     username.setClassName("input");
      *     username.setInputType("android.widget.EditText");
      *     username.setAutofillHints("username");
-     *     username.setIdEntry("username");
+     *     username.setHtmlInfo(child.newHtmlInfoBuilder("input")
+     *         .addAttribute("name", "username")
+     *         .addAttribute("id", "user")
+     *         .build());
      *     username.setHint("Email or username");
      *     username.setAutofillType(View.AUTOFILL_TYPE_TEXT);
      *     username.setAutofillValue(AutofillValue.forText("mr.sparkle"));
      *     username.setText("mr.sparkle");
      *     username.setDataIsSensitive(true); // Contains real username, which is sensitive
      *
-     *     ViewStructure password = //structure.newChildForAutofill(...);
+     *     ViewStructure password = structure.newChild(index + 1);
+     *     username.setAutofillId(structure, 2); // id 2 - second child
      *     password.setInputType("android.widget.EditText");
      *     password.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD);
      *     password.setAutofillHints("current-password");
-     *     password.setIdEntry("password");
+     *     password.setHtmlInfo(child.newHtmlInfoBuilder("input")
+     *         .addAttribute("name", "password")
+     *         .addAttribute("id", "pass")
+     *         .build());
      *     password.setHint("Password");
      *     password.setAutofillType(View.AUTOFILL_TYPE_TEXT);
      *     password.setDataIsSensitive(false); // Value is not set
@@ -2698,9 +2703,11 @@
      * <p>Would map to:
      *
      * <pre class="prettyprint">
-     *     ViewStructure iframe = //structure.newChildForAutofill(...);
-     *     iframe.setClassName("HTML.iframe");
-     *     iframe.setUrl("http://example.com/login");
+     *     int index = structure.addChildCount(1);
+     *     ViewStructure iframe = structure.newChildFor(index);
+     *     iframe.setHtmlInfo(child.newHtmlInfoBuilder("iframe")
+     *         .addAttribute("url", "http://example.com/login")
+     *         .build());
      * </pre>
      */
     @Override
diff --git a/core/java/com/android/internal/os/FuseAppLoop.java b/core/java/com/android/internal/os/FuseAppLoop.java
index 8edd637..088e726 100644
--- a/core/java/com/android/internal/os/FuseAppLoop.java
+++ b/core/java/com/android/internal/os/FuseAppLoop.java
@@ -20,6 +20,7 @@
 import android.annotation.Nullable;
 import android.os.ProxyFileDescriptorCallback;
 import android.os.Handler;
+import android.os.Message;
 import android.os.ParcelFileDescriptor;
 import android.system.ErrnoException;
 import android.system.OsConstants;
@@ -28,10 +29,11 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
 import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.Map;
 import java.util.concurrent.ThreadFactory;
 
-public class FuseAppLoop {
+public class FuseAppLoop implements Handler.Callback {
     private static final String TAG = "FuseAppLoop";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
     public static final int ROOT_INODE = 1;
@@ -43,13 +45,11 @@
         }
     };
     private static final int FUSE_OK = 0;
+    private static final int ARGS_POOL_SIZE = 50;
 
     private final Object mLock = new Object();
     private final int mMountPointId;
     private final Thread mThread;
-    private final Handler mDefaultHandler;
-
-    private static final int CMD_FSYNC = 1;
 
     @GuardedBy("mLock")
     private final SparseArray<CallbackEntry> mCallbackMap = new SparseArray<>();
@@ -57,6 +57,9 @@
     @GuardedBy("mLock")
     private final BytesMap mBytesMap = new BytesMap();
 
+    @GuardedBy("mLock")
+    private final LinkedList<Args> mArgsPool = new LinkedList<>();
+
     /**
      * Sequential number can be used as file name and inode in AppFuse.
      * 0 is regarded as an error, 1 is mount point. So we start the number from 2.
@@ -83,7 +86,6 @@
             }
         });
         mThread.start();
-        mDefaultHandler = null;
     }
 
     public int registerCallback(@NonNull ProxyFileDescriptorCallback callback,
@@ -110,7 +112,8 @@
                     break;
                 }
             }
-            mCallbackMap.put(id, new CallbackEntry(callback, handler));
+            mCallbackMap.put(id, new CallbackEntry(
+                    callback, new Handler(handler.getLooper(), this)));
             return id;
         }
     }
@@ -137,78 +140,113 @@
     // Defined in FuseBuffer.h
     private static final int FUSE_MAX_WRITE = 256 * 1024;
 
+    @Override
+    public boolean handleMessage(Message msg) {
+        final Args args = (Args) msg.obj;
+        final CallbackEntry entry = args.entry;
+        final long inode = args.inode;
+        final long unique = args.unique;
+        final int size = args.size;
+        final long offset = args.offset;
+        final byte[] data = args.data;
+
+        try {
+            switch (msg.what) {
+                case FUSE_LOOKUP: {
+                    final long fileSize = entry.callback.onGetSize();
+                    synchronized (mLock) {
+                        if (mInstance != 0) {
+                            native_replyLookup(mInstance, unique, inode, fileSize);
+                        }
+                        recycleLocked(args);
+                    }
+                    break;
+                }
+                case FUSE_GETATTR: {
+                    final long fileSize = entry.callback.onGetSize();
+                    synchronized (mLock) {
+                        if (mInstance != 0) {
+                            native_replyGetAttr(mInstance, unique, inode, fileSize);
+                        }
+                        recycleLocked(args);
+                    }
+                    break;
+                }
+                case FUSE_READ:
+                    final int readSize = entry.callback.onRead(
+                            offset, size, data);
+                    synchronized (mLock) {
+                        if (mInstance != 0) {
+                            native_replyRead(mInstance, unique, readSize, data);
+                        }
+                        recycleLocked(args);
+                    }
+                    break;
+                case FUSE_WRITE:
+                    final int writeSize = entry.callback.onWrite(offset, size, data);
+                    synchronized (mLock) {
+                        if (mInstance != 0) {
+                            native_replyWrite(mInstance, unique, writeSize);
+                        }
+                        recycleLocked(args);
+                    }
+                    break;
+                case FUSE_FSYNC:
+                    entry.callback.onFsync();
+                    synchronized (mLock) {
+                        if (mInstance != 0) {
+                            native_replySimple(mInstance, unique, FUSE_OK);
+                        }
+                        recycleLocked(args);
+                    }
+                    break;
+                case FUSE_RELEASE:
+                    entry.callback.onRelease();
+                    synchronized (mLock) {
+                        if (mInstance != 0) {
+                            native_replySimple(mInstance, unique, FUSE_OK);
+                        }
+                        mBytesMap.stopUsing(entry.getThreadId());
+                        recycleLocked(args);
+                    }
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unknown FUSE command: " + msg.what);
+            }
+        } catch (Exception error) {
+            synchronized (mLock) {
+                Log.e(TAG, "", error);
+                replySimpleLocked(unique, getError(error));
+                recycleLocked(args);
+            }
+        }
+
+        return true;
+    }
+
     // Called by JNI.
     @SuppressWarnings("unused")
     private void onCommand(int command, long unique, long inode, long offset, int size,
             byte[] data) {
-        synchronized(mLock) {
+        synchronized (mLock) {
             try {
-                final CallbackEntry entry = getCallbackEntryOrThrowLocked(inode);
-                entry.postRunnable(() -> {
-                    try {
-                        switch (command) {
-                            case FUSE_LOOKUP: {
-                                final long fileSize = entry.callback.onGetSize();
-                                synchronized (mLock) {
-                                    if (mInstance != 0) {
-                                        native_replyLookup(mInstance, unique, inode, fileSize);
-                                    }
-                                }
-                                break;
-                            }
-                            case FUSE_GETATTR: {
-                                final long fileSize = entry.callback.onGetSize();
-                                synchronized (mLock) {
-                                    if (mInstance != 0) {
-                                        native_replyGetAttr(mInstance, unique, inode, fileSize);
-                                    }
-                                }
-                                break;
-                            }
-                            case FUSE_READ:
-                                final int readSize = entry.callback.onRead(offset, size, data);
-                                synchronized (mLock) {
-                                    if (mInstance != 0) {
-                                        native_replyRead(mInstance, unique, readSize, data);
-                                    }
-                                }
-                                break;
-                            case FUSE_WRITE:
-                                final int writeSize = entry.callback.onWrite(offset, size, data);
-                                synchronized (mLock) {
-                                    if (mInstance != 0) {
-                                        native_replyWrite(mInstance, unique, writeSize);
-                                    }
-                                }
-                                break;
-                            case FUSE_FSYNC:
-                                entry.callback.onFsync();
-                                synchronized (mLock) {
-                                    if (mInstance != 0) {
-                                        native_replySimple(mInstance, unique, FUSE_OK);
-                                    }
-                                }
-                                break;
-                            case FUSE_RELEASE:
-                                entry.callback.onRelease();
-                                synchronized (mLock) {
-                                    if (mInstance != 0) {
-                                        native_replySimple(mInstance, unique, FUSE_OK);
-                                    }
-                                    mBytesMap.stopUsing(entry.getThreadId());
-                                }
-                                break;
-                            default:
-                                throw new IllegalArgumentException(
-                                        "Unknown FUSE command: " + command);
-                        }
-                    } catch (Exception error) {
-                        Log.e(TAG, "", error);
-                        replySimple(unique, getError(error));
-                    }
-                });
-            } catch (ErrnoException error) {
-                Log.e(TAG, "", error);
+                final Args args;
+                if (mArgsPool.size() == 0) {
+                    args = new Args();
+                } else {
+                    args = mArgsPool.pop();
+                }
+                args.unique = unique;
+                args.inode = inode;
+                args.offset = offset;
+                args.size = size;
+                args.data = data;
+                args.entry = getCallbackEntryOrThrowLocked(inode);
+                if (!args.entry.handler.sendMessage(
+                        Message.obtain(args.entry.handler, command, 0, 0, args))) {
+                    throw new ErrnoException("onCommand", OsConstants.EBADF);
+                }
+            } catch (Exception error) {
                 replySimpleLocked(unique, getError(error));
             }
         }
@@ -253,9 +291,9 @@
         return entry;
     }
 
-    private void replySimple(long unique, int result) {
-        synchronized (mLock) {
-            replySimpleLocked(unique, result);
+    private void recycleLocked(Args args) {
+        if (mArgsPool.size() < ARGS_POOL_SIZE) {
+            mArgsPool.add(args);
         }
     }
 
@@ -296,13 +334,6 @@
         long getThreadId() {
             return handler.getLooper().getThread().getId();
         }
-
-        void postRunnable(Runnable runnable) throws ErrnoException {
-            final boolean result = handler.post(runnable);
-            if (!result) {
-                throw new ErrnoException("postRunnable", OsConstants.EBADF);
-            }
-        }
     }
 
     /**
@@ -342,4 +373,13 @@
             mEntries.clear();
         }
     }
+
+    private static class Args {
+        long unique;
+        long inode;
+        long offset;
+        int size;
+        byte[] data;
+        CallbackEntry entry;
+    }
 }
diff --git a/core/java/com/android/internal/util/DumpUtils.java b/core/java/com/android/internal/util/DumpUtils.java
index 64e1d10..4659d3c 100644
--- a/core/java/com/android/internal/util/DumpUtils.java
+++ b/core/java/com/android/internal/util/DumpUtils.java
@@ -16,7 +16,12 @@
 
 package com.android.internal.util;
 
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Binder;
 import android.os.Handler;
+import android.util.Slog;
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
@@ -25,6 +30,9 @@
  * Helper functions for dumping the state of system services.
  */
 public final class DumpUtils {
+    private static final String TAG = "DumpUtils";
+    private static final boolean DEBUG = true;
+
     private DumpUtils() {
     }
 
@@ -55,4 +63,90 @@
     public interface Dump {
         void dump(PrintWriter pw, String prefix);
     }
+
+    private static void logMessage(PrintWriter pw, String msg) {
+        if (DEBUG) Slog.v(TAG, msg);
+        pw.println(msg);
+    }
+
+    /**
+     * Verify that caller holds {@link android.Manifest.permission#DUMP}.
+     *
+     * @return true if access should be granted.
+     * @hide
+     */
+    public static boolean checkDumpPermission(Context context, String tag, PrintWriter pw) {
+        if (context.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+                != PackageManager.PERMISSION_GRANTED) {
+            logMessage(pw, "Permission Denial: can't dump " + tag + " from from pid="
+                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
+                    + " due to missing android.permission.DUMP permission");
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+    /**
+     * Verify that caller holds
+     * {@link android.Manifest.permission#PACKAGE_USAGE_STATS} and that they
+     * have {@link AppOpsManager#OP_GET_USAGE_STATS} access.
+     *
+     * @return true if access should be granted.
+     * @hide
+     */
+    public static boolean checkUsageStatsPermission(Context context, String tag, PrintWriter pw) {
+        // System internals always get access
+        final int uid = Binder.getCallingUid();
+        switch (uid) {
+            case android.os.Process.ROOT_UID:
+            case android.os.Process.SYSTEM_UID:
+            case android.os.Process.SHELL_UID:
+                return true;
+        }
+
+        // Caller always needs to hold permission
+        if (context.checkCallingOrSelfPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)
+                != PackageManager.PERMISSION_GRANTED) {
+            logMessage(pw, "Permission Denial: can't dump " + tag + " from from pid="
+                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
+                    + " due to missing android.permission.PACKAGE_USAGE_STATS permission");
+            return false;
+        }
+
+        // And finally, caller needs to have appops access; this is totally
+        // hacky, but it's the easiest way to wire this up without retrofitting
+        // Binder.dump() to pass through package names.
+        final AppOpsManager appOps = context.getSystemService(AppOpsManager.class);
+        final String[] pkgs = context.getPackageManager().getPackagesForUid(uid);
+        if (pkgs != null) {
+            for (String pkg : pkgs) {
+                if (appOps.checkOpNoThrow(AppOpsManager.OP_GET_USAGE_STATS, uid,
+                        pkg) == AppOpsManager.MODE_ALLOWED) {
+                    appOps.noteOp(AppOpsManager.OP_GET_USAGE_STATS, uid, pkg);
+                    if (DEBUG) Slog.v(TAG, "Found package " + pkg + " with "
+                                + "android:get_usage_stats access");
+                    return true;
+                }
+            }
+        }
+
+        logMessage(pw, "Permission Denial: can't dump " + tag + " from from pid="
+                + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
+                + " due to android:get_usage_stats app-op not allowed");
+        return false;
+    }
+
+    /**
+     * Verify that caller holds both {@link android.Manifest.permission#DUMP}
+     * and {@link android.Manifest.permission#PACKAGE_USAGE_STATS}, and that
+     * they have {@link AppOpsManager#OP_GET_USAGE_STATS} access.
+     *
+     * @return true if access should be granted.
+     * @hide
+     */
+    public static boolean checkDumpAndUsageStatsPermission(Context context, String tag,
+            PrintWriter pw) {
+        return checkDumpPermission(context, tag, pw) && checkUsageStatsPermission(context, tag, pw);
+    }
 }
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index e64a574..3dc1be6 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -39,6 +39,7 @@
 jfieldID gOptions_heightFieldID;
 jfieldID gOptions_mimeFieldID;
 jfieldID gOptions_outConfigFieldID;
+jfieldID gOptions_outColorSpaceFieldID;
 jfieldID gOptions_mCancelID;
 jfieldID gOptions_bitmapFieldID;
 
@@ -50,6 +51,20 @@
 jclass gBitmapConfig_class;
 jmethodID gBitmapConfig_nativeToConfigMethodID;
 
+jclass gColorSpace_class;
+jmethodID gColorSpace_getMethodID;
+jmethodID gColorSpace_matchMethodID;
+
+jclass gColorSpaceRGB_class;
+jmethodID gColorSpaceRGB_constructorMethodID;
+
+jclass gColorSpace_Named_class;
+jfieldID gColorSpace_Named_sRGBFieldID;
+jfieldID gColorSpace_Named_LinearExtendedSRGBFieldID;
+
+jclass gTransferParameters_class;
+jmethodID gTransferParameters_constructorMethodID;
+
 using namespace android;
 
 jstring encodedFormatToString(JNIEnv* env, SkEncodedImageFormat format) {
@@ -228,6 +243,70 @@
            needsFineScale(fullSize.height(), decodedSize.height(), sampleSize);
 }
 
+static jobject getColorSpace(JNIEnv* env,
+        sk_sp<SkColorSpace>& decodeColorSpace, SkColorType decodeColorType) {
+    jobject colorSpace = nullptr;
+
+    // No need to match, we know what the output color space will be
+    if (decodeColorType == kRGBA_F16_SkColorType) {
+        jobject linearExtendedSRGB = env->GetStaticObjectField(
+                gColorSpace_Named_class, gColorSpace_Named_LinearExtendedSRGBFieldID);
+        colorSpace = env->CallStaticObjectMethod(gColorSpace_class,
+                gColorSpace_getMethodID, linearExtendedSRGB);
+    } else {
+        // Same here, no need to match
+        if (decodeColorSpace->isSRGB()) {
+            jobject sRGB = env->GetStaticObjectField(
+                    gColorSpace_Named_class, gColorSpace_Named_sRGBFieldID);
+            colorSpace = env->CallStaticObjectMethod(gColorSpace_class,
+                    gColorSpace_getMethodID, sRGB);
+        } else if (decodeColorSpace.get() != nullptr) {
+            // Try to match against known RGB color spaces using the CIE XYZ D50
+            // conversion matrix and numerical transfer function parameters
+            SkMatrix44 xyzMatrix(SkMatrix44::kUninitialized_Constructor);
+            LOG_ALWAYS_FATAL_IF(!decodeColorSpace->toXYZD50(&xyzMatrix));
+
+            SkColorSpaceTransferFn transferParams;
+            // We can only handle numerical transfer functions at the moment
+            LOG_ALWAYS_FATAL_IF(!decodeColorSpace->isNumericalTransferFn(&transferParams));
+
+            jobject params = env->NewObject(gTransferParameters_class,
+                    gTransferParameters_constructorMethodID,
+                    transferParams.fA, transferParams.fB, transferParams.fC,
+                    transferParams.fD, transferParams.fE, transferParams.fF,
+                    transferParams.fG);
+
+            jfloatArray xyzArray = env->NewFloatArray(9);
+            jfloat xyz[9] = {
+                    xyzMatrix.getFloat(0, 0),
+                    xyzMatrix.getFloat(1, 0),
+                    xyzMatrix.getFloat(2, 0),
+                    xyzMatrix.getFloat(0, 1),
+                    xyzMatrix.getFloat(1, 1),
+                    xyzMatrix.getFloat(2, 1),
+                    xyzMatrix.getFloat(0, 2),
+                    xyzMatrix.getFloat(1, 2),
+                    xyzMatrix.getFloat(2, 2)
+            };
+            env->SetFloatArrayRegion(xyzArray, 0, 9, xyz);
+
+            colorSpace = env->CallStaticObjectMethod(gColorSpace_class,
+                    gColorSpace_matchMethodID, xyzArray, params);
+
+            if (colorSpace == nullptr) {
+                // We couldn't find an exact match, let's create a new color space
+                // instance with the 3x3 conversion matrix and transfer function
+                colorSpace = env->NewObject(gColorSpaceRGB_class,
+                        gColorSpaceRGB_constructorMethodID,
+                        env->NewStringUTF("Unknown"), xyzArray, params);
+            }
+
+            env->DeleteLocalRef(xyzArray);
+        }
+    }
+    return colorSpace;
+}
+
 static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding, jobject options) {
     // This function takes ownership of the input stream.  Since the SkAndroidCodec
     // will take ownership of the stream, we don't necessarily need to take ownership
@@ -263,6 +342,7 @@
         env->SetIntField(options, gOptions_heightFieldID, -1);
         env->SetObjectField(options, gOptions_mimeFieldID, 0);
         env->SetObjectField(options, gOptions_outConfigFieldID, 0);
+        env->SetObjectField(options, gOptions_outColorSpaceFieldID, 0);
 
         jobject jconfig = env->GetObjectField(options, gOptions_configFieldID);
         prefColorType = GraphicsJNI::getNativeBitmapColorType(env, jconfig);
@@ -319,6 +399,7 @@
 
     // Set the decode colorType
     SkColorType decodeColorType = codec->computeOutputColorType(prefColorType);
+    sk_sp<SkColorSpace> decodeColorSpace = codec->computeOutputColorSpace(decodeColorType);
 
     // Set the options and return if the client only wants the size.
     if (options != NULL) {
@@ -345,6 +426,9 @@
                 gBitmapConfig_nativeToConfigMethodID, configID);
         env->SetObjectField(options, gOptions_outConfigFieldID, config);
 
+        env->SetObjectField(options, gOptions_outColorSpaceFieldID,
+                getColorSpace(env, decodeColorSpace, decodeColorType));
+
         if (onlyDecodeSize) {
             return nullptr;
         }
@@ -412,7 +496,7 @@
     SkAlphaType alphaType = codec->computeOutputAlphaType(requireUnpremultiplied);
 
     const SkImageInfo decodeInfo = SkImageInfo::Make(size.width(), size.height(),
-            decodeColorType, alphaType, codec->computeOutputColorSpace(decodeColorType));
+            decodeColorType, alphaType, decodeColorSpace);
 
     // For wide gamut images, we will leave the color space on the SkBitmap.  Otherwise,
     // use the default.
@@ -725,6 +809,8 @@
     gOptions_mimeFieldID = GetFieldIDOrDie(env, options_class, "outMimeType", "Ljava/lang/String;");
     gOptions_outConfigFieldID = GetFieldIDOrDie(env, options_class, "outConfig",
              "Landroid/graphics/Bitmap$Config;");
+    gOptions_outColorSpaceFieldID = GetFieldIDOrDie(env, options_class, "outColorSpace",
+             "Landroid/graphics/ColorSpace;");
     gOptions_mCancelID = GetFieldIDOrDie(env, options_class, "mCancel", "Z");
 
     jclass bitmap_class = FindClassOrDie(env, "android/graphics/Bitmap");
@@ -741,6 +827,29 @@
     gBitmapConfig_nativeToConfigMethodID = GetStaticMethodIDOrDie(env, gBitmapConfig_class,
             "nativeToConfig", "(I)Landroid/graphics/Bitmap$Config;");
 
+    gColorSpace_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/ColorSpace"));
+    gColorSpace_getMethodID = GetStaticMethodIDOrDie(env, gColorSpace_class,
+            "get", "(Landroid/graphics/ColorSpace$Named;)Landroid/graphics/ColorSpace;");
+    gColorSpace_matchMethodID = GetStaticMethodIDOrDie(env, gColorSpace_class, "match",
+            "([FLandroid/graphics/ColorSpace$Rgb$TransferParameters;)Landroid/graphics/ColorSpace;");
+
+    gColorSpaceRGB_class = MakeGlobalRefOrDie(env,
+            FindClassOrDie(env, "android/graphics/ColorSpace$Rgb"));
+    gColorSpaceRGB_constructorMethodID = GetMethodIDOrDie(env, gColorSpaceRGB_class,
+            "<init>", "(Ljava/lang/String;[FLandroid/graphics/ColorSpace$Rgb$TransferParameters;)V");
+
+    gColorSpace_Named_class = MakeGlobalRefOrDie(env,
+            FindClassOrDie(env, "android/graphics/ColorSpace$Named"));
+    gColorSpace_Named_sRGBFieldID = GetStaticFieldIDOrDie(env,
+            gColorSpace_Named_class, "SRGB", "Landroid/graphics/ColorSpace$Named;");
+    gColorSpace_Named_LinearExtendedSRGBFieldID = GetStaticFieldIDOrDie(env,
+            gColorSpace_Named_class, "LINEAR_EXTENDED_SRGB", "Landroid/graphics/ColorSpace$Named;");
+
+    gTransferParameters_class = MakeGlobalRefOrDie(env, FindClassOrDie(env,
+            "android/graphics/ColorSpace$Rgb$TransferParameters"));
+    gTransferParameters_constructorMethodID = GetMethodIDOrDie(env, gTransferParameters_class,
+            "<init>", "(DDDDDDD)V");
+
     return android::RegisterMethodsOrDie(env, "android/graphics/BitmapFactory",
                                          gMethods, NELEM(gMethods));
 }
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index b926270..d606c2d 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -78,6 +78,9 @@
                           camera_frame_metadata_t *metadata);
     virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
     virtual void postRecordingFrameHandleTimestamp(nsecs_t timestamp, native_handle_t* handle);
+    virtual void postRecordingFrameHandleTimestampBatch(
+            const std::vector<nsecs_t>& timestamps,
+            const std::vector<native_handle_t*>& handles);
     void postMetadata(JNIEnv *env, int32_t msgType, camera_frame_metadata_t *metadata);
     void addCallbackBuffer(JNIEnv *env, jbyteArray cbb, int msgType);
     void setCallbackMode(JNIEnv *env, bool installed, bool manualMode);
@@ -362,6 +365,22 @@
     }
 }
 
+void JNICameraContext::postRecordingFrameHandleTimestampBatch(
+        const std::vector<nsecs_t>&,
+        const std::vector<native_handle_t*>& handles) {
+    // Video buffers are not needed at app layer so just return the video buffers here.
+    // This may be called when stagefright just releases camera but there are still outstanding
+    // video buffers.
+    if (mCamera != nullptr) {
+        mCamera->releaseRecordingFrameHandleBatch(handles);
+    } else {
+        for (auto& handle : handles) {
+            native_handle_close(handle);
+            native_handle_delete(handle);
+        }
+    }
+}
+
 void JNICameraContext::postMetadata(JNIEnv *env, int32_t msgType, camera_frame_metadata_t *metadata)
 {
     jobjectArray obj = NULL;
diff --git a/core/jni/android_text_AndroidBidi.cpp b/core/jni/android_text_AndroidBidi.cpp
index 2a3f036..d744b7c 100644
--- a/core/jni/android_text_AndroidBidi.cpp
+++ b/core/jni/android_text_AndroidBidi.cpp
@@ -22,6 +22,7 @@
 #include "utils/misc.h"
 #include "utils/Log.h"
 #include "unicode/ubidi.h"
+#include <minikin/Emoji.h>
 
 namespace android {
 
@@ -38,6 +39,9 @@
         if (info != NULL) {
             UErrorCode status = U_ZERO_ERROR;
             UBiDi* bidi = ubidi_openSized(n, 0, &status);
+            // Set callbacks to override bidi classes of new emoji
+            ubidi_setClassCallback(
+                    bidi, minikin::emojiBidiOverride, nullptr, nullptr, nullptr, &status);
             ubidi_setPara(bidi, chs, n, dir, NULL, &status);
             if (U_SUCCESS(status)) {
                 for (int i = 0; i < n; ++i) {
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 5e3488c..344f3c8 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -181,10 +181,6 @@
     <allow-in-power-save package="com.android.cellbroadcastreceiver" />
     <allow-in-power-save package="com.android.shell" />
 
-    <!-- Package in charge of provisioning that needs to freely run in the background -->
-    <!-- STOPSHIP: Revert this once it is fixed properly -->
-    <allow-in-power-save package="com.android.managedprovisioning" />
-
     <!-- These are the packages that are white-listed to be able to run as system user -->
     <system-user-whitelisted-app package="com.android.settings" />
 
diff --git a/docs/html/reference/images/graphics/composite_ADD.png b/docs/html/reference/images/graphics/composite_ADD.png
new file mode 100644
index 0000000..90932c5
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_ADD.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_CLEAR.png b/docs/html/reference/images/graphics/composite_CLEAR.png
new file mode 100644
index 0000000..7c0731d
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_CLEAR.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_DARKEN.png b/docs/html/reference/images/graphics/composite_DARKEN.png
new file mode 100644
index 0000000..a798b97
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_DARKEN.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_DST.png b/docs/html/reference/images/graphics/composite_DST.png
new file mode 100644
index 0000000..6dde48f
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_DST.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_DST_ATOP.png b/docs/html/reference/images/graphics/composite_DST_ATOP.png
new file mode 100644
index 0000000..c6767bd
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_DST_ATOP.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_DST_IN.png b/docs/html/reference/images/graphics/composite_DST_IN.png
new file mode 100644
index 0000000..cf50a7b
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_DST_IN.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_DST_OUT.png b/docs/html/reference/images/graphics/composite_DST_OUT.png
new file mode 100644
index 0000000..ee8a46e
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_DST_OUT.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_DST_OVER.png b/docs/html/reference/images/graphics/composite_DST_OVER.png
new file mode 100644
index 0000000..1838972
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_DST_OVER.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_LIGHTEN.png b/docs/html/reference/images/graphics/composite_LIGHTEN.png
new file mode 100644
index 0000000..8fc0a10
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_LIGHTEN.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_MULTIPLY.png b/docs/html/reference/images/graphics/composite_MULTIPLY.png
new file mode 100644
index 0000000..8816ab0
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_MULTIPLY.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_OVERLAY.png b/docs/html/reference/images/graphics/composite_OVERLAY.png
new file mode 100644
index 0000000..700a6b2
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_OVERLAY.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_SCREEN.png b/docs/html/reference/images/graphics/composite_SCREEN.png
new file mode 100644
index 0000000..b698819
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_SCREEN.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_SRC.png b/docs/html/reference/images/graphics/composite_SRC.png
new file mode 100644
index 0000000..2d70a54
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_SRC.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_SRC_ATOP.png b/docs/html/reference/images/graphics/composite_SRC_ATOP.png
new file mode 100644
index 0000000..111869e
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_SRC_ATOP.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_SRC_IN.png b/docs/html/reference/images/graphics/composite_SRC_IN.png
new file mode 100644
index 0000000..1d6145b
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_SRC_IN.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_SRC_OUT.png b/docs/html/reference/images/graphics/composite_SRC_OUT.png
new file mode 100644
index 0000000..39c0c17
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_SRC_OUT.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_SRC_OVER.png b/docs/html/reference/images/graphics/composite_SRC_OVER.png
new file mode 100644
index 0000000..1489487
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_SRC_OVER.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_XOR.png b/docs/html/reference/images/graphics/composite_XOR.png
new file mode 100644
index 0000000..6d0c5ba
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_XOR.png
Binary files differ
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index a3c6c6e..ceedc1f 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -361,6 +361,15 @@
         public Bitmap.Config outConfig;
 
         /**
+         * If known, the color space the decoded bitmap will have. Note that the
+         * output color space is not guaranteed to be the color space the bitmap
+         * is encoded with. If not known (when the config is
+         * {@link Bitmap.Config#ALPHA_8} for instance), or there is an error,
+         * it is set to null.
+         */
+        public ColorSpace outColorSpace;
+
+        /**
          * Temp storage to use for decoding.  Suggest 16K or so.
          */
         public byte[] inTempStorage;
diff --git a/graphics/java/android/graphics/ColorSpace.java b/graphics/java/android/graphics/ColorSpace.java
index 929ac22..e03dcf3 100644
--- a/graphics/java/android/graphics/ColorSpace.java
+++ b/graphics/java/android/graphics/ColorSpace.java
@@ -143,7 +143,7 @@
  *     .render();
  * </pre>
  * <p>
- *     <img src="{@docRoot}reference/android/images/graphics/colorspace_renderer.png" />
+ *     <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_renderer.png" />
  *     <figcaption style="text-align: center;">DCI-P3 vs ProPhoto RGB</figcaption>
  * </p>
  *
@@ -281,7 +281,7 @@
          *     <tr><td>Range</td><td colspan="4">\([0..1]\)</td></tr>
          * </table>
          * <p>
-         *     <img src="{@docRoot}reference/android/images/graphics/colorspace_srgb.png" />
+         *     <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_srgb.png" />
          *     <figcaption style="text-align: center;">sRGB</figcaption>
          * </p>
          */
@@ -308,7 +308,7 @@
          *     <tr><td>Range</td><td colspan="4">\([0..1]\)</td></tr>
          * </table>
          * <p>
-         *     <img src="{@docRoot}reference/android/images/graphics/colorspace_srgb.png" />
+         *     <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_srgb.png" />
          *     <figcaption style="text-align: center;">sRGB</figcaption>
          * </p>
          */
@@ -347,7 +347,7 @@
          *     <tr><td>Range</td><td colspan="4">\([-0.799..2.399[\)</td></tr>
          * </table>
          * <p>
-         *     <img src="{@docRoot}reference/android/images/graphics/colorspace_scrgb.png" />
+         *     <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_scrgb.png" />
          *     <figcaption style="text-align: center;">Extended sRGB (orange) vs sRGB (white)</figcaption>
          * </p>
          */
@@ -374,7 +374,7 @@
          *     <tr><td>Range</td><td colspan="4">\([-0.5..7.499[\)</td></tr>
          * </table>
          * <p>
-         *     <img src="{@docRoot}reference/android/images/graphics/colorspace_scrgb.png" />
+         *     <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_scrgb.png" />
          *     <figcaption style="text-align: center;">Extended sRGB (orange) vs sRGB (white)</figcaption>
          * </p>
          */
@@ -409,7 +409,7 @@
          *     <tr><td>Range</td><td colspan="4">\([0..1]\)</td></tr>
          * </table>
          * <p>
-         *     <img src="{@docRoot}reference/android/images/graphics/colorspace_bt709.png" />
+         *     <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_bt709.png" />
          *     <figcaption style="text-align: center;">BT.709</figcaption>
          * </p>
          */
@@ -444,7 +444,7 @@
          *     <tr><td>Range</td><td colspan="4">\([0..1]\)</td></tr>
          * </table>
          * <p>
-         *     <img src="{@docRoot}reference/android/images/graphics/colorspace_bt2020.png" />
+         *     <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_bt2020.png" />
          *     <figcaption style="text-align: center;">BT.2020 (orange) vs sRGB (white)</figcaption>
          * </p>
          */
@@ -471,7 +471,7 @@
          *     <tr><td>Range</td><td colspan="4">\([0..1]\)</td></tr>
          * </table>
          * <p>
-         *     <img src="{@docRoot}reference/android/images/graphics/colorspace_dci_p3.png" />
+         *     <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_dci_p3.png" />
          *     <figcaption style="text-align: center;">DCI-P3 (orange) vs sRGB (white)</figcaption>
          * </p>
          */
@@ -506,7 +506,7 @@
          *     <tr><td>Range</td><td colspan="4">\([0..1]\)</td></tr>
          * </table>
          * <p>
-         *     <img src="{@docRoot}reference/android/images/graphics/colorspace_display_p3.png" />
+         *     <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_display_p3.png" />
          *     <figcaption style="text-align: center;">Display P3 (orange) vs sRGB (white)</figcaption>
          * </p>
          */
@@ -541,7 +541,7 @@
          *     <tr><td>Range</td><td colspan="4">\([0..1]\)</td></tr>
          * </table>
          * <p>
-         *     <img src="{@docRoot}reference/android/images/graphics/colorspace_ntsc_1953.png" />
+         *     <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_ntsc_1953.png" />
          *     <figcaption style="text-align: center;">NTSC 1953 (orange) vs sRGB (white)</figcaption>
          * </p>
          */
@@ -576,7 +576,7 @@
          *     <tr><td>Range</td><td colspan="4">\([0..1]\)</td></tr>
          * </table>
          * <p>
-         *     <img src="{@docRoot}reference/android/images/graphics/colorspace_smpte_c.png" />
+         *     <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_smpte_c.png" />
          *     <figcaption style="text-align: center;">SMPTE-C (orange) vs sRGB (white)</figcaption>
          * </p>
          */
@@ -603,7 +603,7 @@
          *     <tr><td>Range</td><td colspan="4">\([0..1]\)</td></tr>
          * </table>
          * <p>
-         *     <img src="{@docRoot}reference/android/images/graphics/colorspace_adobe_rgb.png" />
+         *     <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_adobe_rgb.png" />
          *     <figcaption style="text-align: center;">Adobe RGB (orange) vs sRGB (white)</figcaption>
          * </p>
          */
@@ -638,7 +638,7 @@
          *     <tr><td>Range</td><td colspan="4">\([0..1]\)</td></tr>
          * </table>
          * <p>
-         *     <img src="{@docRoot}reference/android/images/graphics/colorspace_pro_photo_rgb.png" />
+         *     <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_pro_photo_rgb.png" />
          *     <figcaption style="text-align: center;">ProPhoto RGB (orange) vs sRGB (white)</figcaption>
          * </p>
          */
@@ -665,7 +665,7 @@
          *     <tr><td>Range</td><td colspan="4">\([-65504.0, 65504.0]\)</td></tr>
          * </table>
          * <p>
-         *     <img src="{@docRoot}reference/android/images/graphics/colorspace_aces.png" />
+         *     <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_aces.png" />
          *     <figcaption style="text-align: center;">ACES (orange) vs sRGB (white)</figcaption>
          * </p>
          */
@@ -692,7 +692,7 @@
          *     <tr><td>Range</td><td colspan="4">\([-65504.0, 65504.0]\)</td></tr>
          * </table>
          * <p>
-         *     <img src="{@docRoot}reference/android/images/graphics/colorspace_acescg.png" />
+         *     <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_acescg.png" />
          *     <figcaption style="text-align: center;">ACEScg (orange) vs sRGB (white)</figcaption>
          * </p>
          */
@@ -1931,7 +1931,7 @@
      * are internally converted to xyY.</p>
      *
      * <p>
-     *     <img src="{@docRoot}reference/android/images/graphics/colorspace_srgb.png" />
+     *     <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_srgb.png" />
      *     <figcaption style="text-align: center;">sRGB primaries and white point</figcaption>
      * </p>
      *
@@ -1989,7 +1989,7 @@
      * the range \([-65504, 65504]\).</p>
      *
      * <p>
-     *     <img src="{@docRoot}reference/android/images/graphics/colorspace_scrgb.png" />
+     *     <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_scrgb.png" />
      *     <figcaption style="text-align: center;">Extended sRGB and its large range</figcaption>
      * </p>
      *
@@ -3703,7 +3703,7 @@
      *     .render();
      * </pre>
      * <p>
-     *     <img src="{@docRoot}reference/android/images/graphics/colorspace_clipped.png" />
+     *     <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_clipped.png" />
      *     <figcaption style="text-align: center;">sRGB vs DCI-P3</figcaption>
      * </p>
      *
@@ -3746,7 +3746,7 @@
          *     .render();
          * </pre>
          * <p>
-         *     <img src="{@docRoot}reference/android/images/graphics/colorspace_comparison.png" />
+         *     <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_comparison.png" />
          *     <figcaption style="text-align: center;">Clipping disabled</figcaption>
          * </p>
          *
@@ -3759,7 +3759,7 @@
          *     .render();
          * </pre>
          * <p>
-         *     <img src="{@docRoot}reference/android/images/graphics/colorspace_clipped.png" />
+         *     <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_clipped.png" />
          *     <figcaption style="text-align: center;">Clipping enabled</figcaption>
          * </p>
          *
@@ -3789,7 +3789,7 @@
          *     .render();
          * </pre>
          * <p>
-         *     <img src="{@docRoot}reference/android/images/graphics/colorspace_ucs.png" />
+         *     <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_ucs.png" />
          *     <figcaption style="text-align: center;">CIE 1976 UCS diagram</figcaption>
          * </p>
          *
@@ -3847,7 +3847,7 @@
          *     .render();
          * </pre>
          * <p>
-         *     <img src="{@docRoot}reference/android/images/graphics/colorspace_comparison.png" />
+         *     <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_comparison.png" />
          *     <figcaption style="text-align: center;">sRGB vs DCI-P3</figcaption>
          * </p>
          *
@@ -3863,7 +3863,7 @@
          *     .render();
          * </pre>
          * <p>
-         *     <img src="{@docRoot}reference/android/images/graphics/colorspace_comparison2.png" />
+         *     <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_comparison2.png" />
          *     <figcaption style="text-align: center;">sRGB, DCI-P3, ACES and scRGB</figcaption>
          * </p>
          *
@@ -3901,7 +3901,7 @@
          *     .render();
          * </pre>
          * <p>
-         *     <img src="{@docRoot}reference/android/images/graphics/colorspace_points.png" />
+         *     <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_points.png" />
          *     <figcaption style="text-align: center;">
          *         Locating colors on the chromaticity diagram
          *     </figcaption>
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index f4bf079..c4f7dc3 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -1067,19 +1067,23 @@
     }
 
     /**
-     * Get the paint's xfermode object.
+     * Get the paint's transfer mode object.
      *
-     * @return the paint's xfermode (or null)
+     * @return the paint's transfer mode (or null)
      */
     public Xfermode getXfermode() {
         return mXfermode;
     }
 
     /**
-     * Set or clear the xfermode object.
+     * Set or clear the transfer mode object. A transfer mode defines how
+     * source pixels (generate by a drawing command) are composited with
+     * the destination pixels (content of the render target).
      * <p />
-     * Pass null to clear any previous xfermode.
+     * Pass null to clear any previous transfer mode.
      * As a convenience, the parameter passed is also returned.
+     * <p />
+     * {@link PorterDuffXfermode} is the most common transfer mode.
      *
      * @param xfermode May be null. The xfermode to be installed in the paint
      * @return         xfermode
diff --git a/graphics/java/android/graphics/PorterDuff.java b/graphics/java/android/graphics/PorterDuff.java
index 2bbbff3..d7d3049 100644
--- a/graphics/java/android/graphics/PorterDuff.java
+++ b/graphics/java/android/graphics/PorterDuff.java
@@ -16,46 +16,345 @@
 
 package android.graphics;
 
+/**
+ * <p>This class contains the list of alpha compositing and blending modes
+ * that can be passed to {@link PorterDuffXfermode}, a specialized implementation
+ * of {@link Paint}'s {@link Paint#setXfermode(Xfermode) transfer mode}.
+ * All the available modes can be found in the {@link Mode} enum.</p>
+ */
 public class PorterDuff {
+    /**
+     * {@usesMathJax}
+     *
+     * <h3>Porter-Duff</h3>
+     *
+     * <p>The name of the parent class is an homage to the work of Thomas Porter and
+     * Tom Duff, presented in their seminal 1984 paper titled "Compositing Digital Images".
+     * In this paper, the authors describe 12 compositing operators that govern how to
+     * compute the color resulting of the composition of a source (the graphics object
+     * to render) with a destination (the content of the render target).</p>
+     *
+     * <p>"Compositing Digital Images" was published in <em>Computer Graphics</em>
+     * Volume 18, Number 3 dated July 1984.</p>
+     *
+     * <p>Because the work of Porter and Duff focuses solely on the effects of the alpha
+     * channel of the source and destination, the 12 operators described in the original
+     * paper are called alpha compositing modes here.</p>
+     *
+     * <p>For convenience, this class also provides several blending modes, which similarly
+     * define the result of compositing a source and a destination but without being
+     * constrained to the alpha channel. These blending modes are not defined by Porter
+     * and Duff but have been included in this class for convenience purposes.</p>
+     *
+     * <h3>Diagrams</h3>
+     *
+     * <p>All the example diagrams presented below use the same source and destination
+     * images:</p>
+     *
+     * <table summary="Source and Destination" style="background-color: transparent;">
+     *     <tr>
+     *         <td style="border: none; text-align: center;">
+     *             <img src="{@docRoot}reference/android/images/graphics/composite_SRC.png" />
+     *             <figcaption>Source image</figcaption>
+     *         </td>
+     *         <td style="border: none; text-align: center;">
+     *             <img src="{@docRoot}reference/android/images/graphics/composite_DST.png" />
+     *             <figcaption>Destination image</figcaption>
+     *         </td>
+     *     </tr>
+     * </table>
+     *
+     * <p>The order of drawing operations used to generate each diagram is shown in the
+     * following code snippet:</p>
+     *
+     * <pre class="prettyprint">
+     * Paint paint = new Paint();
+     * canvas.drawBitmap(destinationImage, 0, 0, paint);
+     *
+     * PorterDuff.Mode mode = // choose a mode
+     * paint.setXfermode(new PorterDuffXfermode(mode));
+     *
+     * canvas.drawBitmap(sourceImage, 0, 0, paint);
+     * </pre>
 
-    // these value must match their native equivalents. See SkXfermode.h
+     *
+     * <h3>Alpha compositing modes</h3>
+     *
+     * <table summary="Alpha compositing modes" style="background-color: transparent;">
+     *     <tr>
+     *         <td style="border: none; text-align: center;">
+     *             <img src="{@docRoot}reference/android/images/graphics/composite_SRC.png" />
+     *             <figcaption>{@link #SRC Source}</figcaption>
+     *         </td>
+     *         <td style="border: none; text-align: center;">
+     *             <img src="{@docRoot}reference/android/images/graphics/composite_SRC_OVER.png" />
+     *             <figcaption>{@link #SRC_OVER Source Over}</figcaption>
+     *         </td>
+     *         <td style="border: none; text-align: center;">
+     *             <img src="{@docRoot}reference/android/images/graphics/composite_SRC_IN.png" />
+     *             <figcaption>{@link #SRC_IN Source In}</figcaption>
+     *         </td>
+     *         <td style="border: none; text-align: center;">
+     *             <img src="{@docRoot}reference/android/images/graphics/composite_SRC_ATOP.png" />
+     *             <figcaption>{@link #SRC_ATOP Source Atop}</figcaption>
+     *         </td>
+     *     </tr>
+     *     <tr>
+     *         <td style="border: none; text-align: center;">
+     *             <img src="{@docRoot}reference/android/images/graphics/composite_DST.png" />
+     *             <figcaption>{@link #DST Destination}</figcaption>
+     *         </td>
+     *         <td style="border: none; text-align: center;">
+     *             <img src="{@docRoot}reference/android/images/graphics/composite_DST_OVER.png" />
+     *             <figcaption>{@link #DST_OVER Destination Over}</figcaption>
+     *         </td>
+     *         <td style="border: none; text-align: center;">
+     *             <img src="{@docRoot}reference/android/images/graphics/composite_DST_IN.png" />
+     *             <figcaption>{@link #DST_IN Destination In}</figcaption>
+     *         </td>
+     *         <td style="border: none; text-align: center;">
+     *             <img src="{@docRoot}reference/android/images/graphics/composite_DST_ATOP.png" />
+     *             <figcaption>{@link #DST_ATOP Destination Atop}</figcaption>
+     *         </td>
+     *     </tr>
+     *     <tr>
+     *         <td style="border: none; text-align: center;">
+     *             <img src="{@docRoot}reference/android/images/graphics/composite_CLEAR.png" />
+     *             <figcaption>{@link #CLEAR Clear}</figcaption>
+     *         </td>
+     *         <td style="border: none; text-align: center;">
+     *             <img src="{@docRoot}reference/android/images/graphics/composite_SRC_OUT.png" />
+     *             <figcaption>{@link #SRC_OUT Source Out}</figcaption>
+     *         </td>
+     *         <td style="border: none; text-align: center;">
+     *             <img src="{@docRoot}reference/android/images/graphics/composite_DST_OUT.png" />
+     *             <figcaption>{@link #DST_OUT Destination Out}</figcaption>
+     *         </td>
+     *         <td style="border: none; text-align: center;">
+     *             <img src="{@docRoot}reference/android/images/graphics/composite_XOR.png" />
+     *             <figcaption>{@link #XOR Exclusive Or}</figcaption>
+     *         </td>
+     *     </tr>
+     * </table>
+     *
+     * <h3>Blending modes</h3>
+     *
+     * <table summary="Blending modes" style="background-color: transparent;">
+     *     <tr>
+     *         <td style="border: none; text-align: center;">
+     *             <img src="{@docRoot}reference/android/images/graphics/composite_DARKEN.png" />
+     *             <figcaption>{@link #DARKEN Darken}</figcaption>
+     *         </td>
+     *         <td style="border: none; text-align: center;">
+     *             <img src="{@docRoot}reference/android/images/graphics/composite_LIGHTEN.png" />
+     *             <figcaption>{@link #LIGHTEN Lighten}</figcaption>
+     *         </td>
+     *         <td style="border: none; text-align: center;">
+     *             <img src="{@docRoot}reference/android/images/graphics/composite_MULTIPLY.png" />
+     *             <figcaption>{@link #MULTIPLY Multiply}</figcaption>
+     *         </td>
+     *     </tr>
+     *     <tr>
+     *         <td style="border: none; text-align: center;">
+     *             <img src="{@docRoot}reference/android/images/graphics/composite_SCREEN.png" />
+     *             <figcaption>{@link #SCREEN Screen}</figcaption>
+     *         </td>
+     *         <td style="border: none; text-align: center;">
+     *             <img src="{@docRoot}reference/android/images/graphics/composite_OVERLAY.png" />
+     *             <figcaption>{@link #OVERLAY Overlay}</figcaption>
+     *         </td>
+     *     </tr>
+     * </table>
+     *
+     * <h3>Compositing equations</h3>
+     *
+     * <p>The documentation of each individual alpha compositing or blending mode below
+     * provides the exact equation used to compute alpha and color value of the result
+     * of the composition of a source and destination.</p>
+     *
+     * <p>The result (or output) alpha value is noted \(\alpha_{out}\). The result (or output)
+     * color value is noted \(C_{out}\).</p>
+     */
     public enum Mode {
-        /** [0, 0] */
+        // these value must match their native equivalents. See SkXfermode.h
+        /**
+         * <p>
+         *     <img src="{@docRoot}reference/android/images/graphics/composite_CLEAR.png" />
+         *     <figcaption>Destination pixels covered by the source are cleared to 0.</figcaption>
+         * </p>
+         * <p>\(\alpha_{out} = 0\)</p>
+         * <p>\(C_{out} = 0\)</p>
+         */
         CLEAR       (0),
-        /** [Sa, Sc] */
+        /**
+         * <p>
+         *     <img src="{@docRoot}reference/android/images/graphics/composite_SRC.png" />
+         *     <figcaption>The source pixels replace the destination pixels.</figcaption>
+         * </p>
+         * <p>\(\alpha_{out} = \alpha_{src}\)</p>
+         * <p>\(C_{out} = C_{src}\)</p>
+         */
         SRC         (1),
-        /** [Da, Dc] */
+        /**
+         * <p>
+         *     <img src="{@docRoot}reference/android/images/graphics/composite_DST.png" />
+         *     <figcaption>The source pixels are discarded, leaving the destination intact.</figcaption>
+         * </p>
+         * <p>\(\alpha_{out} = \alpha_{dst}\)</p>
+         * <p>\(C_{out} = C_{dst}\)</p>
+         */
         DST         (2),
-        /** [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] */
+        /**
+         * <p>
+         *     <img src="{@docRoot}reference/android/images/graphics/composite_SRC_OVER.png" />
+         *     <figcaption>The source pixels are drawn over the destination pixels.</figcaption>
+         * </p>
+         * <p>\(\alpha_{out} = \alpha_{src} + (1 - \alpha_{src}) * \alpha_{dst}\)</p>
+         * <p>\(C_{out} = C_{src} + (1 - \alpha_{src}) * C_{dst}\)</p>
+         */
         SRC_OVER    (3),
-        /** [Sa + (1 - Sa)*Da, Rc = Dc + (1 - Da)*Sc] */
+        /**
+         * <p>
+         *     <img src="{@docRoot}reference/android/images/graphics/composite_DST_OVER.png" />
+         *     <figcaption>The source pixels are drawn behind the destination pixels.</figcaption>
+         * </p>
+         * <p>\(\alpha_{out} = \alpha_{dst} + (1 - \alpha_{dst}) * \alpha_{src}\)</p>
+         * <p>\(C_{out} = C_{dst} + (1 - \alpha_{dst}) * C_{src}\)</p>
+         */
         DST_OVER    (4),
-        /** [Sa * Da, Sc * Da] */
+        /**
+         * <p>
+         *     <img src="{@docRoot}reference/android/images/graphics/composite_SRC_IN.png" />
+         *     <figcaption>Keeps the source pixels that cover the destination pixels,
+         *     discards the remaining source and destination pixels.</figcaption>
+         * </p>
+         * <p>\(\alpha_{out} = \alpha_{src} * \alpha_{dst}\)</p>
+         * <p>\(C_{out} = C_{src} * \alpha_{dst}\)</p>
+         */
         SRC_IN      (5),
-        /** [Sa * Da, Sa * Dc] */
+        /**
+         * <p>
+         *     <img src="{@docRoot}reference/android/images/graphics/composite_DST_IN.png" />
+         *     <figcaption>Keeps the destination pixels that cover source pixels,
+         *     discards the remaining source and destination pixels.</figcaption>
+         * </p>
+         * <p>\(\alpha_{out} = \alpha_{src} * \alpha_{dst}\)</p>
+         * <p>\(C_{out} = C_{dst} * \alpha_{src}\)</p>
+         */
         DST_IN      (6),
-        /** [Sa * (1 - Da), Sc * (1 - Da)] */
+        /**
+         * <p>
+         *     <img src="{@docRoot}reference/android/images/graphics/composite_SRC_OUT.png" />
+         *     <figcaption>Keeps the source pixels that do not cover destination pixels.
+         *     Discards source pixels that cover destination pixels. Discards all
+         *     destination pixels.</figcaption>
+         * </p>
+         * <p>\(\alpha_{out} = (1 - \alpha_{dst}) * \alpha_{src}\)</p>
+         * <p>\(C_{out} = (1 - \alpha_{dst}) * C_{src}\)</p>
+         */
         SRC_OUT     (7),
-        /** [Da * (1 - Sa), Dc * (1 - Sa)] */
+        /**
+         * <p>
+         *     <img src="{@docRoot}reference/android/images/graphics/composite_DST_OUT.png" />
+         *     <figcaption>Keeps the destination pixels that are not covered by source pixels.
+         *     Discards destination pixels that are covered by source pixels. Discards all
+         *     source pixels.</figcaption>
+         * </p>
+         * <p>\(\alpha_{out} = (1 - \alpha_{src}) * \alpha_{dst}\)</p>
+         * <p>\(C_{out} = (1 - \alpha_{src}) * C_{dst}\)</p>
+         */
         DST_OUT     (8),
-        /** [Da, Sc * Da + (1 - Sa) * Dc] */
+        /**
+         * <p>
+         *     <img src="{@docRoot}reference/android/images/graphics/composite_SRC_ATOP.png" />
+         *     <figcaption>Discards the source pixels that do not cover destination pixels.
+         *     Draws remaining source pixels over destination pixels.</figcaption>
+         * </p>
+         * <p>\(\alpha_{out} = \alpha_{dst}\)</p>
+         * <p>\(C_{out} = \alpha_{dst} * C_{src} + (1 - \alpha_{src}) * C_{dst}\)</p>
+         */
         SRC_ATOP    (9),
-        /** [Sa, Sa * Dc + Sc * (1 - Da)] */
+        /**
+         * <p>
+         *     <img src="{@docRoot}reference/android/images/graphics/composite_DST_ATOP.png" />
+         *     <figcaption>Discards the destination pixels that are not covered by source pixels.
+         *     Draws remaining destination pixels over source pixels.</figcaption>
+         * </p>
+         * <p>\(\alpha_{out} = \alpha_{src}\)</p>
+         * <p>\(C_{out} = \alpha_{src} * C_{dst} + (1 - \alpha_{dst}) * C_{src}\)</p>
+         */
         DST_ATOP    (10),
-        /** [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] */
+        /**
+         * <p>
+         *     <img src="{@docRoot}reference/android/images/graphics/composite_XOR.png" />
+         *     <figcaption>Discards the source and destination pixels where source pixels
+         *     cover destination pixels. Draws remaining source pixels.</figcaption>
+         * </p>
+         * <p>\(\alpha_{out} = (1 - \alpha_{dst}) * \alpha_{src} + (1 - \alpha_{src}) * \alpha_{dst}\)</p>
+         * <p>\(C_{out} = (1 - \alpha_{dst}) * C_{src} + (1 - \alpha_{src}) * C_{dst}\)</p>
+         */
         XOR         (11),
-        /** [Sa + Da - Sa*Da,
-             Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)] */
+        /**
+         * <p>
+         *     <img src="{@docRoot}reference/android/images/graphics/composite_DARKEN.png" />
+         *     <figcaption>Retains the smallest component of the source and
+         *     destination pixels.</figcaption>
+         * </p>
+         * <p>\(\alpha_{out} = \alpha_{src} + \alpha_{dst} - \alpha_{src} * \alpha_{dst}\)</p>
+         * <p>\(C_{out} = (1 - \alpha_{dst}) * C_{src} + (1 - \alpha_{src}) * C_{dst} + min(C_{src}, C_{dst})\)</p>
+         */
         DARKEN      (16),
-        /** [Sa + Da - Sa*Da,
-             Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)] */
+        /**
+         * <p>
+         *     <img src="{@docRoot}reference/android/images/graphics/composite_LIGHTEN.png" />
+         *     <figcaption>Retains the largest component of the source and
+         *     destination pixel.</figcaption>
+         * </p>
+         * <p>\(\alpha_{out} = \alpha_{src} + \alpha_{dst} - \alpha_{src} * \alpha_{dst}\)</p>
+         * <p>\(C_{out} = (1 - \alpha_{dst}) * C_{src} + (1 - \alpha_{src}) * C_{dst} + max(C_{src}, C_{dst})\)</p>
+         */
         LIGHTEN     (17),
-        /** [Sa * Da, Sc * Dc] */
+        /**
+         * <p>
+         *     <img src="{@docRoot}reference/android/images/graphics/composite_MULTIPLY.png" />
+         *     <figcaption>Multiplies the source and destination pixels.</figcaption>
+         * </p>
+         * <p>\(\alpha_{out} = \alpha_{src} * \alpha_{dst}\)</p>
+         * <p>\(C_{out} = C_{src} * C_{dst}\)</p>
+         */
         MULTIPLY    (13),
-        /** [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] */
+        /**
+         * <p>
+         *     <img src="{@docRoot}reference/android/images/graphics/composite_SCREEN.png" />
+         *     <figcaption>Adds the source and destination pixels, then subtracts the
+         *     source pixels multiplied by the destination.</figcaption>
+         * </p>
+         * <p>\(\alpha_{out} = \alpha_{src} + \alpha_{dst} - \alpha_{src} * \alpha_{dst}\)</p>
+         * <p>\(C_{out} = C_{src} + C_{dst} - C_{src} * C_{dst}\)</p>
+         */
         SCREEN      (14),
-        /** Saturate(S + D) */
+        /**
+         * <p>
+         *     <img src="{@docRoot}reference/android/images/graphics/composite_ADD.png" />
+         *     <figcaption>Adds the source pixels to the destination pixels and saturates
+         *     the result.</figcaption>
+         * </p>
+         * <p>\(\alpha_{out} = max(0, min(\alpha_{src} + \alpha_{dst}, 1))\)</p>
+         * <p>\(C_{out} = max(0, min(C_{src} + C_{dst}, 1))\)</p>
+         */
         ADD         (12),
+        /**
+         * <p>
+         *     <img src="{@docRoot}reference/android/images/graphics/composite_OVERLAY.png" />
+         *     <figcaption>Multiplies or screens the source and destination depending on the
+         *     destination color.</figcaption>
+         * </p>
+         * <p>\(\alpha_{out} = \alpha_{src} + \alpha_{dst} - \alpha_{src} * \alpha_{dst}\)</p>
+         * <p>\(\begin{equation}
+         * C_{out} = \begin{cases} 2 * C_{src} * C_{dst} & 2 * C_{dst} \lt \alpha_{dst} \\
+         * \alpha_{src} * \alpha_{dst} - 2 (\alpha_{dst} - C_{src}) (\alpha_{src} - C_{dst}) & otherwise \end{cases}
+         * \end{equation}\)</p>
+         */
         OVERLAY     (15);
 
         Mode(int nativeInt) {
@@ -71,14 +370,14 @@
     /**
      * @hide
      */
-    public static final int modeToInt(Mode mode) {
+    public static int modeToInt(Mode mode) {
         return mode.nativeInt;
     }
 
     /**
      * @hide
      */
-    public static final Mode intToMode(int val) {
+    public static Mode intToMode(int val) {
         switch (val) {
             default:
             case  0: return Mode.CLEAR;
diff --git a/graphics/java/android/graphics/PorterDuffXfermode.java b/graphics/java/android/graphics/PorterDuffXfermode.java
index 5104410..84d953d 100644
--- a/graphics/java/android/graphics/PorterDuffXfermode.java
+++ b/graphics/java/android/graphics/PorterDuffXfermode.java
@@ -16,6 +16,12 @@
 
 package android.graphics;
 
+/**
+ * <p>Specialized implementation of {@link Paint}'s
+ * {@link Paint#setXfermode(Xfermode) transfer mode}. Refer to the
+ * documentation of the {@link PorterDuff.Mode} enum for more
+ * information on the available alpha compositing and blending modes.</p>
+ */
 public class PorterDuffXfermode extends Xfermode {
     /**
      * Create an xfermode that uses the specified porter-duff mode.
diff --git a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
index c6c9271..643c0da 100644
--- a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
+++ b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
@@ -304,6 +304,9 @@
 
     @Override
     public void draw(Canvas canvas) {
+        if (mLayersBitmap == null) {
+            return;
+        }
         if (mLayersShader == null) {
             mCanvas.setBitmap(mLayersBitmap);
             for (int i = 0; i < mLayerState.N_CHILDREN; i++) {
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index 9739319..06fc4bc 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -1802,8 +1802,9 @@
          * {@link #TYPE_OTHER},
          * {@link #TYPE_PAL},
          * {@link #TYPE_SECAM},
-         * {@link #TYPE_S_DMB}, and
-         * {@link #TYPE_T_DMB}.
+         * {@link #TYPE_S_DMB},
+         * {@link #TYPE_T_DMB}, and
+         * {@link #TYPE_PREVIEW}.
          *
          * <p>This value cannot be changed once it's set. Trying to modify it will make the update
          * fail.
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index cc1e01a..37a68e0 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -220,14 +220,8 @@
         public long[] getFileSystemStats(String path) {
             Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
 
-            try {
-                final StructStatVfs stat = Os.statvfs(path);
-                final long totalSize = stat.f_blocks * stat.f_bsize;
-                final long availSize = stat.f_bavail * stat.f_bsize;
-                return new long[] { totalSize, availSize };
-            } catch (ErrnoException e) {
-                throw new IllegalStateException(e);
-            }
+            final File file = new File(path);
+            return new long[] { file.getTotalSpace(), file.getUsableSpace() };
         }
 
         @Override
diff --git a/packages/ExtServices/src/android/ext/services/storage/CacheQuotaServiceImpl.java b/packages/ExtServices/src/android/ext/services/storage/CacheQuotaServiceImpl.java
index 18863ca..862f50b2 100644
--- a/packages/ExtServices/src/android/ext/services/storage/CacheQuotaServiceImpl.java
+++ b/packages/ExtServices/src/android/ext/services/storage/CacheQuotaServiceImpl.java
@@ -1,4 +1,3 @@
-
 /*
  * Copyright (C) 2017 The Android Open Source Project
  *
@@ -123,10 +122,10 @@
         StorageManager storageManager = getSystemService(StorageManager.class);
         long freeBytes = 0;
         if (uuid == StorageManager.UUID_PRIVATE_INTERNAL) { // regular equals because of null
-            freeBytes = Environment.getDataDirectory().getFreeSpace();
+            freeBytes = Environment.getDataDirectory().getUsableSpace();
         } else {
             final VolumeInfo vol = storageManager.findVolumeByUuid(uuid);
-            freeBytes = vol.getPath().getFreeSpace();
+            freeBytes = vol.getPath().getUsableSpace();
         }
         return Math.round(freeBytes * CACHE_RESERVE_RATIO);
     }
diff --git a/packages/ExtServices/tests/src/android/ext/services/storage/CacheQuotaServiceImplTest.java b/packages/ExtServices/tests/src/android/ext/services/storage/CacheQuotaServiceImplTest.java
index cc1699a..df4738f 100644
--- a/packages/ExtServices/tests/src/android/ext/services/storage/CacheQuotaServiceImplTest.java
+++ b/packages/ExtServices/tests/src/android/ext/services/storage/CacheQuotaServiceImplTest.java
@@ -61,7 +61,7 @@
         setContext(mContext);
         when(mContext.getSystemService(Context.STORAGE_SERVICE)).thenReturn(mStorageManager);
 
-        when(mFile.getFreeSpace()).thenReturn(10000L);
+        when(mFile.getUsableSpace()).thenReturn(10000L);
         when(mVolume.getPath()).thenReturn(mFile);
         when(mStorageManager.findVolumeByUuid(sTestVolUuid)).thenReturn(mVolume);
         when(mStorageManager.findVolumeByUuid(sSecondTestVolUuid)).thenReturn(mVolume);
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index b60e2fe..b958c28 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -386,7 +386,7 @@
                 row.add(Root.COLUMN_TITLE, root.title);
                 row.add(Root.COLUMN_DOCUMENT_ID, root.docId);
                 row.add(Root.COLUMN_AVAILABLE_BYTES,
-                        root.reportAvailableBytes ? root.path.getFreeSpace() : -1);
+                        root.reportAvailableBytes ? root.path.getUsableSpace() : -1);
             }
         }
         return result;
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java
index ca8edf5..40abb6c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java
@@ -16,18 +16,15 @@
 
 package com.android.settingslib.deviceinfo;
 
-import android.os.storage.StorageManager;
+import android.app.AppGlobals;
+import android.app.usage.StorageStatsManager;
+import android.content.Context;
 import android.os.storage.VolumeInfo;
-import android.util.Log;
-
-import java.io.File;
-import java.util.Objects;
 
 /**
  * PrivateStorageInfo provides information about the total and free storage on the device.
  */
 public class PrivateStorageInfo {
-    private static final String TAG = "PrivateStorageInfo";
     public final long freeBytes;
     public final long totalBytes;
 
@@ -37,45 +34,23 @@
     }
 
     public static PrivateStorageInfo getPrivateStorageInfo(StorageVolumeProvider sm) {
-        long totalInternalStorage = sm.getPrimaryStorageSize();
+        final Context context = AppGlobals.getInitialApplication();
+        final StorageStatsManager stats = context.getSystemService(StorageStatsManager.class);
+
         long privateFreeBytes = 0;
         long privateTotalBytes = 0;
         for (VolumeInfo info : sm.getVolumes()) {
-            final File path = info.getPath();
-            if (info.getType() != VolumeInfo.TYPE_PRIVATE || path == null) {
-                continue;
+            if (info.getType() == VolumeInfo.TYPE_PRIVATE && info.isMountedReadable()) {
+                privateTotalBytes += stats.getTotalBytes(info.getFsUuid());
+                privateFreeBytes += stats.getFreeBytes(info.getFsUuid());
             }
-            privateTotalBytes += getTotalSize(info, totalInternalStorage);
-            privateFreeBytes += path.getFreeSpace();
         }
         return new PrivateStorageInfo(privateFreeBytes, privateTotalBytes);
     }
 
-    /**
-     * Returns the total size in bytes for a given volume info.
-     * @param info Info of the volume to check.
-     * @param totalInternalStorage Total number of bytes in the internal storage to use if the
-     *                             volume is the internal disk.
-     */
     public static long getTotalSize(VolumeInfo info, long totalInternalStorage) {
-        // Device could have more than one primary storage, which could be located in the
-        // internal flash (UUID_PRIVATE_INTERNAL) or in an external disk.
-        // If it's internal, try to get its total size from StorageManager first
-        // (totalInternalStorage), because that size is more precise because it accounts for
-        // the system partition.
-        if (info.getType() == VolumeInfo.TYPE_PRIVATE
-                && Objects.equals(info.getFsUuid(), StorageManager.UUID_PRIVATE_INTERNAL)
-                && totalInternalStorage > 0) {
-            return totalInternalStorage;
-        } else {
-            final File path = info.getPath();
-            if (path == null) {
-                // Should not happen, caller should have checked.
-                Log.e(TAG, "info's path is null on getTotalSize(): " + info);
-                return 0;
-            }
-            return path.getTotalSpace();
-        }
+        final Context context = AppGlobals.getInitialApplication();
+        final StorageStatsManager stats = context.getSystemService(StorageStatsManager.class);
+        return stats.getTotalBytes(info.getFsUuid());
     }
-
 }
diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk
index 635c96f..53c5b1b 100644
--- a/packages/SystemUI/Android.mk
+++ b/packages/SystemUI/Android.mk
@@ -34,6 +34,7 @@
     android-support-v7-recyclerview \
     android-support-v7-preference \
     android-support-v7-appcompat \
+    android-support-v7-mediarouter \
     android-support-v14-preference \
     android-support-v17-leanback
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 22b6a63..2725a32 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -20,22 +20,29 @@
 import android.content.Intent;
 import android.provider.Settings;
 import android.service.quicksettings.Tile;
+import android.support.v7.app.MediaRouteChooserDialog;
+import android.support.v7.app.MediaRouteControllerDialog;
+import android.support.v7.media.MediaControlIntent;
+import android.support.v7.media.MediaRouteSelector;
 import android.util.Log;
+import android.view.ContextThemeWrapper;
 import android.view.View;
 import android.view.View.OnAttachStateChangeListener;
 import android.view.ViewGroup;
+import android.view.WindowManager;
 import android.widget.Button;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
+import com.android.systemui.R.style;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.qs.DetailAdapter;
+import com.android.systemui.plugins.qs.QSTile.BooleanState;
 import com.android.systemui.qs.QSDetailItems;
 import com.android.systemui.qs.QSDetailItems.Item;
 import com.android.systemui.qs.QSHost;
-import com.android.systemui.plugins.qs.QSTile.BooleanState;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.statusbar.policy.CastController;
 import com.android.systemui.statusbar.policy.CastController.CastDevice;
@@ -109,7 +116,6 @@
         if (mKeyguard.isSecure() && !mKeyguard.canSkipBouncer()) {
             mActivityStarter.postQSRunnableDismissingKeyguard(() -> {
                 showDetail(true);
-                mHost.openPanels();
             });
             return;
         }
@@ -117,6 +123,29 @@
     }
 
     @Override
+    public void showDetail(boolean show) {
+        mUiHandler.post(() -> {
+            Context context = new ContextThemeWrapper(mContext,
+                    R.style.Theme_AppCompat_Light_Dialog_Alert);
+            if (mState.value) {
+                MediaRouteControllerDialog dialog = new MediaRouteControllerDialog(context);
+                dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL);
+                dialog.show();
+            } else {
+                // Instead of showing detail, show standard media routing UI.
+                MediaRouteChooserDialog dialog = new MediaRouteChooserDialog(context);
+                MediaRouteSelector selector = new MediaRouteSelector.Builder()
+                        .addControlCategory(MediaControlIntent.CATEGORY_LIVE_VIDEO)
+                        .build();
+                dialog.setRouteSelector(selector);
+                dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL);
+                dialog.show();
+            }
+            mHost.collapsePanels();
+        });
+    }
+
+    @Override
     public CharSequence getTileLabel() {
         return mContext.getString(R.string.quick_settings_cast_title);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
index 4eb1db6..9c69b98 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
@@ -110,10 +110,35 @@
     }
 
     public static class SubSettingsFragment extends PreferenceFragment {
+        private PreferenceScreen mParentScreen;
+
         @Override
         public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
-            setPreferenceScreen((PreferenceScreen) ((PreferenceFragment) getTargetFragment())
-                    .getPreferenceScreen().findPreference(rootKey));
+            mParentScreen =
+                    (PreferenceScreen) ((PreferenceFragment) getTargetFragment())
+                            .getPreferenceScreen().findPreference(rootKey);
+            PreferenceScreen screen =
+                    getPreferenceManager().createPreferenceScreen(
+                            getPreferenceManager().getContext());
+            setPreferenceScreen(screen);
+            // Copy all the preferences over to this screen so they go into the attached state.
+            while (mParentScreen.getPreferenceCount() > 0) {
+                Preference p = mParentScreen.getPreference(0);
+                mParentScreen.removePreference(p);
+                screen.addPreference(p);
+            }
+        }
+
+        @Override
+        public void onDestroy() {
+            super.onDestroy();
+            // Copy all the preferences back so we don't lose them.
+            PreferenceScreen screen = getPreferenceScreen();
+            while (screen.getPreferenceCount() > 0) {
+                Preference p = screen.getPreference(0);
+                screen.removePreference(p);
+                mParentScreen.addPreference(p);
+            }
         }
     }
 
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index ddd8d7b..8eedf31 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -41,6 +41,7 @@
     android-support-v7-recyclerview \
     android-support-v7-preference \
     android-support-v7-appcompat \
+    android-support-v7-mediarouter \
     android-support-v14-preference \
     android-support-v17-leanback
 
diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto
index 97099df..f6d91f4 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -153,10 +153,34 @@
     // Package: android
     NOTE_SSL_CERT_INFO = 33;
 
+    // Warn the user they are approaching their data limit.
+    // Package: android
+    NOTE_NET_WARNING = 34;
+
+    // Warn the user they have reached their data limit.
+    // Package: android
+    NOTE_NET_LIMIT = 35;
+
+    // Warn the user they have exceeded their data limit.
+    // Package: android
+    NOTE_NET_LIMIT_SNOOZED = 36;
+
     // ADD_NEW_IDS_ABOVE_THIS_LINE
     // Legacy IDs with arbitrary values appear below
     // Legacy IDs existed as stable non-conflicting constants prior to the O release
 
+    // Network status notes, previously decleared in metrics_constants with these values
+    // Package: android
+    //
+    // A captive portal was detected during network validation
+    NOTE_NETWORK_SIGN_IN = 740;
+    // An unvalidated network without Internet was selected by the user
+    NOTE_NETWORK_NO_INTERNET = 741;
+    // A validated network failed revalidation and lost Internet access
+    NOTE_NETWORK_LOST_INTERNET = 742;
+    // The system default network switched to a different network
+    NOTE_NETWORK_SWITCH = 743;
+
     // Notify the user that their work profile has been deleted
     // Package: android
     NOTE_PROFILE_WIPED = 1001;
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index acaae7b..087c248 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -104,6 +104,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.os.SomeArgs;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IntPair;
 import com.android.server.LocalServices;
 import com.android.server.policy.AccessibilityShortcutController;
@@ -2360,7 +2361,7 @@
 
     @Override
     public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
-        mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP);
+        if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
         synchronized (mLock) {
             pw.println("ACCESSIBILITY MANAGER (dumpsys accessibility)");
             pw.println();
@@ -3658,7 +3659,7 @@
 
         @Override
         public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
-            mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP);
+            if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
             synchronized (mLock) {
                 pw.append("Service[label=" + mAccessibilityServiceInfo.getResolveInfo()
                         .loadLabel(mContext.getPackageManager()));
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 8aa37ef..0482e73 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -97,6 +97,7 @@
 import com.android.internal.appwidget.IAppWidgetService;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.os.SomeArgs;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.widget.IRemoteViewsAdapterConnection;
 import com.android.internal.widget.IRemoteViewsFactory;
@@ -714,10 +715,7 @@
 
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP,
-                                                "Permission Denial: can't dump from from pid="
-                                                + Binder.getCallingPid()
-                                                + ", uid=" + Binder.getCallingUid());
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
         synchronized (mLock) {
             if (args.length > 0 && "--proto".equals(args[0])) {
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 72d37ad..be14440 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -60,6 +60,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.os.IResultReceiver;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.Preconditions;
 import com.android.server.FgThread;
 import com.android.server.LocalServices;
@@ -418,13 +419,7 @@
 
         @Override
         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            if (mContext.checkCallingPermission(
-                    Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) {
-                pw.println("Permission Denial: can't dump autofill from from pid="
-                        + Binder.getCallingPid()
-                        + ", uid=" + Binder.getCallingUid());
-                return;
-            }
+            if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
             synchronized (mLock) {
                 pw.print("Disabled users: "); pw.println(mDisabledUsers);
                 final int size = mServicesCache.size();
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 57d3570..413746f 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -117,6 +117,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.backup.IBackupTransport;
 import com.android.internal.backup.IObbBackupService;
+import com.android.internal.util.DumpUtils;
 import com.android.server.AppWidgetBackupBridge;
 import com.android.server.EventLogTags;
 import com.android.server.SystemConfig;
@@ -11138,7 +11139,7 @@
     }
 
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+        if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
 
         long identityToken = Binder.clearCallingIdentity();
         try {
diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java
index c40f2ca..a109e631 100644
--- a/services/backup/java/com/android/server/backup/Trampoline.java
+++ b/services/backup/java/com/android/server/backup/Trampoline.java
@@ -35,6 +35,8 @@
 import android.os.UserHandle;
 import android.util.Slog;
 
+import com.android.internal.util.DumpUtils;
+
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.IOException;
@@ -372,7 +374,7 @@
 
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
         BackupManagerService svc = mService;
         if (svc != null) {
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index c6af290..8b32c16 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -80,6 +80,7 @@
 import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP;
 import static android.app.AlarmManager.ELAPSED_REALTIME;
 
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.LocalLog;
 
 class AlarmManagerService extends SystemService {
@@ -1384,14 +1385,7 @@
 
         @Override
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                    != PackageManager.PERMISSION_GRANTED) {
-                pw.println("Permission Denial: can't dump AlarmManager from from pid="
-                        + Binder.getCallingPid()
-                        + ", uid=" + Binder.getCallingUid());
-                return;
-            }
-
+            if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return;
             dumpImpl(pw);
         }
     };
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index a5e357c..dcf6fd7 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -70,6 +70,7 @@
 import com.android.internal.app.IAppOpsCallback;
 import com.android.internal.os.Zygote;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.XmlUtils;
@@ -2028,13 +2029,7 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-            pw.println("Permission Denial: can't dump ApOps service from from pid="
-                    + Binder.getCallingPid()
-                    + ", uid=" + Binder.getCallingUid());
-            return;
-        }
+        if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
 
         if (args != null) {
             for (int i=0; i<args.length; i++) {
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index fd44794..83bd9eb 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -24,6 +24,7 @@
 import android.os.ShellCallback;
 import android.os.ShellCommand;
 import com.android.internal.app.IBatteryStats;
+import com.android.internal.util.DumpUtils;
 import com.android.server.am.BatteryStatsService;
 import com.android.server.lights.Light;
 import com.android.server.lights.LightsManager;
@@ -945,14 +946,7 @@
 
     private final class BinderService extends Binder {
         @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                    != PackageManager.PERMISSION_GRANTED) {
-
-                pw.println("Permission Denial: can't dump Battery service from from pid="
-                        + Binder.getCallingPid()
-                        + ", uid=" + Binder.getCallingUid());
-                return;
-            }
+            if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
             if (args.length > 0 && "--proto".equals(args[0])) {
                 dumpProto(fd);
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 58e8631..6c4895c 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -60,6 +60,7 @@
 import android.provider.Settings.SettingNotFoundException;
 import android.util.Slog;
 
+import com.android.internal.util.DumpUtils;
 import com.android.server.pm.PackageManagerService;
 
 import java.io.FileDescriptor;
@@ -2084,7 +2085,7 @@
 
     @Override
     public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
         String errorMsg = null;
 
         boolean protoOut = (args.length > 0) && args[0].startsWith("--proto");
diff --git a/services/core/java/com/android/server/CommonTimeManagementService.java b/services/core/java/com/android/server/CommonTimeManagementService.java
index 60b366a..07c8679 100644
--- a/services/core/java/com/android/server/CommonTimeManagementService.java
+++ b/services/core/java/com/android/server/CommonTimeManagementService.java
@@ -37,6 +37,7 @@
 import android.os.SystemProperties;
 import android.util.Log;
 
+import com.android.internal.util.DumpUtils;
 import com.android.server.net.BaseNetworkObserver;
 
 /**
@@ -177,13 +178,7 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-            pw.println(String.format(
-                        "Permission Denial: can't dump CommonTimeManagement service from from " +
-                        "pid=%d, uid=%d", Binder.getCallingPid(), Binder.getCallingUid()));
-            return;
-        }
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
         if (!mDetectedAtStartup) {
             pw.println("Native Common Time service was not detected at startup.  " +
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index d02b726..0e752ff 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -125,6 +125,7 @@
 import com.android.internal.net.VpnInfo;
 import com.android.internal.net.VpnProfile;
 import com.android.internal.util.AsyncChannel;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.MessageUtils;
 import com.android.internal.util.WakeupMessage;
@@ -1927,14 +1928,7 @@
     @Override
     protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
         final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
-        if (mContext.checkCallingOrSelfPermission(
-                android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-            pw.println("Permission Denial: can't dump ConnectivityService " +
-                    "from from pid=" + Binder.getCallingPid() + ", uid=" +
-                    Binder.getCallingUid());
-            return;
-        }
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
         if (argsContain(args, "--diag")) {
             dumpNetworkDiagnostics(pw);
diff --git a/services/core/java/com/android/server/CountryDetectorService.java b/services/core/java/com/android/server/CountryDetectorService.java
index a478b2f..d8a2fe3 100644
--- a/services/core/java/com/android/server/CountryDetectorService.java
+++ b/services/core/java/com/android/server/CountryDetectorService.java
@@ -21,6 +21,7 @@
 import java.util.HashMap;
 
 import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.DumpUtils;
 import com.android.server.location.ComprehensiveCountryDetector;
 
 import android.content.Context;
@@ -208,8 +209,7 @@
     @SuppressWarnings("unused")
     @Override
     protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
-
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, fout)) return;
         if (!DEBUG) return;
         try {
             final Printer p = new PrintWriterPrinter(fout);
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 26b15d8..8945952 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -81,6 +81,7 @@
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.os.AtomicFile;
 import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.XmlUtils;
 import com.android.server.am.BatteryStatsService;
@@ -2879,13 +2880,7 @@
     }
 
     void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-            pw.println("Permission Denial: can't dump DeviceIdleController from from pid="
-                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
-                    + " without permission " + android.Manifest.permission.DUMP);
-            return;
-        }
+        if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
 
         if (args != null) {
             int userId = UserHandle.USER_SYSTEM;
diff --git a/services/core/java/com/android/server/DiskStatsService.java b/services/core/java/com/android/server/DiskStatsService.java
index 1bdff6b..800081e 100644
--- a/services/core/java/com/android/server/DiskStatsService.java
+++ b/services/core/java/com/android/server/DiskStatsService.java
@@ -30,6 +30,7 @@
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 
+import com.android.internal.util.DumpUtils;
 import com.android.server.storage.DiskStatsFileLogger;
 import com.android.server.storage.DiskStatsLoggingService;
 
@@ -62,7 +63,7 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+        if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
 
         // Run a quick-and-dirty performance test: write 512 bytes
         byte[] junk = new byte[512];
diff --git a/services/core/java/com/android/server/DockObserver.java b/services/core/java/com/android/server/DockObserver.java
index 122074b..e5a7b4e 100644
--- a/services/core/java/com/android/server/DockObserver.java
+++ b/services/core/java/com/android/server/DockObserver.java
@@ -35,6 +35,8 @@
 import android.util.Log;
 import android.util.Slog;
 
+import com.android.internal.util.DumpUtils;
+
 import java.io.FileDescriptor;
 import java.io.FileNotFoundException;
 import java.io.FileReader;
@@ -252,14 +254,7 @@
     private final class BinderService extends Binder {
         @Override
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                    != PackageManager.PERMISSION_GRANTED) {
-                pw.println("Permission Denial: can't dump dock observer service from from pid="
-                        + Binder.getCallingPid()
-                        + ", uid=" + Binder.getCallingUid());
-                return;
-            }
-
+            if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
             final long ident = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
diff --git a/services/core/java/com/android/server/DropBoxManagerService.java b/services/core/java/com/android/server/DropBoxManagerService.java
index 040d22c..9d3d531 100644
--- a/services/core/java/com/android/server/DropBoxManagerService.java
+++ b/services/core/java/com/android/server/DropBoxManagerService.java
@@ -40,6 +40,7 @@
 import libcore.io.IoUtils;
 
 import com.android.internal.os.IDropBoxManagerService;
+import com.android.internal.util.DumpUtils;
 
 import java.io.BufferedOutputStream;
 import java.io.File;
@@ -350,11 +351,7 @@
     }
 
     public synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-            pw.println("Permission Denial: Can't dump DropBoxManagerService");
-            return;
-        }
+        if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return;
 
         try {
             init();
diff --git a/services/core/java/com/android/server/GraphicsStatsService.java b/services/core/java/com/android/server/GraphicsStatsService.java
index 19bedfb..d3f77b6 100644
--- a/services/core/java/com/android/server/GraphicsStatsService.java
+++ b/services/core/java/com/android/server/GraphicsStatsService.java
@@ -37,6 +37,8 @@
 import android.view.IGraphicsStats;
 import android.view.IGraphicsStatsCallback;
 
+import com.android.internal.util.DumpUtils;
+
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.IOException;
@@ -345,7 +347,7 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+        if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, fout)) return;
         boolean dumpProto = false;
         for (String str : args) {
             if ("--proto".equals(str)) {
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index e619e8bf..39bfeda 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -33,6 +33,7 @@
 import com.android.internal.os.HandlerCaller;
 import com.android.internal.os.SomeArgs;
 import com.android.internal.os.TransferPipe;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.view.IInputContext;
 import com.android.internal.view.IInputMethod;
@@ -4378,14 +4379,7 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-
-            pw.println("Permission Denial: can't dump InputMethodManager from from pid="
-                    + Binder.getCallingPid()
-                    + ", uid=" + Binder.getCallingUid());
-            return;
-        }
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
         IInputMethod method;
         ClientState client;
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 979096e..f0720f3 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -26,6 +26,7 @@
 import com.android.internal.location.ProviderRequest;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.DumpUtils;
 import com.android.server.location.ActivityRecognitionProxy;
 import com.android.server.location.FlpHardwareProvider;
 import com.android.server.location.FusedProxy;
@@ -3026,13 +3027,7 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-            pw.println("Permission Denial: can't dump LocationManagerService from from pid="
-                    + Binder.getCallingPid()
-                    + ", uid=" + Binder.getCallingUid());
-            return;
-        }
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
         synchronized (mLock) {
             pw.println("Current Location Manager state:");
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 6f3ff10..e26630b 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -79,6 +79,7 @@
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.widget.ICheckCredentialProgressCallback;
 import com.android.internal.widget.ILockSettings;
 import com.android.internal.widget.LockPatternUtils;
@@ -2178,14 +2179,7 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args){
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-
-            pw.println("Permission Denial: can't dump LockSettingsService from from pid="
-                    + Binder.getCallingPid()
-                    + ", uid=" + Binder.getCallingUid());
-            return;
-        }
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
         synchronized (this) {
             pw.println("Current lock settings service state:");
diff --git a/services/core/java/com/android/server/LockSettingsShellCommand.java b/services/core/java/com/android/server/LockSettingsShellCommand.java
index 91bd98e..9d671e39 100644
--- a/services/core/java/com/android/server/LockSettingsShellCommand.java
+++ b/services/core/java/com/android/server/LockSettingsShellCommand.java
@@ -35,6 +35,7 @@
     private static final String COMMAND_SET_PASSWORD = "set-password";
     private static final String COMMAND_CLEAR = "clear";
     private static final String COMMAND_SP = "sp";
+    private static final String COMMAND_SET_DISABLED = "set-disabled";
 
     private int mCurrentUserId;
     private final LockPatternUtils mLockPatternUtils;
@@ -72,6 +73,9 @@
                 case COMMAND_SP:
                     runEnableSp();
                     break;
+                case COMMAND_SET_DISABLED:
+                    runSetDisabled();
+                    break;
                 default:
                     getErrPrintWriter().println("Unknown command: " + cmd);
                     break;
@@ -132,6 +136,12 @@
         getOutPrintWriter().println("Lock credential cleared");
     }
 
+    private void runSetDisabled() throws RemoteException {
+        final boolean disabled = Boolean.parseBoolean(mNew);
+        mLockPatternUtils.setLockScreenDisabled(disabled, mCurrentUserId);
+        getOutPrintWriter().println("Lock screen disabled set to " + disabled);
+    }
+
     private boolean checkCredential() throws RemoteException, RequestThrottledException {
         final boolean havePassword = mLockPatternUtils.isLockPasswordEnabled(mCurrentUserId);
         final boolean havePattern = mLockPatternUtils.isLockPatternEnabled(mCurrentUserId);
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 74328c0..ce4efd1 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -95,6 +95,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.net.NetworkStatsFactory;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.HexDump;
 import com.android.internal.util.Preconditions;
 import com.android.server.NativeDaemonConnector.Command;
@@ -2313,7 +2314,7 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        mContext.enforceCallingOrSelfPermission(DUMP, TAG);
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
         pw.println("NetworkManagementService NativeDaemonConnector Log:");
         mConnector.dump(fd, pw, args);
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index 78c0fe6..a5debda 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -69,6 +69,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.os.TransferPipe;
+import com.android.internal.util.DumpUtils;
 
 import java.io.FileDescriptor;
 import java.io.IOException;
@@ -925,7 +926,7 @@
 
     @Override
     protected void dump(final FileDescriptor fd, final PrintWriter writer, final String[] args) {
-        mContext.enforceCallingOrSelfPermission(permission.DUMP, TAG);
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
         final long token = Binder.clearCallingIdentity();
         try {
             NetworkScorerAppData currentScorer = mNetworkScorerAppManager.getActiveScorer();
diff --git a/services/core/java/com/android/server/NetworkTimeUpdateService.java b/services/core/java/com/android/server/NetworkTimeUpdateService.java
index b64c65d..ebcda44 100644
--- a/services/core/java/com/android/server/NetworkTimeUpdateService.java
+++ b/services/core/java/com/android/server/NetworkTimeUpdateService.java
@@ -40,6 +40,7 @@
 import android.util.TrustedTime;
 
 import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.util.DumpUtils;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -323,15 +324,7 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-            pw.println("Permission Denial: can't dump NetworkTimeUpdateService from from pid="
-                    + Binder.getCallingPid()
-                    + ", uid=" + Binder.getCallingUid()
-                    + " without permission "
-                    + android.Manifest.permission.DUMP);
-            return;
-        }
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
         pw.print("PollingIntervalMs: ");
         TimeUtils.formatDuration(mPollingIntervalMs, pw);
         pw.print("\nPollingIntervalShorterMs: ");
diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java
index a44b065..8ae95d5 100644
--- a/services/core/java/com/android/server/NsdService.java
+++ b/services/core/java/com/android/server/NsdService.java
@@ -41,6 +41,7 @@
 import java.util.concurrent.CountDownLatch;
 
 import com.android.internal.util.AsyncChannel;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.Protocol;
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
@@ -811,13 +812,7 @@
 
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-            pw.println("Permission Denial: can't dump ServiceDiscoverService from from pid="
-                    + Binder.getCallingPid()
-                    + ", uid=" + Binder.getCallingUid());
-            return;
-        }
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
         for (ClientInfo client : mClients.values()) {
             pw.println("Client Info");
diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java
index fa5a52c..a94bf79 100644
--- a/services/core/java/com/android/server/PinnerService.java
+++ b/services/core/java/com/android/server/PinnerService.java
@@ -37,6 +37,7 @@
 
 import com.android.internal.app.ResolverActivity;
 import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.DumpUtils;
 
 import dalvik.system.DexFile;
 import dalvik.system.VMRuntime;
@@ -333,7 +334,7 @@
     private final class BinderService extends Binder {
         @Override
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+            if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
             pw.println("Pinned Files:");
             synchronized(this) {
                 for (int i = 0; i < mPinnedFiles.size(); i++) {
diff --git a/services/core/java/com/android/server/RescueParty.java b/services/core/java/com/android/server/RescueParty.java
index cecd7e5..3b36c3c 100644
--- a/services/core/java/com/android/server/RescueParty.java
+++ b/services/core/java/com/android/server/RescueParty.java
@@ -18,14 +18,13 @@
 
 import android.content.ContentResolver;
 import android.content.Context;
-import android.content.pm.UserInfo;
 import android.os.Build;
+import android.os.Environment;
 import android.os.FileUtils;
 import android.os.RecoverySystem;
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.UserHandle;
-import android.os.UserManager;
 import android.provider.Settings;
 import android.text.format.DateUtils;
 import android.util.ExceptionUtils;
@@ -70,7 +69,7 @@
 
     private static boolean isDisabled() {
         // Check if we're explicitly enabled for testing
-        if (SystemProperties.getBoolean(PROP_ENABLE_RESCUE, true)) {
+        if (SystemProperties.getBoolean(PROP_ENABLE_RESCUE, false)) {
             return false;
         }
 
@@ -203,7 +202,7 @@
         } catch (Throwable t) {
             res = new RuntimeException("Failed to reset global settings", t);
         }
-        for (int userId : getAllUserIds(context)) {
+        for (int userId : getAllUserIds()) {
             try {
                 Settings.Secure.resetToDefaultsAsUser(resolver, null, mode, userId);
             } catch (Throwable t) {
@@ -314,13 +313,16 @@
         @Override public void setStart(long start) { this.start = start; }
     }
 
-    private static int[] getAllUserIds(Context context) {
+    private static int[] getAllUserIds() {
         int[] userIds = { UserHandle.USER_SYSTEM };
         try {
-            final UserManager um = context.getSystemService(UserManager.class);
-            for (UserInfo user : um.getUsers()) {
-                if (user.id != UserHandle.USER_SYSTEM) {
-                    userIds = ArrayUtils.appendInt(userIds, user.id);
+            for (File file : FileUtils.listFilesOrEmpty(Environment.getDataSystemDeDirectory())) {
+                try {
+                    final int userId = Integer.parseInt(file.getName());
+                    if (userId != UserHandle.USER_SYSTEM) {
+                        userIds = ArrayUtils.appendInt(userIds, userId);
+                    }
+                } catch (NumberFormatException ignored) {
                 }
             }
         } catch (Throwable t) {
diff --git a/services/core/java/com/android/server/SamplingProfilerService.java b/services/core/java/com/android/server/SamplingProfilerService.java
index fbf1aa4..5f92695 100644
--- a/services/core/java/com/android/server/SamplingProfilerService.java
+++ b/services/core/java/com/android/server/SamplingProfilerService.java
@@ -27,6 +27,7 @@
 import android.os.SystemProperties;
 import android.provider.Settings;
 import com.android.internal.os.SamplingProfilerIntegration;
+import com.android.internal.util.DumpUtils;
 
 import java.io.File;
 import java.io.FileDescriptor;
@@ -96,7 +97,7 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
         pw.println("SamplingProfilerService:");
         pw.println("Watching directory: " + SNAPSHOT_DIR);
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index c68000a..d796098 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -102,6 +102,7 @@
 import com.android.internal.os.SomeArgs;
 import com.android.internal.os.Zygote;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.HexDump;
 import com.android.internal.util.IndentingPrintWriter;
@@ -3911,7 +3912,7 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
 
         final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ", 160);
         synchronized (mLock) {
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 531df81..7c1a609 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -60,6 +60,7 @@
 import com.android.internal.telephony.PhoneConstantConversions;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.util.DumpUtils;
 import com.android.server.am.BatteryStatsService;
 
 /**
@@ -1391,12 +1392,7 @@
 
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-            pw.println("Permission Denial: can't dump telephony.registry from from pid="
-                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
-            return;
-        }
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
         synchronized (mRecords) {
             final int recordCount = mRecords.size();
             pw.println("last known state:");
diff --git a/services/core/java/com/android/server/TextServicesManagerService.java b/services/core/java/com/android/server/TextServicesManagerService.java
index feda273..9068745 100644
--- a/services/core/java/com/android/server/TextServicesManagerService.java
+++ b/services/core/java/com/android/server/TextServicesManagerService.java
@@ -25,6 +25,7 @@
 import com.android.internal.textservice.ISpellCheckerSessionListener;
 import com.android.internal.textservice.ITextServicesManager;
 import com.android.internal.textservice.ITextServicesSessionListener;
+import com.android.internal.util.DumpUtils;
 
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -757,14 +758,7 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-
-            pw.println("Permission Denial: can't dump TextServicesManagerService from from pid="
-                    + Binder.getCallingPid()
-                    + ", uid=" + Binder.getCallingUid());
-            return;
-        }
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
         synchronized(mSpellCheckerMap) {
             pw.println("Current Text Services Manager state:");
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 227e2a2..04421cc 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -60,6 +60,7 @@
 import com.android.internal.app.DisableCarModeActivity;
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.internal.notification.SystemNotificationChannels;
+import com.android.internal.util.DumpUtils;
 import com.android.server.power.ShutdownThread;
 import com.android.server.twilight.TwilightListener;
 import com.android.server.twilight.TwilightManager;
@@ -352,15 +353,7 @@
 
         @Override
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                    != PackageManager.PERMISSION_GRANTED) {
-
-                pw.println("Permission Denial: can't dump uimode service from from pid="
-                        + Binder.getCallingPid()
-                        + ", uid=" + Binder.getCallingUid());
-                return;
-            }
-
+            if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
             dumpImpl(pw);
         }
     };
diff --git a/services/core/java/com/android/server/UpdateLockService.java b/services/core/java/com/android/server/UpdateLockService.java
index 7f33973..06f73e2 100644
--- a/services/core/java/com/android/server/UpdateLockService.java
+++ b/services/core/java/com/android/server/UpdateLockService.java
@@ -29,6 +29,8 @@
 import android.os.UserHandle;
 import android.util.Slog;
 
+import com.android.internal.util.DumpUtils;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
@@ -112,14 +114,7 @@
 
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-            pw.println("Permission Denial: can't dump update lock service from from pid="
-                    + Binder.getCallingPid()
-                    + ", uid=" + Binder.getCallingUid());
-            return;
-        }
-
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
         mLocks.dump(pw);
     }
 }
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index c4676d1..678ae38 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -54,6 +54,7 @@
 
 import com.android.internal.app.IAppOpsService;
 import com.android.internal.app.IBatteryStats;
+import com.android.internal.util.DumpUtils;
 import com.android.server.power.BatterySaverPolicy.ServiceType;
 
 import java.io.FileDescriptor;
@@ -874,14 +875,8 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
-            pw.println("Permission Denial: can't dump vibrator service from from pid="
-                    + Binder.getCallingPid()
-                    + ", uid=" + Binder.getCallingUid());
-            return;
-        }
         pw.println("Previous vibrations:");
         synchronized (mLock) {
             for (VibrationInfo info : mPreviousVibrations) {
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index ad2ed93..d996ee2 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -92,6 +92,7 @@
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
 import com.android.server.LocalServices;
@@ -4867,13 +4868,7 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-            fout.println("Permission Denial: can't dump AccountsManager from from pid="
-                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
-                    + " without permission " + android.Manifest.permission.DUMP);
-            return;
-        }
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, fout)) return;
         final boolean isCheckinRequest = scanArgs(args, "--checkin") || scanArgs(args, "-c");
         final IndentingPrintWriter ipw = new IndentingPrintWriter(fout, "  ");
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 81d0a7c..c27fa1b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -350,6 +350,7 @@
 import com.android.internal.policy.IKeyguardDismissCallback;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.MemInfoReader;
@@ -2656,14 +2657,8 @@
 
         @Override
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP)
-                    != PackageManager.PERMISSION_GRANTED) {
-                pw.println("Permission Denial: can't dump meminfo from from pid="
-                        + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
-                        + " without permission " + android.Manifest.permission.DUMP);
-                return;
-            }
-
+            if (!DumpUtils.checkDumpAndUsageStatsPermission(mActivityManagerService.mContext,
+                    "meminfo", pw)) return;
             mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, "  ", args, false, null);
         }
     }
@@ -2676,14 +2671,8 @@
 
         @Override
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP)
-                    != PackageManager.PERMISSION_GRANTED) {
-                pw.println("Permission Denial: can't dump gfxinfo from from pid="
-                        + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
-                        + " without permission " + android.Manifest.permission.DUMP);
-                return;
-            }
-
+            if (!DumpUtils.checkDumpAndUsageStatsPermission(mActivityManagerService.mContext,
+                    "gfxinfo", pw)) return;
             mActivityManagerService.dumpGraphicsHardwareUsage(fd, pw, args);
         }
     }
@@ -2696,14 +2685,8 @@
 
         @Override
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP)
-                    != PackageManager.PERMISSION_GRANTED) {
-                pw.println("Permission Denial: can't dump dbinfo from from pid="
-                        + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
-                        + " without permission " + android.Manifest.permission.DUMP);
-                return;
-            }
-
+            if (!DumpUtils.checkDumpAndUsageStatsPermission(mActivityManagerService.mContext,
+                    "dbinfo", pw)) return;
             mActivityManagerService.dumpDbInfo(fd, pw, args);
         }
     }
@@ -2716,14 +2699,8 @@
 
         @Override
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP)
-                    != PackageManager.PERMISSION_GRANTED) {
-                pw.println("Permission Denial: can't dump cpuinfo from from pid="
-                        + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
-                        + " without permission " + android.Manifest.permission.DUMP);
-                return;
-            }
-
+            if (!DumpUtils.checkDumpAndUsageStatsPermission(mActivityManagerService.mContext,
+                    "cpuinfo", pw)) return;
             synchronized (mActivityManagerService.mProcessCpuTracker) {
                 pw.print(mActivityManagerService.mProcessCpuTracker.printCurrentLoad());
                 pw.print(mActivityManagerService.mProcessCpuTracker.printCurrentState(
@@ -14758,15 +14735,7 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (checkCallingPermission(android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-            pw.println("Permission Denial: can't dump ActivityManager from from pid="
-                    + Binder.getCallingPid()
-                    + ", uid=" + Binder.getCallingUid()
-                    + " without permission "
-                    + android.Manifest.permission.DUMP);
-            return;
-        }
+        if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
 
         boolean dumpAll = false;
         boolean dumpClient = false;
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index a623df7..432988a 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -25,8 +25,20 @@
 import static android.app.ActivityManager.StackId.HOME_STACK_ID;
 import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.app.ActivityManager.TaskDescription.ATTR_TASKDESCRIPTION_PREFIX;
+import static android.app.ActivityOptions.ANIM_CLIP_REVEAL;
+import static android.app.ActivityOptions.ANIM_CUSTOM;
+import static android.app.ActivityOptions.ANIM_SCALE_UP;
+import static android.app.ActivityOptions.ANIM_SCENE_TRANSITION;
+import static android.app.ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_DOWN;
+import static android.app.ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP;
+import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN;
+import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_UP;
 import static android.app.AppOpsManager.MODE_ALLOWED;
 import static android.app.AppOpsManager.OP_PICTURE_IN_PICTURE;
+import static android.content.Intent.ACTION_MAIN;
+import static android.content.Intent.CATEGORY_HOME;
+import static android.content.Intent.CATEGORY_LAUNCHER;
 import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
 import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
@@ -43,15 +55,19 @@
 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
+import static android.content.pm.ActivityInfo.PERSIST_ACROSS_REBOOTS;
+import static android.content.pm.ActivityInfo.PERSIST_ROOT_ONLY;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
 import static android.content.res.Configuration.EMPTY;
+import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
 import static android.content.res.Configuration.UI_MODE_TYPE_VR_HEADSET;
 import static android.os.Build.VERSION_CODES.HONEYCOMB;
 import static android.os.Build.VERSION_CODES.O;
 import static android.os.Process.SYSTEM_UID;
+import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SAVED_STATE;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SCREENSHOTS;
@@ -68,8 +84,30 @@
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBILITY;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.am.ActivityManagerService.IS_USER_BUILD;
 import static com.android.server.am.ActivityManagerService.TAKE_FULLSCREEN_SCREENSHOTS;
+import static com.android.server.am.ActivityStack.ActivityState.DESTROYED;
+import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
+import static com.android.server.am.ActivityStack.ActivityState.INITIALIZING;
+import static com.android.server.am.ActivityStack.ActivityState.PAUSED;
+import static com.android.server.am.ActivityStack.ActivityState.PAUSING;
+import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
+import static com.android.server.am.ActivityStack.ActivityState.STOPPED;
+import static com.android.server.am.ActivityStack.ActivityState.STOPPING;
+import static com.android.server.am.ActivityStack.LAUNCH_TICK;
+import static com.android.server.am.ActivityStack.LAUNCH_TICK_MSG;
+import static com.android.server.am.ActivityStack.PAUSE_TIMEOUT_MSG;
+import static com.android.server.am.ActivityStack.STOP_TIMEOUT_MSG;
+import static com.android.server.am.EventLogTags.AM_ACTIVITY_FULLY_DRAWN_TIME;
+import static com.android.server.am.EventLogTags.AM_ACTIVITY_LAUNCH_TIME;
+import static com.android.server.am.EventLogTags.AM_RELAUNCH_ACTIVITY;
+import static com.android.server.am.EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY;
+import static com.android.server.am.TaskPersister.DEBUG;
+import static com.android.server.am.TaskPersister.IMAGE_EXTENSION;
 import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
+import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
+import static org.xmlpull.v1.XmlPullParser.END_TAG;
+import static org.xmlpull.v1.XmlPullParser.START_TAG;
 
 import android.annotation.NonNull;
 import android.app.ActivityManager.TaskDescription;
@@ -109,6 +147,7 @@
 import com.android.internal.content.ReferrerIntent;
 import com.android.internal.util.XmlUtils;
 import com.android.server.AttributeCache;
+import com.android.server.AttributeCache.Entry;
 import com.android.server.am.ActivityStack.ActivityState;
 import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
 import com.android.server.wm.AppWindowContainerController;
@@ -199,6 +238,8 @@
     long cpuTimeAtResume;   // the cpu time of host process at the time of resuming activity
     long pauseTime;         // last time we started pausing the activity
     long launchTickTime;    // base time for launch tick messages
+    // TODO: Refactor mLastReportedConfiguration and mLastReportedOverrideConfiguration to use a
+    // MergedConfiguration object for clarity.
     private Configuration mLastReportedConfiguration; // configuration activity was last running in
     // Overridden configuration by the activity task
     // WARNING: Reference points to {@link TaskRecord#getMergedOverrideConfig}, so its internal
@@ -299,6 +340,7 @@
      */
     private final Configuration mTmpConfig1 = new Configuration();
     private final Configuration mTmpConfig2 = new Configuration();
+    private final Configuration mTmpConfig3 = new Configuration();
     private final Point mTmpPoint = new Point();
     private final Rect mTmpBounds = new Rect();
 
@@ -684,7 +726,7 @@
         resultTo = _resultTo;
         resultWho = _resultWho;
         requestCode = _reqCode;
-        state = ActivityState.INITIALIZING;
+        state = INITIALIZING;
         frontOfTask = false;
         launchFailed = false;
         stopped = false;
@@ -768,7 +810,7 @@
         packageName = aInfo.applicationInfo.packageName;
         launchMode = aInfo.launchMode;
 
-        AttributeCache.Entry ent = AttributeCache.instance().get(packageName,
+        Entry ent = AttributeCache.instance().get(packageName,
                 realTheme, com.android.internal.R.styleable.Window, userId);
         final boolean translucent = ent != null && (ent.array.getBoolean(
                 com.android.internal.R.styleable.Window_windowIsTranslucent, false)
@@ -860,16 +902,16 @@
     }
 
     private boolean isHomeIntent(Intent intent) {
-        return Intent.ACTION_MAIN.equals(intent.getAction())
-                && intent.hasCategory(Intent.CATEGORY_HOME)
+        return ACTION_MAIN.equals(intent.getAction())
+                && intent.hasCategory(CATEGORY_HOME)
                 && intent.getCategories().size() == 1
                 && intent.getData() == null
                 && intent.getType() == null;
     }
 
     static boolean isMainIntent(Intent intent) {
-        return Intent.ACTION_MAIN.equals(intent.getAction())
-                && intent.hasCategory(Intent.CATEGORY_LAUNCHER)
+        return ACTION_MAIN.equals(intent.getAction())
+                && intent.hasCategory(CATEGORY_LAUNCHER)
                 && intent.getCategories().size() == 1
                 && intent.getData() == null
                 && intent.getType() == null;
@@ -986,8 +1028,8 @@
     }
 
     boolean isPersistable() {
-        return (info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY ||
-                info.persistableMode == ActivityInfo.PERSIST_ACROSS_REBOOTS) &&
+        return (info.persistableMode == PERSIST_ROOT_ONLY ||
+                info.persistableMode == PERSIST_ACROSS_REBOOTS) &&
                 (intent == null ||
                         (intent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0);
     }
@@ -1203,13 +1245,13 @@
         // - It is currently resumed or paused. i.e. it is currently visible to the user and we want
         //   the user to see the visual effects caused by the intent delivery now.
         // - The device is sleeping and it is the top activity behind the lock screen (b/6700897).
-        if ((state == ActivityState.RESUMED || state == ActivityState.PAUSED
+        if ((state == RESUMED || state == PAUSED
                 || isTopActivityWhileSleeping) && app != null && app.thread != null) {
             try {
                 ArrayList<ReferrerIntent> ar = new ArrayList<>(1);
                 ar.add(rintent);
                 app.thread.scheduleNewIntent(
-                        ar, appToken, state == ActivityState.PAUSED /* andPause */);
+                        ar, appToken, state == PAUSED /* andPause */);
                 unsent = false;
             } catch (RemoteException e) {
                 Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
@@ -1233,17 +1275,17 @@
 
     void applyOptionsLocked() {
         if (pendingOptions != null
-                && pendingOptions.getAnimationType() != ActivityOptions.ANIM_SCENE_TRANSITION) {
+                && pendingOptions.getAnimationType() != ANIM_SCENE_TRANSITION) {
             final int animationType = pendingOptions.getAnimationType();
             switch (animationType) {
-                case ActivityOptions.ANIM_CUSTOM:
+                case ANIM_CUSTOM:
                     service.mWindowManager.overridePendingAppTransition(
                             pendingOptions.getPackageName(),
                             pendingOptions.getCustomEnterResId(),
                             pendingOptions.getCustomExitResId(),
                             pendingOptions.getOnAnimationStartListener());
                     break;
-                case ActivityOptions.ANIM_CLIP_REVEAL:
+                case ANIM_CLIP_REVEAL:
                     service.mWindowManager.overridePendingAppTransitionClipReveal(
                             pendingOptions.getStartX(), pendingOptions.getStartY(),
                             pendingOptions.getWidth(), pendingOptions.getHeight());
@@ -1254,7 +1296,7 @@
                                 pendingOptions.getStartY()+pendingOptions.getHeight()));
                     }
                     break;
-                case ActivityOptions.ANIM_SCALE_UP:
+                case ANIM_SCALE_UP:
                     service.mWindowManager.overridePendingAppTransitionScaleUp(
                             pendingOptions.getStartX(), pendingOptions.getStartY(),
                             pendingOptions.getWidth(), pendingOptions.getHeight());
@@ -1265,9 +1307,9 @@
                                 pendingOptions.getStartY()+pendingOptions.getHeight()));
                     }
                     break;
-                case ActivityOptions.ANIM_THUMBNAIL_SCALE_UP:
-                case ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN:
-                    boolean scaleUp = (animationType == ActivityOptions.ANIM_THUMBNAIL_SCALE_UP);
+                case ANIM_THUMBNAIL_SCALE_UP:
+                case ANIM_THUMBNAIL_SCALE_DOWN:
+                    boolean scaleUp = (animationType == ANIM_THUMBNAIL_SCALE_UP);
                     service.mWindowManager.overridePendingAppTransitionThumb(
                             pendingOptions.getThumbnail(),
                             pendingOptions.getStartX(), pendingOptions.getStartY(),
@@ -1282,10 +1324,10 @@
                                         + pendingOptions.getThumbnail().getHeight()));
                     }
                     break;
-                case ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP:
-                case ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
+                case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
+                case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
                     final AppTransitionAnimationSpec[] specs = pendingOptions.getAnimSpecs();
-                    if (animationType == ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_DOWN
+                    if (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_DOWN
                             && specs != null) {
                         service.mWindowManager.overridePendingAppTransitionMultiThumb(
                                 specs, pendingOptions.getOnAnimationStartListener(),
@@ -1296,7 +1338,7 @@
                                 pendingOptions.getStartX(), pendingOptions.getStartY(),
                                 pendingOptions.getWidth(), pendingOptions.getHeight(),
                                 pendingOptions.getOnAnimationStartListener(),
-                                (animationType == ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP));
+                                (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_UP));
                         if (intent.getSourceBounds() == null) {
                             intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
                                     pendingOptions.getStartY(),
@@ -1478,7 +1520,7 @@
 
     void makeVisibleIfNeeded(ActivityRecord starting) {
         // This activity is not currently visible, but is running. Tell it to become visible.
-        if (state == ActivityState.RESUMED || this == starting) {
+        if (state == RESUMED || this == starting) {
             if (DEBUG_VISIBILITY) Slog.d(TAG_VISIBILITY,
                     "Not making visible, r=" + this + " state=" + state + " starting=" + starting);
             return;
@@ -1515,7 +1557,7 @@
             }
         } catch(RemoteException e) {
         }
-        return state == ActivityState.RESUMED;
+        return state == RESUMED;
     }
 
     static void activityResumedLocked(IBinder token) {
@@ -1586,9 +1628,9 @@
     final void activityStoppedLocked(Bundle newIcicle, PersistableBundle newPersistentState,
             CharSequence description) {
         final ActivityStack stack = getStack();
-        if (state != ActivityState.STOPPING) {
+        if (state != STOPPING) {
             Slog.i(TAG, "Activity reported stop, but no longer stopping: " + this);
-            stack.mHandler.removeMessages(ActivityStack.STOP_TIMEOUT_MSG, this);
+            stack.mHandler.removeMessages(STOP_TIMEOUT_MSG, this);
             return;
         }
         if (newPersistentState != null) {
@@ -1607,9 +1649,9 @@
         }
         if (!stopped) {
             if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to STOPPED: " + this + " (stop complete)");
-            stack.mHandler.removeMessages(ActivityStack.STOP_TIMEOUT_MSG, this);
+            stack.mHandler.removeMessages(STOP_TIMEOUT_MSG, this);
             stopped = true;
-            state = ActivityState.STOPPED;
+            state = STOPPED;
 
             mWindowContainerController.notifyAppStopped();
 
@@ -1630,7 +1672,7 @@
     }
 
     void startLaunchTickingLocked() {
-        if (ActivityManagerService.IS_USER_BUILD) {
+        if (IS_USER_BUILD) {
             return;
         }
         if (launchTickTime == 0) {
@@ -1649,9 +1691,9 @@
             return false;
         }
 
-        Message msg = stack.mHandler.obtainMessage(ActivityStack.LAUNCH_TICK_MSG, this);
-        stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG);
-        stack.mHandler.sendMessageDelayed(msg, ActivityStack.LAUNCH_TICK);
+        Message msg = stack.mHandler.obtainMessage(LAUNCH_TICK_MSG, this);
+        stack.mHandler.removeMessages(LAUNCH_TICK_MSG);
+        stack.mHandler.sendMessageDelayed(msg, LAUNCH_TICK);
         return true;
     }
 
@@ -1659,7 +1701,7 @@
         launchTickTime = 0;
         final ActivityStack stack = getStack();
         if (stack != null) {
-            stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG);
+            stack.mHandler.removeMessages(LAUNCH_TICK_MSG);
         }
     }
 
@@ -1697,8 +1739,8 @@
             final long totalTime = stack.mFullyDrawnStartTime != 0
                     ? (curTime - stack.mFullyDrawnStartTime) : thisTime;
             if (SHOW_ACTIVITY_START_TIME) {
-                Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
-                EventLog.writeEvent(EventLogTags.AM_ACTIVITY_FULLY_DRAWN_TIME,
+                Trace.asyncTraceEnd(TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
+                EventLog.writeEvent(AM_ACTIVITY_FULLY_DRAWN_TIME,
                         userId, System.identityHashCode(this), shortComponentName,
                         thisTime, totalTime);
                 StringBuilder sb = service.mStringBuilder;
@@ -1731,8 +1773,8 @@
         final long totalTime = stack.mLaunchStartTime != 0
                 ? (curTime - stack.mLaunchStartTime) : thisTime;
         if (SHOW_ACTIVITY_START_TIME) {
-            Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "launching: " + packageName, 0);
-            EventLog.writeEvent(EventLogTags.AM_ACTIVITY_LAUNCH_TIME,
+            Trace.asyncTraceEnd(TRACE_TAG_ACTIVITY_MANAGER, "launching: " + packageName, 0);
+            EventLog.writeEvent(AM_ACTIVITY_LAUNCH_TIME,
                     userId, System.identityHashCode(this), shortComponentName,
                     thisTime, totalTime);
             StringBuilder sb = service.mStringBuilder;
@@ -1869,8 +1911,8 @@
      * currently pausing, or is resumed.
      */
     public boolean isInterestingToUserLocked() {
-        return visible || nowVisible || state == ActivityState.PAUSING ||
-                state == ActivityState.RESUMED;
+        return visible || nowVisible || state == PAUSING ||
+                state == RESUMED;
     }
 
     void setSleeping(boolean _sleeping) {
@@ -1932,8 +1974,8 @@
     }
 
     final boolean isDestroyable() {
-        if (finishing || app == null || state == ActivityState.DESTROYING
-                || state == ActivityState.DESTROYED) {
+        if (finishing || app == null || state == DESTROYING
+                || state == DESTROYED) {
             // This would be redundant.
             return false;
         }
@@ -1952,7 +1994,7 @@
 
     private static String createImageFilename(long createTime, int taskId) {
         return String.valueOf(taskId) + ACTIVITY_ICON_SUFFIX + createTime +
-                TaskPersister.IMAGE_EXTENSION;
+                IMAGE_EXTENSION;
     }
 
     void setTaskDescription(TaskDescription _taskDescription) {
@@ -1994,7 +2036,7 @@
     }
 
     void removeOrphanedStartingWindow(boolean behindFullscreenActivity) {
-        if (state == ActivityState.INITIALIZING
+        if (state == INITIALIZING
                 && mStartingWindowState == STARTING_WINDOW_SHOWN
                 && behindFullscreenActivity) {
             if (DEBUG_VISIBILITY) Slog.w(TAG_VISIBILITY, "Found orphaned starting window " + this);
@@ -2181,6 +2223,9 @@
         // to decide whether to relaunch an activity or just report a configuration change.
         final int changes = getConfigurationChanges(mTmpConfig1);
 
+        // Preserve configuration used to generate this set of configuration changes.
+        mTmpConfig3.setTo(mTmpConfig1);
+
         // Update last reported values.
         final Configuration newGlobalConfig = service.getGlobalConfiguration();
         final Configuration newMergedOverrideConfig = getMergedOverrideConfiguration();
@@ -2224,8 +2269,7 @@
                         + ", newGlobalConfig=" + newGlobalConfig
                         + ", newMergedOverrideConfig=" + newMergedOverrideConfig);
 
-        if (shouldRelaunchLocked(changes, newGlobalConfig, newMergedOverrideConfig)
-                || forceNewConfig) {
+        if (shouldRelaunchLocked(changes, mTmpConfig3) || forceNewConfig) {
             // Aha, the activity isn't handling the change, so DIE DIE DIE.
             configChangeFlags |= changes;
             startFreezingScreenLocked(app, globalChanges);
@@ -2235,7 +2279,7 @@
                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                         "Config is destroying non-running " + this);
                 stack.destroyActivityLocked(this, true, "config");
-            } else if (state == ActivityState.PAUSING) {
+            } else if (state == PAUSING) {
                 // A little annoying: we are waiting for this activity to finish pausing. Let's not
                 // do anything now, but just flag that it needs to be restarted when done pausing.
                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
@@ -2243,7 +2287,7 @@
                 deferRelaunchUntilPaused = true;
                 preserveWindowOnDeferredRelaunch = preserveWindow;
                 return true;
-            } else if (state == ActivityState.RESUMED) {
+            } else if (state == RESUMED) {
                 // Try to optimize this case: the configuration is changing and we need to restart
                 // the top, resumed activity. Instead of doing the normal handshaking, just say
                 // "restart!".
@@ -2283,10 +2327,14 @@
     /**
      * When assessing a configuration change, decide if the changes flags and the new configurations
      * should cause the Activity to relaunch.
+     *
+     * @param changes the changes due to the given configuration.
+     * @param changesConfig the configuration that was used to calculate the given changes via a
+     *        call to getConfigurationChanges.
      */
-    private boolean shouldRelaunchLocked(int changes, Configuration newGlobalConfig,
-            Configuration newTaskMergedOverrideConfig) {
+    private boolean shouldRelaunchLocked(int changes, Configuration changesConfig) {
         int configChanged = info.getRealConfigChanged();
+        boolean onlyVrUiModeChanged = onlyVrUiModeChanged(changes, changesConfig);
 
         // Override for apps targeting pre-O sdks
         // If a device is in VR mode, and we're transitioning into VR ui mode, add ignore ui mode
@@ -2294,13 +2342,23 @@
         // For O and later, apps will be required to add configChanges="uimode" to their manifest.
         if (appInfo.targetSdkVersion < O
                 && requestedVrComponent != null
-                && (isInVrUiMode(newGlobalConfig) || isInVrUiMode(newTaskMergedOverrideConfig))) {
+                && onlyVrUiModeChanged) {
             configChanged |= CONFIG_UI_MODE;
         }
 
         return (changes&(~configChanged)) != 0;
     }
 
+    /**
+     * Returns true if the configuration change is solely due to the UI mode switching into or out
+     * of UI_MODE_TYPE_VR_HEADSET.
+     */
+    private boolean onlyVrUiModeChanged(int changes, Configuration lastReportedConfig) {
+        final Configuration currentConfig = getConfiguration();
+        return changes == CONFIG_UI_MODE && (isInVrUiMode(currentConfig)
+            != isInVrUiMode(lastReportedConfig));
+    }
+
     private int getConfigurationChanges(Configuration lastReportedConfig) {
         // Determine what has changed.  May be nothing, if this is a config that has come back from
         // the app after going idle.  In that case we just want to leave the official config object
@@ -2349,8 +2407,8 @@
                 "Relaunching: " + this + " with results=" + pendingResults
                         + " newIntents=" + pendingNewIntents + " andResume=" + andResume
                         + " preserveWindow=" + preserveWindow);
-        EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
-                        : EventLogTags.AM_RELAUNCH_ACTIVITY, userId, System.identityHashCode(this),
+        EventLog.writeEvent(andResume ? AM_RELAUNCH_RESUME_ACTIVITY
+                        : AM_RELAUNCH_ACTIVITY, userId, System.identityHashCode(this),
                 task.taskId, shortComponentName);
 
         startFreezingScreenLocked(app, 0);
@@ -2383,8 +2441,8 @@
             service.showUnsupportedZoomDialogIfNeededLocked(this);
             service.showAskCompatModeDialogLocked(this);
         } else {
-            service.mHandler.removeMessages(ActivityStack.PAUSE_TIMEOUT_MSG, this);
-            state = ActivityState.PAUSED;
+            service.mHandler.removeMessages(PAUSE_TIMEOUT_MSG, this);
+            state = PAUSED;
             // if the app is relaunched when it's stopped, and we're not resuming,
             // put it back into stopped state.
             if (stopped) {
@@ -2448,7 +2506,7 @@
         for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
             final String attrName = in.getAttributeName(attrNdx);
             final String attrValue = in.getAttributeValue(attrNdx);
-            if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG,
+            if (DEBUG) Slog.d(TaskPersister.TAG,
                         "ActivityRecord: attribute name=" + attrName + " value=" + attrValue);
             if (ATTR_ID.equals(attrName)) {
                 createTime = Long.parseLong(attrValue);
@@ -2462,7 +2520,7 @@
                 componentSpecified = Boolean.parseBoolean(attrValue);
             } else if (ATTR_USERID.equals(attrName)) {
                 userId = Integer.parseInt(attrValue);
-            } else if (attrName.startsWith(TaskDescription.ATTR_TASKDESCRIPTION_PREFIX)) {
+            } else if (attrName.startsWith(ATTR_TASKDESCRIPTION_PREFIX)) {
                 taskDescription.restoreFromXml(attrName, attrValue);
             } else {
                 Log.d(TAG, "Unknown ActivityRecord attribute=" + attrName);
@@ -2470,19 +2528,19 @@
         }
 
         int event;
-        while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
-                (event != XmlPullParser.END_TAG || in.getDepth() >= outerDepth)) {
-            if (event == XmlPullParser.START_TAG) {
+        while (((event = in.next()) != END_DOCUMENT) &&
+                (event != END_TAG || in.getDepth() >= outerDepth)) {
+            if (event == START_TAG) {
                 final String name = in.getName();
-                if (TaskPersister.DEBUG)
+                if (DEBUG)
                         Slog.d(TaskPersister.TAG, "ActivityRecord: START_TAG name=" + name);
                 if (TAG_INTENT.equals(name)) {
                     intent = Intent.restoreFromXml(in);
-                    if (TaskPersister.DEBUG)
+                    if (DEBUG)
                             Slog.d(TaskPersister.TAG, "ActivityRecord: intent=" + intent);
                 } else if (TAG_PERSISTABLEBUNDLE.equals(name)) {
                     persistentState = PersistableBundle.restoreFromXml(in);
-                    if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG,
+                    if (DEBUG) Slog.d(TaskPersister.TAG,
                             "ActivityRecord: persistentState=" + persistentState);
                 } else {
                     Slog.w(TAG, "restoreActivity: unexpected name=" + name);
@@ -2526,7 +2584,7 @@
     }
 
     private static boolean isInVrUiMode(Configuration config) {
-        return (config.uiMode & Configuration.UI_MODE_TYPE_MASK) == UI_MODE_TYPE_VR_HEADSET;
+        return (config.uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_VR_HEADSET;
     }
 
     int getUid() {
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index d3935d1..e5b2eca 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -59,6 +59,7 @@
 import com.android.internal.os.BatteryStatsHelper;
 import com.android.internal.os.BatteryStatsImpl;
 import com.android.internal.os.PowerProfile;
+import com.android.internal.util.DumpUtils;
 import com.android.server.LocalServices;
 import com.android.server.ServiceThread;
 import com.android.server.power.BatterySaverPolicy.ServiceType;
@@ -1188,13 +1189,7 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-            pw.println("Permission Denial: can't dump BatteryStats from from pid="
-                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
-                    + " without permission " + android.Manifest.permission.DUMP);
-            return;
-        }
+        if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
 
         int flags = 0;
         boolean useCheckinFormat = false;
diff --git a/services/core/java/com/android/server/am/ProcessStatsService.java b/services/core/java/com/android/server/am/ProcessStatsService.java
index d210ed7..deb3b28 100644
--- a/services/core/java/com/android/server/am/ProcessStatsService.java
+++ b/services/core/java/com/android/server/am/ProcessStatsService.java
@@ -616,13 +616,8 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mAm.checkCallingPermission(android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-            pw.println("Permission Denial: can't dump procstats from from pid="
-                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
-                    + " without permission " + android.Manifest.permission.DUMP);
-            return;
-        }
+        if (!com.android.internal.util.DumpUtils.checkDumpAndUsageStatsPermission(mAm.mContext,
+                TAG, pw)) return;
 
         long ident = Binder.clearCallingIdentity();
         try {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 49d1521..70e56b0 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -114,6 +114,7 @@
 import android.view.KeyEvent;
 import android.view.accessibility.AccessibilityManager;
 
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.XmlUtils;
 import com.android.server.EventLogTags;
 import com.android.server.LocalServices;
@@ -6116,7 +6117,7 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
         mMediaFocusControl.dump(pw);
         dumpStreamStates(pw);
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index 83751a9..4315aaa 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -31,7 +31,7 @@
 import android.widget.Toast;
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.internal.notification.SystemNotificationChannels;
 
 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
@@ -40,11 +40,12 @@
 
 public class NetworkNotificationManager {
 
+
     public static enum NotificationType {
-        LOST_INTERNET(MetricsEvent.NOTIFICATION_NETWORK_LOST_INTERNET),
-        NETWORK_SWITCH(MetricsEvent.NOTIFICATION_NETWORK_SWITCH),
-        NO_INTERNET(MetricsEvent.NOTIFICATION_NETWORK_NO_INTERNET),
-        SIGN_IN(MetricsEvent.NOTIFICATION_NETWORK_SIGN_IN);
+        LOST_INTERNET(SystemMessage.NOTE_NETWORK_LOST_INTERNET),
+        NETWORK_SWITCH(SystemMessage.NOTE_NETWORK_SWITCH),
+        NO_INTERNET(SystemMessage.NOTE_NETWORK_NO_INTERNET),
+        SIGN_IN(SystemMessage.NOTE_NETWORK_SIGN_IN);
 
         public final int eventId;
 
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 07ab067..0e593bd 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -70,6 +70,7 @@
 import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.MessageUtils;
 import com.android.internal.util.Protocol;
@@ -1585,13 +1586,7 @@
         // Binder.java closes the resource for us.
         @SuppressWarnings("resource")
         final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
-        if (mContext.checkCallingOrSelfPermission(
-                android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) {
-            pw.println("Permission Denial: can't dump ConnectivityService.Tether " +
-                    "from from pid=" + Binder.getCallingPid() + ", uid=" +
-                    Binder.getCallingUid());
-                    return;
-        }
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
         pw.println("Tethering:");
         pw.increaseIndent();
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index f47a9079..13054a6 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -60,6 +60,7 @@
 import android.util.SparseIntArray;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
@@ -162,9 +163,7 @@
 
     @Override
     protected synchronized void dump(FileDescriptor fd, PrintWriter pw_, String[] args) {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.DUMP,
-                "caller doesn't have the DUMP permission");
-
+        if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw_)) return;
         final IndentingPrintWriter pw = new IndentingPrintWriter(pw_, "  ");
 
         // This makes it so that future permission checks will be in the context of this
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index fd89b97..a1a7437 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -23,6 +23,7 @@
 import static android.hardware.display.DisplayManager
         .VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
 
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
 
 import android.Manifest;
@@ -1538,13 +1539,7 @@
 
         @Override // Binder call
         public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
-            if (mContext == null
-                    || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
-                            != PackageManager.PERMISSION_GRANTED) {
-                pw.println("Permission Denial: can't dump DisplayManager from from pid="
-                        + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
-                return;
-            }
+            if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
             final long token = Binder.clearCallingIdentity();
             try {
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index 1991c00..313abab 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -479,14 +479,7 @@
     private final class BinderService extends IDreamManager.Stub {
         @Override // Binder call
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
-                    != PackageManager.PERMISSION_GRANTED) {
-                pw.println("Permission Denial: can't dump DreamManager from from pid="
-                        + Binder.getCallingPid()
-                        + ", uid=" + Binder.getCallingUid());
-                return;
-            }
-
+            if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
             final long ident = Binder.clearCallingIdentity();
             try {
                 dumpInternal(pw);
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 7d97ce4..2b85570 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -56,6 +56,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.util.DumpUtils;
 import com.android.server.SystemServerInitThreadPool;
 import com.android.server.SystemService;
 
@@ -1071,13 +1072,7 @@
 
         @Override // Binder call
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
-                    != PackageManager.PERMISSION_GRANTED) {
-                pw.println("Permission Denial: can't dump Fingerprint from from pid="
-                        + Binder.getCallingPid()
-                        + ", uid=" + Binder.getCallingUid());
-                return;
-            }
+            if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
             final long ident = Binder.clearCallingIdentity();
             try {
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 6864e1e..807b1b1 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -68,6 +68,7 @@
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.SystemService;
 import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
@@ -1677,7 +1678,7 @@
 
         @Override
         protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) {
-            getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+            if (!DumpUtils.checkDumpPermission(getContext(), TAG, writer)) return;
             final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
 
             pw.println("mHdmiControlEnabled: " + mHdmiControlEnabled);
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 65a4604..aafc9a8 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -27,6 +27,7 @@
 import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.os.SomeArgs;
 import com.android.internal.R;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.XmlUtils;
 import com.android.server.DisplayThread;
@@ -1747,13 +1748,7 @@
 
     @Override
     public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
-        if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-            pw.println("Permission Denial: can't dump InputManager from from pid="
-                    + Binder.getCallingPid()
-                    + ", uid=" + Binder.getCallingUid());
-            return;
-        }
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
         pw.println("INPUT MANAGER (dumpsys input)\n");
         String dumpStr = nativeDump(mPtr);
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 2de9aae..7c231ff 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -72,6 +72,7 @@
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.app.procstats.ProcessStats;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.DumpUtils;
 import com.android.server.DeviceIdleController;
 import com.android.server.LocalServices;
 import com.android.server.job.JobStore.JobStatusFunctor;
@@ -1790,7 +1791,7 @@
          */
         @Override
         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+            if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return;
 
             long identityToken = Binder.clearCallingIdentity();
             try {
diff --git a/services/core/java/com/android/server/location/ContextHubService.java b/services/core/java/com/android/server/location/ContextHubService.java
index 0a15db6..5e9f355 100644
--- a/services/core/java/com/android/server/location/ContextHubService.java
+++ b/services/core/java/com/android/server/location/ContextHubService.java
@@ -31,6 +31,8 @@
 import android.os.RemoteException;
 import android.util.Log;
 
+import com.android.internal.util.DumpUtils;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.nio.ByteBuffer;
@@ -242,11 +244,7 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
-            != PackageManager.PERMISSION_GRANTED) {
-            pw.println("Permission Denial: can't dump contexthub service");
-            return;
-        }
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
         pw.println("Dumping ContextHub Service");
 
diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java
index f91ea8c..7b0e51e 100644
--- a/services/core/java/com/android/server/media/MediaRouterService.java
+++ b/services/core/java/com/android/server/media/MediaRouterService.java
@@ -16,6 +16,7 @@
 
 package com.android.server.media;
 
+import com.android.internal.util.DumpUtils;
 import com.android.server.Watchdog;
 
 import android.Manifest;
@@ -258,13 +259,7 @@
     // Binder call
     @Override
     public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
-        if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-            pw.println("Permission Denial: can't dump MediaRouterService from from pid="
-                    + Binder.getCallingPid()
-                    + ", uid=" + Binder.getCallingUid());
-            return;
-        }
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
         pw.println("MEDIA ROUTER SERVICE (dumpsys media_router)");
         pw.println();
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 4bf9d8f..64ab848 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -71,6 +71,7 @@
 import android.view.KeyEvent;
 import android.view.ViewConfiguration;
 
+import com.android.internal.util.DumpUtils;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.Watchdog;
@@ -1283,13 +1284,7 @@
 
         @Override
         public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
-            if (getContext().checkCallingOrSelfPermission(Manifest.permission.DUMP)
-                    != PackageManager.PERMISSION_GRANTED) {
-                pw.println("Permission Denial: can't dump MediaSessionService from from pid="
-                        + Binder.getCallingPid()
-                        + ", uid=" + Binder.getCallingUid());
-                return;
-            }
+            if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
 
             pw.println("MEDIA SESSION SERVICE (dumpsys media_session)");
             pw.println();
diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
index 3ea4f2c..9d92cbc 100644
--- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
+++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
@@ -39,6 +39,7 @@
 import android.util.ArrayMap;
 import android.util.Slog;
 
+import com.android.internal.util.DumpUtils;
 import com.android.server.SystemService;
 
 import java.io.FileDescriptor;
@@ -314,14 +315,7 @@
 
         @Override // Binder call
         public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
-            if (mContext == null
-                    || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
-                    != PackageManager.PERMISSION_GRANTED) {
-                pw.println("Permission Denial: can't dump MediaProjectionManager from from pid="
-                        + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
-                return;
-            }
-
+            if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
             final long token = Binder.clearCallingIdentity();
             try {
                 MediaProjectionManagerService.this.dump(pw);
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index f180c50..4e1166b 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -178,9 +178,11 @@
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.DeviceIdleController;
@@ -212,6 +214,7 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.Calendar;
+import java.util.Objects;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -268,11 +271,11 @@
             ActivityManager.isLowRamDeviceStatic() ? 50 : 200;
 
     @VisibleForTesting
-    public static final int TYPE_WARNING = 0x1;
+    public static final int TYPE_WARNING = SystemMessage.NOTE_NET_WARNING;
     @VisibleForTesting
-    public static final int TYPE_LIMIT = 0x2;
+    public static final int TYPE_LIMIT = SystemMessage.NOTE_NET_LIMIT;
     @VisibleForTesting
-    public static final int TYPE_LIMIT_SNOOZED = 0x3;
+    public static final int TYPE_LIMIT_SNOOZED = SystemMessage.NOTE_NET_LIMIT_SNOOZED;
 
     private static final String TAG_POLICY_LIST = "policy-list";
     private static final String TAG_NETWORK_POLICY = "network-policy";
@@ -419,7 +422,7 @@
 
     /** Set of currently active {@link Notification} tags. */
     @GuardedBy("mNetworkPoliciesSecondLock")
-    private final ArraySet<String> mActiveNotifs = new ArraySet<String>();
+    private final ArraySet<NotificationId> mActiveNotifs = new ArraySet<>();
 
     /** Foreground at UID granularity. */
     @GuardedBy("mUidRulesFirstLock")
@@ -1054,7 +1057,7 @@
         if (LOGV) Slog.v(TAG, "updateNotificationsNL()");
 
         // keep track of previously active notifications
-        final ArraySet<String> beforeNotifs = new ArraySet<String>(mActiveNotifs);
+        final ArraySet<NotificationId> beforeNotifs = new ArraySet<NotificationId>(mActiveNotifs);
         mActiveNotifs.clear();
 
         // TODO: when switching to kernel notifications, compute next future
@@ -1091,9 +1094,9 @@
 
         // cancel stale notifications that we didn't renew above
         for (int i = beforeNotifs.size()-1; i >= 0; i--) {
-            final String tag = beforeNotifs.valueAt(i);
-            if (!mActiveNotifs.contains(tag)) {
-                cancelNotification(tag);
+            final NotificationId notificationId = beforeNotifs.valueAt(i);
+            if (!mActiveNotifs.contains(notificationId)) {
+                cancelNotification(notificationId);
             }
         }
     }
@@ -1141,19 +1144,11 @@
     }
 
     /**
-     * Build unique tag that identifies an active {@link NetworkPolicy}
-     * notification of a specific type, like {@link #TYPE_LIMIT}.
-     */
-    private String buildNotificationTag(NetworkPolicy policy, int type) {
-        return TAG + ":" + policy.template.hashCode() + ":" + type;
-    }
-
-    /**
      * Show notification for combined {@link NetworkPolicy} and specific type,
      * like {@link #TYPE_LIMIT}. Okay to call multiple times.
      */
     private void enqueueNotification(NetworkPolicy policy, int type, long totalBytes) {
-        final String tag = buildNotificationTag(policy, type);
+        final NotificationId notificationId = new NotificationId(policy, type);
         final Notification.Builder builder =
                 new Notification.Builder(mContext, SystemNotificationChannels.NETWORK_STATUS);
         builder.setOnlyAlertOnce(true);
@@ -1261,25 +1256,26 @@
         try {
             final String packageName = mContext.getPackageName();
             final int[] idReceived = new int[1];
-            if(!TextUtils.isEmpty(body)) {
+            if (!TextUtils.isEmpty(body)) {
                 builder.setStyle(new Notification.BigTextStyle()
                         .bigText(body));
             }
             mNotifManager.enqueueNotificationWithTag(
-                    packageName, packageName, tag, 0x0, builder.build(), idReceived,
-                    UserHandle.USER_ALL);
-            mActiveNotifs.add(tag);
+                    packageName, packageName, notificationId.getTag(), notificationId.getId(),
+                    builder.build(), idReceived, UserHandle.USER_ALL);
+            mActiveNotifs.add(notificationId);
         } catch (RemoteException e) {
             // ignored; service lives in system_server
         }
     }
 
-    private void cancelNotification(String tag) {
+    private void cancelNotification(NotificationId notificationId) {
         // TODO: move to NotificationManager once we can mock it
         try {
             final String packageName = mContext.getPackageName();
             mNotifManager.cancelNotificationWithTag(
-                    packageName, tag, 0x0, UserHandle.USER_ALL);
+                    packageName, notificationId.getTag(), notificationId.getId(),
+                    UserHandle.USER_ALL);
         } catch (RemoteException e) {
             // ignored; service lives in system_server
         }
@@ -2585,7 +2581,7 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
-        mContext.enforceCallingOrSelfPermission(DUMP, TAG);
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
 
         final IndentingPrintWriter fout = new IndentingPrintWriter(writer, "  ");
 
@@ -4124,4 +4120,43 @@
             return next;
         }
     }
+
+    private class NotificationId {
+        private final String mTag;
+        private final int mId;
+
+        NotificationId(NetworkPolicy policy, int type) {
+            mTag = buildNotificationTag(policy, type);
+            mId = type;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (!(o instanceof NotificationId)) return false;
+            NotificationId that = (NotificationId) o;
+            return Objects.equals(mTag, that.mTag);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(mTag);
+        }
+
+        /**
+         * Build unique tag that identifies an active {@link NetworkPolicy}
+         * notification of a specific type, like {@link #TYPE_LIMIT}.
+         */
+        private String buildNotificationTag(NetworkPolicy policy, int type) {
+            return TAG + ":" + policy.template.hashCode() + ":" + type;
+        }
+
+        public String getTag() {
+            return mTag;
+        }
+
+        public int getId() {
+            return mId;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 6d666e8..e746355 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -122,6 +122,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.net.VpnInfo;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FileRotator;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.EventLogTags;
@@ -1234,7 +1235,7 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter rawWriter, String[] args) {
-        mContext.enforceCallingOrSelfPermission(DUMP, TAG);
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, rawWriter)) return;
 
         long duration = DateUtils.DAY_IN_MILLIS;
         final HashSet<String> argSet = new HashSet<String>();
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index ede5a5e..44c715b 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -144,6 +144,7 @@
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.statusbar.NotificationVisibility;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.Preconditions;
 import com.android.server.DeviceIdleController;
@@ -2451,14 +2452,7 @@
 
         @Override
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                    != PackageManager.PERMISSION_GRANTED) {
-                pw.println("Permission Denial: can't dump NotificationManager from pid="
-                        + Binder.getCallingPid()
-                        + ", uid=" + Binder.getCallingUid());
-                return;
-            }
-
+            if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return;
             final DumpFilter filter = DumpFilter.parseFromArguments(args);
             if (filter != null && filter.stats) {
                 dumpJson(pw, filter);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 2115f31..0d9b052 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -254,6 +254,7 @@
 import com.android.internal.telephony.CarrierAppUtils;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.ConcurrentUtils;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.IndentingPrintWriter;
@@ -1181,7 +1182,6 @@
     // Stores a list of users whose package restrictions file needs to be updated
     private ArraySet<Integer> mDirtyUsers = new ArraySet<Integer>();
 
-    static final long DEFAULT_CONTAINER_WHITELIST_DURATION = 10 * 60 * 1000;
     final private DefaultContainerConnection mDefContainerConn =
             new DefaultContainerConnection();
     class DefaultContainerConnection implements ServiceConnection {
@@ -12915,9 +12915,6 @@
         IActivityManager am = ActivityManager.getService();
         if (am != null) {
             try {
-                getDeviceIdleController().addPowerSaveTempWhitelistApp(Process.SYSTEM_UID,
-                        DEFAULT_CONTAINER_PACKAGE, DEFAULT_CONTAINER_WHITELIST_DURATION,
-                        UserHandle.USER_SYSTEM, false, "cleaning packages");
                 am.startService(null, intent, null, -1, null, false, mContext.getOpPackageName(),
                         UserHandle.USER_SYSTEM);
             } catch (RemoteException e) {
@@ -20230,15 +20227,7 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-            pw.println("Permission Denial: can't dump ActivityManager from from pid="
-                    + Binder.getCallingPid()
-                    + ", uid=" + Binder.getCallingUid()
-                    + " without permission "
-                    + android.Manifest.permission.DUMP);
-            return;
-        }
+        if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
 
         DumpState dumpState = new DumpState();
         boolean fullPreferred = false;
@@ -22238,7 +22227,7 @@
         if (DEBUG_INSTALL) Slog.d(TAG, "Measured code size " + stats.codeSize + ", data size "
                 + stats.dataSize);
 
-        final long startFreeBytes = measurePath.getFreeSpace();
+        final long startFreeBytes = measurePath.getUsableSpace();
         final long sizeBytes;
         if (moveCompleteApp) {
             sizeBytes = stats.codeSize + stats.dataSize;
@@ -22302,7 +22291,7 @@
                         } catch (InterruptedException ignored) {
                         }
 
-                        final long deltaFreeBytes = startFreeBytes - measurePath.getFreeSpace();
+                        final long deltaFreeBytes = startFreeBytes - measurePath.getUsableSpace();
                         final int progress = 10 + (int) MathUtils.constrain(
                                 ((deltaFreeBytes * 80) / sizeBytes), 0, 80);
                         mMoveCallbacks.notifyStatusChanged(moveId, progress);
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 21fe5ba..6f7e0de 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -708,8 +708,6 @@
 
         getPackageInfo().updateVersionInfo(pi);
 
-        boolean changed = false;
-
         // For existing shortcuts, update timestamps if they have any resources.
         // Also check if shortcuts' activities are still main activities.  Otherwise, disable them.
         if (!isNewApp) {
@@ -733,7 +731,6 @@
                         }
                         // Still pinned, so fall-through and possibly update the resources.
                     }
-                    changed = true;
                 }
 
                 if (si.hasAnyResources()) {
@@ -750,29 +747,23 @@
                         // non-manifest at the moment, but icons can still be resources.)
                         si.lookupAndFillInResourceIds(publisherRes);
                     }
-                    changed = true;
                     si.setTimestamp(s.injectCurrentTimeMillis());
                 }
             }
         }
 
         // (Re-)publish manifest shortcut.
-        changed |= publishManifestShortcuts(newManifestShortcutList);
+        publishManifestShortcuts(newManifestShortcutList);
 
         if (newManifestShortcutList != null) {
-            changed |= pushOutExcessShortcuts();
+            pushOutExcessShortcuts();
         }
 
         s.verifyStates();
 
-        if (changed) {
-            // This will send a notification to the launcher, and also save .
-            s.packageShortcutsChanged(getPackageName(), getPackageUserId());
-        } else {
-            // Still save the version code.
-            s.scheduleSaveUser(getPackageUserId());
-        }
-        return changed;
+        // This will send a notification to the launcher, and also save .
+        s.packageShortcutsChanged(getPackageName(), getPackageUserId());
+        return true; // true means changed.
     }
 
     private boolean publishManifestShortcuts(List<ShortcutInfo> newManifestShortcutList) {
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index ef46bae..9bf6895 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -96,6 +96,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.Preconditions;
 import com.android.server.LocalServices;
@@ -1575,15 +1576,15 @@
      * - Write to file
      */
     void packageShortcutsChanged(@NonNull String packageName, @UserIdInt int userId) {
-        if (DEBUG) {
-            Slog.d(TAG, String.format(
-                    "Shortcut changes: package=%s, user=%d", packageName, userId));
-        }
         notifyListeners(packageName, userId);
         scheduleSaveUser(userId);
     }
 
     private void notifyListeners(@NonNull String packageName, @UserIdInt int userId) {
+        if (DEBUG) {
+            Slog.d(TAG, String.format(
+                    "Shortcut changes: package=%s, user=%d", packageName, userId));
+        }
         injectPostToHandler(() -> {
             try {
                 final ArrayList<ShortcutChangeListener> copy;
@@ -2896,6 +2897,11 @@
     }
 
     private void handlePackageChanged(String packageName, int packageUserId) {
+        if (!isPackageInstalled(packageName, packageUserId)) {
+            // Probably disabled, which is the same thing as uninstalled.
+            handlePackageRemoved(packageName, packageUserId);
+            return;
+        }
         if (DEBUG) {
             Slog.d(TAG, String.format("handlePackageChanged: %s user=%d", packageName,
                     packageUserId));
@@ -3111,7 +3117,7 @@
     }
 
     private static boolean isInstalled(@Nullable ApplicationInfo ai) {
-        return (ai != null) && (ai.flags & ApplicationInfo.FLAG_INSTALLED) != 0;
+        return (ai != null) && ai.enabled && (ai.flags & ApplicationInfo.FLAG_INSTALLED) != 0;
     }
 
     private static boolean isEphemeralApp(@Nullable ApplicationInfo ai) {
@@ -3442,8 +3448,7 @@
 
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        enforceCallingOrSelfPermission(android.Manifest.permission.DUMP,
-                "can't dump by this caller");
+        if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
         boolean checkin = false;
         boolean clear = false;
         if (args != null) {
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 8ecf6f7..63e2d4770 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -89,6 +89,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IAppOpsService;
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.XmlUtils;
@@ -3358,15 +3359,7 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-            pw.println("Permission Denial: can't dump UserManager from from pid="
-                    + Binder.getCallingPid()
-                    + ", uid=" + Binder.getCallingUid()
-                    + " without permission "
-                    + android.Manifest.permission.DUMP);
-            return;
-        }
+        if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
 
         long now = System.currentTimeMillis();
         StringBuilder sb = new StringBuilder();
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 4f67e8c..9c4e700 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -75,6 +75,7 @@
 import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.DumpUtils;
 import com.android.server.EventLogTags;
 import com.android.server.LockGuard;
 import com.android.server.RescueParty;
@@ -4503,13 +4504,7 @@
 
         @Override // Binder call
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
-                    != PackageManager.PERMISSION_GRANTED) {
-                pw.println("Permission Denial: can't dump PowerManager from from pid="
-                        + Binder.getCallingPid()
-                        + ", uid=" + Binder.getCallingUid());
-                return;
-            }
+            if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
             final long ident = Binder.clearCallingIdentity();
 
diff --git a/services/core/java/com/android/server/search/SearchManagerService.java b/services/core/java/com/android/server/search/SearchManagerService.java
index edeb774..8c31731 100644
--- a/services/core/java/com/android/server/search/SearchManagerService.java
+++ b/services/core/java/com/android/server/search/SearchManagerService.java
@@ -47,6 +47,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
@@ -371,7 +372,7 @@
 
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
         IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
         synchronized (mSearchables) {
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 83ea075..212bd61 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -39,6 +39,7 @@
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.internal.statusbar.StatusBarIcon;
+import com.android.internal.util.DumpUtils;
 import com.android.server.LocalServices;
 import com.android.server.notification.NotificationDelegate;
 import com.android.server.power.ShutdownThread;
@@ -981,13 +982,7 @@
     // ================================================================================
 
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-            pw.println("Permission Denial: can't dump StatusBar from from pid="
-                    + Binder.getCallingPid()
-                    + ", uid=" + Binder.getCallingUid());
-            return;
-        }
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
         synchronized (mLock) {
             pw.println("  mDisabled1=0x" + Integer.toHexString(mDisabled1));
diff --git a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
index a847a3c..275b612 100644
--- a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
+++ b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
@@ -20,6 +20,7 @@
 
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.internal.notification.SystemNotificationChannels;
+import com.android.internal.util.DumpUtils;
 import com.android.server.EventLogTags;
 import com.android.server.SystemService;
 import com.android.server.pm.InstructionSets;
@@ -467,15 +468,7 @@
     private final Binder mRemoteService = new Binder() {
         @Override
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                    != PackageManager.PERMISSION_GRANTED) {
-
-                pw.println("Permission Denial: can't dump " + SERVICE + " from from pid="
-                        + Binder.getCallingPid()
-                        + ", uid=" + Binder.getCallingUid());
-                return;
-            }
-
+            if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
             dumpImpl(fd, pw, args);
         }
 
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 4570b0d..f4f7e24 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -59,6 +59,7 @@
 import android.view.WindowManagerGlobal;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.content.PackageMonitor;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.server.SystemService;
 import java.io.FileDescriptor;
@@ -849,8 +850,7 @@
 
         @Override
         protected void dump(FileDescriptor fd, final PrintWriter fout, String[] args) {
-            mContext.enforceCallingPermission(Manifest.permission.DUMP,
-                    "dumping TrustManagerService");
+            if (!DumpUtils.checkDumpPermission(mContext, TAG, fout)) return;
             if (isSafeMode()) {
                 fout.println("disabled because the system is in safe mode.");
                 return;
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index 08eca73..6117da7 100644
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -59,6 +59,7 @@
 import android.view.KeyEvent;
 import android.view.Surface;
 
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.SystemService;
 
@@ -549,12 +550,7 @@
 
     public void dump(FileDescriptor fd, final PrintWriter writer, String[] args) {
         final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-            pw.println("Permission Denial: can't dump TvInputHardwareManager from pid="
-                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
-            return;
-        }
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
         synchronized (mLock) {
             pw.println("TvInputHardwareManager Info:");
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 52763a1..be91f48 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -77,6 +77,7 @@
 
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.os.SomeArgs;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.IoThread;
 import com.android.server.SystemService;
@@ -1912,12 +1913,7 @@
         @SuppressWarnings("resource")
         protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) {
             final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
-            if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                    != PackageManager.PERMISSION_GRANTED) {
-                pw.println("Permission Denial: can't dump TvInputManager from pid="
-                        + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
-                return;
-            }
+            if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
             synchronized (mLock) {
                 pw.println("User Ids (Current user: " + mCurrentUserId + "):");
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 324faff..cc08918 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -55,6 +55,7 @@
 import android.util.SparseArray;
 
 import com.android.internal.R;
+import com.android.internal.util.DumpUtils;
 import com.android.server.LocalServices;
 import com.android.server.SystemConfig;
 import com.android.server.SystemService;
@@ -444,12 +445,8 @@
 
         @Override
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                    != PackageManager.PERMISSION_GRANTED) {
-                pw.println("Permission Denial: can't dump VrManagerService from pid="
-                        + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
-                return;
-            }
+            if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
+
             pw.println("********* Dump of VrManagerService *********");
             pw.println("VR mode is currently: " + ((mVrModeAllowed) ? "allowed" : "disallowed"));
             pw.println("Persistent VR mode is currently: " +
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index c6b032b..6a18beb 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -87,6 +87,7 @@
 import com.android.internal.R;
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.JournaledFile;
 import com.android.server.EventLogTags;
@@ -2297,14 +2298,7 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-
-            pw.println("Permission Denial: can't dump wallpaper service from from pid="
-                    + Binder.getCallingPid()
-                    + ", uid=" + Binder.getCallingUid());
-            return;
-        }
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
         synchronized (mLock) {
             pw.println("System wallpaper state:");
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateService.java b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
index 4a105e1..3b400b4 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateService.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
@@ -33,6 +33,7 @@
 import android.webkit.WebViewProviderInfo;
 import android.webkit.WebViewProviderResponse;
 
+import com.android.internal.util.DumpUtils;
 import com.android.server.SystemService;
 
 import java.io.FileDescriptor;
@@ -293,14 +294,7 @@
 
         @Override
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                    != PackageManager.PERMISSION_GRANTED) {
-
-                pw.println("Permission Denial: can't dump webviewupdate service from pid="
-                        + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
-                return;
-            }
-
+            if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
             WebViewUpdateService.this.mImpl.dumpState(pw);
         }
     }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 6c7da50..95fbbb8 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -204,6 +204,7 @@
 import com.android.internal.os.IResultReceiver;
 import com.android.internal.policy.IKeyguardDismissCallback;
 import com.android.internal.policy.IShortcutService;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastPrintWriter;
 import com.android.internal.view.IInputContext;
 import com.android.internal.view.IInputMethodClient;
@@ -6517,13 +6518,7 @@
 
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
-                != PackageManager.PERMISSION_GRANTED) {
-            pw.println("Permission Denial: can't dump WindowManager from from pid="
-                    + Binder.getCallingPid()
-                    + ", uid=" + Binder.getCallingUid());
-            return;
-        }
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
         boolean dumpAll = false;
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index db7c99e..6f49324 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -169,6 +169,7 @@
 import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.JournaledFile;
 import com.android.internal.util.Preconditions;
@@ -7269,14 +7270,7 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-
-            pw.println("Permission Denial: can't dump DevicePolicyManagerService from from pid="
-                    + mInjector.binderGetCallingPid()
-                    + ", uid=" + mInjector.binderGetCallingUid());
-            return;
-        }
+        if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
 
         synchronized (this) {
             pw.println("Current Device Policy Manager state:");
diff --git a/services/midi/java/com/android/server/midi/MidiService.java b/services/midi/java/com/android/server/midi/MidiService.java
index 1c18c9b..100e459 100644
--- a/services/midi/java/com/android/server/midi/MidiService.java
+++ b/services/midi/java/com/android/server/midi/MidiService.java
@@ -45,6 +45,7 @@
 import android.util.Log;
 
 import com.android.internal.content.PackageMonitor;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.XmlUtils;
 import com.android.server.SystemService;
@@ -1011,7 +1012,7 @@
 
     @Override
     public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
         final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
 
         pw.println("MIDI Manager State:");
diff --git a/services/print/java/com/android/server/print/PrintManagerService.java b/services/print/java/com/android/server/print/PrintManagerService.java
index d7666d9..3ec8380 100644
--- a/services/print/java/com/android/server/print/PrintManagerService.java
+++ b/services/print/java/com/android/server/print/PrintManagerService.java
@@ -19,7 +19,6 @@
 import static android.content.pm.PackageManager.GET_SERVICES;
 import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
 
-import android.Manifest;
 import android.annotation.NonNull;
 import android.app.ActivityManager;
 import android.content.ComponentName;
@@ -40,22 +39,23 @@
 import android.print.IPrintDocumentAdapter;
 import android.print.IPrintJobStateChangeListener;
 import android.print.IPrintManager;
-import android.printservice.recommendation.IRecommendationsChangeListener;
 import android.print.IPrintServicesChangeListener;
 import android.print.IPrinterDiscoveryObserver;
 import android.print.PrintAttributes;
 import android.print.PrintJobId;
 import android.print.PrintJobInfo;
 import android.print.PrintManager;
-import android.printservice.recommendation.RecommendationInfo;
 import android.print.PrinterId;
 import android.printservice.PrintServiceInfo;
+import android.printservice.recommendation.IRecommendationsChangeListener;
+import android.printservice.recommendation.RecommendationInfo;
 import android.provider.Settings;
 import android.util.Log;
 import android.util.SparseArray;
 
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.Preconditions;
 import com.android.server.SystemService;
 
@@ -628,13 +628,7 @@
             fd = Preconditions.checkNotNull(fd);
             pw = Preconditions.checkNotNull(pw);
 
-            if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
-                    != PackageManager.PERMISSION_GRANTED) {
-                pw.println("Permission Denial: can't dump PrintManager from from pid="
-                        + Binder.getCallingPid()
-                        + ", uid=" + Binder.getCallingUid());
-                return;
-            }
+            if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
 
             synchronized (mLock) {
                 final long identity = Binder.clearCallingIdentity();
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 7c37027..0f51c49 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -569,6 +569,7 @@
     protected Map<String, PackageInfo> mInjectedPackages;
 
     protected Set<PackageWithUser> mUninstalledPackages;
+    protected Set<PackageWithUser> mDisabledPackages;
     protected Set<PackageWithUser> mEphemeralPackages;
     protected Set<String> mSystemPackages;
 
@@ -740,6 +741,7 @@
                 pi -> pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_ALLOW_BACKUP);
 
         mUninstalledPackages = new HashSet<>();
+        mDisabledPackages = new HashSet<>();
         mSystemPackages = new HashSet<>();
         mEphemeralPackages = new HashSet<>();
 
@@ -1026,7 +1028,7 @@
 
     protected void uninstallPackage(int userId, String packageName) {
         if (ENABLE_DUMP) {
-            Log.v(TAG, "Unnstall package " + packageName + " / " + userId);
+            Log.v(TAG, "Uninstall package " + packageName + " / " + userId);
         }
         mUninstalledPackages.add(PackageWithUser.of(userId, packageName));
     }
@@ -1038,6 +1040,20 @@
         mUninstalledPackages.remove(PackageWithUser.of(userId, packageName));
     }
 
+    protected void disablePackage(int userId, String packageName) {
+        if (ENABLE_DUMP) {
+            Log.v(TAG, "Disable package " + packageName + " / " + userId);
+        }
+        mDisabledPackages.add(PackageWithUser.of(userId, packageName));
+    }
+
+    protected void enablePackage(int userId, String packageName) {
+        if (ENABLE_DUMP) {
+            Log.v(TAG, "Enable package " + packageName + " / " + userId);
+        }
+        mDisabledPackages.remove(PackageWithUser.of(userId, packageName));
+    }
+
     PackageInfo getInjectedPackageInfo(String packageName, @UserIdInt int userId,
             boolean getSignatures) {
         final PackageInfo pi = mInjectedPackages.get(packageName);
@@ -1061,6 +1077,8 @@
         if (mSystemPackages.contains(packageName)) {
             ret.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
         }
+        ret.applicationInfo.enabled =
+                !mDisabledPackages.contains(PackageWithUser.of(userId, packageName));
 
         if (getSignatures) {
             ret.signatures = pi.signatures;
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 796cc16..dd0871a 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -102,6 +102,8 @@
 import java.io.IOException;
 import java.util.List;
 import java.util.Locale;
+import java.util.function.BiConsumer;
+import java.util.function.BiPredicate;
 
 /**
  * Tests for ShortcutService and ShortcutManager.
@@ -3967,6 +3969,22 @@
     }
 
     public void testHandlePackageDelete() {
+        checkHandlePackageDeleteInner((userId, packageName) -> {
+            uninstallPackage(userId, packageName);
+            mService.mPackageMonitor.onReceive(getTestContext(),
+                    genPackageDeleteIntent(packageName, userId));
+        });
+    }
+
+    public void testHandlePackageDisable() {
+        checkHandlePackageDeleteInner((userId, packageName) -> {
+            disablePackage(userId, packageName);
+            mService.mPackageMonitor.onReceive(getTestContext(),
+                    genPackageChangedIntent(packageName, userId));
+        });
+    }
+
+    private void checkHandlePackageDeleteInner(BiConsumer<Integer, String> remover) {
         final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource(
                 getTestContext().getResources(), R.drawable.black_32x32));
         setCaller(CALLING_PACKAGE_1, USER_0);
@@ -4019,9 +4037,7 @@
         assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
         assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
 
-        uninstallPackage(USER_0, CALLING_PACKAGE_1);
-                mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageDeleteIntent(CALLING_PACKAGE_1, USER_0));
+        remover.accept(USER_0, CALLING_PACKAGE_1);
 
         assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_0));
@@ -4039,9 +4055,7 @@
 
         mRunningUsers.put(USER_10, true);
 
-        uninstallPackage(USER_10, CALLING_PACKAGE_2);
-                mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageDeleteIntent(CALLING_PACKAGE_2, USER_10));
+        remover.accept(USER_10, CALLING_PACKAGE_2);
 
         assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_0));
diff --git a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
index 132ed98..c342933 100644
--- a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
+++ b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
@@ -26,6 +26,7 @@
 import static org.mockito.Matchers.anyList;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.times;
@@ -1096,7 +1097,7 @@
         public ShortcutListAsserter assertCallbackCalledForPackageAndUser(
                 String publisherPackageName, UserHandle publisherUserHandle) {
             final ArgumentCaptor<List> shortcuts = ArgumentCaptor.forClass(List.class);
-            verify(mCallback, times(1)).onShortcutsChanged(
+            verify(mCallback, atLeastOnce()).onShortcutsChanged(
                     eq(publisherPackageName),
                     shortcuts.capture(),
                     eq(publisherUserHandle));
diff --git a/services/usage/java/com/android/server/usage/StorageStatsService.java b/services/usage/java/com/android/server/usage/StorageStatsService.java
index 68c4c56..3f39e4f 100644
--- a/services/usage/java/com/android/server/usage/StorageStatsService.java
+++ b/services/usage/java/com/android/server/usage/StorageStatsService.java
@@ -398,7 +398,7 @@
             super(looper);
             // TODO: Handle all private volumes.
             mStats = new StatFs(Environment.getDataDirectory().getAbsolutePath());
-            mPreviousBytes = mStats.getFreeBytes();
+            mPreviousBytes = mStats.getAvailableBytes();
             mMinimumThresholdBytes = mStats.getTotalBytes() * MINIMUM_CHANGE_DELTA;
         }
 
@@ -413,9 +413,9 @@
 
             switch (msg.what) {
                 case MSG_CHECK_STORAGE_DELTA: {
-                    long bytesDelta = Math.abs(mPreviousBytes - mStats.getFreeBytes());
+                    long bytesDelta = Math.abs(mPreviousBytes - mStats.getAvailableBytes());
                     if (bytesDelta > mMinimumThresholdBytes) {
-                        mPreviousBytes = mStats.getFreeBytes();
+                        mPreviousBytes = mStats.getAvailableBytes();
                         recalculateQuotas(getInitializedStrategy());
                     }
                     sendEmptyMessageDelayed(MSG_CHECK_STORAGE_DELTA, DELAY_IN_MILLIS);
@@ -434,7 +434,7 @@
 
                     // If errors occurred getting the quotas from disk, let's re-calc them.
                     if (mPreviousBytes < 0) {
-                        mPreviousBytes = mStats.getFreeBytes();
+                        mPreviousBytes = mStats.getAvailableBytes();
                         recalculateQuotas(strategy);
                     }
                     sendEmptyMessageDelayed(MSG_CHECK_STORAGE_DELTA, DELAY_IN_MILLIS);
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 7be2b0f..4ba457d 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -78,6 +78,7 @@
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.os.SomeArgs;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.SystemService;
 
@@ -1465,13 +1466,7 @@
 
         @Override
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                    != PackageManager.PERMISSION_GRANTED) {
-                pw.println("Permission Denial: can't dump UsageStats from pid="
-                        + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
-                        + " without permission " + android.Manifest.permission.DUMP);
-                return;
-            }
+            if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return;
             UsageStatsService.this.dump(args, pw);
         }
 
diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
index a87ac9e..61e1e8f 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -40,6 +40,7 @@
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
 import com.android.server.SystemService;
@@ -480,7 +481,7 @@
 
     @Override
     public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
 
         final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
         final long ident = Binder.clearCallingIdentity();
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 03a7db7..dc4b41c 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -62,6 +62,7 @@
 import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.DumpUtils;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.UiThread;
@@ -1117,13 +1118,7 @@
 
         @Override
         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
-                    != PackageManager.PERMISSION_GRANTED) {
-                pw.println("Permission Denial: can't dump voiceinteraction from from pid="
-                        + Binder.getCallingPid()
-                        + ", uid=" + Binder.getCallingUid());
-                return;
-            }
+            if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
             synchronized (this) {
                 pw.println("VOICE INTERACTION MANAGER (dumpsys voiceinteraction)");
                 pw.println("  mEnableService: " + mEnableService);
diff --git a/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java
index e3bc34b..c20ee12 100644
--- a/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java
@@ -33,7 +33,6 @@
 import com.android.layoutlib.bridge.util.NinePatchInputStream;
 import com.android.ninepatch.NinePatch;
 import com.android.resources.ResourceType;
-import com.android.resources.ResourceUrl;
 import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
 import com.android.util.Pair;
 
@@ -60,8 +59,6 @@
 import java.io.InputStream;
 import java.util.Iterator;
 
-import static com.android.SdkConstants.ANDROID_NS_NAME;
-
 @SuppressWarnings("deprecation")
 public class Resources_Delegate {
 
@@ -140,8 +137,8 @@
 
             if (value == null) {
                 // Unable to resolve the attribute, just leave the unresolved value
-                value = new ResourceValue(ResourceUrl.create(resourceInfo.getFirst(), attributeName,
-                        platformResFlag_out[0]), attributeName);
+                value = new ResourceValue(resourceInfo.getFirst(), attributeName, attributeName,
+                        platformResFlag_out[0]);
             }
             return Pair.of(attributeName, value);
         }
@@ -681,7 +678,7 @@
         String packageName;
         if (resourceInfo != null) {
             if (platformOut[0]) {
-                packageName = ANDROID_NS_NAME;
+                packageName = SdkConstants.ANDROID_NS_NAME;
             } else {
                 packageName = resources.mContext.getPackageName();
                 packageName = packageName == null ? SdkConstants.APP_PREFIX : packageName;
@@ -699,7 +696,7 @@
         Pair<ResourceType, String> resourceInfo = getResourceInfo(resources, resid, platformOut);
         if (resourceInfo != null) {
             if (platformOut[0]) {
-                return ANDROID_NS_NAME;
+                return SdkConstants.ANDROID_NS_NAME;
             }
             String packageName = resources.mContext.getPackageName();
             return packageName == null ? SdkConstants.APP_PREFIX : packageName;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index cc5a0c3..328fc0a 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -31,7 +31,6 @@
 import com.android.layoutlib.bridge.impl.ParserFactory;
 import com.android.layoutlib.bridge.impl.Stack;
 import com.android.resources.ResourceType;
-import com.android.resources.ResourceUrl;
 import com.android.util.Pair;
 import com.android.util.PropertiesMap;
 import com.android.util.PropertiesMap.Property;
@@ -87,6 +86,7 @@
 import android.view.BridgeInflater;
 import android.view.Display;
 import android.view.DisplayAdjustments;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
@@ -107,7 +107,6 @@
 import java.util.Map;
 
 import static android.os._Original_Build.VERSION_CODES.JELLY_BEAN_MR1;
-import static com.android.SdkConstants.ANDROID_NS_NAME;
 import static com.android.layoutlib.bridge.android.RenderParamsFlags.FLAG_KEY_APPLICATION_PACKAGE;
 
 /**
@@ -122,23 +121,20 @@
 
     static {
         FRAMEWORK_PATCHED_VALUES.put("animateFirstView", new ResourceValue(
-                ResourceUrl.create(ANDROID_NS_NAME, ResourceType.BOOL, "animateFirstView"),
-                "false"));
-        FRAMEWORK_PATCHED_VALUES.put("animateLayoutChanges", new ResourceValue(
-                ResourceUrl.create(ANDROID_NS_NAME, ResourceType.BOOL, "animateLayoutChanges"),
-                "false"));
+                ResourceType.BOOL, "animateFirstView", "false", false));
+        FRAMEWORK_PATCHED_VALUES.put("animateLayoutChanges",
+                new ResourceValue(ResourceType.BOOL, "animateLayoutChanges", "false", false));
 
 
-        FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionItemLayout", new ResourceValue(
-                ResourceUrl.create(ANDROID_NS_NAME, ResourceType.LAYOUT,
-                        "textEditSuggestionItemLayout"), "text_edit_suggestion_item"));
-        FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionContainerLayout", new ResourceValue(
-                ResourceUrl.create(ANDROID_NS_NAME, ResourceType.LAYOUT,
-                        "textEditSuggestionContainerLayout"), "text_edit_suggestion_container"));
-        FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionHighlightStyle", new ResourceValue(
-                ResourceUrl.create(ANDROID_NS_NAME, ResourceType.STYLE,
-                        "textEditSuggestionHighlightStyle"),
-                "TextAppearance.Holo.SuggestionHighlight"));
+        FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionItemLayout",
+                new ResourceValue(ResourceType.LAYOUT, "textEditSuggestionItemLayout",
+                        "text_edit_suggestion_item", true));
+        FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionContainerLayout",
+                new ResourceValue(ResourceType.LAYOUT, "textEditSuggestionContainerLayout",
+                        "text_edit_suggestion_container", true));
+        FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionHighlightStyle",
+                new ResourceValue(ResourceType.STYLE, "textEditSuggestionHighlightStyle",
+                        "TextAppearance.Holo.SuggestionHighlight", true));
 
     }
 
@@ -974,9 +970,7 @@
                     // there is a value in the XML, but we need to resolve it in case it's
                     // referencing another resource or a theme value.
                     ta.bridgeSetValue(index, attrName, frameworkAttr,
-                            mRenderResources.resolveResValue(new ResourceValue(
-                                    ResourceUrl.create(ResourceType.STRING, attrName,
-                                            isPlatformFile), value)));
+                            mRenderResources.resolveValue(null, attrName, value, isPlatformFile));
                 }
             }
         }