Merge "Fix error in width of nanoAppId"
diff --git a/api/current.txt b/api/current.txt
index d68610e..6a62fde 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -609,7 +609,7 @@
     field public static final int fontProviderAuthority = 16844114; // 0x1010552
     field public static final int fontProviderPackage = 16844122; // 0x101055a
     field public static final int fontProviderQuery = 16844115; // 0x1010553
-    field public static final int fontStyle = 16844081; // 0x1010531
+    field public static final int fontStyle = 16844095; // 0x101053f
     field public static final int fontWeight = 16844083; // 0x1010533
     field public static final int footerDividersEnabled = 16843311; // 0x101022f
     field public static final int forceHasOverlappingRendering = 16844065; // 0x1010521
@@ -710,6 +710,7 @@
     field public static final int imeSubtypeMode = 16843501; // 0x10102ed
     field public static final int immersive = 16843456; // 0x10102c0
     field public static final int importantForAccessibility = 16843690; // 0x10103aa
+    field public static final int importantForAutofill = 16844123; // 0x101055b
     field public static final int inAnimation = 16843127; // 0x1010177
     field public static final int includeFontPadding = 16843103; // 0x101015f
     field public static final int includeInGlobalSearch = 16843374; // 0x101026e
@@ -1460,7 +1461,7 @@
     field public static final int viewportWidth = 16843778; // 0x1010402
     field public static final int visibility = 16842972; // 0x10100dc
     field public static final int visible = 16843156; // 0x1010194
-    field public static final int visibleToInstantApps = 16844095; // 0x101053f
+    field public static final int visibleToInstantApps = 16844081; // 0x1010531
     field public static final int vmSafeMode = 16843448; // 0x10102b8
     field public static final int voiceIcon = 16843908; // 0x1010484
     field public static final int voiceLanguage = 16843349; // 0x1010255
@@ -6562,8 +6563,9 @@
     method public int getAutoFillHint();
     method public android.view.autofill.AutoFillId getAutoFillId();
     method public java.lang.String[] getAutoFillOptions();
-    method public android.view.autofill.AutoFillType getAutoFillType();
+    method public deprecated android.view.autofill.AutoFillType getAutoFillType();
     method public android.view.autofill.AutoFillValue getAutoFillValue();
+    method public int getAutofillType();
     method public android.app.assist.AssistStructure.ViewNode getChildAt(int);
     method public int getChildCount();
     method public java.lang.String getClassName();
@@ -10703,7 +10705,7 @@
     ctor public PackageManager.NameNotFoundException(java.lang.String);
   }
 
-  public class PackageStats implements android.os.Parcelable {
+  public deprecated class PackageStats implements android.os.Parcelable {
     ctor public PackageStats(java.lang.String);
     ctor public PackageStats(android.os.Parcel);
     ctor public PackageStats(android.content.pm.PackageStats);
@@ -43586,6 +43588,7 @@
     field public static final int STATE_OFF = 1; // 0x1
     field public static final int STATE_ON = 2; // 0x2
     field public static final int STATE_UNKNOWN = 0; // 0x0
+    field public static final int STATE_VR = 5; // 0x5
   }
 
   public static final class Display.HdrCapabilities implements android.os.Parcelable {
@@ -45051,8 +45054,9 @@
     method public android.os.IBinder getApplicationWindowToken();
     method public int getAutoFillHint();
     method public int getAutoFillMode();
-    method public android.view.autofill.AutoFillType getAutoFillType();
+    method public final deprecated android.view.autofill.AutoFillType getAutoFillType();
     method public android.view.autofill.AutoFillValue getAutoFillValue();
+    method public int getAutofillType();
     method public android.graphics.drawable.Drawable getBackground();
     method public android.content.res.ColorStateList getBackgroundTintList();
     method public android.graphics.PorterDuff.Mode getBackgroundTintMode();
@@ -45096,6 +45100,7 @@
     method protected int getHorizontalScrollbarHeight();
     method public int getId();
     method public int getImportantForAccessibility();
+    method public int getImportantForAutofill();
     method public boolean getKeepScreenOn();
     method public android.view.KeyEvent.DispatcherState getKeyDispatcherState();
     method public int getLabelFor();
@@ -45225,6 +45230,7 @@
     method public boolean isHorizontalScrollBarEnabled();
     method public boolean isHovered();
     method public boolean isImportantForAccessibility();
+    method public final boolean isImportantForAutofill();
     method public boolean isInEditMode();
     method public boolean isInLayout();
     method public boolean isInTouchMode();
@@ -45407,6 +45413,7 @@
     method public void setHovered(boolean);
     method public void setId(int);
     method public void setImportantForAccessibility(int);
+    method public void setImportantForAutofill(int);
     method public void setKeepScreenOn(boolean);
     method public void setKeyboardNavigationCluster(boolean);
     method public void setLabelFor(int);
@@ -45510,6 +45517,11 @@
     field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
     field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
     field public static final android.util.Property<android.view.View, java.lang.Float> ALPHA;
+    field public static final int AUTOFILL_TYPE_DATE = 4; // 0x4
+    field public static final int AUTOFILL_TYPE_LIST = 3; // 0x3
+    field public static final int AUTOFILL_TYPE_NONE = 0; // 0x0
+    field public static final int AUTOFILL_TYPE_TEXT = 1; // 0x1
+    field public static final int AUTOFILL_TYPE_TOGGLE = 2; // 0x2
     field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DATE = 512; // 0x200
     field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DAY = 4096; // 0x1000
     field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_MONTH = 1024; // 0x400
@@ -45567,6 +45579,9 @@
     field public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 2; // 0x2
     field public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 4; // 0x4
     field public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 1; // 0x1
+    field public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0; // 0x0
+    field public static final int IMPORTANT_FOR_AUTOFILL_NO = 2; // 0x2
+    field public static final int IMPORTANT_FOR_AUTOFILL_YES = 1; // 0x1
     field public static final int INVISIBLE = 4; // 0x4
     field public static final int KEEP_SCREEN_ON = 67108864; // 0x4000000
     field public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
@@ -46179,8 +46194,9 @@
     method public abstract void setAlpha(float);
     method public abstract void setAutoFillHint(int);
     method public abstract void setAutoFillOptions(java.lang.String[]);
-    method public abstract void setAutoFillType(android.view.autofill.AutoFillType);
+    method public abstract deprecated void setAutoFillType(android.view.autofill.AutoFillType);
     method public abstract void setAutoFillValue(android.view.autofill.AutoFillValue);
+    method public abstract void setAutofillType(int);
     method public abstract void setCheckable(boolean);
     method public abstract void setChecked(boolean);
     method public abstract void setChildCount(int);
@@ -47436,17 +47452,27 @@
   }
 
   public final class AutoFillManager {
+    method public void registerCallback(android.view.autofill.AutoFillManager.AutofillCallback);
     method public void reset();
     method public void startAutoFillRequest(android.view.View);
     method public void startAutoFillRequestOnVirtualView(android.view.View, int, android.graphics.Rect);
     method public void stopAutoFillRequest(android.view.View);
     method public void stopAutoFillRequestOnVirtualView(android.view.View, int);
+    method public void unregisterCallback(android.view.autofill.AutoFillManager.AutofillCallback);
     method public void valueChanged(android.view.View);
     method public void virtualValueChanged(android.view.View, int, android.view.autofill.AutoFillValue);
     field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE";
     field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT";
   }
 
+  public static abstract class AutoFillManager.AutofillCallback {
+    ctor public AutoFillManager.AutofillCallback();
+    method public void onAutofillEvent(android.view.View, int);
+    method public void onAutofillEventVirtual(android.view.View, int, int);
+    field public static final int EVENT_INPUT_HIDDEN = 2; // 0x2
+    field public static final int EVENT_INPUT_SHOWN = 1; // 0x1
+  }
+
   public final class AutoFillType implements android.os.Parcelable {
     method public int describeContents();
     method public static android.view.autofill.AutoFillType forDate();
@@ -47911,9 +47937,9 @@
   }
 
   public abstract interface TextClassifier {
-    method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int);
-    method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int);
-    method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int);
+    method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int, android.os.LocaleList);
+    method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int, android.os.LocaleList);
+    method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int, android.os.LocaleList);
     field public static final android.view.textclassifier.TextClassifier NO_OP;
     field public static final java.lang.String TYPE_ADDRESS = "address";
     field public static final java.lang.String TYPE_EMAIL = "email";
diff --git a/api/removed.txt b/api/removed.txt
index c5dbf8d..148f3f1 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -369,6 +369,16 @@
 
 }
 
+package android.view.textclassifier {
+
+  public abstract interface TextClassifier {
+    method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int);
+    method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int);
+    method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int);
+  }
+
+}
+
 package android.webkit {
 
   public class WebViewClient {
diff --git a/api/system-current.txt b/api/system-current.txt
index 48f8ce5..339f40b 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -721,7 +721,7 @@
     field public static final int fontProviderAuthority = 16844114; // 0x1010552
     field public static final int fontProviderPackage = 16844122; // 0x101055a
     field public static final int fontProviderQuery = 16844115; // 0x1010553
-    field public static final int fontStyle = 16844081; // 0x1010531
+    field public static final int fontStyle = 16844095; // 0x101053f
     field public static final int fontWeight = 16844083; // 0x1010533
     field public static final int footerDividersEnabled = 16843311; // 0x101022f
     field public static final int forceHasOverlappingRendering = 16844065; // 0x1010521
@@ -822,6 +822,7 @@
     field public static final int imeSubtypeMode = 16843501; // 0x10102ed
     field public static final int immersive = 16843456; // 0x10102c0
     field public static final int importantForAccessibility = 16843690; // 0x10103aa
+    field public static final int importantForAutofill = 16844123; // 0x101055b
     field public static final int inAnimation = 16843127; // 0x1010177
     field public static final int includeFontPadding = 16843103; // 0x101015f
     field public static final int includeInGlobalSearch = 16843374; // 0x101026e
@@ -1576,7 +1577,7 @@
     field public static final int viewportWidth = 16843778; // 0x1010402
     field public static final int visibility = 16842972; // 0x10100dc
     field public static final int visible = 16843156; // 0x1010194
-    field public static final int visibleToInstantApps = 16844095; // 0x101053f
+    field public static final int visibleToInstantApps = 16844081; // 0x1010531
     field public static final int vmSafeMode = 16843448; // 0x10102b8
     field public static final int voiceIcon = 16843908; // 0x1010484
     field public static final int voiceLanguage = 16843349; // 0x1010255
@@ -6811,8 +6812,9 @@
     method public int getAutoFillHint();
     method public android.view.autofill.AutoFillId getAutoFillId();
     method public java.lang.String[] getAutoFillOptions();
-    method public android.view.autofill.AutoFillType getAutoFillType();
+    method public deprecated android.view.autofill.AutoFillType getAutoFillType();
     method public android.view.autofill.AutoFillValue getAutoFillValue();
+    method public int getAutofillType();
     method public android.app.assist.AssistStructure.ViewNode getChildAt(int);
     method public int getChildCount();
     method public java.lang.String getClassName();
@@ -11423,7 +11425,7 @@
   public static abstract class PackageManager.PermissionFlags implements java.lang.annotation.Annotation {
   }
 
-  public class PackageStats implements android.os.Parcelable {
+  public deprecated class PackageStats implements android.os.Parcelable {
     ctor public PackageStats(java.lang.String);
     ctor public PackageStats(android.os.Parcel);
     ctor public PackageStats(android.content.pm.PackageStats);
@@ -16491,6 +16493,7 @@
     method public android.hardware.hdmi.HdmiPlaybackClient getPlaybackClient();
     method public android.hardware.hdmi.HdmiTvClient getTvClient();
     method public void removeHotplugEventListener(android.hardware.hdmi.HdmiControlManager.HotplugEventListener);
+    method public void setStandbyMode(boolean);
     field public static final java.lang.String ACTION_OSD_MESSAGE = "android.hardware.hdmi.action.OSD_MESSAGE";
     field public static final int AVR_VOLUME_MUTED = 101; // 0x65
     field public static final int CLEAR_TIMER_STATUS_CEC_DISABLE = 162; // 0xa2
@@ -47047,6 +47050,7 @@
     field public static final int STATE_OFF = 1; // 0x1
     field public static final int STATE_ON = 2; // 0x2
     field public static final int STATE_UNKNOWN = 0; // 0x0
+    field public static final int STATE_VR = 5; // 0x5
   }
 
   public static final class Display.HdrCapabilities implements android.os.Parcelable {
@@ -48512,8 +48516,9 @@
     method public android.os.IBinder getApplicationWindowToken();
     method public int getAutoFillHint();
     method public int getAutoFillMode();
-    method public android.view.autofill.AutoFillType getAutoFillType();
+    method public final deprecated android.view.autofill.AutoFillType getAutoFillType();
     method public android.view.autofill.AutoFillValue getAutoFillValue();
+    method public int getAutofillType();
     method public android.graphics.drawable.Drawable getBackground();
     method public android.content.res.ColorStateList getBackgroundTintList();
     method public android.graphics.PorterDuff.Mode getBackgroundTintMode();
@@ -48557,6 +48562,7 @@
     method protected int getHorizontalScrollbarHeight();
     method public int getId();
     method public int getImportantForAccessibility();
+    method public int getImportantForAutofill();
     method public boolean getKeepScreenOn();
     method public android.view.KeyEvent.DispatcherState getKeyDispatcherState();
     method public int getLabelFor();
@@ -48686,6 +48692,7 @@
     method public boolean isHorizontalScrollBarEnabled();
     method public boolean isHovered();
     method public boolean isImportantForAccessibility();
+    method public final boolean isImportantForAutofill();
     method public boolean isInEditMode();
     method public boolean isInLayout();
     method public boolean isInTouchMode();
@@ -48868,6 +48875,7 @@
     method public void setHovered(boolean);
     method public void setId(int);
     method public void setImportantForAccessibility(int);
+    method public void setImportantForAutofill(int);
     method public void setKeepScreenOn(boolean);
     method public void setKeyboardNavigationCluster(boolean);
     method public void setLabelFor(int);
@@ -48971,6 +48979,11 @@
     field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
     field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
     field public static final android.util.Property<android.view.View, java.lang.Float> ALPHA;
+    field public static final int AUTOFILL_TYPE_DATE = 4; // 0x4
+    field public static final int AUTOFILL_TYPE_LIST = 3; // 0x3
+    field public static final int AUTOFILL_TYPE_NONE = 0; // 0x0
+    field public static final int AUTOFILL_TYPE_TEXT = 1; // 0x1
+    field public static final int AUTOFILL_TYPE_TOGGLE = 2; // 0x2
     field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DATE = 512; // 0x200
     field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DAY = 4096; // 0x1000
     field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_MONTH = 1024; // 0x400
@@ -49028,6 +49041,9 @@
     field public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 2; // 0x2
     field public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 4; // 0x4
     field public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 1; // 0x1
+    field public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0; // 0x0
+    field public static final int IMPORTANT_FOR_AUTOFILL_NO = 2; // 0x2
+    field public static final int IMPORTANT_FOR_AUTOFILL_YES = 1; // 0x1
     field public static final int INVISIBLE = 4; // 0x4
     field public static final int KEEP_SCREEN_ON = 67108864; // 0x4000000
     field public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
@@ -49640,8 +49656,9 @@
     method public abstract void setAlpha(float);
     method public abstract void setAutoFillHint(int);
     method public abstract void setAutoFillOptions(java.lang.String[]);
-    method public abstract void setAutoFillType(android.view.autofill.AutoFillType);
+    method public abstract deprecated void setAutoFillType(android.view.autofill.AutoFillType);
     method public abstract void setAutoFillValue(android.view.autofill.AutoFillValue);
+    method public abstract void setAutofillType(int);
     method public abstract void setCheckable(boolean);
     method public abstract void setChecked(boolean);
     method public abstract void setChildCount(int);
@@ -50900,17 +50917,27 @@
   }
 
   public final class AutoFillManager {
+    method public void registerCallback(android.view.autofill.AutoFillManager.AutofillCallback);
     method public void reset();
     method public void startAutoFillRequest(android.view.View);
     method public void startAutoFillRequestOnVirtualView(android.view.View, int, android.graphics.Rect);
     method public void stopAutoFillRequest(android.view.View);
     method public void stopAutoFillRequestOnVirtualView(android.view.View, int);
+    method public void unregisterCallback(android.view.autofill.AutoFillManager.AutofillCallback);
     method public void valueChanged(android.view.View);
     method public void virtualValueChanged(android.view.View, int, android.view.autofill.AutoFillValue);
     field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE";
     field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT";
   }
 
+  public static abstract class AutoFillManager.AutofillCallback {
+    ctor public AutoFillManager.AutofillCallback();
+    method public void onAutofillEvent(android.view.View, int);
+    method public void onAutofillEventVirtual(android.view.View, int, int);
+    field public static final int EVENT_INPUT_HIDDEN = 2; // 0x2
+    field public static final int EVENT_INPUT_SHOWN = 1; // 0x1
+  }
+
   public final class AutoFillType implements android.os.Parcelable {
     method public int describeContents();
     method public static android.view.autofill.AutoFillType forDate();
@@ -51375,9 +51402,9 @@
   }
 
   public abstract interface TextClassifier {
-    method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int);
-    method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int);
-    method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int);
+    method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int, android.os.LocaleList);
+    method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int, android.os.LocaleList);
+    method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int, android.os.LocaleList);
     field public static final android.view.textclassifier.TextClassifier NO_OP;
     field public static final java.lang.String TYPE_ADDRESS = "address";
     field public static final java.lang.String TYPE_EMAIL = "email";
diff --git a/api/system-removed.txt b/api/system-removed.txt
index a3093e2..bd535d2 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -363,6 +363,16 @@
 
 }
 
+package android.view.textclassifier {
+
+  public abstract interface TextClassifier {
+    method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int);
+    method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int);
+    method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int);
+  }
+
+}
+
 package android.webkit {
 
   public class WebViewClient {
diff --git a/api/test-current.txt b/api/test-current.txt
index f8e6785..fc96532 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -609,7 +609,7 @@
     field public static final int fontProviderAuthority = 16844114; // 0x1010552
     field public static final int fontProviderPackage = 16844122; // 0x101055a
     field public static final int fontProviderQuery = 16844115; // 0x1010553
-    field public static final int fontStyle = 16844081; // 0x1010531
+    field public static final int fontStyle = 16844095; // 0x101053f
     field public static final int fontWeight = 16844083; // 0x1010533
     field public static final int footerDividersEnabled = 16843311; // 0x101022f
     field public static final int forceHasOverlappingRendering = 16844065; // 0x1010521
@@ -710,6 +710,7 @@
     field public static final int imeSubtypeMode = 16843501; // 0x10102ed
     field public static final int immersive = 16843456; // 0x10102c0
     field public static final int importantForAccessibility = 16843690; // 0x10103aa
+    field public static final int importantForAutofill = 16844123; // 0x101055b
     field public static final int inAnimation = 16843127; // 0x1010177
     field public static final int includeFontPadding = 16843103; // 0x101015f
     field public static final int includeInGlobalSearch = 16843374; // 0x101026e
@@ -1460,7 +1461,7 @@
     field public static final int viewportWidth = 16843778; // 0x1010402
     field public static final int visibility = 16842972; // 0x10100dc
     field public static final int visible = 16843156; // 0x1010194
-    field public static final int visibleToInstantApps = 16844095; // 0x101053f
+    field public static final int visibleToInstantApps = 16844081; // 0x1010531
     field public static final int vmSafeMode = 16843448; // 0x10102b8
     field public static final int voiceIcon = 16843908; // 0x1010484
     field public static final int voiceLanguage = 16843349; // 0x1010255
@@ -6589,8 +6590,9 @@
     method public int getAutoFillHint();
     method public android.view.autofill.AutoFillId getAutoFillId();
     method public java.lang.String[] getAutoFillOptions();
-    method public android.view.autofill.AutoFillType getAutoFillType();
+    method public deprecated android.view.autofill.AutoFillType getAutoFillType();
     method public android.view.autofill.AutoFillValue getAutoFillValue();
+    method public int getAutofillType();
     method public android.app.assist.AssistStructure.ViewNode getChildAt(int);
     method public int getChildCount();
     method public java.lang.String getClassName();
@@ -10739,7 +10741,7 @@
     ctor public PackageManager.NameNotFoundException(java.lang.String);
   }
 
-  public class PackageStats implements android.os.Parcelable {
+  public deprecated class PackageStats implements android.os.Parcelable {
     ctor public PackageStats(java.lang.String);
     ctor public PackageStats(android.os.Parcel);
     ctor public PackageStats(android.content.pm.PackageStats);
@@ -43944,6 +43946,7 @@
     field public static final int STATE_OFF = 1; // 0x1
     field public static final int STATE_ON = 2; // 0x2
     field public static final int STATE_UNKNOWN = 0; // 0x0
+    field public static final int STATE_VR = 5; // 0x5
   }
 
   public static final class Display.HdrCapabilities implements android.os.Parcelable {
@@ -45411,8 +45414,9 @@
     method public android.os.IBinder getApplicationWindowToken();
     method public int getAutoFillHint();
     method public int getAutoFillMode();
-    method public android.view.autofill.AutoFillType getAutoFillType();
+    method public final deprecated android.view.autofill.AutoFillType getAutoFillType();
     method public android.view.autofill.AutoFillValue getAutoFillValue();
+    method public int getAutofillType();
     method public android.graphics.drawable.Drawable getBackground();
     method public android.content.res.ColorStateList getBackgroundTintList();
     method public android.graphics.PorterDuff.Mode getBackgroundTintMode();
@@ -45456,6 +45460,7 @@
     method protected int getHorizontalScrollbarHeight();
     method public int getId();
     method public int getImportantForAccessibility();
+    method public int getImportantForAutofill();
     method public boolean getKeepScreenOn();
     method public android.view.KeyEvent.DispatcherState getKeyDispatcherState();
     method public int getLabelFor();
@@ -45586,6 +45591,7 @@
     method public boolean isHorizontalScrollBarEnabled();
     method public boolean isHovered();
     method public boolean isImportantForAccessibility();
+    method public final boolean isImportantForAutofill();
     method public boolean isInEditMode();
     method public boolean isInLayout();
     method public boolean isInTouchMode();
@@ -45770,6 +45776,7 @@
     method public void setHovered(boolean);
     method public void setId(int);
     method public void setImportantForAccessibility(int);
+    method public void setImportantForAutofill(int);
     method public void setKeepScreenOn(boolean);
     method public void setKeyboardNavigationCluster(boolean);
     method public void setLabelFor(int);
@@ -45873,6 +45880,11 @@
     field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
     field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
     field public static final android.util.Property<android.view.View, java.lang.Float> ALPHA;
+    field public static final int AUTOFILL_TYPE_DATE = 4; // 0x4
+    field public static final int AUTOFILL_TYPE_LIST = 3; // 0x3
+    field public static final int AUTOFILL_TYPE_NONE = 0; // 0x0
+    field public static final int AUTOFILL_TYPE_TEXT = 1; // 0x1
+    field public static final int AUTOFILL_TYPE_TOGGLE = 2; // 0x2
     field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DATE = 512; // 0x200
     field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DAY = 4096; // 0x1000
     field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_MONTH = 1024; // 0x400
@@ -45930,6 +45942,9 @@
     field public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 2; // 0x2
     field public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 4; // 0x4
     field public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 1; // 0x1
+    field public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0; // 0x0
+    field public static final int IMPORTANT_FOR_AUTOFILL_NO = 2; // 0x2
+    field public static final int IMPORTANT_FOR_AUTOFILL_YES = 1; // 0x1
     field public static final int INVISIBLE = 4; // 0x4
     field public static final int KEEP_SCREEN_ON = 67108864; // 0x4000000
     field public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
@@ -46546,8 +46561,9 @@
     method public abstract void setAlpha(float);
     method public abstract void setAutoFillHint(int);
     method public abstract void setAutoFillOptions(java.lang.String[]);
-    method public abstract void setAutoFillType(android.view.autofill.AutoFillType);
+    method public abstract deprecated void setAutoFillType(android.view.autofill.AutoFillType);
     method public abstract void setAutoFillValue(android.view.autofill.AutoFillValue);
+    method public abstract void setAutofillType(int);
     method public abstract void setCheckable(boolean);
     method public abstract void setChecked(boolean);
     method public abstract void setChildCount(int);
@@ -47805,17 +47821,27 @@
   }
 
   public final class AutoFillManager {
+    method public void registerCallback(android.view.autofill.AutoFillManager.AutofillCallback);
     method public void reset();
     method public void startAutoFillRequest(android.view.View);
     method public void startAutoFillRequestOnVirtualView(android.view.View, int, android.graphics.Rect);
     method public void stopAutoFillRequest(android.view.View);
     method public void stopAutoFillRequestOnVirtualView(android.view.View, int);
+    method public void unregisterCallback(android.view.autofill.AutoFillManager.AutofillCallback);
     method public void valueChanged(android.view.View);
     method public void virtualValueChanged(android.view.View, int, android.view.autofill.AutoFillValue);
     field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE";
     field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT";
   }
 
+  public static abstract class AutoFillManager.AutofillCallback {
+    ctor public AutoFillManager.AutofillCallback();
+    method public void onAutofillEvent(android.view.View, int);
+    method public void onAutofillEventVirtual(android.view.View, int, int);
+    field public static final int EVENT_INPUT_HIDDEN = 2; // 0x2
+    field public static final int EVENT_INPUT_SHOWN = 1; // 0x1
+  }
+
   public final class AutoFillType implements android.os.Parcelable {
     method public int describeContents();
     method public static android.view.autofill.AutoFillType forDate();
@@ -48280,9 +48306,9 @@
   }
 
   public abstract interface TextClassifier {
-    method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int);
-    method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int);
-    method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int);
+    method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int, android.os.LocaleList);
+    method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int, android.os.LocaleList);
+    method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int, android.os.LocaleList);
     field public static final android.view.textclassifier.TextClassifier NO_OP;
     field public static final java.lang.String TYPE_ADDRESS = "address";
     field public static final java.lang.String TYPE_EMAIL = "email";
diff --git a/api/test-removed.txt b/api/test-removed.txt
index c5dbf8d..148f3f1 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -369,6 +369,16 @@
 
 }
 
+package android.view.textclassifier {
+
+  public abstract interface TextClassifier {
+    method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int);
+    method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int);
+    method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int);
+  }
+
+}
+
 package android.webkit {
 
   public class WebViewClient {
diff --git a/cmds/uiautomator/library/Android.mk b/cmds/uiautomator/library/Android.mk
index f932388..e70bd11 100644
--- a/cmds/uiautomator/library/Android.mk
+++ b/cmds/uiautomator/library/Android.mk
@@ -49,7 +49,7 @@
     -api $(uiautomator_internal_api_file) \
     -removedApi $(uiautomator_internal_removed_api_file)
 
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR := build/tools/droiddoc/templates-sdk
+LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR := external/doclava/res/assets/templates-sdk
 LOCAL_UNINSTALLABLE_MODULE := true
 
 LOCAL_MODULE := uiautomator-stubs
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 8e0098f..2e0ca02 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -538,7 +538,7 @@
         // TODO(b/33197203): once we have more flags, it might be better to store the individual
         // fields (viewId and childId) of the field.
         AutoFillId mAutoFillId;
-        AutoFillType mAutoFillType;
+        @View.AutofillType int mAutofillType;
         @View.AutoFillHint int mAutoFillHint;
         AutoFillValue mAutoFillValue;
         String[] mAutoFillOptions;
@@ -623,7 +623,7 @@
             if ((flags&FLAGS_HAS_AUTO_FILL_DATA) != 0) {
                 mSanitized = in.readInt() == 1;
                 mAutoFillId = in.readParcelable(null);
-                mAutoFillType = in.readParcelable(null);
+                mAutofillType = in.readInt();
                 mAutoFillHint = in.readInt();
                 mAutoFillValue = in.readParcelable(null);
                 mAutoFillOptions = in.readStringArray();
@@ -757,7 +757,7 @@
                 writeSensitive = mSanitized || !sanitizeOnWrite;
                 out.writeInt(mSanitized ? 1 : 0);
                 out.writeParcelable(mAutoFillId, 0);
-                out.writeParcelable(mAutoFillType,  0);
+                out.writeInt(mAutofillType);
                 out.writeInt(mAutoFillHint);
                 final AutoFillValue sanitizedValue = writeSensitive ? mAutoFillValue : null;
                 out.writeParcelable(sanitizedValue,  0);
@@ -851,14 +851,32 @@
         }
 
         /**
+         * @deprecated TODO(b/35956626): remove once clients use getAutoFilltype()
+         */
+        @Deprecated
+        public AutoFillType getAutoFillType() {
+            switch (getAutofillType()) {
+                case View.AUTOFILL_TYPE_TEXT:
+                    return AutoFillType.forText();
+                case View.AUTOFILL_TYPE_TOGGLE:
+                    return AutoFillType.forToggle();
+                case View.AUTOFILL_TYPE_LIST:
+                    return AutoFillType.forList();
+                case View.AUTOFILL_TYPE_DATE:
+                    return AutoFillType.forDate();
+                default:
+                    return null;
+            }
+        }
+
+        /**
          * Gets the the type of value that can be used to auto-fill the view contents.
          *
          * <p>It's only set when the {@link AssistStructure} is used for auto-filling purposes, not
          * for assist.
          */
-        // TODO(b/33197203, b/33802548): add CTS/unit test
-        public AutoFillType getAutoFillType() {
-            return mAutoFillType;
+        public @View.AutofillType int getAutofillType() {
+            return mAutofillType;
         }
 
         /**
@@ -1562,7 +1580,22 @@
 
         @Override
         public void setAutoFillType(AutoFillType type) {
-           mNode.mAutoFillType = type;
+            if (type == null) return;
+
+            if (type.isText()) {
+                mNode.mAutofillType = View.AUTOFILL_TYPE_TEXT;
+            } else if (type.isToggle()) {
+                mNode.mAutofillType = View.AUTOFILL_TYPE_TOGGLE;
+            } else if (type.isList()) {
+                mNode.mAutofillType = View.AUTOFILL_TYPE_LIST;
+            } else if (type.isDate()) {
+                mNode.mAutofillType = View.AUTOFILL_TYPE_DATE;
+            }
+        }
+
+        @Override
+        public void setAutofillType(@View.AutofillType int type) {
+            mNode.mAutofillType = type;
         }
 
         @Override
@@ -1711,7 +1744,7 @@
             Log.i(TAG, prefix + " NO AUTO-FILL ID");
         } else {
             Log.i(TAG, prefix + "AutoFill info: id= " + autoFillId
-                    + ", type=" + node.getAutoFillType()
+                    + ", type=" + node.getAutofillType()
                     + ", options=" + Arrays.toString(node.getAutoFillOptions())
                     + ", inputType=" + node.getInputType()
                     + ", hint=" + Integer.toHexString(node.getAutoFillHint())
diff --git a/core/java/android/content/AsyncTaskLoader.java b/core/java/android/content/AsyncTaskLoader.java
index 7241e0d..b7545bf 100644
--- a/core/java/android/content/AsyncTaskLoader.java
+++ b/core/java/android/content/AsyncTaskLoader.java
@@ -170,6 +170,9 @@
     protected boolean onCancelLoad() {
         if (DEBUG) Log.v(TAG, "onCancelLoad: mTask=" + mTask);
         if (mTask != null) {
+            if (!mStarted) {
+                mContentChanged = true;
+            }
             if (mCancellingTask != null) {
                 // There was a pending task already waiting for a previous
                 // one being canceled; just drop it.
diff --git a/core/java/android/content/om/IOverlayManager.aidl b/core/java/android/content/om/IOverlayManager.aidl
index 4f5d960..86c1aa8 100644
--- a/core/java/android/content/om/IOverlayManager.aidl
+++ b/core/java/android/content/om/IOverlayManager.aidl
@@ -89,6 +89,11 @@
     boolean setEnabled(in String packageName, in boolean enable, in int userId);
 
     /**
+     * Version of setEnabled that will also disable any other overlays for the target package.
+     */
+    boolean setEnabledExclusive(in String packageName, in boolean enable, in int userId);
+
+    /**
      * Change the priority of the given overlay to be just higher than the
      * overlay with package name newParentPackageName. Both overlay packages
      * must have the same target and user.
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 664e76b..3a875bc 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -34,6 +34,7 @@
 import android.app.PackageDeleteObserver;
 import android.app.PackageInstallObserver;
 import android.app.admin.DevicePolicyManager;
+import android.app.usage.StorageStatsManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -5466,8 +5467,10 @@
      * the status of the operation. observer may be null to indicate that
      * no callback is desired.
      *
+     * @deprecated use {@link StorageStatsManager} instead.
      * @hide
      */
+    @Deprecated
     public abstract void getPackageSizeInfoAsUser(String packageName, @UserIdInt int userId,
             IPackageStatsObserver observer);
 
@@ -5475,8 +5478,10 @@
      * Like {@link #getPackageSizeInfoAsUser(String, int, IPackageStatsObserver)}, but
      * returns the size for the calling user.
      *
+     * @deprecated use {@link StorageStatsManager} instead.
      * @hide
      */
+    @Deprecated
     public void getPackageSizeInfo(String packageName, IPackageStatsObserver observer) {
         getPackageSizeInfoAsUser(packageName, UserHandle.myUserId(), observer);
     }
diff --git a/core/java/android/content/pm/PackageStats.java b/core/java/android/content/pm/PackageStats.java
index c746af4..27b3506 100644
--- a/core/java/android/content/pm/PackageStats.java
+++ b/core/java/android/content/pm/PackageStats.java
@@ -16,6 +16,7 @@
 
 package android.content.pm;
 
+import android.app.usage.StorageStatsManager;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.UserHandle;
@@ -24,9 +25,13 @@
 import java.util.Objects;
 
 /**
- * implementation of PackageStats associated with a
- * application package.
+ * implementation of PackageStats associated with a application package.
+ *
+ * @deprecated this class is an orphan that could never be obtained from a valid
+ *             public API. If you need package storage statistics use the new
+ *             {@link StorageStatsManager} APIs.
  */
+@Deprecated
 public class PackageStats implements Parcelable {
     /** Name of the package to which this stats applies. */
     public String packageName;
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 493ed8c..7bfb5d0 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -731,7 +731,7 @@
     @SystemApi
     @TestApi
     public static final int SESSION_OPERATION_MODE_NORMAL =
-            ICameraDeviceUser.NORMAL_MODE;
+            0; // ICameraDeviceUser.NORMAL_MODE;
 
     /**
      * Constrained high-speed operation mode.
@@ -742,7 +742,7 @@
     @SystemApi
     @TestApi
     public static final int SESSION_OPERATION_MODE_CONSTRAINED_HIGH_SPEED =
-            ICameraDeviceUser.CONSTRAINED_HIGH_SPEED_MODE;
+            1; // ICameraDeviceUser.CONSTRAINED_HIGH_SPEED_MODE;
 
     /**
      * First vendor-specific operating mode
@@ -753,7 +753,7 @@
     @SystemApi
     @TestApi
     public static final int SESSION_OPERATION_MODE_VENDOR_START =
-            ICameraDeviceUser.VENDOR_MODE_START;
+            0x8000; // ICameraDeviceUser.VENDOR_MODE_START;
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 98a5749..b276008 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -213,6 +213,10 @@
         // If true, scales the brightness to half of desired.
         public boolean lowPowerMode;
 
+        // The factor to adjust the screen brightness in low power mode in the range
+        // 0 (screen off) to 1 (no change)
+        public float screenLowPowerBrightnessFactor;
+
         // If true, applies a brightness boost.
         public boolean boostScreenBrightness;
 
@@ -235,6 +239,7 @@
             useProximitySensor = false;
             screenBrightness = PowerManager.BRIGHTNESS_ON;
             screenAutoBrightnessAdjustment = 0.0f;
+            screenLowPowerBrightnessFactor = 0.5f;
             useAutoBrightness = false;
             blockScreenOn = false;
             dozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
@@ -258,6 +263,7 @@
             useProximitySensor = other.useProximitySensor;
             screenBrightness = other.screenBrightness;
             screenAutoBrightnessAdjustment = other.screenAutoBrightnessAdjustment;
+            screenLowPowerBrightnessFactor = other.screenLowPowerBrightnessFactor;
             brightnessSetByUser = other.brightnessSetByUser;
             useAutoBrightness = other.useAutoBrightness;
             blockScreenOn = other.blockScreenOn;
@@ -279,6 +285,8 @@
                     && useProximitySensor == other.useProximitySensor
                     && screenBrightness == other.screenBrightness
                     && screenAutoBrightnessAdjustment == other.screenAutoBrightnessAdjustment
+                    && screenLowPowerBrightnessFactor
+                    == other.screenLowPowerBrightnessFactor
                     && brightnessSetByUser == other.brightnessSetByUser
                     && useAutoBrightness == other.useAutoBrightness
                     && blockScreenOn == other.blockScreenOn
@@ -299,6 +307,7 @@
                     + ", useProximitySensor=" + useProximitySensor
                     + ", screenBrightness=" + screenBrightness
                     + ", screenAutoBrightnessAdjustment=" + screenAutoBrightnessAdjustment
+                    + ", screenLowPowerBrightnessFactor=" + screenLowPowerBrightnessFactor
                     + ", brightnessSetByUser=" + brightnessSetByUser
                     + ", useAutoBrightness=" + useAutoBrightness
                     + ", blockScreenOn=" + blockScreenOn
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index ff87b67..27e2a50 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -338,6 +338,20 @@
     }
 
     /**
+     * Controls standby mode of the system. It will also try to turn on/off the connected devices if
+     * necessary.
+     *
+     * @param isStandbyModeOn target status of the system's standby mode
+     */
+    public void setStandbyMode(boolean isStandbyModeOn) {
+        try {
+            mService.setStandbyMode(isStandbyModeOn);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Listener used to get hotplug event from HDMI port.
      */
     public interface HotplugEventListener {
diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
index c1e924e..67e2d18 100644
--- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
@@ -71,4 +71,5 @@
     void clearTimerRecording(int recorderAddress, int sourceType, in byte[] recordSource);
     void sendMhlVendorCommand(int portId, int offset, int length, in byte[] data);
     void addHdmiMhlVendorCommandListener(IHdmiMhlVendorCommandListener listener);
+    void setStandbyMode(boolean isStandbyModeOn);
 }
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index d50a838..dc170ed 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -2410,6 +2410,10 @@
     // Step duration mode: the screen is on, off, dozed, etc; value is Display.STATE_* - 1.
     public static final int STEP_LEVEL_MODE_SCREEN_STATE = 0x03;
 
+    // The largest value for screen state that is tracked in battery states. Any values above
+    // this should be mapped back to one of the tracked values before being tracked here.
+    public static final int MAX_TRACKED_SCREEN_STATE = Display.STATE_DOZE_SUSPEND;
+
     // Step duration mode: power save is on.
     public static final int STEP_LEVEL_MODE_POWER_SAVE = 0x04;
 
@@ -3137,8 +3141,8 @@
                 for (Map.Entry<String, ? extends Timer> ent : kernelWakelocks.entrySet()) {
                     sb.setLength(0);
                     printWakeLockCheckin(sb, ent.getValue(), rawRealtime, null, which, "");
-                    dumpLine(pw, 0 /* uid */, category, KERNEL_WAKELOCK_DATA, ent.getKey(),
-                            sb.toString());
+                    dumpLine(pw, 0 /* uid */, category, KERNEL_WAKELOCK_DATA,
+                            "\"" + ent.getKey() + "\"", sb.toString());
                 }
             }
             final Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats();
@@ -3339,7 +3343,8 @@
                 final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
                 final int count = timer.getCountLocked(which);
                 if (totalTime != 0) {
-                    dumpLine(pw, uid, category, SYNC_DATA, syncs.keyAt(isy), totalTime, count);
+                    dumpLine(pw, uid, category, SYNC_DATA, "\"" + syncs.keyAt(isy) + "\"",
+                            totalTime, count);
                 }
             }
 
@@ -3350,7 +3355,8 @@
                 final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
                 final int count = timer.getCountLocked(which);
                 if (totalTime != 0) {
-                    dumpLine(pw, uid, category, JOB_DATA, jobs.keyAt(ij), totalTime, count);
+                    dumpLine(pw, uid, category, JOB_DATA, "\"" + jobs.keyAt(ij) + "\"",
+                            totalTime, count);
                 }
             }
 
@@ -3422,8 +3428,8 @@
 
                 if (userMillis != 0 || systemMillis != 0 || foregroundMillis != 0
                         || starts != 0 || numAnrs != 0 || numCrashes != 0) {
-                    dumpLine(pw, uid, category, PROCESS_DATA, processStats.keyAt(ipr), userMillis,
-                            systemMillis, foregroundMillis, starts, numAnrs, numCrashes);
+                    dumpLine(pw, uid, category, PROCESS_DATA, "\"" + processStats.keyAt(ipr) + "\"",
+                            userMillis, systemMillis, foregroundMillis, starts, numAnrs, numCrashes);
                 }
             }
 
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index af05ee7..50b4f8c 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -777,10 +777,15 @@
      * "29.5GB" in UI.
      */
     public static long roundStorageSize(long size) {
-        long res = 1;
-        while (res < size) {
-            res <<= 1;
+        long val = 1;
+        long pow = 1;
+        while ((val * pow) < size) {
+            val <<= 1;
+            if (val > 512) {
+                val = 1;
+                pow *= 1000;
+            }
         }
-        return res;
+        return val * pow;
     }
 }
diff --git a/core/java/android/os/HwBinder.java b/core/java/android/os/HwBinder.java
index e025494..b09c51c 100644
--- a/core/java/android/os/HwBinder.java
+++ b/core/java/android/os/HwBinder.java
@@ -43,9 +43,7 @@
             int code, HwParcel request, HwParcel reply, int flags)
         throws RemoteException;
 
-    public native final void registerService(
-            ArrayList<String> interfaceChain,
-            String serviceName)
+    public native final void registerService(String serviceName)
         throws RemoteException;
 
     public static native final IHwBinder getService(
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 1d464c0..b715780 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -2,22 +2,23 @@
 **
 ** Copyright 2007, The Android Open Source Project
 **
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
 **
-**     http://www.apache.org/licenses/LICENSE-2.0 
+**     http://www.apache.org/licenses/LICENSE-2.0
 **
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
 
 package android.os;
 
 import android.os.WorkSource;
+import android.os.PowerSaveState;
 
 /** @hide */
 
@@ -45,6 +46,7 @@
     void nap(long time);
     boolean isInteractive();
     boolean isPowerSaveMode();
+    PowerSaveState getPowerSaveState(int serviceType);
     boolean setPowerSaveMode(boolean mode);
     boolean isDeviceIdleMode();
     boolean isLightDeviceIdleMode();
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 31b3bc9..a713eef 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -971,6 +971,24 @@
     }
 
     /**
+     * Get data about the battery saver mode for a specific service
+     * @param serviceType unique key for the service, one of
+     *             {@link com.android.server.power.BatterySaverPolicy.ServiceType}
+     * @return Battery saver state data.
+     *
+     * @hide
+     * @see com.android.server.power.BatterySaverPolicy
+     * @see PowerSaveState
+     */
+    public PowerSaveState getPowerSaveState(int serviceType) {
+        try {
+            return mService.getPowerSaveState(serviceType);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Returns true if the device is currently in idle mode.  This happens when a device
      * has been sitting unused and unmoving for a sufficiently long period of time, so that
      * it decides to go into a lower power-use state.  This may involve things like turning
diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java
index d0db255..44addfc 100644
--- a/core/java/android/os/PowerManagerInternal.java
+++ b/core/java/android/os/PowerManagerInternal.java
@@ -131,12 +131,13 @@
     public abstract void setDozeOverrideFromDreamManager(
             int screenState, int screenBrightness);
 
-    public abstract boolean getLowPowerModeEnabled();
+    public abstract PowerSaveState getLowPowerState(int serviceType);
 
     public abstract void registerLowPowerModeObserver(LowPowerModeListener listener);
 
     public interface LowPowerModeListener {
-        public void onLowPowerModeChanged(boolean enabled);
+        int getServiceType();
+        void onLowPowerModeChanged(PowerSaveState state);
     }
 
     public abstract boolean setDeviceIdleMode(boolean enabled);
diff --git a/core/java/android/os/PowerSaveState.aidl b/core/java/android/os/PowerSaveState.aidl
new file mode 100644
index 0000000..e3f572d
--- /dev/null
+++ b/core/java/android/os/PowerSaveState.aidl
@@ -0,0 +1,19 @@
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.os;
+
+parcelable PowerSaveState;
\ No newline at end of file
diff --git a/core/java/android/os/PowerSaveState.java b/core/java/android/os/PowerSaveState.java
new file mode 100644
index 0000000..9269e76
--- /dev/null
+++ b/core/java/android/os/PowerSaveState.java
@@ -0,0 +1,95 @@
+/* Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package android.os;
+
+/**
+ * Data class for battery saver state. It contains the data
+ * <p>
+ * 1. Whether battery saver mode is enabled
+ * 2. Specific parameters to use in battery saver mode(i.e. screen brightness, gps mode)
+ *
+ * @hide
+ */
+public class PowerSaveState implements Parcelable {
+    public final boolean batterySaverEnabled;
+    public final int gpsMode;
+    public final float brightnessFactor;
+
+    public PowerSaveState(Builder builder) {
+        batterySaverEnabled = builder.mBatterySaverEnabled;
+        gpsMode = builder.mGpsMode;
+        brightnessFactor = builder.mBrightnessFactor;
+    }
+
+    public PowerSaveState(Parcel in) {
+        batterySaverEnabled = in.readByte() != 0;
+        gpsMode = in.readInt();
+        brightnessFactor = in.readFloat();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeByte((byte) (batterySaverEnabled ? 1 : 0));
+        dest.writeInt(gpsMode);
+        dest.writeFloat(brightnessFactor);
+    }
+
+    public static final class Builder {
+        private boolean mBatterySaverEnabled = false;
+        private int mGpsMode = 0;
+        private float mBrightnessFactor = 0.5f;
+
+        public Builder() {}
+
+        public Builder setBatterySaverEnabled(boolean enabled) {
+            mBatterySaverEnabled = enabled;
+            return this;
+        }
+
+        public Builder setGpsMode(int mode) {
+            mGpsMode = mode;
+            return this;
+        }
+
+        public Builder setBrightnessFactor(float factor) {
+            mBrightnessFactor = factor;
+            return this;
+        }
+
+        public PowerSaveState build() {
+            return new PowerSaveState(this);
+        }
+    }
+
+    public static final Parcelable.Creator<PowerSaveState>
+            CREATOR = new Parcelable.Creator<PowerSaveState>() {
+
+        @Override
+        public PowerSaveState createFromParcel(Parcel source) {
+            return new PowerSaveState(source);
+        }
+
+        @Override
+        public PowerSaveState[] newArray(int size) {
+            return new PowerSaveState[size];
+        }
+    };
+}
\ No newline at end of file
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index a1f8dfb..e1fb37b 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -56,6 +56,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.MetricsLogger;
 import com.android.internal.os.AppFuseMount;
 import com.android.internal.os.FuseAppLoop;
 import com.android.internal.os.RoSystemProperties;
@@ -1006,7 +1007,8 @@
         for (String path : INTERNAL_STORAGE_SIZE_PATHS) {
             final long numberBlocks = readLong(path);
             if (numberBlocks > 0) {
-                return new Pair<>(path, Long.valueOf(numberBlocks * INTERNAL_STORAGE_SECTOR_SIZE));
+                return new Pair<>(path,
+                        FileUtils.roundStorageSize(numberBlocks * INTERNAL_STORAGE_SECTOR_SIZE));
             }
         }
         return null;
@@ -1386,6 +1388,7 @@
     public @NonNull ParcelFileDescriptor openProxyFileDescriptor(
             int mode, ProxyFileDescriptorCallback callback, ThreadFactory factory)
                     throws IOException {
+        MetricsLogger.count(mContext, "storage_open_proxy_file_descriptor", 1);
         // Retry is needed because the mount point mFuseAppLoop is using may be unmounted before
         // invoking StorageManagerService#openProxyFileDescriptor. In this case, we need to re-mount
         // the bridge by calling mountProxyFileDescriptorBridge.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 280400a..e3a9d80 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -295,7 +295,9 @@
      * In some cases, a matching Activity may not exist, so ensure you
      * safeguard against this.
      * <p>
-     * Input: Nothing.
+     * Input: Optionally, the Intent's data URI can specify the application package name to
+     * directly invoke the management GUI specific to the package name. For example
+     * "package:com.my.app".
      * <p>
      * Output: Nothing.
      */
@@ -8963,6 +8965,30 @@
         public static final String DEVICE_IDLE_CONSTANTS_WATCH = "device_idle_constants_watch";
 
         /**
+         * Battery Saver specific settings
+         * This is encoded as a key=value list, separated by commas. Ex:
+         *
+         * "vibration_disabled=true,adjust_brightness_factor=0.5"
+         *
+         * The following keys are supported:
+         *
+         * <pre>
+         * vibration_disabled                (boolean)
+         * animation_disabled                (boolean)
+         * soundtrigger_disabled             (boolean)
+         * fullbackup_deferred               (boolean)
+         * keyvaluebackup_deferred           (boolean)
+         * firewall_disabled                 (boolean)
+         * gps_mode                          (int)
+         * adjust_brightness_disabled        (boolean)
+         * adjust_brightness_factor          (float)
+         * </pre>
+         * @hide
+         * @see com.android.server.power.BatterySaverPolicy
+         */
+        public static final String BATTERY_SAVER_CONSTANTS = "battery_saver_constants";
+
+        /**
          * App standby (app idle) specific settings.
          * This is encoded as a key=value list, separated by commas. Ex:
          *
diff --git a/core/java/android/util/MathUtils.java b/core/java/android/util/MathUtils.java
index 32aac13..5c718f1 100644
--- a/core/java/android/util/MathUtils.java
+++ b/core/java/android/util/MathUtils.java
@@ -24,7 +24,6 @@
  * @hide Pending API council approval
  */
 public final class MathUtils {
-    private static final Random sRandom = new Random();
     private static final float DEG_TO_RAD = 3.1415926f / 180.0f;
     private static final float RAD_TO_DEG = 180.0f / 3.1415926f;
 
@@ -185,28 +184,6 @@
         return maxStart + (maxStart - maxStop) * ((value - minStart) / (minStop - minStart));
     }
 
-    public static int random(int howbig) {
-        return (int) (sRandom.nextFloat() * howbig);
-    }
-
-    public static int random(int howsmall, int howbig) {
-        if (howsmall >= howbig) return howsmall;
-        return (int) (sRandom.nextFloat() * (howbig - howsmall) + howsmall);
-    }
-
-    public static float random(float howbig) {
-        return sRandom.nextFloat() * howbig;
-    }
-
-    public static float random(float howsmall, float howbig) {
-        if (howsmall >= howbig) return howsmall;
-        return sRandom.nextFloat() * (howbig - howsmall) + howsmall;
-    }
-
-    public static void randomSeed(long seed) {
-        sRandom.setSeed(seed);
-    }
-
     /**
      * Returns the sum of the two parameters, or throws an exception if the resulting sum would
      * cause an overflow or underflow.
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 7ec7ba7..5494377 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -302,7 +302,6 @@
      *
      * @see #getState
      * @see android.os.PowerManager#isInteractive
-     * @hide
      */
     public static final int STATE_VR = 5;
 
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 040a59b..8cfd6a7 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1115,6 +1115,89 @@
      */
     @AutoFillHint private int mAutoFillHint;
 
+    /** @hide */
+    @IntDef({
+            AUTOFILL_TYPE_NONE,
+            AUTOFILL_TYPE_TEXT,
+            AUTOFILL_TYPE_TOGGLE,
+            AUTOFILL_TYPE_LIST,
+            AUTOFILL_TYPE_DATE
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface AutofillType {}
+
+    /**
+     * Autofill type for views that cannot be autofilled.
+     */
+    public static final int AUTOFILL_TYPE_NONE = 0;
+
+    /**
+     * Autofill type for a text field, which is filled by a {@link CharSequence}.
+     *
+     * <p>{@link AutoFillValue} instances for autofilling a {@link View} can be obtained through
+     * {@link AutoFillValue#forText(CharSequence)}, and the value passed to auto-fill a
+     * {@link View} can be fetched through {@link AutoFillValue#getTextValue()}.
+     */
+    public static final int AUTOFILL_TYPE_TEXT = 1;
+
+    /**
+     * Autofill type for a togglable field, which is filled by a {@code boolean}.
+     *
+     * <p>{@link AutoFillValue} instances for auto-filling a {@link View} can be obtained through
+     * {@link AutoFillValue#forToggle(boolean)}, and the value passed to auto-fill a
+     * {@link View} can be fetched through {@link AutoFillValue#getToggleValue()}.
+     */
+    public static final int AUTOFILL_TYPE_TOGGLE = 2;
+
+    /**
+     * Autofill type for a selection list field, which is filled by an {@code int}
+     * representing the element index inside the list (starting at {@code 0}).
+     *
+     * <p>{@link AutoFillValue} instances for autofilling a {@link View} can be obtained through
+     * {@link AutoFillValue#forList(int)}, and the value passed to auto-fill a
+     * {@link View} can be fetched through {@link AutoFillValue#getListValue()}.
+     *
+     * <p>The available options in the selection list are typically provided by
+     * {@link android.app.assist.AssistStructure.ViewNode#getAutoFillOptions()}.
+     */
+    public static final int AUTOFILL_TYPE_LIST = 3;
+
+
+    /**
+     * Autofill type for a field that contains a date, which is represented by a long representing
+     * the number of milliseconds since the standard base time known as "the epoch", namely
+     * January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}.
+     *
+     * <p>{@link AutoFillValue} instances for autofilling a {@link View} can be obtained through
+     * {@link AutoFillValue#forDate(long)}, and the values passed to
+     * auto-fill a {@link View} can be fetched through {@link AutoFillValue#getDateValue()}.
+     */
+    public static final int AUTOFILL_TYPE_DATE = 4;
+
+    /** @hide */
+    @IntDef({
+            IMPORTANT_FOR_AUTOFILL_AUTO,
+            IMPORTANT_FOR_AUTOFILL_YES,
+            IMPORTANT_FOR_AUTOFILL_NO
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface AutofillImportance {}
+
+    /**
+     * Automatically determine whether a view is important for auto-fill.
+     */
+    public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0x0;
+
+    /**
+     * The view is important for important for auto-fill.
+     */
+    public static final int IMPORTANT_FOR_AUTOFILL_YES = 0x1;
+
+    /**
+     * The view is not important for auto-fill.
+     */
+    public static final int IMPORTANT_FOR_AUTOFILL_NO = 0x2;
+
     /**
      * This view is enabled. Interpretation varies by subclass.
      * Use with ENABLED_MASK when calling setFlags.
@@ -2686,7 +2769,7 @@
      *                1                  PFLAG3_FINGER_DOWN
      *               1                   PFLAG3_FOCUSED_BY_DEFAULT
      *             11                    PFLAG3_AUTO_FILL_MODE_MASK
-     *           xx                      * NO LONGER NEEDED, SHOULD BE REUSED *
+     *           11                      PFLAG3_IMPORTANT_FOR_AUTOFILL
      *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
      *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
      *        1                          PFLAG3_TEMPORARY_DETACH
@@ -2924,6 +3007,20 @@
             | AUTO_FILL_MODE_AUTO | AUTO_FILL_MODE_MANUAL) << PFLAG3_AUTO_FILL_MODE_SHIFT;
 
     /**
+     * Shift for the bits in {@link #mPrivateFlags3} related to the
+     * "importantForAutofill" attribute.
+     */
+    static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT = 21;
+
+    /**
+     * Mask for obtaining the bits which specify how to determine
+     * whether a view is important for autofill.
+     */
+    static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK = (IMPORTANT_FOR_AUTOFILL_AUTO
+            | IMPORTANT_FOR_AUTOFILL_YES | IMPORTANT_FOR_AUTOFILL_NO)
+            << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
+
+    /**
      * Whether this view has rendered elements that overlap (see {@link
      * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
      * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
@@ -4950,6 +5047,11 @@
                         setAutoFillHint(a.getInt(attr, AUTO_FILL_HINT_NONE));
                     }
                     break;
+                case R.styleable.View_importantForAutofill:
+                    if (a.peekValue(attr) != null) {
+                        setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
+                    }
+                    break;
             }
         }
 
@@ -7178,14 +7280,14 @@
         }
 
         if (forAutoFill) {
-            final AutoFillType autoFillType = getAutoFillType();
+            final @AutofillType int autofillType = getAutofillType();
             // Don't need to fill auto-fill info if view does not support it.
             // For example, only TextViews that are editable support auto-fill
-            if (autoFillType != null) {
+            if (autofillType != AUTOFILL_TYPE_NONE) {
                 // The auto-fill id needs to be unique, but its value doesn't matter, so it's better
                 // to reuse the accessibility id to save space.
                 structure.setAutoFillId(getAccessibilityViewId());
-                structure.setAutoFillType(autoFillType);
+                structure.setAutofillType(autofillType);
                 structure.setAutoFillHint(getAutoFillHint());
                 structure.setAutoFillValue(getAutoFillValue());
             }
@@ -7291,7 +7393,7 @@
     /**
      * Automatically fills the content of this view with the {@code value}.
      *
-     * <p>By default does nothing, but views should override it (and {@link #getAutoFillType()},
+     * <p>By default does nothing, but views should override it (and {@link #getAutofillType()},
      * {@link #getAutoFillValue()}, and {@link #onProvideAutoFillStructure(ViewStructure, int)}
      * to support the AutoFill Framework.
      *
@@ -7330,15 +7432,34 @@
     }
 
     /**
+     * @deprecated TODO(b/35956626): remove once clients use getAutoFilltype
+     */
+    @Deprecated
+    @Nullable
+    public final AutoFillType getAutoFillType() {
+        switch (getAutofillType()) {
+            case AUTOFILL_TYPE_TEXT:
+                return AutoFillType.forText();
+            case AUTOFILL_TYPE_TOGGLE:
+                return AutoFillType.forToggle();
+            case AUTOFILL_TYPE_LIST:
+                return AutoFillType.forList();
+            case AUTOFILL_TYPE_DATE:
+                return AutoFillType.forDate();
+            default:
+                return null;
+        }
+    }
+
+    /**
      * Describes the auto-fill type that should be used on calls to
      * {@link #autoFill(AutoFillValue)} and {@link #autoFillVirtual(int, AutoFillValue)}.
      *
-     * <p>By default returns {@code null}, but views should override it (and
+     * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it (and
      * {@link #autoFill(AutoFillValue)} to support the AutoFill Framework.
      */
-    @Nullable
-    public AutoFillType getAutoFillType() {
-        return null;
+    public @AutofillType int getAutofillType() {
+        return AUTOFILL_TYPE_NONE;
     }
 
     /**
@@ -7357,7 +7478,7 @@
      * Gets the {@link View}'s current auto-fill value.
      *
      * <p>By default returns {@code null}, but views should override it (and
-     * {@link #autoFill(AutoFillValue)}, and {@link #getAutoFillType()} to support the AutoFill
+     * {@link #autoFill(AutoFillValue)}, and {@link #getAutofillType()} to support the AutoFill
      * Framework.
      */
     @Nullable
@@ -7365,13 +7486,125 @@
         return null;
     }
 
+    /**
+     * Gets the mode for determining whether this View is important for autofill.
+     *
+     * <p>See {@link #setImportantForAutofill(int)} for more info about this mode.
+     *
+     * @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to
+     * {@link #setImportantForAutofill(int)}.
+     *
+     * @attr ref android.R.styleable#View_importantForAutofill
+     */
+    @ViewDebug.ExportedProperty(mapping = {
+            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_AUTO, to = "auto"),
+            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES, to = "yes"),
+            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO, to = "no")})
+    public @AutofillImportance int getImportantForAutofill() {
+        return (mPrivateFlags3
+                & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK) >> PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
+    }
+
+    /**
+     * Sets the mode for determining whether this View is important for autofill.
+     *
+     * <p>See {@link #setImportantForAutofill(int)} for more info about this mode.
+     *
+     * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES},
+     * or {@link #IMPORTANT_FOR_AUTOFILL_NO}.
+     *
+     * @attr ref android.R.styleable#View_importantForAutofill
+     */
+    public void setImportantForAutofill(@AutofillImportance int mode) {
+        mPrivateFlags3 &= ~PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
+        mPrivateFlags3 |= (mode << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT)
+                & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
+    }
+
+    /**
+     * Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode}
+     * associated with this View should be included in a {@link ViewStructure} used for
+     * autofill purposes.
+     *
+     * <p>Generally speaking, a view is important for autofill if:
+     * <ol>
+     * <li>The view can-be autofilled by an {@link android.service.autofill.AutoFillService}.
+     * <li>The view contents can help an {@link android.service.autofill.AutoFillService} to
+     * autofill other views.
+     * <ol>
+     *
+     * <p>For example, view containers should typically return {@code false} for performance reasons
+     * (since the important info is provided by their children), but if the container is actually
+     * whose children are part of a compound view, it should return {@code true} (and then override
+     * {@link #dispatchProvideAutoFillStructure(ViewStructure, int)} to simply call
+     * {@link #onProvideAutoFillStructure(ViewStructure, int)} so its children are not included in
+     * the structure). On the other hand, views representing labels or editable fields should
+     * typically return {@code true}, but in some cases they could return {@code false} (for
+     * example, if they're part of a "Captcha" mechanism).
+     *
+     * <p>By default, this method returns {@code true} if {@link #getImportantForAutofill()} returns
+     * {@link #IMPORTANT_FOR_AUTOFILL_YES}, {@code false } if it returns
+     * {@link #IMPORTANT_FOR_AUTOFILL_NO}, and use some heuristics to define the importance when it
+     * returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}. Hence, it should rarely be overridden - Views
+     * should use {@link #setImportantForAutofill(int)} instead.
+     *
+     * <p><strong>Note:</strong> returning {@code false} does not guarantee the view will be
+     * excluded from the structure; for example, if the user explicitly requested auto-fill, the
+     * View might be always included.
+     *
+     * <p>This decision applies just for the view, not its children - if the view children are not
+     * important for autofill, the view should override
+     * {@link #dispatchProvideAutoFillStructure(ViewStructure, int)} to simply call
+     * {@link #onProvideAutoFillStructure(ViewStructure, int)} (instead of calling
+     * {@link #dispatchProvideAutoFillStructure(ViewStructure, int)} for each child).
+     *
+     * @return whether the view is considered important for autofill.
+     *
+     * @see #IMPORTANT_FOR_AUTOFILL_AUTO
+     * @see #IMPORTANT_FOR_AUTOFILL_YES
+     * @see #IMPORTANT_FOR_AUTOFILL_NO
+     */
+    public final boolean isImportantForAutofill() {
+        final int flag = getImportantForAutofill();
+
+        // First, check if view explicity set it to YES or NO
+        if ((flag & IMPORTANT_FOR_AUTOFILL_YES) != 0) {
+            return true;
+        }
+        if ((flag & IMPORTANT_FOR_AUTOFILL_NO) != 0) {
+            return false;
+        }
+
+        // Then use some heuristics to handle AUTO.
+
+        // Always include views that have a explicity resource id.
+        final int id = mID;
+        if (id != NO_ID && !isViewIdGenerated(id)) {
+            final Resources res = getResources();
+            String entry = null;
+            String pkg = null;
+            try {
+                entry = res.getResourceEntryName(id);
+                pkg = res.getResourcePackageName(id);
+            } catch (Resources.NotFoundException e) {
+                // ignore
+            }
+            if (entry != null && pkg != null && pkg.equals(mContext.getPackageName())) {
+                return true;
+            }
+        }
+
+        // Otherwise, assume it's not important...
+        return false;
+    }
+
     @Nullable
     private AutoFillManager getAutoFillManager() {
         return mContext.getSystemService(AutoFillManager.class);
     }
 
     private boolean isAutoFillable() {
-        return getAutoFillType() != null && !isAutoFillBlocked();
+        return getAutofillType() != AUTOFILL_TYPE_NONE && !isAutoFillBlocked();
     }
 
     private void populateVirtualStructure(ViewStructure structure,
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 3dd3ba8..214249f 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -595,6 +595,7 @@
 
     public ViewGroup(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
+
         initViewGroup();
         initFromAttributes(context, attrs, defStyleAttr, defStyleRes);
     }
@@ -3341,82 +3342,122 @@
         dispatchProvideStructureForAssistOrAutoFill(structure, true);
     }
 
+    /** @hide */
+    private ArrayList<View> getChildrenForAutofill() {
+        final ArrayList<View> list = new ArrayList<>();
+        populateChildrenForAutofill(list);
+        return list;
+    }
+
+    /** @hide */
+    private void populateChildrenForAutofill(ArrayList<View> list) {
+        final int count = mChildrenCount;
+        for (int i = 0; i < count; i++) {
+            final View child = mChildren[i];
+            if (child.isImportantForAutofill()) {
+                list.add(child);
+            } else if (child instanceof ViewGroup) {
+                ((ViewGroup) child).populateChildrenForAutofill(list);
+            }
+        }
+    }
+
     private void dispatchProvideStructureForAssistOrAutoFill(ViewStructure structure,
             boolean forAutoFill) {
         boolean blocked = forAutoFill ? isAutoFillBlocked() : isAssistBlocked();
+        if (blocked || structure.getChildCount() != 0) {
+            return;
+        }
+        final View[] childrenArray;
+        final ArrayList<View> childrenList;
+        final int childrenCount;
 
-        if (!blocked) {
-            if (structure.getChildCount() == 0) {
-                final int childrenCount = getChildCount();
-                if (childrenCount > 0) {
-                    structure.setChildCount(childrenCount);
-                    ArrayList<View> preorderedList = buildOrderedChildList();
-                    boolean customOrder = preorderedList == null
-                            && isChildrenDrawingOrderEnabled();
-                    final View[] children = mChildren;
-                    for (int i=0; i<childrenCount; i++) {
-                        int childIndex;
-                        try {
-                            childIndex = getAndVerifyPreorderedIndex(childrenCount, i, customOrder);
-                        } catch (IndexOutOfBoundsException e) {
-                            childIndex = i;
-                            if (mContext.getApplicationInfo().targetSdkVersion
-                                    < Build.VERSION_CODES.M) {
-                                Log.w(TAG, "Bad getChildDrawingOrder while collecting assist @ "
-                                        + i + " of " + childrenCount, e);
-                                // At least one app is failing when we call getChildDrawingOrder
-                                // at this point, so deal semi-gracefully with it by falling back
-                                // on the basic order.
-                                customOrder = false;
-                                if (i > 0) {
-                                    // If we failed at the first index, there really isn't
-                                    // anything to do -- we will just proceed with the simple
-                                    // sequence order.
-                                    // Otherwise, we failed in the middle, so need to come up
-                                    // with an order for the remaining indices and use that.
-                                    // Failed at the first one, easy peasy.
-                                    int[] permutation = new int[childrenCount];
-                                    SparseBooleanArray usedIndices = new SparseBooleanArray();
-                                    // Go back and collected the indices we have done so far.
-                                    for (int j=0; j<i; j++) {
-                                        permutation[j] = getChildDrawingOrder(childrenCount, j);
-                                        usedIndices.put(permutation[j], true);
-                                    }
-                                    // Fill in the remaining indices with indices that have not
-                                    // yet been used.
-                                    int nextIndex = 0;
-                                    for (int j=i; j<childrenCount; j++) {
-                                        while (usedIndices.get(nextIndex, false)) {
-                                            nextIndex++;
-                                        }
-                                        permutation[j] = nextIndex;
-                                        nextIndex++;
-                                    }
-                                    // Build the final view list.
-                                    preorderedList = new ArrayList<>(childrenCount);
-                                    for (int j=0; j<childrenCount; j++) {
-                                        preorderedList.add(children[permutation[j]]);
-                                    }
+        if (forAutoFill) {
+            childrenArray = null;
+            // TODO(b/33197203): the current algorithm allocates a new list for each children that
+            // is a view group; ideally, we should use mAttachInfo.mTempArrayList instead, but that
+            // would complicated the algorithm a lot...
+            childrenList = getChildrenForAutofill();
+
+            childrenCount = childrenList.size();
+        } else {
+            childrenArray = mChildren;
+            childrenList = null;
+            childrenCount = getChildCount();
+        }
+
+        if (childrenCount > 0) {
+            structure.setChildCount(childrenCount);
+            ArrayList<View> preorderedList = buildOrderedChildList();
+            boolean customOrder = preorderedList == null
+                    && isChildrenDrawingOrderEnabled();
+            for (int i = 0; i < childrenCount; i++) {
+                int childIndex;
+                try {
+                    childIndex = getAndVerifyPreorderedIndex(childrenCount, i, customOrder);
+                } catch (IndexOutOfBoundsException e) {
+                    childIndex = i;
+                    if (mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.M) {
+                        Log.w(TAG, "Bad getChildDrawingOrder while collecting assist @ "
+                                + i + " of " + childrenCount, e);
+                        // At least one app is failing when we call getChildDrawingOrder
+                        // at this point, so deal semi-gracefully with it by falling back
+                        // on the basic order.
+                        customOrder = false;
+                        if (i > 0) {
+                            // If we failed at the first index, there really isn't
+                            // anything to do -- we will just proceed with the simple
+                            // sequence order.
+                            // Otherwise, we failed in the middle, so need to come up
+                            // with an order for the remaining indices and use that.
+                            // Failed at the first one, easy peasy.
+                            int[] permutation = new int[childrenCount];
+                            SparseBooleanArray usedIndices = new SparseBooleanArray();
+                            // Go back and collected the indices we have done so far.
+                            for (int j = 0; j < i; j++) {
+                                permutation[j] = getChildDrawingOrder(childrenCount, j);
+                                usedIndices.put(permutation[j], true);
+                            }
+                            // Fill in the remaining indices with indices that have not
+                            // yet been used.
+                            int nextIndex = 0;
+                            for (int j = i; j < childrenCount; j++) {
+                                while (usedIndices.get(nextIndex, false)) {
+                                    nextIndex++;
                                 }
-                            } else {
-                                throw e;
+                                permutation[j] = nextIndex;
+                                nextIndex++;
+                            }
+                            // Build the final view list.
+                            preorderedList = new ArrayList<>(childrenCount);
+                            for (int j = 0; j < childrenCount; j++) {
+                                final int index = permutation[j];
+                                final View child = forAutoFill
+                                        ? childrenList.get(index)
+                                        : childrenArray[index];
+                                preorderedList.add(child);
                             }
                         }
-
-                        final View child = getAndVerifyPreorderedView(
-                                preorderedList, children, childIndex);
-                        final ViewStructure cstructure = structure.newChild(i);
-
-                        // Must explicitly check which recursive method to call.
-                        if (forAutoFill) {
-                            // NOTE: flags are not currently supported, hence 0
-                            child.dispatchProvideAutoFillStructure(cstructure, 0);
-                        } else {
-                            child.dispatchProvideStructure(cstructure);
-                        }
+                    } else {
+                        throw e;
                     }
-                    if (preorderedList != null) preorderedList.clear();
                 }
+
+                final View child = forAutoFill
+                        ? getAndVerifyPreorderedView(preorderedList, childrenList, childIndex)
+                        : getAndVerifyPreorderedView(preorderedList, childrenArray, childIndex);
+                final ViewStructure cstructure = structure.newChild(i);
+
+                // Must explicitly check which recursive method to call.
+                if (forAutoFill) {
+                    // NOTE: flags are not currently supported, hence 0
+                    child.dispatchProvideAutoFillStructure(cstructure, 0);
+                } else {
+                    child.dispatchProvideStructure(cstructure);
+                }
+            }
+            if (preorderedList != null) {
+                preorderedList.clear();
             }
         }
     }
@@ -3436,6 +3477,21 @@
         return child;
     }
 
+    private static View getAndVerifyPreorderedView(ArrayList<View> preorderedList,
+            ArrayList<View> children, int childIndex) {
+        final View child;
+        if (preorderedList != null) {
+            child = preorderedList.get(childIndex);
+            if (child == null) {
+                throw new RuntimeException("Invalid preorderedList contained null child at index "
+                        + childIndex);
+            }
+        } else {
+            child = children.get(childIndex);
+        }
+        return child;
+    }
+
     /** @hide */
     @Override
     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index 92f78b9..c7c2bb8 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -311,12 +311,17 @@
     public abstract ViewStructure asyncNewChildForAutoFill(int index, int virtualId, int flags);
 
     /**
-     * Sets the {@link AutoFillType} that can be used to auto-fill this node.
+     * @deprecated TODO(b/35956626): remove once clients use setAutoFilltype()
      */
-    // TODO(b/33197203, b/33802548): add CTS/unit test
+    @Deprecated
     public abstract void setAutoFillType(AutoFillType info);
 
     /**
+     * Sets the {@link View#getAutofillType()} that can be used to autofill this node.
+     */
+    public abstract void setAutofillType(@View.AutofillType int type);
+
+    /**
      * Sets the a hint that helps the auto-fill service to select the appropriate data to fill the
      * view.
      */
diff --git a/core/java/android/view/autofill/AutoFillManager.java b/core/java/android/view/autofill/AutoFillManager.java
index e8325e8..8beaf4e 100644
--- a/core/java/android/view/autofill/AutoFillManager.java
+++ b/core/java/android/view/autofill/AutoFillManager.java
@@ -19,7 +19,9 @@
 import static android.view.autofill.Helper.DEBUG;
 import static android.view.autofill.Helper.VERBOSE;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
@@ -30,7 +32,10 @@
 import android.os.RemoteException;
 import android.util.Log;
 import android.view.View;
+import android.view.WindowManagerGlobal;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.lang.ref.WeakReference;
 import java.util.List;
 
@@ -76,6 +81,8 @@
     private final IAutoFillManager mService;
     private IAutoFillManagerClient mServiceClient;
 
+    private AutofillCallback mCallback;
+
     private Context mContext;
 
     private boolean mHasSession;
@@ -276,11 +283,11 @@
         }
     }
 
-    private AutoFillId getAutoFillId(View view) {
+    private static AutoFillId getAutoFillId(View view) {
         return new AutoFillId(view.getAccessibilityViewId());
     }
 
-    private AutoFillId getAutoFillId(View parent, int childId) {
+    private static AutoFillId getAutoFillId(View parent, int childId) {
         return new AutoFillId(parent.getAccessibilityViewId(), childId);
     }
 
@@ -289,10 +296,12 @@
         if (DEBUG) {
             Log.d(TAG, "startSession(): id=" + id + ", bounds=" + bounds + ", value=" + value);
         }
+
         try {
             mService.startSession(mContext.getActivityToken(), windowToken,
-                    mServiceClient.asBinder(), id, bounds, value, mContext.getUserId());
-            AutoFillClient client = getClient();
+                    mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(),
+                    mCallback != null);
+            final AutoFillClient client = getClient();
             if (client != null) {
                 client.resetableStateAvailable();
             }
@@ -344,6 +353,119 @@
         }
     }
 
+    /**
+     * Registers a {@link AutofillCallback} to receive autofill events.
+     *
+     * @param callback callback to receive events.
+     */
+    public void registerCallback(@Nullable AutofillCallback callback) {
+        if (callback == null) return;
+
+        final boolean hadCallback = mCallback != null;
+        mCallback = callback;
+
+        if (mHasSession && !hadCallback) {
+            try {
+                mService.setHasCallback(mContext.getActivityToken(), mContext.getUserId(), true);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    /**
+     * Unregisters a {@link AutofillCallback} to receive autofill events.
+     *
+     * @param callback callback to stop receiving events.
+     */
+    public void unregisterCallback(@Nullable AutofillCallback callback) {
+        if (callback == null || mCallback == null || callback != mCallback) return;
+
+        mCallback = null;
+
+        if (mHasSession) {
+            try {
+                mService.setHasCallback(mContext.getActivityToken(), mContext.getUserId(), false);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    private void onAutofillEvent(IBinder windowToken, AutoFillId id, int event) {
+        if (mCallback == null) return;
+        if (id == null) {
+            Log.w(TAG, "onAutofillEvent(): no id for event " + event);
+            return;
+        }
+
+        final View root = WindowManagerGlobal.getInstance().getWindowView(windowToken);
+        if (root == null) {
+            Log.w(TAG, "onAutofillEvent() for " + id + ": root view gone");
+            return;
+        }
+        final View view = root.findViewByAccessibilityIdTraversal(id.getViewId());
+        if (view == null) {
+            Log.w(TAG, "onAutofillEvent() for " + id + ": view gone");
+            return;
+        }
+        if (id.isVirtual()) {
+            mCallback.onAutofillEventVirtual(view, id.getVirtualChildId(), event);
+        } else {
+            mCallback.onAutofillEvent(view, event);
+        }
+    }
+
+    /**
+     * Callback for auto-fill related events.
+     *
+     * <p>Typically used for applications that display their own "auto-complete" views, so they can
+     * enable / disable such views when the auto-fill UI affordance is shown / hidden.
+     */
+    public abstract static class AutofillCallback {
+
+        /** @hide */
+        @IntDef({EVENT_INPUT_SHOWN, EVENT_INPUT_HIDDEN})
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface AutofillEventType {}
+
+        /**
+         * The auto-fill input UI affordance associated with the view was shown.
+         *
+         * <p>If the view provides its own auto-complete UI affordance and its currently shown, it
+         * should be hidden upon receiving this event.
+         */
+        public static final int EVENT_INPUT_SHOWN = 1;
+
+        /**
+         * The auto-fill input UI affordance associated with the view was hidden.
+         *
+         * <p>If the view provides its own auto-complete UI affordance that was hidden upon a
+         * {@link #EVENT_INPUT_SHOWN} event, it could be shown again now.
+         */
+        public static final int EVENT_INPUT_HIDDEN = 2;
+
+        /**
+         * Called after a change in the autofill state associated with a view.
+         *
+         * @param view view associated with the change.
+         *
+         * @param event currently either {@link #EVENT_INPUT_SHOWN} or {@link #EVENT_INPUT_HIDDEN}.
+         */
+        public void onAutofillEvent(@NonNull View view, @AutofillEventType int event) {}
+
+        /**
+         * Called after a change in the autofill state associated with a virtual view.
+         *
+         * @param view parent view associated with the change.
+         * @param childId id identifying the virtual child inside the parent view.
+         *
+         * @param event currently either {@link #EVENT_INPUT_SHOWN} or {@link #EVENT_INPUT_HIDDEN}.
+         */
+        public void onAutofillEventVirtual(@NonNull View view, int childId,
+                @AutofillEventType int event) {}
+    }
+
     private static final class AutoFillManagerClient extends IAutoFillManagerClient.Stub {
         private final WeakReference<AutoFillManager> mAutoFillManager;
 
@@ -385,5 +507,17 @@
                 });
             }
         }
+
+        @Override
+        public void onAutofillEvent(IBinder windowToken, AutoFillId id, int event) {
+            final AutoFillManager autoFillManager = mAutoFillManager.get();
+            if (autoFillManager != null) {
+                autoFillManager.mContext.getMainThreadHandler().post(() -> {
+                    if (autoFillManager.getClient() != null) {
+                        autoFillManager.onAutofillEvent(windowToken, id, event);
+                    }
+                });
+            }
+        }
     }
 }
diff --git a/core/java/android/view/autofill/AutoFillType.aidl b/core/java/android/view/autofill/AutoFillType.aidl
index a63d7c5..4606b48 100644
--- a/core/java/android/view/autofill/AutoFillType.aidl
+++ b/core/java/android/view/autofill/AutoFillType.aidl
@@ -16,4 +16,7 @@
 
 package android.view.autofill;
 
+/*
+ * TODO(b/35956626): remove once clients use getAutoFilltype()
+ */
 parcelable AutoFillType;
\ No newline at end of file
diff --git a/core/java/android/view/autofill/AutoFillType.java b/core/java/android/view/autofill/AutoFillType.java
index 536d5e0..37966b2 100644
--- a/core/java/android/view/autofill/AutoFillType.java
+++ b/core/java/android/view/autofill/AutoFillType.java
@@ -26,6 +26,8 @@
  * Defines the type of a object that can be used to auto-fill a {@link View} so the
  * {@link android.service.autofill.AutoFillService} can use the proper {@link AutoFillValue} to
  * fill it.
+ *
+ * TODO(b/35956626): remove once clients use getAutoFilltype
  */
 public final class AutoFillType implements Parcelable {
 
@@ -95,8 +97,6 @@
      * <p>{@link AutoFillValue} instances for auto-filling a {@link View} can be obtained through
      * {@link AutoFillValue#forDate(long)}, and the values passed to
      * auto-fill a {@link View} can be fetched through {@link AutoFillValue#getDateValue()}.
-     *
-     * <p>This type has no sub-types.
      */
     public boolean isDate() {
         return mType == TYPE_DATE;
diff --git a/core/java/android/view/autofill/AutoFillValue.java b/core/java/android/view/autofill/AutoFillValue.java
index c24e04e..11fab68 100644
--- a/core/java/android/view/autofill/AutoFillValue.java
+++ b/core/java/android/view/autofill/AutoFillValue.java
@@ -45,38 +45,36 @@
     }
 
     /**
-     * Gets the value to auto-fill a text field.
+     * Gets the value to autofill a text field.
      *
-     * <p>See {@link AutoFillType#isText()} for more info.
+     * <p>See {@link View#AUTOFILL_TYPE_TEXT} for more info.
      */
     public CharSequence getTextValue() {
         return mText;
     }
 
     /**
-     * Gets the value to auto-fill a toggable field.
+     * Gets the value to autofill a toggable field.
      *
-     * <p>See {@link AutoFillType#isToggle()} for more info.
+     * <p>See {@link View#AUTOFILL_TYPE_TOGGLE} for more info.
      */
     public boolean getToggleValue() {
         return mToggle;
     }
 
     /**
-     * Gets the value to auto-fill a selection list field.
+     * Gets the value to autofill a selection list field.
      *
-     * <p>See {@link AutoFillType#isList()} for more info.
+     * <p>See {@link View#AUTOFILL_TYPE_LIST} for more info.
      */
     public int getListValue() {
         return mListIndex;
     }
 
     /**
-     * Gets the value representing the the number of milliseconds since the standard base time known
-     * as "the epoch", namely January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}
-     * of a date field.
+     * Gets the value to autofill a date field.
      *
-     * <p>See {@link AutoFillType#isDate()} for more info.
+     * <p>See {@link View#AUTOFILL_TYPE_DATE} for more info.
      */
     public long getDateValue() {
         return mDate;
@@ -174,9 +172,9 @@
 
     // TODO(b/33197203): add unit tests for each supported type (new / get should return same value)
     /**
-     * Creates a new {@link AutoFillValue} to auto-fill a {@link View} representing a text field.
+     * Creates a new {@link AutoFillValue} to autofill a {@link View} representing a text field.
      *
-     * <p>See {@link AutoFillType#isText()} for more info.
+     * <p>See {@link View#AUTOFILL_TYPE_TEXT} for more info.
      */
     // TODO(b/33197203): use cache
     @Nullable
@@ -185,29 +183,29 @@
     }
 
     /**
-     * Creates a new {@link AutoFillValue} to auto-fill a {@link View} representing a toggable
+     * Creates a new {@link AutoFillValue} to autofill a {@link View} representing a toggable
      * field.
      *
-     * <p>See {@link AutoFillType#isToggle()} for more info.
+     * <p>See {@link View#AUTOFILL_TYPE_TOGGLE} for more info.
      */
     public static AutoFillValue forToggle(boolean value) {
         return new AutoFillValue(null, 0, value, 0);
     }
 
     /**
-     * Creates a new {@link AutoFillValue} to auto-fill a {@link View} representing a selection
+     * Creates a new {@link AutoFillValue} to autofill a {@link View} representing a selection
      * list.
      *
-     * <p>See {@link AutoFillType#isList()} for more info.
+     * <p>See {@link View#AUTOFILL_TYPE_LIST} for more info.
      */
     public static AutoFillValue forList(int value) {
         return new AutoFillValue(null, value, false, 0);
     }
 
     /**
-     * Creates a new {@link AutoFillValue} to auto-fill a {@link View} representing a date.
+     * Creates a new {@link AutoFillValue} to autofill a {@link View} representing a date.
      *
-     * <p>See {@link AutoFillType#isDate()} for more info.
+     * <p>See {@link View#AUTOFILL_TYPE_DATE} for more info.
      */
     public static AutoFillValue forDate(long date) {
         return new AutoFillValue(null, 0, false, date);
diff --git a/core/java/android/view/autofill/IAutoFillManager.aidl b/core/java/android/view/autofill/IAutoFillManager.aidl
index d054e97..b36c0f1 100644
--- a/core/java/android/view/autofill/IAutoFillManager.aidl
+++ b/core/java/android/view/autofill/IAutoFillManager.aidl
@@ -31,10 +31,12 @@
 interface IAutoFillManager {
     boolean addClient(in IAutoFillManagerClient client, int userId);
     oneway void startSession(in IBinder activityToken, IBinder windowToken, in IBinder appCallback,
-            in AutoFillId autoFillId, in Rect bounds, in AutoFillValue value, int userId);
+            in AutoFillId autoFillId, in Rect bounds, in AutoFillValue value, int userId,
+            boolean hasCallback);
     oneway void updateSession(in IBinder activityToken, in AutoFillId id, in Rect bounds,
             in AutoFillValue value, int flags, int userId);
     oneway void finishSession(in IBinder activityToken, int userId);
     oneway void setAuthenticationResult(in Bundle data,
             in IBinder activityToken, int userId);
+    oneway void setHasCallback(in IBinder activityToken, int userId, boolean hasIt);
 }
diff --git a/core/java/android/view/autofill/IAutoFillManagerClient.aidl b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
index 45f363d..9eef7d0 100644
--- a/core/java/android/view/autofill/IAutoFillManagerClient.aidl
+++ b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
@@ -20,6 +20,7 @@
 
 import android.content.Intent;
 import android.content.IntentSender;
+import android.os.IBinder;
 import android.view.autofill.AutoFillId;
 import android.view.autofill.AutoFillValue;
 
@@ -43,4 +44,9 @@
       * Authenticates a fill response or a data set.
       */
     void authenticate(in IntentSender intent, in Intent fillInIntent);
+
+    /**
+     * Notifies the client when the auto-fill UI changed.
+     */
+    void onAutofillEvent(in IBinder windowToken, in AutoFillId id, int event);
 }
diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java
index 791543e..46f7a81 100644
--- a/core/java/android/view/textclassifier/TextClassifier.java
+++ b/core/java/android/view/textclassifier/TextClassifier.java
@@ -18,7 +18,9 @@
 
 import android.annotation.IntRange;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.StringDef;
+import android.os.LocaleList;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -51,20 +53,43 @@
 
         @Override
         public TextSelection suggestSelection(
-                CharSequence text, int selectionStartIndex, int selectionEndIndex) {
+                CharSequence text,
+                int selectionStartIndex,
+                int selectionEndIndex,
+                LocaleList defaultLocales) {
             return new TextSelection.Builder(selectionStartIndex, selectionEndIndex).build();
         }
 
         @Override
         public TextClassificationResult getTextClassificationResult(
-                CharSequence text, int startIndex, int endIndex) {
+                CharSequence text, int startIndex, int endIndex, LocaleList defaultLocales) {
             return TextClassificationResult.EMPTY;
         }
 
         @Override
-        public LinksInfo getLinks(CharSequence text, int linkMask) {
+        public LinksInfo getLinks(CharSequence text, int linkMask, LocaleList defaultLocales) {
             return LinksInfo.NO_OP;
         }
+
+        // TODO: Remove
+        @Override
+        public TextSelection suggestSelection(
+                CharSequence text, int selectionStartIndex, int selectionEndIndex) {
+            throw new UnsupportedOperationException("Removed");
+        }
+
+        // TODO: Remove
+        @Override
+        public TextClassificationResult getTextClassificationResult(
+                CharSequence text, int startIndex, int endIndex) {
+            throw new UnsupportedOperationException("Removed");
+        }
+
+        // TODO: Remove
+        @Override
+        public LinksInfo getLinks(CharSequence text, int linkMask) {
+            throw new UnsupportedOperationException("Removed");
+        }
     };
 
     /**
@@ -75,15 +100,20 @@
      *      by the sub sequence starting at selectionStartIndex and ending at selectionEndIndex)
      * @param selectionStartIndex start index of the selected part of text
      * @param selectionEndIndex end index of the selected part of text
+     * @param defaultLocales ordered list of locale preferences that can be used to disambiguate
+     *      the provided text. If no locale preferences exist, set this to null or an empty locale
+     *      list in which case the classifier will decide whether to use no locale information, use
+     *      a default locale, or use the system default.
      *
      * @throws IllegalArgumentException if text is null; selectionStartIndex is negative;
-     *      selectionEndIndex is greater than text.length() or less than selectionStartIndex
+     *      selectionEndIndex is greater than text.length() or not greater than selectionStartIndex
      */
     @NonNull
     TextSelection suggestSelection(
             @NonNull CharSequence text,
             @IntRange(from = 0) int selectionStartIndex,
-            @IntRange(from = 0) int selectionEndIndex);
+            @IntRange(from = 0) int selectionEndIndex,
+            @Nullable LocaleList defaultLocales);
 
     /**
      * Returns a {@link TextClassificationResult} object that can be used to generate a widget for
@@ -93,13 +123,20 @@
      *      by the sub sequence starting at startIndex and ending at endIndex)
      * @param startIndex start index of the text to classify
      * @param endIndex end index of the text to classify
+     * @param defaultLocales ordered list of locale preferences that can be used to disambiguate
+     *      the provided text. If no locale preferences exist, set this to null or an empty locale
+     *      list in which case the classifier will decide whether to use no locale information, use
+     *      a default locale, or use the system default.
      *
      * @throws IllegalArgumentException if text is null; startIndex is negative;
-     *      endIndex is greater than text.length() or less than startIndex
+     *      endIndex is greater than text.length() or not greater than startIndex
      */
     @NonNull
     TextClassificationResult getTextClassificationResult(
-            @NonNull CharSequence text, int startIndex, int endIndex);
+            @NonNull CharSequence text,
+            @IntRange(from = 0) int startIndex,
+            @IntRange(from = 0) int endIndex,
+            @Nullable LocaleList defaultLocales);
 
     /**
      * Returns a {@link LinksInfo} that may be applied to the text to annotate it with links
@@ -108,8 +145,25 @@
      * @param text the text to generate annotations for
      * @param linkMask See {@link android.text.util.Linkify} for a list of linkMasks that may be
      *      specified. Subclasses of this interface may specify additional linkMasks
+     * @param defaultLocales  ordered list of locale preferences that can be used to disambiguate
+     *      the provided text. If no locale preferences exist, set this to null or an empty locale
+     *      list in which case the classifier will decide whether to use no locale information, use
+     *      a default locale, or use the system default.
      *
      * @throws IllegalArgumentException if text is null
      */
-    LinksInfo getLinks(@NonNull CharSequence text, int linkMask);
+    LinksInfo getLinks(
+            @NonNull CharSequence text, int linkMask, @Nullable LocaleList defaultLocales);
+
+    // TODO: Remove
+    /** @removed */
+    TextSelection suggestSelection(
+            CharSequence text, int selectionStartIndex, int selectionEndIndex);
+    // TODO: Remove
+    /** @removed */
+    TextClassificationResult getTextClassificationResult(
+            CharSequence text, int startIndex, int endIndex);
+    // TODO: Remove
+    /** @removed */
+    LinksInfo getLinks(CharSequence text, int linkMask);
 }
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 536d7e0..0486f9f 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -26,6 +26,7 @@
 import android.graphics.drawable.Drawable;
 import android.icu.text.BreakIterator;
 import android.net.Uri;
+import android.os.LocaleList;
 import android.os.ParcelFileDescriptor;
 import android.provider.Browser;
 import android.text.Spannable;
@@ -74,7 +75,8 @@
 
     @Override
     public TextSelection suggestSelection(
-            @NonNull CharSequence text, int selectionStartIndex, int selectionEndIndex) {
+            @NonNull CharSequence text, int selectionStartIndex, int selectionEndIndex,
+            LocaleList defaultLocales) {
         validateInput(text, selectionStartIndex, selectionEndIndex);
         try {
             if (text.length() > 0) {
@@ -101,12 +103,12 @@
         }
         // Getting here means something went wrong, return a NO_OP result.
         return TextClassifier.NO_OP.suggestSelection(
-                text, selectionStartIndex, selectionEndIndex);
+                text, selectionStartIndex, selectionEndIndex, defaultLocales);
     }
 
     @Override
     public TextClassificationResult getTextClassificationResult(
-            @NonNull CharSequence text, int startIndex, int endIndex) {
+            @NonNull CharSequence text, int startIndex, int endIndex, LocaleList defaultLocales) {
         validateInput(text, startIndex, endIndex);
         try {
             if (text.length() > 0) {
@@ -125,11 +127,12 @@
             Log.e(LOG_TAG, "Error getting assist info.", t);
         }
         // Getting here means something went wrong, return a NO_OP result.
-        return TextClassifier.NO_OP.getTextClassificationResult(text, startIndex, endIndex);
+        return TextClassifier.NO_OP.getTextClassificationResult(
+                text, startIndex, endIndex, defaultLocales);
     }
 
     @Override
-    public LinksInfo getLinks(CharSequence text, int linkMask) {
+    public LinksInfo getLinks(CharSequence text, int linkMask, LocaleList defaultLocales) {
         Preconditions.checkArgument(text != null);
         try {
             return LinksInfoFactory.create(
@@ -139,7 +142,27 @@
             Log.e(LOG_TAG, "Error getting links info.", t);
         }
         // Getting here means something went wrong, return a NO_OP result.
-        return TextClassifier.NO_OP.getLinks(text, linkMask);
+        return TextClassifier.NO_OP.getLinks(text, linkMask, defaultLocales);
+    }
+
+    // TODO: Remove
+    @Override
+    public TextSelection suggestSelection(
+            CharSequence text, int selectionStartIndex, int selectionEndIndex) {
+        throw new UnsupportedOperationException("Removed");
+    }
+
+    // TODO: Remove
+    @Override
+    public TextClassificationResult getTextClassificationResult(
+            CharSequence text, int startIndex, int endIndex) {
+        throw new UnsupportedOperationException("Removed");
+    }
+
+    // TODO: Remove
+    @Override
+    public LinksInfo getLinks(CharSequence text, int linkMask) {
+        throw new UnsupportedOperationException("Removed");
     }
 
     private SmartSelection getSmartSelection() throws FileNotFoundException {
@@ -195,7 +218,7 @@
 
     /**
      * @throws IllegalArgumentException if text is null; startIndex is negative;
-     *      endIndex is greater than text.length() or less than startIndex
+     *      endIndex is greater than text.length() or is not greater than startIndex
      */
     private static void validateInput(@NonNull CharSequence text, int startIndex, int endIndex) {
         Preconditions.checkArgument(text != null);
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 4757757..3fbeb03 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -630,6 +630,12 @@
     protected WebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes,
             Map<String, Object> javaScriptInterfaces, boolean privateBrowsing) {
         super(context, attrs, defStyleAttr, defStyleRes);
+
+        // WebView is important by default, unless app developer overrode attribute.
+        if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
+            setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
+        }
+
         if (context == null) {
             throw new IllegalArgumentException("Invalid context argument");
         }
diff --git a/core/java/android/widget/AbsSpinner.java b/core/java/android/widget/AbsSpinner.java
index bc3dfff..e6cd566 100644
--- a/core/java/android/widget/AbsSpinner.java
+++ b/core/java/android/widget/AbsSpinner.java
@@ -26,6 +26,8 @@
 import android.util.SparseArray;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewStructure;
+import android.view.autofill.AutoFillValue;
 
 import com.android.internal.R;
 
@@ -68,6 +70,12 @@
 
     public AbsSpinner(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
+
+        // Spinner is important by default, unless app developer overrode attribute.
+        if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
+            setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
+        }
+
         initAbsSpinner();
 
         final TypedArray a = context.obtainStyledAttributes(
@@ -480,4 +488,43 @@
     public CharSequence getAccessibilityClassName() {
         return AbsSpinner.class.getName();
     }
+
+    // TODO(b/33197203): add unit/CTS tests for auto-fill methods (and make sure they handle enable)
+
+    @Override
+    public void onProvideAutoFillStructure(ViewStructure structure, int flags) {
+        super.onProvideAutoFillStructure(structure, flags);
+
+        if (getAdapter() == null) return;
+
+        // TODO(b/33197203): implement sanitization so initial value is only sanitized when coming
+        // from resources.
+
+        final int count = getAdapter().getCount();
+        if (count > 0) {
+            final String[] options = new String[count];
+            for (int i = 0; i < count; i++) {
+                options[i] = getAdapter().getItem(i).toString();
+            }
+            structure.setAutoFillOptions(options);
+        }
+    }
+
+    @Override
+    public void autoFill(AutoFillValue value) {
+        if (!isEnabled()) return;
+
+        final int position = value.getListValue();
+        setSelection(position);
+    }
+
+    @Override
+    public @AutofillType int getAutofillType() {
+        return isEnabled() ? AUTOFILL_TYPE_LIST : AUTOFILL_TYPE_NONE;
+    }
+
+    @Override
+    public AutoFillValue getAutoFillValue() {
+        return isEnabled() ? AutoFillValue.forList(getSelectedItemPosition()) : null;
+    }
 }
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index 141b52f..dce33a0 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -36,7 +36,6 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.autofill.AutoFillManager;
-import android.view.autofill.AutoFillType;
 import android.view.autofill.AutoFillValue;
 
 import com.android.internal.R;
@@ -590,8 +589,8 @@
     }
 
     @Override
-    public AutoFillType getAutoFillType() {
-        return isEnabled() ? AutoFillType.forToggle() : null;
+    public @AutofillType int getAutofillType() {
+        return isEnabled() ? AUTOFILL_TYPE_TOGGLE : AUTOFILL_TYPE_NONE;
     }
 
     @Override
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 0ffefd0..c905172 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -34,7 +34,6 @@
 import android.view.ViewStructure;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.autofill.AutoFillManager;
-import android.view.autofill.AutoFillType;
 import android.view.autofill.AutoFillValue;
 
 import com.android.internal.R;
@@ -146,6 +145,11 @@
     public DatePicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
 
+        // DatePicker is important by default, unless app developer overrode attribute.
+        if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
+            setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
+        }
+
         final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DatePicker,
                 defStyleAttr, defStyleRes);
         final boolean isDialogMode = a.getBoolean(R.styleable.DatePicker_dialogMode, false);
@@ -775,8 +779,8 @@
     }
 
     @Override
-    public AutoFillType getAutoFillType() {
-        return isEnabled() ? AutoFillType.forDate() : null;
+    public @AutofillType int getAutofillType() {
+        return isEnabled() ? AUTOFILL_TYPE_DATE : AUTOFILL_TYPE_NONE;
     }
 
     @Override
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index cd80651..7e6f2e4 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -156,6 +156,11 @@
 
         initImageView();
 
+        // ImageView is not important by default, unless app developer overrode attribute.
+        if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
+            setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_NO);
+        }
+
         final TypedArray a = context.obtainStyledAttributes(
                 attrs, R.styleable.ImageView, defStyleAttr, defStyleRes);
 
diff --git a/core/java/android/widget/RadioGroup.java b/core/java/android/widget/RadioGroup.java
index be5fc53..bb8cd28 100644
--- a/core/java/android/widget/RadioGroup.java
+++ b/core/java/android/widget/RadioGroup.java
@@ -26,7 +26,6 @@
 import android.view.ViewGroup;
 import android.view.ViewStructure;
 import android.view.autofill.AutoFillManager;
-import android.view.autofill.AutoFillType;
 import android.view.autofill.AutoFillValue;
 
 import com.android.internal.R;
@@ -86,6 +85,11 @@
     public RadioGroup(Context context, AttributeSet attrs) {
         super(context, attrs);
 
+        // RadioGroup is important by default, unless app developer overrode attribute.
+        if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
+            setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
+        }
+
         // retrieve selected radio button as requested by the user in the
         // XML layout file
         TypedArray attributes = context.obtainStyledAttributes(
@@ -435,8 +439,8 @@
     }
 
     @Override
-    public AutoFillType getAutoFillType() {
-        return isEnabled() ? AutoFillType.forList() : null;
+    public @AutofillType int getAutofillType() {
+        return isEnabled() ? AUTOFILL_TYPE_LIST : AUTOFILL_TYPE_NONE;
     }
 
     @Override
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index b751935..a032383 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -21,6 +21,7 @@
 import android.annotation.UiThread;
 import android.annotation.WorkerThread;
 import android.os.AsyncTask;
+import android.os.LocaleList;
 import android.text.Selection;
 import android.text.Spannable;
 import android.text.TextUtils;
@@ -60,7 +61,7 @@
         mEditor = Preconditions.checkNotNull(editor);
         final TextView textView = mEditor.getTextView();
         mTextClassificationHelper = new TextClassificationHelper(
-                textView.getTextClassifier(), textView.getText(), 0, 1);
+                textView.getTextClassifier(), textView.getText(), 0, 1, textView.getTextLocales());
     }
 
     public void startActionModeAsync() {
@@ -170,7 +171,8 @@
     private void resetTextClassificationHelper() {
         final TextView textView = mEditor.getTextView();
         mTextClassificationHelper.reset(textView.getTextClassifier(), textView.getText(),
-                textView.getSelectionStart(), textView.getSelectionEnd());
+                textView.getSelectionStart(), textView.getSelectionEnd(),
+                textView.getTextLocales());
     }
 
     /**
@@ -297,6 +299,7 @@
         private int mSelectionStart;
         /** End index relative to mText. */
         private int mSelectionEnd;
+        private LocaleList mLocales;
 
         /** Trimmed text starting from mTrimStart in mText. */
         private CharSequence mTrimmedText;
@@ -308,18 +311,19 @@
         private int mRelativeEnd;
 
         TextClassificationHelper(TextClassifier textClassifier,
-                CharSequence text, int selectionStart, int selectionEnd) {
-            reset(textClassifier, text, selectionStart, selectionEnd);
+                CharSequence text, int selectionStart, int selectionEnd, LocaleList locales) {
+            reset(textClassifier, text, selectionStart, selectionEnd, locales);
         }
 
         @UiThread
         public void reset(TextClassifier textClassifier,
-                CharSequence text, int selectionStart, int selectionEnd) {
+                CharSequence text, int selectionStart, int selectionEnd, LocaleList locales) {
             mTextClassifier = Preconditions.checkNotNull(textClassifier);
             mText = Preconditions.checkNotNull(text).toString();
             Preconditions.checkArgument(selectionEnd > selectionStart);
             mSelectionStart = selectionStart;
             mSelectionEnd = selectionEnd;
+            mLocales = locales;
         }
 
         @WorkerThread
@@ -329,14 +333,14 @@
                     mSelectionStart,
                     mSelectionEnd,
                     mTextClassifier.getTextClassificationResult(
-                            mTrimmedText, mRelativeStart, mRelativeEnd));
+                            mTrimmedText, mRelativeStart, mRelativeEnd, mLocales));
         }
 
         @WorkerThread
         public SelectionResult suggestSelection() {
             trimText();
             final TextSelection sel = mTextClassifier.suggestSelection(
-                    mTrimmedText, mRelativeStart, mRelativeEnd);
+                    mTrimmedText, mRelativeStart, mRelativeEnd, mLocales);
             mSelectionStart = Math.max(0, sel.getSelectionStartIndex() + mTrimStart);
             mSelectionEnd = Math.min(mText.length(), sel.getSelectionEndIndex() + mTrimStart);
             return classifyText();
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index 1eff26e..3811e1a 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -45,8 +45,6 @@
 import android.view.ViewTreeObserver;
 import android.view.ViewTreeObserver.OnGlobalLayoutListener;
 import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.autofill.AutoFillType;
-import android.view.autofill.AutoFillValue;
 import android.widget.PopupWindow.OnDismissListener;
 
 import com.android.internal.R;
@@ -937,24 +935,6 @@
         }
     }
 
-    @Override
-    public void autoFill(AutoFillValue value) {
-        if (!isEnabled()) return;
-
-        final int position = value.getListValue();
-        setSelection(position);
-    }
-
-    @Override
-    public AutoFillType getAutoFillType() {
-        return AutoFillType.forList();
-    }
-
-    @Override
-    public AutoFillValue getAutoFillValue() {
-        return isEnabled() ? AutoFillValue.forList(getSelectedItemPosition()) : null;
-    }
-
     static class SavedState extends AbsSpinner.SavedState {
         boolean showDropdown;
 
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 5307a08..b901ab4 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -141,7 +141,6 @@
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.AnimationUtils;
 import android.view.autofill.AutoFillManager;
-import android.view.autofill.AutoFillType;
 import android.view.autofill.AutoFillValue;
 import android.view.inputmethod.BaseInputConnection;
 import android.view.inputmethod.CompletionInfo;
@@ -790,6 +789,11 @@
             Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
 
+        // TextView is important by default, unless app developer overrode attribute.
+        if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
+            setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
+        }
+
         mText = "";
 
         final Resources res = getResources();
@@ -10018,9 +10022,8 @@
     }
 
     @Override
-    @Nullable
-    public AutoFillType getAutoFillType() {
-        return isTextEditable() ? AutoFillType.forText() : null;
+    public @AutofillType int getAutofillType() {
+        return isTextEditable() ? AUTOFILL_TYPE_TEXT : AUTOFILL_TYPE_NONE;
     }
 
     @Override
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index 1df202e..3a19f21 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -32,7 +32,6 @@
 import android.view.ViewStructure;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.autofill.AutoFillManager;
-import android.view.autofill.AutoFillType;
 import android.view.autofill.AutoFillValue;
 
 import com.android.internal.R;
@@ -112,6 +111,11 @@
     public TimePicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
 
+        // DatePicker is important by default, unless app developer overrode attribute.
+        if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
+            setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
+        }
+
         final TypedArray a = context.obtainStyledAttributes(
                 attrs, R.styleable.TimePicker, defStyleAttr, defStyleRes);
         final boolean isDialogMode = a.getBoolean(R.styleable.TimePicker_dialogMode, false);
@@ -530,8 +534,8 @@
     }
 
     @Override
-    public AutoFillType getAutoFillType() {
-        return isEnabled() ? AutoFillType.forDate() : null;
+    public @AutofillType int getAutofillType() {
+        return isEnabled() ? AUTOFILL_TYPE_DATE : AUTOFILL_TYPE_NONE;
     }
 
     @Override
diff --git a/core/java/com/android/internal/alsa/AlsaDevicesParser.java b/core/java/com/android/internal/alsa/AlsaDevicesParser.java
index 81b7943..5203723 100644
--- a/core/java/com/android/internal/alsa/AlsaDevicesParser.java
+++ b/core/java/com/android/internal/alsa/AlsaDevicesParser.java
@@ -184,7 +184,7 @@
         }
     }
 
-    private ArrayList<AlsaDeviceRecord> mDeviceRecords = new ArrayList<AlsaDeviceRecord>();
+    private final ArrayList<AlsaDeviceRecord> mDeviceRecords = new ArrayList<AlsaDeviceRecord>();
 
     public AlsaDevicesParser() {}
 
@@ -199,9 +199,11 @@
     //
     // Predicates
     //
+/*
    public boolean hasPlaybackDevices() {
         return mHasPlaybackDevices;
     }
+*/
 
     public boolean hasPlaybackDevices(int card) {
         for (AlsaDeviceRecord deviceRecord : mDeviceRecords) {
@@ -214,9 +216,11 @@
         return false;
     }
 
+/*
     public boolean hasCaptureDevices() {
         return mHasCaptureDevices;
     }
+*/
 
     public boolean hasCaptureDevices(int card) {
         for (AlsaDeviceRecord deviceRecord : mDeviceRecords) {
@@ -229,9 +233,11 @@
         return false;
     }
 
+/*
     public boolean hasMIDIDevices() {
         return mHasMIDIDevices;
     }
+*/
 
     public boolean hasMIDIDevices(int card) {
         for (AlsaDeviceRecord deviceRecord : mDeviceRecords) {
diff --git a/core/java/com/android/internal/alsa/LineTokenizer.java b/core/java/com/android/internal/alsa/LineTokenizer.java
index 43047a9..b395da9 100644
--- a/core/java/com/android/internal/alsa/LineTokenizer.java
+++ b/core/java/com/android/internal/alsa/LineTokenizer.java
@@ -23,7 +23,7 @@
 public class LineTokenizer {
     public static final int kTokenNotFound = -1;
 
-    private String mDelimiters = "";
+    private final String mDelimiters;
 
     public LineTokenizer(String delimiters) {
         mDelimiters = delimiters;
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 85aa6e6..2aeddb3 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -3706,6 +3706,20 @@
 
     public void noteScreenStateLocked(int state) {
         state = mPretendScreenOff ? Display.STATE_OFF : state;
+
+        // Battery stats relies on there being 4 states. To accommodate this, new states beyond the
+        // original 4 are mapped to one of the originals.
+        if (state > MAX_TRACKED_SCREEN_STATE) {
+            switch (state) {
+                case Display.STATE_VR:
+                    state = Display.STATE_ON;
+                    break;
+                default:
+                    Slog.wtf(TAG, "Unknown screen state (not mapped): " + state);
+                    break;
+            }
+        }
+
         if (mScreenState != state) {
             recordDailyStatsIfNeededLocked(true);
             final int oldState = mScreenState;
@@ -3715,9 +3729,9 @@
 
             if (state != Display.STATE_UNKNOWN) {
                 int stepState = state-1;
-                if (stepState < 4) {
-                    mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_SCREEN_STATE) ^ stepState;
-                    mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_SCREEN_STATE) | stepState;
+                if ((stepState & STEP_LEVEL_MODE_SCREEN_STATE) == stepState) {
+                    mModStepMode |= (mCurStepMode & STEP_LEVEL_MODE_SCREEN_STATE) ^ stepState;
+                    mCurStepMode = (mCurStepMode & ~STEP_LEVEL_MODE_SCREEN_STATE) | stepState;
                 } else {
                     Slog.wtf(TAG, "Unexpected screen state: " + state);
                 }
diff --git a/core/java/com/android/server/BootReceiver.java b/core/java/com/android/server/BootReceiver.java
index 5a50fbf..78e8797 100644
--- a/core/java/com/android/server/BootReceiver.java
+++ b/core/java/com/android/server/BootReceiver.java
@@ -35,6 +35,8 @@
 import android.util.Slog;
 import android.util.Xml;
 
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.XmlUtils;
 
@@ -46,6 +48,8 @@
 import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -83,6 +87,12 @@
     private static final File lastHeaderFile = new File(
             Environment.getDataSystemDirectory(), LAST_HEADER_FILE);
 
+    // example: fs_stat,/dev/block/platform/soc/by-name/userdata,0x5
+    private static final String FS_STAT_PATTERN = "fs_stat,[^,]*/([^/,]+),(0x[0-9a-fA-F]+)";
+    // ro.boottime.init.mount_all. + postfix for mount_all duration
+    private static final String[] MOUNT_DURATION_PROPS_POSTFIX =
+            new String[] { "early", "default", "late" };
+
     @Override
     public void onReceive(final Context context, Intent intent) {
         // Log boot events in the background to avoid blocking the main thread with I/O
@@ -200,10 +210,11 @@
             addFileToDropBox(db, timestamps, headers, "/cache/recovery/last_kmsg",
                     -LOG_SIZE, "SYSTEM_RECOVERY_KMSG");
             addAuditErrorsToDropBox(db, timestamps, headers, -LOG_SIZE, "SYSTEM_AUDIT");
-            addFsckErrorsToDropBox(db, timestamps, headers, -LOG_SIZE, "SYSTEM_FSCK");
         } else {
             if (db != null) db.addText("SYSTEM_RESTART", headers);
         }
+        addFsckErrorsToDropBoxAndLogFsStat(db, timestamps, headers, -LOG_SIZE, "SYSTEM_FSCK");
+        logFsMountTime();
 
         // Scan existing tombstones (in case any new ones appeared)
         File[] tombstoneFiles = TOMBSTONE_DIR.listFiles();
@@ -297,11 +308,14 @@
         db.addText(tag, headers + sb.toString());
     }
 
-    private static void addFsckErrorsToDropBox(DropBoxManager db,
+    private static void addFsckErrorsToDropBoxAndLogFsStat(DropBoxManager db,
             HashMap<String, Long> timestamps, String headers, int maxSize, String tag)
             throws IOException {
-        boolean upload_needed = false;
-        if (db == null || !db.isTagEnabled(tag)) return;  // Logging disabled
+        boolean uploadEnabled = true;
+        if (db == null || !db.isTagEnabled(tag)) {
+            uploadEnabled = false;
+        }
+        boolean uploadNeeded = false;
         Slog.i(TAG, "Checking for fsck errors");
 
         File file = new File("/dev/fscklogs/log");
@@ -310,14 +324,21 @@
 
         String log = FileUtils.readTextFile(file, maxSize, "[[TRUNCATED]]\n");
         StringBuilder sb = new StringBuilder();
-        for (String line : log.split("\n")) {
+        Pattern pattern = Pattern.compile(FS_STAT_PATTERN);
+        for (String line : log.split("\n")) { // should check all lines
             if (line.contains("FILE SYSTEM WAS MODIFIED")) {
-                upload_needed = true;
-                break;
+                uploadNeeded = true;
+            } else if (line.contains("fs_stat")){
+                Matcher matcher = pattern.matcher(line);
+                if (matcher.find()) {
+                    handleFsckFsStat(matcher);
+                } else {
+                    Slog.w(TAG, "cannot parse fs_stat:" + line);
+                }
             }
         }
 
-        if (upload_needed) {
+        if (uploadEnabled && uploadNeeded ) {
             addFileToDropBox(db, timestamps, headers, "/dev/fscklogs/log", maxSize, tag);
         }
 
@@ -325,6 +346,29 @@
         file.delete();
     }
 
+    private static void logFsMountTime() {
+        for (String propPostfix : MOUNT_DURATION_PROPS_POSTFIX) {
+            int duration = SystemProperties.getInt("ro.boottime.init.mount_all." + propPostfix, 0);
+            if (duration != 0) {
+                MetricsLogger.histogram(null, "boot_mount_all_duration_" + propPostfix, duration);
+            }
+        }
+    }
+
+    private static void handleFsckFsStat(Matcher match) {
+        String partition = match.group(1);
+        int stat;
+        try {
+            stat = Integer.decode(match.group(2));
+        } catch (NumberFormatException e) {
+            Slog.w(TAG, "cannot parse fs_stat: partition:" + partition + " stat:" + match.group(2));
+            return;
+        }
+
+        MetricsLogger.histogram(null, "boot_fs_stat_" + partition, stat);
+        Slog.i(TAG, "fs_stat, partition:" + partition + " stat:" + match.group(2));
+    }
+
     private static HashMap<String, Long> readTimestamps() {
         synchronized (sFile) {
             HashMap<String, Long> timestamps = new HashMap<String, Long>();
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index e4493b1..f852194 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -8,6 +8,8 @@
 #include "SkImageInfo.h"
 #include "SkColor.h"
 #include "SkColorPriv.h"
+#include "SkColorSpace.h"
+#include "SkColorSpaceXform.h"
 #include "SkHalf.h"
 #include "SkMatrix44.h"
 #include "SkPM4f.h"
@@ -29,6 +31,7 @@
 #include "core_jni_helpers.h"
 
 #include <jni.h>
+#include <string.h>
 #include <memory>
 #include <string>
 
@@ -448,11 +451,32 @@
 
     // reset to to actual choice from caller
     dst = dstBitmap.getAddr(x, y);
-    // now copy/convert each scanline
-    for (int y = 0; y < height; y++) {
-        proc(dst, src, width, x, y);
-        src += srcStride;
-        dst = (char*)dst + dstBitmap.rowBytes();
+
+    SkColorSpace* colorSpace = dstBitmap.colorSpace();
+    if (GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
+        // now copy/convert each scanline
+        for (int y = 0; y < height; y++) {
+            proc(dst, src, width, x, y);
+            src += srcStride;
+            dst = (char*)dst + dstBitmap.rowBytes();
+        }
+    } else {
+        auto sRGB = SkColorSpace::MakeSRGB();
+        auto xform = SkColorSpaceXform::New(sRGB.get(), colorSpace);
+
+        std::unique_ptr<SkColor[]> row(new SkColor[width]);
+
+        // now copy/convert each scanline
+        for (int y = 0; y < height; y++) {
+            memcpy(row.get(), src, sizeof(SkColor) * width);
+            xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, row.get(),
+                    SkColorSpaceXform::kBGRA_8888_ColorFormat, row.get(), width,
+                    SkAlphaType::kUnpremul_SkAlphaType);
+
+            proc(dst, row.get(), width, x, y);
+            src += srcStride;
+            dst = (char*)dst + dstBitmap.rowBytes();
+        }
     }
 
     dstBitmap.notifyPixelsChanged();
@@ -1179,12 +1203,7 @@
     if (!bitmapHolder.valid()) return JNI_TRUE;
 
     SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
-    return colorSpace == nullptr ||
-           colorSpace == SkColorSpace::MakeSRGB().get() ||
-           colorSpace == SkColorSpace::MakeRGB(
-                  SkColorSpace::kSRGB_RenderTargetGamma,
-                  SkColorSpace::kSRGB_Gamut,
-                  SkColorSpace::kNonLinearBlending_ColorSpaceFlag).get();
+    return GraphicsJNI::isColorSpaceSRGB(colorSpace);
 }
 
 static jboolean Bitmap_getColorSpace(JNIEnv* env, jobject, jlong bitmapHandle,
@@ -1246,6 +1265,16 @@
 
     SkColor dst[1];
     proc(dst, src, 1, bitmap.getColorTable());
+
+    SkColorSpace* colorSpace = bitmap.colorSpace();
+    if (!GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
+        auto sRGB = SkColorSpace::MakeSRGB();
+        auto xform = SkColorSpaceXform::New(colorSpace, sRGB.get());
+        xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, &dst[0],
+                SkColorSpaceXform::kBGRA_8888_ColorFormat, &dst[0], 1,
+                SkAlphaType::kUnpremul_SkAlphaType);
+    }
+
     return static_cast<jint>(dst[0]);
 }
 
@@ -1268,11 +1297,30 @@
     SkColorTable* ctable = bitmap.getColorTable();
     jint* dst = env->GetIntArrayElements(pixelArray, NULL);
     SkColor* d = (SkColor*)dst + offset;
-    while (--height >= 0) {
-        proc(d, src, width, ctable);
-        d += stride;
-        src = (void*)((const char*)src + bitmap.rowBytes());
+
+    SkColorSpace* colorSpace = bitmap.colorSpace();
+    if (GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
+        while (--height >= 0) {
+            proc(d, src, width, ctable);
+            d += stride;
+            src = (void*)((const char*)src + bitmap.rowBytes());
+        }
+    } else {
+        auto sRGB = SkColorSpace::MakeSRGB();
+        auto xform = SkColorSpaceXform::New(colorSpace, sRGB.get());
+
+        while (--height >= 0) {
+            proc(d, src, width, ctable);
+
+            xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, d,
+                    SkColorSpaceXform::kBGRA_8888_ColorFormat, d, width,
+                    SkAlphaType::kUnpremul_SkAlphaType);
+
+            d += stride;
+            src = (void*)((const char*)src + bitmap.rowBytes());
+        }
     }
+
     env->ReleaseIntArrayElements(pixelArray, dst, 0);
 }
 
@@ -1293,6 +1341,15 @@
         return;
     }
 
+    SkColorSpace* colorSpace = bitmap.colorSpace();
+    if (!GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
+        auto sRGB = SkColorSpace::MakeSRGB();
+        auto xform = SkColorSpaceXform::New(sRGB.get(), colorSpace);
+        xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, &color,
+                SkColorSpaceXform::kBGRA_8888_ColorFormat, &color, 1,
+                SkAlphaType::kUnpremul_SkAlphaType);
+    }
+
     proc(bitmap.getAddr(x, y), &color, 1, x, y);
     bitmap.notifyPixelsChanged();
 }
diff --git a/core/jni/android/graphics/GraphicBuffer.cpp b/core/jni/android/graphics/GraphicBuffer.cpp
index e661c21..73e53c6 100644
--- a/core/jni/android/graphics/GraphicBuffer.cpp
+++ b/core/jni/android/graphics/GraphicBuffer.cpp
@@ -30,8 +30,6 @@
 #include <ui/GraphicBuffer.h>
 #include <ui/PixelFormat.h>
 
-#include <gui/IGraphicBufferAlloc.h>
-#include <gui/ISurfaceComposer.h>
 #include <hwui/Bitmap.h>
 
 #include <SkCanvas.h>
@@ -111,21 +109,14 @@
 static jlong android_graphics_GraphicBuffer_create(JNIEnv* env, jobject clazz,
         jint width, jint height, jint format, jint usage) {
 
-    sp<ISurfaceComposer> composer(ComposerService::getComposerService());
-    sp<IGraphicBufferAlloc> alloc(composer->createGraphicBufferAlloc());
-    if (alloc == NULL) {
-        if (kDebugGraphicBuffer) {
-            ALOGW("createGraphicBufferAlloc() failed in GraphicBuffer.create()");
-        }
-        return NULL;
-    }
+    sp<GraphicBuffer> buffer = new GraphicBuffer(
+            uint32_t(width), uint32_t(height), PixelFormat(format), uint32_t(usage),
+            std::string("android_graphics_GraphicBuffer_create pid [") +
+                    std::to_string(getpid()) +"]");
 
-    status_t error;
-    sp<GraphicBuffer> buffer(alloc->createGraphicBuffer(width, height, format, 1, usage, &error));
-    if (buffer == NULL) {
-        if (kDebugGraphicBuffer) {
-            ALOGW("createGraphicBuffer() failed in GraphicBuffer.create()");
-        }
+    status_t error = buffer->initCheck();
+    if (error < 0) {
+        ALOGW_IF(kDebugGraphicBuffer, "createGraphicBuffer() failed in GraphicBuffer.create()");
         return NULL;
     }
 
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 5d73101..7c56c7b 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -460,6 +460,15 @@
     }
 }
 
+bool GraphicsJNI::isColorSpaceSRGB(SkColorSpace* colorSpace) {
+    return colorSpace == nullptr
+            || colorSpace == SkColorSpace::MakeSRGB().get()
+            || colorSpace == SkColorSpace::MakeRGB(
+                  SkColorSpace::kSRGB_RenderTargetGamma,
+                  SkColorSpace::kSRGB_Gamut,
+                  SkColorSpace::kNonLinearBlending_ColorSpaceFlag).get();
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 bool HeapAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
     mStorage = android::Bitmap::allocateHeapBitmap(bitmap, ctable);
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index 8a1ef6e..7d7c881 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -111,6 +111,7 @@
     static sk_sp<SkColorSpace> defaultColorSpace();
     static sk_sp<SkColorSpace> linearColorSpace();
     static sk_sp<SkColorSpace> colorSpaceForType(SkColorType type);
+    static bool isColorSpaceSRGB(SkColorSpace* colorSpace);
 };
 
 class HeapAllocator : public SkBRDAllocator {
diff --git a/core/jni/android/graphics/PathEffect.cpp b/core/jni/android/graphics/PathEffect.cpp
index e801da3..a4992de 100644
--- a/core/jni/android/graphics/PathEffect.cpp
+++ b/core/jni/android/graphics/PathEffect.cpp
@@ -20,7 +20,7 @@
                                      jlong outerHandle, jlong innerHandle) {
         SkPathEffect* outer = reinterpret_cast<SkPathEffect*>(outerHandle);
         SkPathEffect* inner = reinterpret_cast<SkPathEffect*>(innerHandle);
-        SkPathEffect* effect = SkComposePathEffect::Make(sk_ref_sp(outer),
+        SkPathEffect* effect = SkPathEffect::MakeCompose(sk_ref_sp(outer),
                 sk_ref_sp(inner)).release();
         return reinterpret_cast<jlong>(effect);
     }
@@ -29,7 +29,7 @@
                                  jlong firstHandle, jlong secondHandle) {
         SkPathEffect* first = reinterpret_cast<SkPathEffect*>(firstHandle);
         SkPathEffect* second = reinterpret_cast<SkPathEffect*>(secondHandle);
-        SkPathEffect* effect = SkSumPathEffect::Make(sk_ref_sp(first),
+        SkPathEffect* effect = SkPathEffect::MakeSum(sk_ref_sp(first),
                 sk_ref_sp(second)).release();
         return reinterpret_cast<jlong>(effect);
     }
diff --git a/core/jni/android_hardware_HardwareBuffer.cpp b/core/jni/android_hardware_HardwareBuffer.cpp
index b91bd5c..ed0ab60 100644
--- a/core/jni/android_hardware_HardwareBuffer.cpp
+++ b/core/jni/android_hardware_HardwareBuffer.cpp
@@ -31,8 +31,6 @@
 #include <binder/Parcel.h>
 
 #include <ui/GraphicBuffer.h>
-#include <gui/IGraphicBufferAlloc.h>
-#include <gui/ISurfaceComposer.h>
 #include <private/gui/ComposerService.h>
 
 #include <hardware/gralloc1.h>
@@ -73,15 +71,6 @@
 static jlong android_hardware_HardwareBuffer_create(JNIEnv* env, jobject clazz,
         jint width, jint height, jint format, jint layers, jlong usage) {
 
-    sp<ISurfaceComposer> composer(ComposerService::getComposerService());
-    sp<IGraphicBufferAlloc> alloc(composer->createGraphicBufferAlloc());
-    if (alloc == NULL) {
-        if (kDebugGraphicBuffer) {
-            ALOGW("createGraphicBufferAlloc() failed in HardwareBuffer.create()");
-        }
-        return NULL;
-    }
-
     // TODO: update createGraphicBuffer to take two 64-bit values.
     int pixelFormat = android_hardware_HardwareBuffer_convertToPixelFormat(format);
     if (pixelFormat == 0) {
@@ -92,14 +81,14 @@
     }
     uint64_t producerUsage = 0;
     uint64_t consumerUsage = 0;
-    android_hardware_HardwareBuffer_convertToGrallocUsageBits(&producerUsage, &consumerUsage, usage,
-            0);
-    status_t error;
-    sp<GraphicBuffer> buffer(alloc->createGraphicBuffer(width, height, pixelFormat,
-            layers, producerUsage, consumerUsage,
-            std::string("HardwareBuffer pid [") + std::to_string(getpid()) +"]",
-            &error));
-    if (buffer == NULL) {
+    android_hardware_HardwareBuffer_convertToGrallocUsageBits(
+            &producerUsage, &consumerUsage, usage, 0);
+
+    sp<GraphicBuffer> buffer = new GraphicBuffer(width, height, pixelFormat, layers,
+            producerUsage, consumerUsage,
+            std::string("HardwareBuffer pid [") + std::to_string(getpid()) +"]");
+    status_t error = buffer->initCheck();
+    if (error < 0) {
         if (kDebugGraphicBuffer) {
             ALOGW("createGraphicBuffer() failed in HardwareBuffer.create()");
         }
diff --git a/core/jni/android_os_HwBinder.cpp b/core/jni/android_os_HwBinder.cpp
index 2439b82..15b2f35 100644
--- a/core/jni/android_os_HwBinder.cpp
+++ b/core/jni/android_os_HwBinder.cpp
@@ -49,12 +49,6 @@
 
 namespace android {
 
-static jclass gArrayListClass;
-static struct {
-    jmethodID size;
-    jmethodID get;
-} gArrayListMethods;
-
 static jclass gErrorClass;
 
 static struct fields_t {
@@ -239,7 +233,6 @@
 static void JHwBinder_native_registerService(
         JNIEnv *env,
         jobject thiz,
-        jobject interfaceChainArrayList,
         jstring serviceNameObj) {
     if (serviceNameObj == NULL) {
         jniThrowException(env, "java/lang/NullPointerException", NULL);
@@ -251,24 +244,6 @@
         return;  // XXX exception already pending?
     }
 
-    jint numInterfaces = env->CallIntMethod(interfaceChainArrayList,
-                                            gArrayListMethods.size);
-    hidl_string *strings = new hidl_string[numInterfaces];
-
-    for (jint i = 0; i < numInterfaces; i++) {
-        jstring strObj = static_cast<jstring>(
-            env->CallObjectMethod(interfaceChainArrayList,
-                                  gArrayListMethods.get,
-                                  i)
-        );
-        const char * str = env->GetStringUTFChars(strObj, nullptr);
-        strings[i] = hidl_string(str);
-        env->ReleaseStringUTFChars(strObj, str);
-    }
-
-    hidl_vec<hidl_string> interfaceChain;
-    interfaceChain.setToExternal(strings, numInterfaces, true /* shouldOwn */);
-
     sp<hardware::IBinder> binder = JHwBinder::GetNativeContext(env, thiz);
 
     /* TODO(b/33440494) this is not right */
@@ -282,7 +257,7 @@
         return;
     }
 
-    Return<bool> ret = manager->add(interfaceChain, serviceName, base);
+    Return<bool> ret = manager->add(serviceName, base);
 
     env->ReleaseStringUTFChars(serviceNameObj, serviceName);
     serviceName = NULL;
@@ -385,7 +360,7 @@
         "(IL" PACKAGE_PATH "/HwParcel;L" PACKAGE_PATH "/HwParcel;I)V",
         (void *)JHwBinder_native_transact },
 
-    { "registerService", "(Ljava/util/ArrayList;Ljava/lang/String;)V",
+    { "registerService", "(Ljava/lang/String;)V",
         (void *)JHwBinder_native_registerService },
 
     { "getService", "(Ljava/lang/String;Ljava/lang/String;)L" PACKAGE_PATH "/IHwBinder;",
@@ -395,11 +370,6 @@
 namespace android {
 
 int register_android_os_HwBinder(JNIEnv *env) {
-    jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList");
-    gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass);
-    gArrayListMethods.size = GetMethodIDOrDie(env, arrayListClass, "size", "()I");
-    gArrayListMethods.get = GetMethodIDOrDie(env, arrayListClass, "get", "(I)Ljava/lang/Object;");
-
     jclass errorClass = FindClassOrDie(env, "java/lang/Error");
     gErrorClass = MakeGlobalRefOrDie(env, errorClass);
 
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index f8d5241..b3cb2c7 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2339,6 +2339,17 @@
             <flag name="creditCardExpirationDay" value="0x1000" />
         </attr>
 
+        <!-- Hints the Android System whether the view node associated with this View should be
+             included in a view structure used for autofill purposes. -->
+        <attr name="importantForAutofill">
+            <!-- Let the Android System use its heuristics to determine if the view is important for autofill. -->
+            <flag name="auto" value="0" />
+            <!-- Hint the Android System that this view is important for autofill. -->
+            <flag name="yes" value="0x1" />
+            <!-- Hint the Android System that this view is *not* important for autofill. -->
+            <flag name="no" value="0x2" />
+        </attr>
+
         <!-- Boolean that controls whether a view can take focus while in touch mode.
              If this is true for a view, that view can gain focus when clicked on, and can keep
              focus if another view is clicked on that doesn't have this attribute set to true. -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 0d90cd2..b664448 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2760,8 +2760,9 @@
        =============================================================== -->
     <eat-comment />
 
-    <public-group type="attr" first-id="0x01010531">
-        <public name="fontStyle" />
+    <public type="attr" name="visibleToInstantApps" id="0x01010531" />
+
+    <public-group type="attr" first-id="0x01010532">
         <public name="font" />
         <public name="fontWeight" />
         <public name="tooltipText" />
@@ -2775,7 +2776,7 @@
         <public name="layout_marginVertical" />
         <public name="paddingHorizontal" />
         <public name="paddingVertical" />
-        <public name="visibleToInstantApps" />
+        <public name="fontStyle" />
         <public name="keyboardNavigationCluster" />
         <public name="targetProcess" />
         <public name="nextClusterForward" />
@@ -2803,6 +2804,7 @@
         <public name="requiredNotFeature" />
         <public name="autoFillHint" />
         <public name="fontProviderPackage" />
+        <public name="importantForAutofill" />
     </public-group>
 
     <public-group type="style" first-id="0x010302e0">
diff --git a/core/tests/coretests/src/android/os/FileUtilsTest.java b/core/tests/coretests/src/android/os/FileUtilsTest.java
index 5c7da70..3a751af 100644
--- a/core/tests/coretests/src/android/os/FileUtilsTest.java
+++ b/core/tests/coretests/src/android/os/FileUtilsTest.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import static android.os.FileUtils.roundStorageSize;
 import static android.text.format.DateUtils.DAY_IN_MILLIS;
 import static android.text.format.DateUtils.HOUR_IN_MILLIS;
 import static android.text.format.DateUtils.WEEK_IN_MILLIS;
@@ -25,10 +26,10 @@
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.MediumTest;
 
-import com.google.android.collect.Sets;
-
 import libcore.io.IoUtils;
 
+import com.google.android.collect.Sets;
+
 import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileOutputStream;
@@ -312,25 +313,31 @@
     }
 
     public void testRoundStorageSize() throws Exception {
-        final long M128 = 134217728L;
-        final long M256 = M128 * 2;
-        final long M512 = M256 * 2;
-        final long M1024 = M512 * 2;
-        final long G16 = M1024 * 16;
-        final long G32 = M1024 * 32;
-        final long G64 = M1024 * 64;
+        final long M128 = 128000000L;
+        final long M256 = 256000000L;
+        final long M512 = 512000000L;
+        final long G1 = 1000000000L;
+        final long G2 = 2000000000L;
+        final long G16 = 16000000000L;
+        final long G32 = 32000000000L;
+        final long G64 = 64000000000L;
 
-        assertEquals(M128, FileUtils.roundStorageSize(M128));
-        assertEquals(M256, FileUtils.roundStorageSize(M128 + 1));
-        assertEquals(M256, FileUtils.roundStorageSize(M256 - 1));
-        assertEquals(M256, FileUtils.roundStorageSize(M256));
-        assertEquals(M512, FileUtils.roundStorageSize(M256 + 1));
+        assertEquals(M128, roundStorageSize(M128));
+        assertEquals(M256, roundStorageSize(M128 + 1));
+        assertEquals(M256, roundStorageSize(M256 - 1));
+        assertEquals(M256, roundStorageSize(M256));
+        assertEquals(M512, roundStorageSize(M256 + 1));
+        assertEquals(M512, roundStorageSize(M512 - 1));
+        assertEquals(M512, roundStorageSize(M512));
+        assertEquals(G1, roundStorageSize(M512 + 1));
+        assertEquals(G1, roundStorageSize(G1));
+        assertEquals(G2, roundStorageSize(G1 + 1));
 
-        assertEquals(G16, FileUtils.roundStorageSize(G16));
-        assertEquals(G32, FileUtils.roundStorageSize(G16 + 1));
-        assertEquals(G32, FileUtils.roundStorageSize(G32 - 1));
-        assertEquals(G32, FileUtils.roundStorageSize(G32));
-        assertEquals(G64, FileUtils.roundStorageSize(G32 + 1));
+        assertEquals(G16, roundStorageSize(G16));
+        assertEquals(G32, roundStorageSize(G16 + 1));
+        assertEquals(G32, roundStorageSize(G32 - 1));
+        assertEquals(G32, roundStorageSize(G32));
+        assertEquals(G64, roundStorageSize(G32 + 1));
     }
 
     private static void assertNameEquals(String expected, File actual) {
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 9a64507..696d498 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -158,6 +158,7 @@
                     Settings.Global.DEVICE_DEMO_MODE,
                     Settings.Global.DEVICE_IDLE_CONSTANTS,
                     Settings.Global.DEVICE_IDLE_CONSTANTS_WATCH,
+                    Settings.Global.BATTERY_SAVER_CONSTANTS,
                     Settings.Global.DEVICE_NAME,
                     Settings.Global.DEVICE_PROVISIONED,
                     Settings.Global.DEVICE_PROVISIONING_MOBILE_DATA_ENABLED,
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 6bb8a2c..3d5ba79 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -522,7 +522,7 @@
      * <p>The content of the bitmap is copied into the buffer as-is. This means
      * that if this bitmap stores its pixels pre-multiplied
      * (see {@link #isPremultiplied()}, the values in the buffer will also be
-     * pre-multiplied.</p>
+     * pre-multiplied. The pixels remain in the color space of the bitmap.</p>
      * <p>After this method returns, the current position of the buffer is
      * updated: the position is incremented by the number of elements written
      * in the buffer.</p>
@@ -562,7 +562,8 @@
      * <p>Copy the pixels from the buffer, beginning at the current position,
      * overwriting the bitmap's pixels. The data in the buffer is not changed
      * in any way (unlike setPixels(), which converts from unpremultipled 32bit
-     * to whatever the bitmap's native format is.</p>
+     * to whatever the bitmap's native format is. The pixels in the source
+     * buffer are assumed to be in the bitmap's color space.</p>
      * <p>After this method returns, the current position of the buffer is
      * updated: the position is incremented by the number of elements read from
      * the buffer. If you need to read the bitmap from the buffer again you must
@@ -1495,7 +1496,8 @@
     /**
      * Returns the {@link Color} at the specified location. Throws an exception
      * if x or y are out of bounds (negative or >= to the width or height
-     * respectively). The returned color is a non-premultiplied ARGB value.
+     * respectively). The returned color is a non-premultiplied ARGB value in
+     * the {@link ColorSpace.Named#SRGB sRGB} color space.
      *
      * @param x    The x coordinate (0...width-1) of the pixel to return
      * @param y    The y coordinate (0...height-1) of the pixel to return
@@ -1517,7 +1519,8 @@
      * a packed int representing a {@link Color}. The stride parameter allows
      * the caller to allow for gaps in the returned pixels array between
      * rows. For normal packed results, just pass width for the stride value.
-     * The returned colors are non-premultiplied ARGB values.
+     * The returned colors are non-premultiplied ARGB values in the
+     * {@link ColorSpace.Named#SRGB sRGB} color space.
      *
      * @param pixels   The array to receive the bitmap's colors
      * @param offset   The first index to write into pixels[]
@@ -1610,7 +1613,8 @@
     /**
      * <p>Write the specified {@link Color} into the bitmap (assuming it is
      * mutable) at the x,y coordinate. The color must be a
-     * non-premultiplied ARGB value.</p>
+     * non-premultiplied ARGB value in the {@link ColorSpace.Named#SRGB sRGB}
+     * color space.</p>
      *
      * @param x     The x coordinate of the pixel to replace (0...width-1)
      * @param y     The y coordinate of the pixel to replace (0...height-1)
@@ -1632,7 +1636,7 @@
     /**
      * <p>Replace pixels in the bitmap with the colors in the array. Each element
      * in the array is a packed int representing a non-premultiplied ARGB
-     * {@link Color}.</p>
+     * {@link Color} in the {@link ColorSpace.Named#SRGB sRGB} color space.</p>
      *
      * @param pixels   The colors to write to the bitmap
      * @param offset   The index of the first color to read from pixels[]
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index 49b69eb..72a9f4e 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -30,8 +30,6 @@
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 
-#include <gui/IGraphicBufferAlloc.h>
-#include <gui/ISurfaceComposer.h>
 #include <private/gui/ComposerService.h>
 #include <binder/IServiceManager.h>
 #include <ui/PixelFormat.h>
@@ -219,13 +217,6 @@
     renderThread.eglManager().initialize();
     uirenderer::Caches& caches = uirenderer::Caches::getInstance();
 
-    sp<ISurfaceComposer> composer(ComposerService::getComposerService());
-    sp<IGraphicBufferAlloc> alloc(composer->createGraphicBufferAlloc());
-    if (alloc == NULL) {
-        ALOGW("createGraphicBufferAlloc() failed in GraphicBuffer.create()");
-        return nullptr;
-    }
-
     const SkImageInfo& info = skBitmap.info();
     if (info.colorType() == kUnknown_SkColorType || info.colorType() == kAlpha_8_SkColorType) {
         ALOGW("unable to create hardware bitmap of colortype: %d", info.colorType());
@@ -240,12 +231,14 @@
             needSRGB, &internalFormat, &format, &type);
 
     PixelFormat pixelFormat = internalFormatToPixelFormat(internalFormat);
-    status_t error;
-    sp<GraphicBuffer> buffer = alloc->createGraphicBuffer(info.width(), info.height(), pixelFormat,
-            1, GraphicBuffer::USAGE_HW_TEXTURE | GraphicBuffer::USAGE_SW_WRITE_NEVER
-            | GraphicBuffer::USAGE_SW_READ_NEVER , &error);
+    sp<GraphicBuffer> buffer = new GraphicBuffer(info.width(), info.height(), pixelFormat,
+            GraphicBuffer::USAGE_HW_TEXTURE |
+            GraphicBuffer::USAGE_SW_WRITE_NEVER |
+            GraphicBuffer::USAGE_SW_READ_NEVER,
+            std::string("Bitmap::allocateHardwareBitmap pid [") + std::to_string(getpid()) + "]");
 
-    if (!buffer.get()) {
+    status_t error = buffer->initCheck();
+    if (error < 0) {
         ALOGW("createGraphicBuffer() failed in GraphicBuffer.create()");
         return nullptr;
     }
diff --git a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
index 83b01e9..a461426 100644
--- a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
+++ b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
@@ -17,10 +17,6 @@
 #include "TestSceneBase.h"
 #include "utils/Color.h"
 
-#include <gui/IGraphicBufferAlloc.h>
-#include <gui/ISurfaceComposer.h>
-#include <private/gui/ComposerService.h>
-#include <binder/IServiceManager.h>
 #include <ui/PixelFormat.h>
 #include <SkGradientShader.h>
 #include <SkImagePriv.h>
@@ -39,14 +35,11 @@
     void createContent(int width, int height, Canvas& canvas) override {
         canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
 
-        status_t error;
-        sp<ISurfaceComposer> composer(ComposerService::getComposerService());
-        sp<IGraphicBufferAlloc> alloc(composer->createGraphicBufferAlloc());
         uint32_t usage = GraphicBuffer::USAGE_HW_TEXTURE
                 | GraphicBuffer::USAGE_SW_READ_NEVER
                 | GRALLOC_USAGE_SW_WRITE_RARELY;
-        sp<GraphicBuffer> buffer = alloc->createGraphicBuffer(400, 200, PIXEL_FORMAT_RGBA_8888, 1,
-                usage, &error);
+
+        sp<GraphicBuffer> buffer = new GraphicBuffer(400, 200, PIXEL_FORMAT_RGBA_8888, usage);
 
         unsigned char* pixels = nullptr;
         buffer->lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, ((void**)&pixels));
@@ -88,4 +81,4 @@
         return image->makeShader(SkShader::TileMode::kClamp_TileMode,
                 SkShader::TileMode::kClamp_TileMode);
     }
-};
\ No newline at end of file
+};
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 3ac4c34..c157a47 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -1119,6 +1119,10 @@
                 sampleRates = new int[] { 8000 };
                 bitRates = Range.create(13000, 13000);
                 maxChannels = 1;
+            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AC3)) {
+                maxChannels = 6;
+            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_EAC3)) {
+                maxChannels = 16;
             } else {
                 Log.w(TAG, "Unsupported mime " + mime);
                 mParent.mError |= ERROR_UNSUPPORTED;
diff --git a/media/java/android/media/VolumeShaper.java b/media/java/android/media/VolumeShaper.java
index cb27d10..796d6f3 100644
--- a/media/java/android/media/VolumeShaper.java
+++ b/media/java/android/media/VolumeShaper.java
@@ -25,6 +25,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.lang.AutoCloseable;
 import java.lang.ref.WeakReference;
+import java.util.Arrays;
 import java.util.Objects;
 
 /**
@@ -115,6 +116,7 @@
      * @param configuration
      * @param operation
      * @return id a non-negative shaper id.
+     * @throws IllegalStateException if the player has been deallocated or is uninitialized.
      */
     private int applyPlayer(
             @NonNull VolumeShaper.Configuration configuration,
@@ -147,6 +149,7 @@
      * Internal call to retrieve the current VolumeShaper state.
      * @param id
      * @return the current {@vode VolumeShaper.State}
+     * @throws IllegalStateException if the player has been deallocated or is uninitialized.
      */
     private @NonNull VolumeShaper.State getStatePlayer(int id) {
         final VolumeShaper.State state;
@@ -172,10 +175,10 @@
      * <p>
      * A {@code VolumeShaper.Configuration} is used by
      * {@link VolumeAutomation#createVolumeShaper(Configuration)
-     * VolumeAutomation#createVolumeShaper(Configuration)} to create
+     * VolumeAutomation.createVolumeShaper(Configuration)} to create
      * a {@code VolumeShaper} and
      * by {@link VolumeShaper#replace(Configuration, Operation, boolean)
-     * VolumeShaper#replace(Configuration, Operation, boolean)}
+     * VolumeShaper.replace(Configuration, Operation, boolean)}
      * to replace an existing {@code configuration}.
      */
     public static final class Configuration implements Parcelable {
@@ -365,31 +368,34 @@
         private final int mId;
 
         // valid when mType is TYPE_SCALE
-        private final int mInterpolatorType;
         private final int mOptionFlags;
         private final double mDurationMs;
+        private final int mInterpolatorType;
         private final float[] mTimes;
         private final float[] mVolumes;
 
         @Override
         public String toString() {
-            return "VolumeShaper.Configuration["
-                    + "mType=" + mType
+            return "VolumeShaper.Configuration{"
+                    + "mType = " + mType
+                    + ", mId = " + mId
                     + (mType == TYPE_ID
-                    ? ",mId" + mId
-                    : ",mInterpolatorType=" + mInterpolatorType
-                    + ",mOptionFlags=" + mOptionFlags
-                    + ",mDurationMs=" + mDurationMs
-                    + ",mTimes[]=" + mTimes
-                    + ",mVolumes[]=" + mVolumes
-                    + "]");
+                        ? "}"
+                        : ", mOptionFlags = 0x" + Integer.toHexString(mOptionFlags).toUpperCase()
+                        + ", mDurationMs = " + mDurationMs
+                        + ", mInterpolatorType = " + mInterpolatorType
+                        + ", mTimes[] = " + Arrays.toString(mTimes)
+                        + ", mVolumes[] = " + Arrays.toString(mVolumes)
+                        + "}");
         }
 
         @Override
         public int hashCode() {
             return mType == TYPE_ID
                     ? Objects.hash(mType, mId)
-                    : Objects.hash(mType, mInterpolatorType, mDurationMs, mTimes, mVolumes);
+                    : Objects.hash(mType, mId,
+                            mOptionFlags, mDurationMs, mInterpolatorType,
+                            Arrays.hashCode(mTimes), Arrays.hashCode(mVolumes));
         }
 
         @Override
@@ -397,12 +403,17 @@
             if (!(o instanceof Configuration)) return false;
             if (o == this) return true;
             final Configuration other = (Configuration) o;
-            return mType == other.mType &&
-                    (mType == TYPE_ID ? mId == other.mId
-                    : mInterpolatorType == other.mInterpolatorType
-                    && mDurationMs == other.mDurationMs
-                    && mTimes == other.mTimes
-                    && mVolumes == other.mVolumes);
+            // Note that exact floating point equality may not be guaranteed
+            // for a theoretically idempotent operation; for example,
+            // there are many cases where a + b - b != a.
+            return mType == other.mType
+                    && mId == other.mId
+                    && (mType == TYPE_ID
+                        ||  (mOptionFlags == other.mOptionFlags
+                            && mDurationMs == other.mDurationMs
+                            && mInterpolatorType == other.mInterpolatorType
+                            && Arrays.equals(mTimes, other.mTimes)
+                            && Arrays.equals(mVolumes, other.mVolumes)));
         }
 
         @Override
@@ -412,14 +423,22 @@
 
         @Override
         public void writeToParcel(Parcel dest, int flags) {
+            // this needs to match the native VolumeShaper.Configuration parceling
             dest.writeInt(mType);
             dest.writeInt(mId);
             if (mType != TYPE_ID) {
-                dest.writeInt(mInterpolatorType);
                 dest.writeInt(mOptionFlags);
                 dest.writeDouble(mDurationMs);
-                dest.writeFloatArray(mTimes);
-                dest.writeFloatArray(mVolumes);
+                // this needs to match the native Interpolator parceling
+                dest.writeInt(mInterpolatorType);
+                dest.writeFloat(0.f); // first slope
+                dest.writeFloat(0.f); // last slope
+                // mTimes and mVolumes should have the same length.
+                dest.writeInt(mTimes.length);
+                for (int i = 0; i < mTimes.length; ++i) {
+                    dest.writeFloat(mTimes[i]);
+                    dest.writeFloat(mVolumes[i]);
+                }
             }
         }
 
@@ -427,19 +446,34 @@
                 = new Parcelable.Creator<VolumeShaper.Configuration>() {
             @Override
             public VolumeShaper.Configuration createFromParcel(Parcel p) {
+                // this needs to match the native VolumeShaper.Configuration parceling
                 final int type = p.readInt();
                 final int id = p.readInt();
                 if (type == TYPE_ID) {
                     return new VolumeShaper.Configuration(id);
                 } else {
+                    final int optionFlags = p.readInt();
+                    final double durationMs = p.readDouble();
+                    // this needs to match the native Interpolator parceling
+                    final int interpolatorType = p.readInt();
+                    final float firstSlope = p.readFloat(); // ignored
+                    final float lastSlope = p.readFloat();  // ignored
+                    final int length = p.readInt();
+                    final float[] times = new float[length];
+                    final float[] volumes = new float[length];
+                    for (int i = 0; i < length; ++i) {
+                        times[i] = p.readFloat();
+                        volumes[i] = p.readFloat();
+                    }
+
                     return new VolumeShaper.Configuration(
                         type,
-                        id,                    // id
-                        p.readInt(),           // interpolatorType
-                        p.readInt(),           // optionFlags
-                        p.readDouble(),        // durationMs
-                        p.createFloatArray(),  // times
-                        p.createFloatArray()); // volumes
+                        id,
+                        optionFlags,
+                        durationMs,
+                        interpolatorType,
+                        times,
+                        volumes);
                 }
             }
 
@@ -482,16 +516,16 @@
          */
         private Configuration(@Type int type,
                 int id,
-                @InterpolatorType int interpolatorType,
                 @OptionFlag int optionFlags,
                 double durationMs,
+                @InterpolatorType int interpolatorType,
                 @NonNull float[] times,
                 @NonNull float[] volumes) {
             mType = type;
             mId = id;
-            mInterpolatorType = interpolatorType;
             mOptionFlags = optionFlags;
             mDurationMs = durationMs;
+            mInterpolatorType = interpolatorType;
             // Builder should have cloned these arrays already.
             mTimes = times;
             mVolumes = volumes;
@@ -568,8 +602,12 @@
          * @return null if no error, or the reason in a {@code String} for an error.
          */
         private static @Nullable String checkCurveForErrors(
-                @NonNull float[] times, @NonNull float[] volumes, boolean log) {
-            if (times.length != volumes.length) {
+                @Nullable float[] times, @Nullable float[] volumes, boolean log) {
+            if (times == null) {
+                return "times array must be non-null";
+            } else if (volumes == null) {
+                return "volumes array must be non-null";
+            } else if (times.length != volumes.length) {
                 return "array length must match";
             } else if (times.length < 2) {
                 return "array length must be at least 2";
@@ -605,7 +643,15 @@
             return null; // no errors
         }
 
-        private static void checkValidVolume(float volume, boolean log) {
+        private static void checkCurveForErrorsAndThrowException(
+                @Nullable float[] times, @Nullable float[] volumes, boolean log) {
+            final String error = checkCurveForErrors(times, volumes, log);
+            if (error != null) {
+                throw new IllegalArgumentException(error);
+            }
+        }
+
+        private static void checkValidVolumeAndThrowException(float volume, boolean log) {
             if (log) {
                 if (!(volume <= 0.f) /* handle nan */) {
                     throw new IllegalArgumentException("dbfs volume must be 0.f or less");
@@ -678,17 +724,22 @@
                 mOptionFlags = configuration.getAllOptionFlags();
                 mInterpolatorType = configuration.getInterpolatorType();
                 mDurationMs = configuration.getDurationMs();
-                mTimes = configuration.getTimes();
-                mVolumes = configuration.getVolumes();
+                mTimes = configuration.getTimes().clone();
+                mVolumes = configuration.getVolumes().clone();
             }
 
             /**
              * @hide
-             * Set the id for system defined shapers.
-             * @param id
-             * @return
+             * Set the {@code id} for system defined shapers.
+             * @param id the {@code id} to set. If non-negative, then it is used.
+             *        If -1, then the system is expected to assign one.
+             * @return the same {@code Builder} instance.
+             * @throws IllegalArgumentException if {@code id} < -1.
              */
             public @NonNull Builder setId(int id) {
+                if (id < -1) {
+                    throw new IllegalArgumentException("invalid id: " + id);
+                }
                 mId = id;
                 return this;
             }
@@ -789,11 +840,8 @@
              */
 
             public @NonNull Builder setCurve(@NonNull float[] times, @NonNull float[] volumes) {
-                String error = checkCurveForErrors(
+                checkCurveForErrorsAndThrowException(
                         times, volumes, (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0);
-                if (error != null) {
-                    throw new IllegalArgumentException(error);
-                }
                 mTimes = times.clone();
                 mVolumes = volumes.clone();
                 return this;
@@ -805,13 +853,19 @@
              * to the start.
              *
              * @return the same {@code Builder} instance.
+             * @throws IllegalArgumentException if curve has not been set.
              */
             public @NonNull Builder reflectTimes() {
+                checkCurveForErrorsAndThrowException(
+                        mTimes, mVolumes, (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0);
                 int i;
                 for (i = 0; i < mTimes.length / 2; ++i) {
-                    float temp = mTimes[0];
+                    float temp = mTimes[i];
                     mTimes[i] = 1.f - mTimes[mTimes.length - 1 - i];
                     mTimes[mTimes.length - 1 - i] = 1.f - temp;
+                    temp = mVolumes[i];
+                    mVolumes[i] = mVolumes[mVolumes.length - 1 - i];
+                    mVolumes[mVolumes.length - 1 - i] = temp;
                 }
                 if ((mTimes.length & 1) != 0) {
                     mTimes[i] = 1.f - mTimes[i];
@@ -824,23 +878,24 @@
              * becomes the min volume and vice versa.
              *
              * @return the same {@code Builder} instance.
+             * @throws IllegalArgumentException if curve has not been set.
              */
             public @NonNull Builder invertVolumes() {
-                if (mVolumes.length >= 2) {
-                    float min = mVolumes[0];
-                    float max = mVolumes[0];
-                    for (int i = 1; i < mVolumes.length; ++i) {
-                        if (mVolumes[i] < min) {
-                            min = mVolumes[i];
-                        } else if (mVolumes[i] > max) {
-                            max = mVolumes[i];
-                        }
+                checkCurveForErrorsAndThrowException(
+                        mTimes, mVolumes, (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0);
+                float min = mVolumes[0];
+                float max = mVolumes[0];
+                for (int i = 1; i < mVolumes.length; ++i) {
+                    if (mVolumes[i] < min) {
+                        min = mVolumes[i];
+                    } else if (mVolumes[i] > max) {
+                        max = mVolumes[i];
                     }
+                }
 
-                    final float maxmin = max + min;
-                    for (int i = 0; i < mVolumes.length; ++i) {
-                        mVolumes[i] = maxmin - mVolumes[i];
-                    }
+                final float maxmin = max + min;
+                for (int i = 0; i < mVolumes.length; ++i) {
+                    mVolumes[i] = maxmin - mVolumes[i];
                 }
                 return this;
             }
@@ -853,11 +908,13 @@
              *
              * @param volume the target end volume to use.
              * @return the same {@code Builder} instance.
-             * @throws IllegalArgumentException if {@code volume} is not valid.
+             * @throws IllegalArgumentException if {@code volume}
+             *         is not valid or if curve has not been set.
              */
             public @NonNull Builder scaleToEndVolume(float volume) {
                 final boolean log = (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0;
-                checkValidVolume(volume, log);
+                checkCurveForErrorsAndThrowException(mTimes, mVolumes, log);
+                checkValidVolumeAndThrowException(volume, log);
                 final float startVolume = mVolumes[0];
                 final float endVolume = mVolumes[mVolumes.length - 1];
                 if (endVolume == startVolume) {
@@ -885,11 +942,13 @@
              *
              * @param volume the target start volume to use.
              * @return the same {@code Builder} instance.
-             * @throws IllegalArgumentException if {@code volume} is not valid.
+             * @throws IllegalArgumentException if {@code volume}
+             *         is not valid or if curve has not been set.
              */
             public @NonNull Builder scaleToStartVolume(float volume) {
                 final boolean log = (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0;
-                checkValidVolume(volume, log);
+                checkCurveForErrorsAndThrowException(mTimes, mVolumes, log);
+                checkValidVolumeAndThrowException(volume, log);
                 final float startVolume = mVolumes[0];
                 final float endVolume = mVolumes[mVolumes.length - 1];
                 if (endVolume == startVolume) {
@@ -911,16 +970,14 @@
             /**
              * Builds a new {@link VolumeShaper} object.
              *
-             * @return a new {@link VolumeShaper} object
+             * @return a new {@link VolumeShaper} object.
+             * @throws IllegalArgumentException if curve is not properly set.
              */
             public @NonNull Configuration build() {
-                String error = checkCurveForErrors(
+                checkCurveForErrorsAndThrowException(
                         mTimes, mVolumes, (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0);
-                if (error != null) {
-                    throw new IllegalArgumentException(error);
-                }
-                return new Configuration(mType, mId, mInterpolatorType, mOptionFlags,
-                        mDurationMs, mTimes, mVolumes);
+                return new Configuration(mType, mId, mOptionFlags, mDurationMs,
+                        mInterpolatorType, mTimes, mVolumes);
             }
         } // Configuration.Builder
     } // Configuration
@@ -1011,10 +1068,10 @@
 
         @Override
         public String toString() {
-            return "VolumeShaper.Operation["
-                    + "mFlags=" + mFlags
-                    + ",mReplaceId" + mReplaceId
-                    + "]";
+            return "VolumeShaper.Operation{"
+                    + "mFlags = 0x" + Integer.toHexString(mFlags).toUpperCase()
+                    + ", mReplaceId = " + mReplaceId
+                    + "}";
         }
 
         @Override
@@ -1027,6 +1084,8 @@
             if (!(o instanceof Operation)) return false;
             if (o == this) return true;
             final Operation other = (Operation) o;
+            // if xOffset (native field only) is brought into Java
+            // we need to do proper NaN comparison as that is allowed.
             return mFlags == other.mFlags
                     && mReplaceId == other.mReplaceId;
         }
@@ -1038,17 +1097,24 @@
 
         @Override
         public void writeToParcel(Parcel dest, int flags) {
+            // this needs to match the native VolumeShaper.Operation parceling
             dest.writeInt(mFlags);
             dest.writeInt(mReplaceId);
+            dest.writeFloat(Float.NaN); // xOffset (ignored at Java level)
         }
 
         public static final Parcelable.Creator<VolumeShaper.Operation> CREATOR
                 = new Parcelable.Creator<VolumeShaper.Operation>() {
             @Override
             public VolumeShaper.Operation createFromParcel(Parcel p) {
+                // this needs to match the native VolumeShaper.Operation parceling
+                final int flags = p.readInt();
+                final int replaceId = p.readInt();
+                final float xOffset = p.readFloat(); // ignored at Java level
+
                 return new VolumeShaper.Operation(
-                        p.readInt()     // flags
-                        , p.readInt()); // replaceId
+                        flags
+                        , replaceId);
             }
 
             @Override
@@ -1154,6 +1220,7 @@
              *
              * @param flags new value for {@code flags}, consisting of ORed flags.
              * @return the same {@code Builder} instance.
+             * @throws IllegalArgumentException if {@code flags} contains invalid set bits.
              */
             private @NonNull Builder setFlags(@Flag int flags) {
                 if ((flags & ~FLAG_PUBLIC_ALL) != 0) {
@@ -1187,10 +1254,10 @@
 
         @Override
         public String toString() {
-            return "VolumeShaper.State["
-                    + "mVolume=" + mVolume
-                    + ",mXOffset" + mXOffset
-                    + "]";
+            return "VolumeShaper.State{"
+                    + "mVolume = " + mVolume
+                    + ", mXOffset = " + mXOffset
+                    + "}";
         }
 
         @Override
diff --git a/media/jni/android_media_VolumeShaper.h b/media/jni/android_media_VolumeShaper.h
index dbbc478..73498a2 100644
--- a/media/jni/android_media_VolumeShaper.h
+++ b/media/jni/android_media_VolumeShaper.h
@@ -29,9 +29,9 @@
         jmethodID coConstructId;
         jfieldID  coTypeId;
         jfieldID  coIdId;
-        jfieldID  coInterpolatorTypeId;
         jfieldID  coOptionFlagsId;
         jfieldID  coDurationMsId;
+        jfieldID  coInterpolatorTypeId;
         jfieldID  coTimesId;
         jfieldID  coVolumesId;
 
@@ -56,12 +56,12 @@
             if (coClazz == nullptr) {
                 return;
             }
-            coConstructId = env->GetMethodID(coClazz, "<init>", "(IIIID[F[F)V");
+            coConstructId = env->GetMethodID(coClazz, "<init>", "(IIIDI[F[F)V");
             coTypeId = env->GetFieldID(coClazz, "mType", "I");
             coIdId = env->GetFieldID(coClazz, "mId", "I");
-            coInterpolatorTypeId = env->GetFieldID(coClazz, "mInterpolatorType", "I");
             coOptionFlagsId = env->GetFieldID(coClazz, "mOptionFlags", "I");
             coDurationMsId = env->GetFieldID(coClazz, "mDurationMs", "D");
+            coInterpolatorTypeId = env->GetFieldID(coClazz, "mInterpolatorType", "I");
             coTimesId = env->GetFieldID(coClazz, "mTimes", "[F");
             coVolumesId = env->GetFieldID(coClazz, "mVolumes", "[F");
             env->DeleteLocalRef(lclazz);
@@ -108,14 +108,14 @@
         configuration->setId(
             (int)env->GetIntField(jshaper, fields.coIdId));
         if (configuration->getType() == VolumeShaper::Configuration::TYPE_SCALE) {
-            configuration->setInterpolatorType(
-                (VolumeShaper::Configuration::InterpolatorType)
-                env->GetIntField(jshaper, fields.coInterpolatorTypeId));
             configuration->setOptionFlags(
                 (VolumeShaper::Configuration::OptionFlag)
                 env->GetIntField(jshaper, fields.coOptionFlagsId));
             configuration->setDurationMs(
                     (double)env->GetDoubleField(jshaper, fields.coDurationMsId));
+            configuration->setInterpolatorType(
+                (VolumeShaper::Configuration::InterpolatorType)
+                env->GetIntField(jshaper, fields.coInterpolatorTypeId));
 
             // convert point arrays
             jobject xobj = env->GetObjectField(jshaper, fields.coTimesId);
@@ -165,9 +165,9 @@
         jvalue args[7];
         args[0].i = (jint)configuration->getType();
         args[1].i = (jint)configuration->getId();
-        args[2].i = (jint)configuration->getInterpolatorType();
-        args[3].i = (jint)configuration->getOptionFlags();
-        args[4].d = (jdouble)configuration->getDurationMs();
+        args[2].i = (jint)configuration->getOptionFlags();
+        args[3].d = (jdouble)configuration->getDurationMs();
+        args[4].i = (jint)configuration->getInterpolatorType();
         args[5].l = xarray;
         args[6].l = yarray;
         jobject jshaper = env->NewObjectA(fields.coClazz, fields.coConstructId, args);
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index 23a8655..6394c64 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -77,8 +77,8 @@
         mCm = ConnectivityManager.from(this);
         mNetwork = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_NETWORK);
         mCaptivePortal = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL);
-        mUserAgent = getIntent().getParcelableExtra(
-                ConnectivityManager.EXTRA_CAPTIVE_PORTAL_USER_AGENT);
+        mUserAgent =
+                getIntent().getStringExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_USER_AGENT);
         mUrl = getUrl();
         if (mUrl == null) {
             // getUrl() failed to parse the url provided in the intent: bail out in a way that
@@ -274,8 +274,17 @@
                     if (mUserAgent != null) {
                        urlConnection.setRequestProperty("User-Agent", mUserAgent);
                     }
+                    // cannot read request header after connection
+                    String requestHeader = urlConnection.getRequestProperties().toString();
+
                     urlConnection.getInputStream();
                     httpResponseCode = urlConnection.getResponseCode();
+                    if (DBG) {
+                        Log.d(TAG, "probe at " + mUrl +
+                                " ret=" + httpResponseCode +
+                                " request=" + requestHeader +
+                                " headers=" + urlConnection.getHeaderFields());
+                    }
                 } catch (IOException e) {
                 } finally {
                     if (urlConnection != null) urlConnection.disconnect();
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index fda3914..8f7efb5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -19,6 +19,8 @@
 import android.app.ActivityManager;
 import android.app.AppGlobals;
 import android.app.Application;
+import android.app.usage.StorageStats;
+import android.app.usage.StorageStatsManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -92,6 +94,7 @@
     final PackageManager mPm;
     final IPackageManager mIpm;
     final UserManager mUm;
+    final StorageStatsManager mStats;
     final int mAdminRetrieveFlags;
     final int mRetrieveFlags;
     PackageIntentReceiver mPackageIntentReceiver;
@@ -111,6 +114,7 @@
     final ArrayList<AppEntry> mAppEntries = new ArrayList<AppEntry>();
     List<ApplicationInfo> mApplications = new ArrayList<ApplicationInfo>();
     long mCurId = 1;
+    String mCurComputingSizeUuid;
     String mCurComputingSizePkg;
     int mCurComputingSizeUserId;
     boolean mSessionsChanged;
@@ -126,7 +130,8 @@
         mContext = app;
         mPm = mContext.getPackageManager();
         mIpm = AppGlobals.getPackageManager();
-        mUm = (UserManager) app.getSystemService(Context.USER_SERVICE);
+        mUm = mContext.getSystemService(UserManager.class);
+        mStats = mContext.getSystemService(StorageStatsManager.class);
         for (int userId : mUm.getProfileIdsWithDisabled(UserHandle.myUserId())) {
             mEntriesMap.put(userId, new HashMap<String, AppEntry>());
         }
@@ -328,7 +333,18 @@
         synchronized (mEntriesMap) {
             AppEntry entry = mEntriesMap.get(userId).get(packageName);
             if (entry != null) {
-                mPm.getPackageSizeInfoAsUser(packageName, userId, mBackgroundHandler.mStatsObserver);
+                mBackgroundHandler.post(() -> {
+                    final StorageStats stats = mStats.queryStatsForPackage(entry.info.volumeUuid,
+                            packageName, UserHandle.of(userId));
+                    final PackageStats legacyStats = new PackageStats(packageName, userId);
+                    legacyStats.codeSize = stats.getCodeBytes();
+                    legacyStats.dataSize = stats.getDataBytes();
+                    legacyStats.cacheSize = stats.getCacheBytes();
+                    try {
+                        mBackgroundHandler.mStatsObserver.onGetStatsCompleted(legacyStats, true);
+                    } catch (RemoteException ignored) {
+                    }
+                });
             }
             if (DEBUG_LOCKING) Log.v(TAG, "...requestSize releasing lock");
         }
@@ -958,10 +974,24 @@
                                         mMainHandler.sendMessage(m);
                                     }
                                     entry.sizeLoadStart = now;
+                                    mCurComputingSizeUuid = entry.info.volumeUuid;
                                     mCurComputingSizePkg = entry.info.packageName;
                                     mCurComputingSizeUserId = UserHandle.getUserId(entry.info.uid);
-                                    mPm.getPackageSizeInfoAsUser(mCurComputingSizePkg,
-                                            mCurComputingSizeUserId, mStatsObserver);
+
+                                    mBackgroundHandler.post(() -> {
+                                        final StorageStats stats = mStats.queryStatsForPackage(
+                                                mCurComputingSizeUuid, mCurComputingSizePkg,
+                                                UserHandle.of(mCurComputingSizeUserId));
+                                        final PackageStats legacyStats = new PackageStats(
+                                                mCurComputingSizePkg, mCurComputingSizeUserId);
+                                        legacyStats.codeSize = stats.getCodeBytes();
+                                        legacyStats.dataSize = stats.getDataBytes();
+                                        legacyStats.cacheSize = stats.getCacheBytes();
+                                        try {
+                                            mStatsObserver.onGetStatsCompleted(legacyStats, true);
+                                        } catch (RemoteException ignored) {
+                                        }
+                                    });
                                 }
                                 if (DEBUG_LOCKING) Log.v(TAG, "MSG_LOAD_SIZES releasing: now computing");
                                 return;
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
index e520319..953dda2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
@@ -16,22 +16,14 @@
 
 package com.android.settingslib.deviceinfo;
 
-import android.app.ActivityManager;
-import android.content.ComponentName;
+import android.app.usage.ExternalStorageStats;
+import android.app.usage.StorageStats;
+import android.app.usage.StorageStatsManager;
 import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageStatsObserver;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageStats;
 import android.content.pm.UserInfo;
+import android.os.AsyncTask;
 import android.os.Environment;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.storage.StorageVolume;
@@ -40,93 +32,54 @@
 import android.util.SparseArray;
 import android.util.SparseLongArray;
 
-import com.android.internal.app.IMediaContainerService;
-import com.android.internal.util.ArrayUtils;
-import com.google.android.collect.Sets;
-
-import java.io.File;
 import java.lang.ref.WeakReference;
-import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
-import java.util.Objects;
-import java.util.Set;
 
 /**
  * Utility for measuring the disk usage of internal storage or a physical
- * {@link StorageVolume}. Connects with a remote {@link IMediaContainerService}
- * and delivers results to {@link MeasurementReceiver}.
+ * {@link StorageVolume}.
  */
 public class StorageMeasurement {
     private static final String TAG = "StorageMeasurement";
 
-    private static final boolean LOCAL_LOGV = false;
-    static final boolean LOGV = LOCAL_LOGV && Log.isLoggable(TAG, Log.VERBOSE);
-
-    private static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer";
-
-    public static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
-            DEFAULT_CONTAINER_PACKAGE, "com.android.defcontainer.DefaultContainerService");
-
-    /** Media types to measure on external storage. */
-    private static final Set<String> sMeasureMediaTypes = Sets.newHashSet(
-            Environment.DIRECTORY_DCIM, Environment.DIRECTORY_MOVIES,
-            Environment.DIRECTORY_PICTURES, Environment.DIRECTORY_MUSIC,
-            Environment.DIRECTORY_ALARMS, Environment.DIRECTORY_NOTIFICATIONS,
-            Environment.DIRECTORY_RINGTONES, Environment.DIRECTORY_PODCASTS,
-            Environment.DIRECTORY_DOWNLOADS, Environment.DIRECTORY_ANDROID);
-
     public static class MeasurementDetails {
+        /** Size of storage device. */
         public long totalSize;
+        /** Size of available space. */
         public long availSize;
+        /** Size of all cached data. */
+        public long cacheSize;
 
         /**
-         * Total apps disk usage per profiles of the current user.
+         * Total disk space used by everything.
          * <p>
-         * When measuring internal storage, this value includes the code size of
-         * all apps (regardless of install status for the given profile), and
-         * internal disk used by the profile's apps. When the device
-         * emulates external storage, this value also includes emulated storage
-         * used by the profile's apps.
-         * <p>
-         * When measuring a physical {@link StorageVolume}, this value includes
-         * usage by all apps on that volume and only for the primary profile.
+         * Key is {@link UserHandle}.
+         */
+        public SparseLongArray usersSize = new SparseLongArray();
+
+        /**
+         * Total disk space used by apps.
          * <p>
          * Key is {@link UserHandle}.
          */
         public SparseLongArray appsSize = new SparseLongArray();
 
         /**
-         * Total cache disk usage by apps (over all users and profiles).
-         */
-        public long cacheSize;
-
-        /**
-         * Total media disk usage, categorized by types such as
-         * {@link Environment#DIRECTORY_MUSIC} for every user profile of the current user.
+         * Total disk space used by media on shared storage.
          * <p>
-         * When measuring internal storage, this reflects media on emulated
-         * storage for the respective profile.
-         * <p>
-         * When measuring a physical {@link StorageVolume}, this reflects media
-         * on that volume.
-         * <p>
-         * Key of the {@link SparseArray} is {@link UserHandle}.
+         * First key is {@link UserHandle}. Second key is media type, such as
+         * {@link Environment#DIRECTORY_PICTURES}.
          */
         public SparseArray<HashMap<String, Long>> mediaSize = new SparseArray<>();
 
         /**
-         * Misc external disk usage for the current user's profiles, unaccounted in
-         * {@link #mediaSize}. Key is {@link UserHandle}.
+         * Total disk space used by non-media on shared storage.
+         * <p>
+         * Key is {@link UserHandle}.
          */
         public SparseLongArray miscSize = new SparseLongArray();
 
-        /**
-         * Total disk usage for users, which is only meaningful for emulated
-         * internal storage. Key is {@link UserHandle}.
-         */
-        public SparseLongArray usersSize = new SparseLongArray();
-
         @Override
         public String toString() {
             return "MeasurementDetails: [totalSize: " + totalSize + " availSize: " + availSize
@@ -142,25 +95,19 @@
     private WeakReference<MeasurementReceiver> mReceiver;
 
     private final Context mContext;
+    private final UserManager mUser;
+    private final StorageStatsManager mStats;
 
     private final VolumeInfo mVolume;
     private final VolumeInfo mSharedVolume;
 
-    private final MainHandler mMainHandler;
-    private final MeasurementHandler mMeasurementHandler;
-
     public StorageMeasurement(Context context, VolumeInfo volume, VolumeInfo sharedVolume) {
         mContext = context.getApplicationContext();
+        mUser = mContext.getSystemService(UserManager.class);
+        mStats = mContext.getSystemService(StorageStatsManager.class);
 
         mVolume = volume;
         mSharedVolume = sharedVolume;
-
-        // Start the thread that will measure the disk usage.
-        final HandlerThread handlerThread = new HandlerThread("MemoryMeasurement");
-        handlerThread.start();
-
-        mMainHandler = new MainHandler();
-        mMeasurementHandler = new MeasurementHandler(handlerThread.getLooper());
     }
 
     public void setReceiver(MeasurementReceiver receiver) {
@@ -170,315 +117,94 @@
     }
 
     public void forceMeasure() {
-        invalidate();
         measure();
     }
 
     public void measure() {
-        if (!mMeasurementHandler.hasMessages(MeasurementHandler.MSG_MEASURE)) {
-            mMeasurementHandler.sendEmptyMessage(MeasurementHandler.MSG_MEASURE);
-        }
+        new MeasureTask().execute();
     }
 
     public void onDestroy() {
         mReceiver = null;
-        mMeasurementHandler.removeMessages(MeasurementHandler.MSG_MEASURE);
-        mMeasurementHandler.sendEmptyMessage(MeasurementHandler.MSG_DISCONNECT);
     }
 
-    private void invalidate() {
-        mMeasurementHandler.sendEmptyMessage(MeasurementHandler.MSG_INVALIDATE);
-    }
-
-    private static class StatsObserver extends IPackageStatsObserver.Stub {
-        private final boolean mIsPrivate;
-        private final MeasurementDetails mDetails;
-        private final int mCurrentUser;
-        private final Message mFinished;
-
-        private int mRemaining;
-
-        public StatsObserver(boolean isPrivate, MeasurementDetails details, int currentUser,
-                List<UserInfo> profiles, Message finished, int remaining) {
-            mIsPrivate = isPrivate;
-            mDetails = details;
-            mCurrentUser = currentUser;
-            if (isPrivate) {
-                // Add the profile ids as keys to detail's app sizes.
-                for (UserInfo userInfo : profiles) {
-                    mDetails.appsSize.put(userInfo.id, 0);
-                }
-            }
-            mFinished = finished;
-            mRemaining = remaining;
+    private class MeasureTask extends AsyncTask<Void, Void, MeasurementDetails> {
+        @Override
+        protected MeasurementDetails doInBackground(Void... params) {
+            return measureExactStorage();
         }
 
         @Override
-        public void onGetStatsCompleted(PackageStats stats, boolean succeeded) {
-            synchronized (mDetails) {
-                if (succeeded) {
-                    addStatsLocked(stats);
-                }
-                if (--mRemaining == 0) {
-                    mFinished.sendToTarget();
-                }
-            }
-        }
-
-        private void addStatsLocked(PackageStats stats) {
-            if (mIsPrivate) {
-                long codeSize = stats.codeSize;
-                long dataSize = stats.dataSize;
-                long cacheSize = stats.cacheSize;
-                if (Environment.isExternalStorageEmulated()) {
-                    // Include emulated storage when measuring internal. OBB is
-                    // shared on emulated storage, so treat as code.
-                    codeSize += stats.externalCodeSize + stats.externalObbSize;
-                    dataSize += stats.externalDataSize + stats.externalMediaSize;
-                    cacheSize += stats.externalCacheSize;
-                }
-
-                // Count code and data for current user's profiles (keys prepared in constructor)
-                addValueIfKeyExists(mDetails.appsSize, stats.userHandle, codeSize + dataSize);
-
-                // User summary only includes data (code is only counted once
-                // for the current user)
-                addValue(mDetails.usersSize, stats.userHandle, dataSize);
-
-                // Include cache for all users
-                mDetails.cacheSize += cacheSize;
-
-            } else {
-                // Physical storage; only count external sizes
-                addValue(mDetails.appsSize, mCurrentUser,
-                        stats.externalCodeSize + stats.externalDataSize
-                        + stats.externalMediaSize + stats.externalObbSize);
-                mDetails.cacheSize += stats.externalCacheSize;
-            }
-        }
-    }
-
-    private class MainHandler extends Handler {
-        @Override
-        public void handleMessage(Message msg) {
-            final MeasurementDetails details = (MeasurementDetails) msg.obj;
+        protected void onPostExecute(MeasurementDetails result) {
             final MeasurementReceiver receiver = (mReceiver != null) ? mReceiver.get() : null;
             if (receiver != null) {
-                receiver.onDetailsChanged(details);
+                receiver.onDetailsChanged(result);
             }
         }
     }
 
-    private class MeasurementHandler extends Handler {
-        public static final int MSG_MEASURE = 1;
-        public static final int MSG_CONNECTED = 2;
-        public static final int MSG_DISCONNECT = 3;
-        public static final int MSG_COMPLETED = 4;
-        public static final int MSG_INVALIDATE = 5;
+    private MeasurementDetails measureExactStorage() {
+        final List<UserInfo> users = mUser.getUsers();
 
-        private Object mLock = new Object();
-
-        private IMediaContainerService mDefaultContainer;
-
-        private volatile boolean mBound = false;
-
-        private MeasurementDetails mCached;
-
-        private final ServiceConnection mDefContainerConn = new ServiceConnection() {
-            @Override
-            public void onServiceConnected(ComponentName name, IBinder service) {
-                final IMediaContainerService imcs = IMediaContainerService.Stub.asInterface(
-                        service);
-                mDefaultContainer = imcs;
-                mBound = true;
-                sendMessage(obtainMessage(MSG_CONNECTED, imcs));
-            }
-
-            @Override
-            public void onServiceDisconnected(ComponentName name) {
-                mBound = false;
-                removeMessages(MSG_CONNECTED);
-            }
-        };
-
-        public MeasurementHandler(Looper looper) {
-            super(looper);
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_MEASURE: {
-                    if (mCached != null) {
-                        mMainHandler.obtainMessage(0, mCached).sendToTarget();
-                        break;
-                    }
-
-                    synchronized (mLock) {
-                        if (mBound) {
-                            removeMessages(MSG_DISCONNECT);
-                            sendMessage(obtainMessage(MSG_CONNECTED, mDefaultContainer));
-                        } else {
-                            Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
-                            mContext.bindServiceAsUser(service, mDefContainerConn,
-                                    Context.BIND_AUTO_CREATE, UserHandle.SYSTEM);
-                        }
-                    }
-                    break;
-                }
-                case MSG_CONNECTED: {
-                    final IMediaContainerService imcs = (IMediaContainerService) msg.obj;
-                    measureExactStorage(imcs);
-                    break;
-                }
-                case MSG_DISCONNECT: {
-                    synchronized (mLock) {
-                        if (mBound) {
-                            mBound = false;
-                            mContext.unbindService(mDefContainerConn);
-                        }
-                    }
-                    break;
-                }
-                case MSG_COMPLETED: {
-                    mCached = (MeasurementDetails) msg.obj;
-                    mMainHandler.obtainMessage(0, mCached).sendToTarget();
-                    break;
-                }
-                case MSG_INVALIDATE: {
-                    mCached = null;
-                    break;
-                }
-            }
-        }
-    }
-
-    private void measureExactStorage(IMediaContainerService imcs) {
-        final UserManager userManager = mContext.getSystemService(UserManager.class);
-        final PackageManager packageManager = mContext.getPackageManager();
-
-        final List<UserInfo> users = userManager.getUsers();
-        final List<UserInfo> currentProfiles = userManager.getEnabledProfiles(
-                ActivityManager.getCurrentUser());
+        final long start = SystemClock.elapsedRealtime();
 
         final MeasurementDetails details = new MeasurementDetails();
-        final Message finished = mMeasurementHandler.obtainMessage(MeasurementHandler.MSG_COMPLETED,
-                details);
+        if (mVolume == null) return details;
 
-        if (mVolume == null || !mVolume.isMountedReadable()) {
-            finished.sendToTarget();
-            return;
-        }
+        details.totalSize = mStats.getTotalBytes(mVolume.fsUuid);
+        details.availSize = mStats.getFreeBytes(mVolume.fsUuid);
+
+        final long finishTotal = SystemClock.elapsedRealtime();
+        Log.d(TAG, "Measured total storage in " + (finishTotal - start) + "ms");
 
         if (mSharedVolume != null && mSharedVolume.isMountedReadable()) {
-            for (UserInfo currentUserInfo : currentProfiles) {
-                final int userId = currentUserInfo.id;
-                final File basePath = mSharedVolume.getPathForUser(userId);
-                HashMap<String, Long> mediaMap = new HashMap<>(sMeasureMediaTypes.size());
-                details.mediaSize.put(userId, mediaMap);
-
-                // Measure media types for emulated storage, or for primary physical
-                // external volume
-                for (String type : sMeasureMediaTypes) {
-                    final File path = new File(basePath, type);
-                    final long size = getDirectorySize(imcs, path);
-                    mediaMap.put(type, size);
-                }
-
-                // Measure misc files not counted under media
-                addValue(details.miscSize, userId, measureMisc(imcs, basePath));
-            }
-
-            if (mSharedVolume.getType() == VolumeInfo.TYPE_EMULATED) {
-                // Measure total emulated storage of all users; internal apps data
-                // will be spliced in later
-                for (UserInfo user : users) {
-                    final File userPath = mSharedVolume.getPathForUser(user.id);
-                    final long size = getDirectorySize(imcs, userPath);
-                    addValue(details.usersSize, user.id, size);
-                }
-            }
-        }
-
-        final File file = mVolume.getPath();
-        if (file != null) {
-            details.totalSize = file.getTotalSpace();
-            details.availSize = file.getFreeSpace();
-        }
-
-        // Measure all apps hosted on this volume for all users
-        if (mVolume.getType() == VolumeInfo.TYPE_PRIVATE) {
-            final List<ApplicationInfo> apps = packageManager.getInstalledApplications(
-                    PackageManager.MATCH_ANY_USER
-                    | PackageManager.MATCH_DISABLED_COMPONENTS);
-
-            final List<ApplicationInfo> volumeApps = new ArrayList<>();
-            for (ApplicationInfo app : apps) {
-                if (Objects.equals(app.volumeUuid, mVolume.getFsUuid())) {
-                    volumeApps.add(app);
-                }
-            }
-
-            final int count = users.size() * volumeApps.size();
-            if (count == 0) {
-                finished.sendToTarget();
-                return;
-            }
-
-            final StatsObserver observer = new StatsObserver(true, details,
-                    ActivityManager.getCurrentUser(), currentProfiles, finished, count);
             for (UserInfo user : users) {
-                for (ApplicationInfo app : volumeApps) {
-                    packageManager.getPackageSizeInfoAsUser(app.packageName, user.id, observer);
+                final HashMap<String, Long> mediaMap = new HashMap<>();
+                details.mediaSize.put(user.id, mediaMap);
+
+                final ExternalStorageStats stats = mStats
+                        .queryExternalStatsForUser(mSharedVolume.fsUuid, UserHandle.of(user.id));
+
+                addValue(details.usersSize, user.id, stats.getTotalBytes());
+
+                // Track detailed data types
+                mediaMap.put(Environment.DIRECTORY_MUSIC, stats.getAudioBytes());
+                mediaMap.put(Environment.DIRECTORY_MOVIES, stats.getVideoBytes());
+                mediaMap.put(Environment.DIRECTORY_PICTURES, stats.getImageBytes());
+
+                final long miscBytes = stats.getTotalBytes() - stats.getAudioBytes()
+                        - stats.getVideoBytes() - stats.getImageBytes();
+                addValue(details.miscSize, user.id, miscBytes);
+            }
+        }
+
+        final long finishShared = SystemClock.elapsedRealtime();
+        Log.d(TAG, "Measured shared storage in " + (finishShared - finishTotal) + "ms");
+
+        if ((mVolume.getType() == VolumeInfo.TYPE_PRIVATE) && mVolume.isMountedReadable()) {
+            for (UserInfo user : users) {
+                final StorageStats stats = mStats.queryStatsForUser(mVolume.fsUuid,
+                        UserHandle.of(user.id));
+
+                // Only count code once against current user
+                if (user.id == UserHandle.myUserId()) {
+                    addValue(details.usersSize, user.id, stats.getCodeBytes());
                 }
-            }
 
-        } else {
-            finished.sendToTarget();
-            return;
-        }
-    }
+                addValue(details.usersSize, user.id, stats.getDataBytes());
+                addValue(details.appsSize, user.id, stats.getCodeBytes() + stats.getDataBytes());
 
-    private static long getDirectorySize(IMediaContainerService imcs, File path) {
-        try {
-            final long size = imcs.calculateDirectorySize(path.toString());
-            if (LOGV) Log.v(TAG, "getDirectorySize(" + path + ") returned " + size);
-            return size;
-        } catch (Exception e) {
-            Log.w(TAG, "Could not read memory from default container service for " + path, e);
-            return 0;
-        }
-    }
-
-    private long measureMisc(IMediaContainerService imcs, File dir) {
-        final File[] files = dir.listFiles();
-        if (ArrayUtils.isEmpty(files)) return 0;
-
-        // Get sizes of all top level nodes except the ones already computed
-        long miscSize = 0;
-        for (File file : files) {
-            final String name = file.getName();
-            if (sMeasureMediaTypes.contains(name)) {
-                continue;
-            }
-
-            if (file.isFile()) {
-                miscSize += file.length();
-            } else if (file.isDirectory()) {
-                miscSize += getDirectorySize(imcs, file);
+                details.cacheSize += stats.getCacheBytes();
             }
         }
-        return miscSize;
+
+        final long finishPrivate = SystemClock.elapsedRealtime();
+        Log.d(TAG, "Measured private storage in " + (finishPrivate - finishShared) + "ms");
+
+        return details;
     }
 
     private static void addValue(SparseLongArray array, int key, long value) {
         array.put(key, array.get(key) + value);
     }
-
-    private static void addValueIfKeyExists(SparseLongArray array, int key, long value) {
-        final int index = array.indexOfKey(key);
-        if (index >= 0) {
-            array.put(key, array.valueAt(index) + value);
-        }
-    }
 }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index de79d3f..5f4b239 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -553,23 +553,23 @@
     }
 
     private void doWriteState() {
+        boolean wroteState = false;
+        final int version;
+        final ArrayMap<String, Setting> settings;
+
+        synchronized (mLock) {
+            version = mVersion;
+            settings = new ArrayMap<>(mSettings);
+            mDirty = false;
+            mWriteScheduled = false;
+        }
+
         synchronized (mWriteLock) {
             if (DEBUG_PERSISTENCE) {
                 Slog.i(LOG_TAG, "[PERSIST START]");
             }
 
             AtomicFile destination = new AtomicFile(mStatePersistFile);
-
-            final int version;
-            final ArrayMap<String, Setting> settings;
-
-            synchronized (mLock) {
-                version = mVersion;
-                settings = new ArrayMap<>(mSettings);
-                mDirty = false;
-                mWriteScheduled = false;
-            }
-
             FileOutputStream out = null;
             try {
                 out = destination.startWrite();
@@ -600,9 +600,7 @@
                 serializer.endDocument();
                 destination.finishWrite(out);
 
-                synchronized (mLock) {
-                    addHistoricalOperationLocked(HISTORICAL_OPERATION_PERSIST, null);
-                }
+                wroteState = true;
 
                 if (DEBUG_PERSISTENCE) {
                     Slog.i(LOG_TAG, "[PERSIST END]");
@@ -614,6 +612,12 @@
                 IoUtils.closeQuietly(out);
             }
         }
+
+        if (wroteState) {
+            synchronized (mLock) {
+                addHistoricalOperationLocked(HISTORICAL_OPERATION_PERSIST, null);
+            }
+        }
     }
 
     static void writeSingleSetting(int version, XmlSerializer serializer, String id,
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 62e11f7..93ae763 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1164,6 +1164,8 @@
     <string name="volume_stream_content_description_unmute">%1$s. Tap to unmute.</string>
     <string name="volume_stream_content_description_vibrate">%1$s. Tap to set to vibrate. Accessibility services may be muted.</string>
     <string name="volume_stream_content_description_mute">%1$s. Tap to mute. Accessibility services may be muted.</string>
+    <string name="volume_stream_content_description_vibrate_a11y">%1$s. Tap to set to vibrate.</string>
+    <string name="volume_stream_content_description_mute_a11y">%1$s. Tap to mute.</string>
 
     <string name="volume_dialog_accessibility_shown_message">%s volume controls shown. Swipe up to dismiss.</string>
     <string name="volume_dialog_accessibility_dismissed_message">Volume controls hidden</string>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index 3559257..9da52d0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -263,7 +263,6 @@
         public TilePage(Context context, AttributeSet attrs) {
             super(context, attrs);
             updateResources();
-            setContentDescription(getContext().getString(R.string.accessibility_desc_quick_settings));
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index 3337090..a30b03b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -175,7 +175,8 @@
             View view = mQs.getView();
             if (count < mNumQuickTiles && mAllowFancy) {
                 // Quick tiles.
-                com.android.systemui.plugins.qs.QSTileView quickTileView = mQuickQsPanel.getTileView(tile);
+                QSTileView quickTileView = mQuickQsPanel.getTileView(tile);
+                if (quickTileView == null) continue;
 
                 lastX = loc1[0];
                 getRelativePosition(loc1, quickTileView.getIcon().getIconView(), view);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 3a93d51..63563b2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -162,8 +162,7 @@
 
     public void setHeaderClickable(boolean clickable) {
         if (DEBUG) Log.d(TAG, "setHeaderClickable " + clickable);
-        mHeader.setClickable(clickable);
-        mFooter.setClickable(clickable);
+        mFooter.getExpandView().setClickable(clickable);
     }
 
     public void setExpanded(boolean expanded) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 8c1c89f..d0d6f61 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -125,9 +125,7 @@
     }
 
     public void updateEverything() {
-        post(() -> {
-            setClickable(false);
-        });
+        post(() -> setClickable(false));
     }
 
     public void setQSPanel(final QSPanel qsPanel) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index fc3bb43..00968ee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -1268,7 +1268,6 @@
         if (mChildrenContainer != null) {
             mChildrenContainer.setVisibility(!mShowingPublic && mIsSummaryWithChildren ? VISIBLE
                     : INVISIBLE);
-            mChildrenContainer.setHeaderVisible(!mShowingPublic && mIsSummaryWithChildren);
         }
         // The limits might have changed if the view suddenly became a group or vice versa
         updateLimits();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index b52c26f..4dc593b8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -188,9 +188,6 @@
     public void panelScrimMinFractionChanged(float minFraction) {
         if (mMinFraction != minFraction) {
             mMinFraction = minFraction;
-            if (minFraction != 0.0f) {
-                mScrimController.animateNextChange();
-            }
             updateScrimFraction();
         }
     }
@@ -203,7 +200,11 @@
     }
 
     private void updateScrimFraction() {
-        float scrimFraction = Math.max(mPanelFraction, mMinFraction);
+        float scrimFraction = mPanelFraction;
+        if (mMinFraction < 1.0f) {
+            scrimFraction = Math.max((mPanelFraction - mMinFraction) / (1.0f - mMinFraction),
+                    0);
+        }
         mScrimController.setPanelExpansion(scrimFraction);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index b30d3ab..dadb749 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -203,10 +203,6 @@
         scheduleUpdate();
     }
 
-    public void animateNextChange() {
-        mAnimateChange = true;
-    }
-
     public void setDozing(boolean dozing) {
         if (mDozing != dozing) {
             mDozing = dozing;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
index 83cbd72..fe249a6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
@@ -89,7 +89,6 @@
     private ViewState mHeaderViewState;
     private int mClipBottomAmount;
     private boolean mIsLowPriority;
-    private boolean mHeaderVisible = true;
     private OnClickListener mHeaderClickListener;
     private boolean mShowingNormalHeader;
 
@@ -324,6 +323,7 @@
             }
             mNotificationHeaderWrapperLowPriority.notifyContentUpdated(mContainingNotification);
         } else {
+            removeView(mNotificationHeaderLowPriority);
             mNotificationHeaderLowPriority = null;
             mNotificationHeaderWrapperLowPriority = null;
         }
@@ -794,11 +794,6 @@
         return mNotificationHeaderLowPriority;
     }
 
-    public void setHeaderVisible(boolean visible) {
-        mHeaderVisible = visible;
-        updateHeaderVisibility(false /* animate */);
-    }
-
     private void updateHeaderVisibility(boolean animate) {
         NotificationHeaderView visibleHeader = mNotificationHeader;
         NotificationHeaderView hiddenHeader = mNotificationHeaderLowPriority;
@@ -809,7 +804,7 @@
             normalHeaderVisible = false;
         }
         if (animate) {
-            if (mHeaderVisible && visibleHeader != null && hiddenHeader != null
+            if (visibleHeader != null && hiddenHeader != null
                     && mShowingNormalHeader != normalHeaderVisible) {
                 hiddenHeader.setVisibility(VISIBLE);
                 visibleHeader.setVisibility(VISIBLE);
@@ -825,7 +820,7 @@
         if (!animate) {
             if (visibleHeader != null) {
                 getWrapperForView(visibleHeader).setVisible(true);
-                visibleHeader.setVisibility(mHeaderVisible ? VISIBLE : INVISIBLE);
+                visibleHeader.setVisibility(VISIBLE);
             }
             if (hiddenHeader != null) {
                 getWrapperForView(hiddenHeader).setVisible(false);
@@ -855,7 +850,7 @@
 
 
     private void updateHeaderTransformation() {
-        if (mUserLocked && mHeaderVisible && showingAsLowPriority()) {
+        if (mUserLocked && showingAsLowPriority()) {
             float fraction = getGroupExpandFraction();
             mNotificationHeaderWrapper.transformFrom(mNotificationHeaderWrapperLowPriority,
                     fraction);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
index b320d60..1933349a 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
@@ -426,34 +426,37 @@
         });
         row.icon = (ImageButton) row.view.findViewById(R.id.volume_row_icon);
         row.icon.setImageResource(iconRes);
-        row.icon.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                Events.writeEvent(mContext, Events.EVENT_ICON_CLICK, row.stream, row.iconState);
-                mController.setActiveStream(row.stream);
-                if (row.stream == AudioManager.STREAM_RING) {
-                    final boolean hasVibrator = mController.hasVibrator();
-                    if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) {
-                        if (hasVibrator) {
-                            mController.setRingerMode(AudioManager.RINGER_MODE_VIBRATE, false);
+        if (row.stream != AudioSystem.STREAM_ACCESSIBILITY) {
+            row.icon.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    Events.writeEvent(mContext, Events.EVENT_ICON_CLICK, row.stream, row.iconState);
+                    mController.setActiveStream(row.stream);
+                    if (row.stream == AudioManager.STREAM_RING) {
+                        final boolean hasVibrator = mController.hasVibrator();
+                        if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) {
+                            if (hasVibrator) {
+                                mController.setRingerMode(AudioManager.RINGER_MODE_VIBRATE, false);
+                            } else {
+                                final boolean wasZero = row.ss.level == 0;
+                                mController.setStreamVolume(stream,
+                                        wasZero ? row.lastAudibleLevel : 0);
+                            }
                         } else {
-                            final boolean wasZero = row.ss.level == 0;
-                            mController.setStreamVolume(stream, wasZero ? row.lastAudibleLevel : 0);
+                            mController.setRingerMode(AudioManager.RINGER_MODE_NORMAL, false);
+                            if (row.ss.level == 0) {
+                                mController.setStreamVolume(stream, 1);
+                            }
                         }
                     } else {
-                        mController.setRingerMode(AudioManager.RINGER_MODE_NORMAL, false);
-                        if (row.ss.level == 0) {
-                            mController.setStreamVolume(stream, 1);
-                        }
+                        final boolean vmute = row.ss.level == row.ss.levelMin;
+                        mController.setStreamVolume(stream,
+                                vmute ? row.lastAudibleLevel : row.ss.levelMin);
                     }
-                } else {
-                    final boolean vmute = row.ss.level == row.ss.levelMin;
-                    mController.setStreamVolume(stream,
-                            vmute ? row.lastAudibleLevel : row.ss.levelMin);
+                    row.userAttempt = 0;  // reset the grace period, slider updates immediately
                 }
-                row.userAttempt = 0;  // reset the grace period, slider should update immediately
-            }
-        });
+            });
+        }
     }
 
     public void destroy() {
@@ -722,6 +725,7 @@
         if (ss.level == row.requestedLevel) {
             row.requestedLevel = -1;
         }
+        final boolean isA11yStream = row.stream == AudioManager.STREAM_ACCESSIBILITY;
         final boolean isRingStream = row.stream == AudioManager.STREAM_RING;
         final boolean isSystemStream = row.stream == AudioManager.STREAM_SYSTEM;
         final boolean isAlarmStream = row.stream == AudioManager.STREAM_ALARM;
@@ -781,14 +785,20 @@
                 } else {
                     if (mController.hasVibrator()) {
                         row.icon.setContentDescription(mContext.getString(
-                                R.string.volume_stream_content_description_vibrate,
+                                mShowA11yStream
+                                        ? R.string.volume_stream_content_description_vibrate_a11y
+                                        : R.string.volume_stream_content_description_vibrate,
                                 getStreamLabelH(ss)));
                     } else {
                         row.icon.setContentDescription(mContext.getString(
-                                R.string.volume_stream_content_description_mute,
+                                mShowA11yStream
+                                        ? R.string.volume_stream_content_description_mute_a11y
+                                        : R.string.volume_stream_content_description_mute,
                                 getStreamLabelH(ss)));
                     }
                 }
+            } else if (isA11yStream) {
+                row.icon.setContentDescription(getStreamLabelH(ss));
             } else {
                 if (ss.muted || mAutomute && ss.level == 0) {
                    row.icon.setContentDescription(mContext.getString(
@@ -796,7 +806,9 @@
                            getStreamLabelH(ss)));
                 } else {
                     row.icon.setContentDescription(mContext.getString(
-                            R.string.volume_stream_content_description_mute,
+                            mShowA11yStream
+                                    ? R.string.volume_stream_content_description_mute_a11y
+                                    : R.string.volume_stream_content_description_mute,
                             getStreamLabelH(ss)));
                 }
             }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysUIRunner.java b/packages/SystemUI/tests/src/com/android/systemui/SysUIRunner.java
index 1607b70..fd99d1d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysUIRunner.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysUIRunner.java
@@ -46,7 +46,7 @@
 
     @Override
     protected Statement methodInvoker(FrameworkMethod method, Object test) {
-        return UiThreadStatement.shouldRunOnUiThread(method) ? new UiThreadStatement(
+        return shouldRunOnUiThread(method) ? new UiThreadStatement(
                 methodInvokerInt(method, test), true) : methodInvokerInt(method, test);
     }
 
@@ -84,4 +84,12 @@
     private long getTimeout(Test annotation) {
         return annotation == null ? 0L : annotation.timeout();
     }
+
+    public boolean shouldRunOnUiThread(FrameworkMethod method) {
+        if (mKlass.getAnnotation(UiThreadTest.class) != null) {
+            return true;
+        } else {
+            return UiThreadStatement.shouldRunOnUiThread(method);
+        }
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/UiThreadTest.java b/packages/SystemUI/tests/src/com/android/systemui/UiThreadTest.java
new file mode 100644
index 0000000..58369b1
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/UiThreadTest.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * When applied to a class, all tests, befores, and afters will behave as if
+ * they have @UiThreadTest applied to them.
+ */
+@Target({ElementType.METHOD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface UiThreadTest {
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
index 32afee9..0cccbe1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
@@ -37,11 +37,12 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.support.test.annotation.UiThreadTest;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.view.Display;
 
+import com.android.systemui.SysUIRunner;
+import com.android.systemui.UiThreadTest;
 import com.android.systemui.statusbar.phone.DozeParameters;
 
 import org.junit.Before;
@@ -49,7 +50,8 @@
 import org.junit.runner.RunWith;
 
 @SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(SysUIRunner.class)
+@UiThreadTest
 public class DozeMachineTest {
 
     DozeMachine mMachine;
@@ -72,7 +74,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testInitialize_initializesParts() {
         mMachine.requestState(INITIALIZED);
 
@@ -80,7 +81,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testInitialize_goesToDoze() {
         when(mParamsMock.getAlwaysOn()).thenReturn(false);
 
@@ -91,7 +91,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testInitialize_goesToAod() {
         when(mParamsMock.getAlwaysOn()).thenReturn(true);
 
@@ -102,7 +101,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testPulseDone_goesToDoze() {
         when(mParamsMock.getAlwaysOn()).thenReturn(false);
         mMachine.requestState(INITIALIZED);
@@ -116,7 +114,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testPulseDone_goesToAoD() {
         when(mParamsMock.getAlwaysOn()).thenReturn(true);
         mMachine.requestState(INITIALIZED);
@@ -130,7 +127,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testFinished_staysFinished() {
         mMachine.requestState(INITIALIZED);
         mMachine.requestState(FINISH);
@@ -143,7 +139,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testFinish_finishesService() {
         mMachine.requestState(INITIALIZED);
 
@@ -153,7 +148,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testWakeLock_heldInTransition() {
         doAnswer((inv) -> {
             assertTrue(mWakeLockFake.isHeld());
@@ -164,7 +158,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testWakeLock_heldInPulseStates() {
         mMachine.requestState(INITIALIZED);
 
@@ -176,7 +169,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testWakeLock_notHeldInDozeStates() {
         mMachine.requestState(INITIALIZED);
 
@@ -188,7 +180,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testWakeLock_releasedAfterPulse() {
         mMachine.requestState(INITIALIZED);
 
@@ -201,7 +192,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testPulseDuringPulse_doesntCrash() {
         mMachine.requestState(INITIALIZED);
 
@@ -213,7 +203,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testSuppressingPulse_doesntCrash() {
         mMachine.requestState(INITIALIZED);
 
@@ -223,7 +212,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testScreen_offInDoze() {
         mMachine.requestState(INITIALIZED);
 
@@ -233,7 +221,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testScreen_onInAod() {
         mMachine.requestState(INITIALIZED);
 
@@ -243,7 +230,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testScreen_onInPulse() {
         mMachine.requestState(INITIALIZED);
 
@@ -254,7 +240,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testScreen_offInRequestPulseWithoutAoD() {
         mMachine.requestState(INITIALIZED);
 
@@ -265,7 +250,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testScreen_onInRequestPulseWithoutAoD() {
         mMachine.requestState(INITIALIZED);
 
@@ -276,7 +260,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testTransitions_canRequestTransitions() {
         mMachine.requestState(INITIALIZED);
         mMachine.requestState(DOZE);
@@ -291,7 +274,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testWakeUp_wakesUp() {
         mMachine.wakeUp();
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notification/PropertyAnimatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/notification/PropertyAnimatorTest.java
index 193250f..53053fa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notification/PropertyAnimatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/notification/PropertyAnimatorTest.java
@@ -16,7 +16,6 @@
 
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
-import android.support.test.annotation.UiThreadTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
 
@@ -28,7 +27,9 @@
 import android.view.View;
 import android.view.animation.Interpolator;
 
+import com.android.systemui.SysUIRunner;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.UiThreadTest;
 import com.android.systemui.statusbar.notification.PropertyAnimator;
 import com.android.systemui.statusbar.stack.AnimationFilter;
 import com.android.systemui.statusbar.stack.AnimationProperties;
@@ -49,7 +50,8 @@
 import static org.mockito.Mockito.when;
 
 @SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(SysUIRunner.class)
+@UiThreadTest
 public class PropertyAnimatorTest extends SysuiTestCase {
 
     private View mView;
@@ -106,13 +108,11 @@
 
 
     @Before
-    @UiThreadTest
     public void setUp() {
         mView = new View(getContext());
     }
 
     @Test
-    @UiThreadTest
     public void testAnimationStarted() {
         mAnimationFilter.reset();
         mAnimationFilter.animate(mProperty.getProperty());
@@ -121,7 +121,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testNoAnimationStarted() {
         mAnimationFilter.reset();
         PropertyAnimator.startAnimation(mView, mProperty, 200, mAnimationProperties);
@@ -129,7 +128,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testEndValueUpdated() {
         mAnimationFilter.reset();
         mAnimationFilter.animate(mProperty.getProperty());
@@ -139,7 +137,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testStartTagUpdated() {
         mEffectiveProperty.set(mView, 100f);
         mAnimationFilter.reset();
@@ -150,7 +147,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testValueIsSetUnAnimated() {
         mAnimationFilter.reset();
         PropertyAnimator.startAnimation(mView, mProperty, 200f, mAnimationProperties);
@@ -158,7 +154,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testAnimationToRightValueUpdated() {
         mAnimationFilter.reset();
         mAnimationFilter.animate(mProperty.getProperty());
@@ -171,7 +166,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testAnimationToRightValueUpdateAnimated() {
         mAnimationFilter.reset();
         mAnimationFilter.animate(mProperty.getProperty());
@@ -185,7 +179,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testStartTagShiftedWhenChanging() {
         mEffectiveProperty.set(mView, 100f);
         mAnimationFilter.reset();
@@ -198,7 +191,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testUsingDuration() {
         mAnimationFilter.reset();
         mAnimationFilter.animate(mProperty.getProperty());
@@ -210,7 +202,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testUsingDelay() {
         mAnimationFilter.reset();
         mAnimationFilter.animate(mProperty.getProperty());
@@ -222,7 +213,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testUsingInterpolator() {
         mAnimationFilter.reset();
         mAnimationFilter.animate(mProperty.getProperty());
@@ -234,7 +224,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testUsingListener() {
         mAnimationFilter.reset();
         mAnimationFilter.animate(mProperty.getProperty());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
index bf741ec..3db2440 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
@@ -17,28 +17,13 @@
 package com.android.systemui.statusbar;
 
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
 
-import android.app.ActivityManager;
-import android.app.Notification;
 import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.UserHandle;
-import android.service.notification.StatusBarNotification;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.annotation.UiThreadTest;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
-import android.view.LayoutInflater;
 import android.view.View;
-import android.widget.RemoteViews;
-
-import com.android.systemui.R;
-import com.android.systemui.statusbar.notification.InflationException;
-import com.android.systemui.statusbar.notification.NotificationCustomViewWrapper;
-import com.android.systemui.statusbar.notification.NotificationInflater;
-import com.android.systemui.statusbar.notification.NotificationViewWrapper;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
 
 import org.junit.Assert;
 import org.junit.Before;
@@ -50,58 +35,32 @@
 public class ExpandableNotificationRowTest {
 
     private Context mContext;
-    private ExpandableNotificationRow mRow;
-    private NotificationGroupManager mGroupManager = new NotificationGroupManager();
-    private int mId;
+    private ExpandableNotificationRow mGroup;
+    private NotificationTestHelper mNotificationTestHelper;
 
     @Before
     @UiThreadTest
     public void setUp() {
         mContext = InstrumentationRegistry.getTargetContext();
-        mRow = createNotification();
-    }
-
-    private ExpandableNotificationRow createNotification() {
-        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
-                Context.LAYOUT_INFLATER_SERVICE);
-        ExpandableNotificationRow row = (ExpandableNotificationRow) inflater.inflate(
-                R.layout.status_bar_notification_row,
-                null, false);
-        row.setGroupManager(mGroupManager);
-        Notification publicVersion = new Notification.Builder(mContext).setSmallIcon(
-                R.drawable.ic_person)
-                .setCustomContentView(new RemoteViews(mContext.getPackageName(),
-                        R.layout.custom_view_dark))
-                .build();
-        Notification notification = new Notification.Builder(mContext).setSmallIcon(
-                R.drawable.ic_person)
-                .setContentTitle("Title")
-                .setContentText("Text")
-                .setPublicVersion(publicVersion)
-                .build();
-        UserHandle mUser = UserHandle.of(ActivityManager.getCurrentUser());
-        StatusBarNotification sbn = new StatusBarNotification("com.android.systemui",
-                "com.android.systemui", mId++, null, 1000,
-                2000, notification, mUser, null, System.currentTimeMillis());
-        NotificationData.Entry entry = new NotificationData.Entry(sbn);
-        entry.row = row;
-        try {
-            entry.createIcons(mContext, sbn);
-            row.updateNotification(entry);
-        } catch (InflationException e) {
-            throw new RuntimeException(e.getMessage());
-        }
-        return row;
+        mNotificationTestHelper = new NotificationTestHelper(mContext);
+        mGroup = mNotificationTestHelper.createGroup();
     }
 
     @Test
     public void testGroupSummaryNotShowingIconWhenPublic() {
-        mRow.setSensitive(true, true);
-        mRow.addChildNotification(createNotification());
-        mRow.addChildNotification(createNotification());
-        mRow.setHideSensitive(true, false, 0, 0);
-        Assert.assertTrue(mRow.isSummaryWithChildren());
-        Assert.assertFalse(mRow.isShowingIcon());
+        mGroup.setSensitive(true, true);
+        mGroup.setHideSensitive(true, false, 0, 0);
+        Assert.assertTrue(mGroup.isSummaryWithChildren());
+        Assert.assertFalse(mGroup.isShowingIcon());
+    }
+
+    @Test
+    public void testNotificationHeaderVisibleWhenAnimating() {
+        mGroup.setSensitive(true, true);
+        mGroup.setHideSensitive(true, false, 0, 0);
+        mGroup.setHideSensitive(false, true, 0, 0);
+        Assert.assertTrue(mGroup.getChildrenContainer().getVisibleHeader().getVisibility()
+                == View.VISIBLE);
     }
 
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
index 92f8c7c..8520bdb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
@@ -44,7 +44,6 @@
 import android.graphics.drawable.Drawable;
 import android.service.notification.StatusBarNotification;
 import android.support.test.InstrumentationRegistry;
-import android.support.test.annotation.UiThreadTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Log;
@@ -55,7 +54,10 @@
 import android.widget.TextView;
 import com.android.internal.util.CharSequences;
 import com.android.systemui.R;
+import com.android.systemui.SysUIRunner;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.UiThreadTest;
+
 import org.junit.Before;
 import org.junit.runner.RunWith;
 import org.junit.Test;
@@ -65,7 +67,8 @@
 import java.util.concurrent.CountDownLatch;
 
 @SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(SysUIRunner.class)
+@UiThreadTest
 public class NotificationInfoTest extends SysuiTestCase {
     private static final String TEST_PACKAGE_NAME = "test_package";
     private static final String TEST_CHANNEL = "test_channel";
@@ -79,7 +82,6 @@
             mock(StatusBarNotification.class);
 
     @Before
-    @UiThreadTest
     public void setUp() throws Exception {
         // Inflate the layout
         final LayoutInflater layoutInflater =
@@ -116,7 +118,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testBindNotification_SetsTextApplicationName() throws Exception {
         when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -126,7 +127,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testBindNotification_SetsPackageIcon() throws Exception {
         final Drawable iconDrawable = mock(Drawable.class);
         when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class)))
@@ -138,7 +138,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testBindNotification_GroupNameHiddenIfNoGroup() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, null, null, null);
@@ -150,7 +149,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testBindNotification_SetsGroupNameIfNonNull() throws Exception {
         mNotificationChannel.setGroup("test_group_id");
         final NotificationChannelGroup notificationChannelGroup =
@@ -169,7 +167,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testBindNotification_SetsGroupName_resId() throws Exception {
         when(mMockPackageManager.getText(eq(TEST_PACKAGE_NAME),
                 eq(R.string.legacy_vpn_name), anyObject())).thenReturn(
@@ -191,7 +188,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testBindNotification_SetsTextChannelName() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, null, null, null);
@@ -200,7 +196,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testBindNotification_SetsTextChannelName_resId() throws Exception {
         when(mMockPackageManager.getText(eq(TEST_PACKAGE_NAME),
                 eq(R.string.notification_menu_accessibility), anyObject())).thenReturn(
@@ -216,7 +211,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testBindNotification_SetsOnClickListenerForSettings() throws Exception {
         final CountDownLatch latch = new CountDownLatch(1);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -231,7 +225,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testBindNotification_SettingsTextWithOneChannel() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, (View v, int appUid) -> {}, null,
@@ -242,7 +235,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testBindNotification_SettingsTextWithMultipleChannels() throws Exception {
         when(mMockINotificationManager.getNumNotificationChannelsForPackage(
                 eq(TEST_PACKAGE_NAME), anyInt(), anyBoolean())).thenReturn(2);
@@ -255,7 +247,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testBindNotification_SetsOnClickListenerForDone() throws Exception {
         final CountDownLatch latch = new CountDownLatch(1);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -270,7 +261,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testBindNotification_NumChannelsTextHiddenWhenDefaultChannel() throws Exception {
         final NotificationChannel defaultChannel = new NotificationChannel(
                 NotificationChannel.DEFAULT_CHANNEL_ID, TEST_CHANNEL_NAME,
@@ -283,7 +273,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testBindNotification_NumChannelsTextDisplaysWhenNotDefaultChannel()
             throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -295,7 +284,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testBindNotification_NumChannelsTextScalesWithNumberOfChannels()
             throws Exception {
         when(mMockINotificationManager.getNumNotificationChannelsForPackage(
@@ -308,7 +296,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testbindNotification_ChannelDisabledTextGoneWhenNotDisabled() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, null, null, null);
@@ -318,7 +305,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testbindNotification_ChannelDisabledTextVisibleWhenDisabled() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_NONE);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -333,7 +319,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testHasImportanceChanged_DefaultsToFalse() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, null, null, null);
@@ -341,7 +326,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testHasImportanceChanged_ReturnsTrueAfterChannelDisabled() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -353,7 +337,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testBindNotification_DoesNotUpdateNotificationChannel() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, null, null, null);
@@ -362,7 +345,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testDoesNotUpdateNotificationChannelAfterImportanceChanged() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -375,7 +357,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnchanged()
             throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -387,7 +368,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnspecified()
             throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_UNSPECIFIED);
@@ -400,7 +380,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testEnabledSwitchOnByDefault() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -411,7 +390,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testEnabledButtonOffWhenAlreadyBanned() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_NONE);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -422,7 +400,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testEnabledSwitchVisibleByDefault() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -433,7 +410,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testEnabledSwitchInvisibleIfNonBlockable() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -445,7 +421,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testEnabledSwitchChangedCallsUpdateNotificationChannel() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -460,7 +435,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testCloseControlsDoesNotUpdateIfSaveIsFalse() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
new file mode 100644
index 0000000..96dbdb3
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar;
+
+import android.app.ActivityManager;
+import android.app.Notification;
+import android.content.Context;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+import android.view.LayoutInflater;
+import android.widget.RemoteViews;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.InflationException;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
+
+/**
+ * A helper class to create {@link ExpandableNotificationRow}
+ */
+public class NotificationTestHelper {
+
+    private final Context mContext;
+    private int mId;
+    private final NotificationGroupManager mGroupManager = new NotificationGroupManager();
+
+    public NotificationTestHelper(Context context) {
+        mContext = context;
+    }
+
+    public ExpandableNotificationRow createRow() {
+        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
+                mContext.LAYOUT_INFLATER_SERVICE);
+        ExpandableNotificationRow row = (ExpandableNotificationRow) inflater.inflate(
+                R.layout.status_bar_notification_row,
+                null, false);
+        row.setGroupManager(mGroupManager);
+        Notification publicVersion = new Notification.Builder(mContext).setSmallIcon(
+                R.drawable.ic_person)
+                .setCustomContentView(new RemoteViews(mContext.getPackageName(),
+                        R.layout.custom_view_dark))
+                .build();
+        Notification notification = new Notification.Builder(mContext).setSmallIcon(
+                R.drawable.ic_person)
+                .setContentTitle("Title")
+                .setContentText("Text")
+                .setPublicVersion(publicVersion)
+                .build();
+        UserHandle mUser = UserHandle.of(ActivityManager.getCurrentUser());
+        StatusBarNotification sbn = new StatusBarNotification("com.android.systemui",
+                "com.android.systemui", mId++, null, 1000,
+                2000, notification, mUser, null, System.currentTimeMillis());
+        NotificationData.Entry entry = new NotificationData.Entry(sbn);
+        entry.row = row;
+        try {
+            entry.createIcons(mContext, sbn);
+            row.updateNotification(entry);
+        } catch (InflationException e) {
+            throw new RuntimeException(e.getMessage());
+        }
+        return row;
+    }
+
+    public ExpandableNotificationRow createGroup() {
+        ExpandableNotificationRow row = createRow();
+        row.addChildNotification(createRow());
+        row.addChildNotification(createRow());
+        return row;
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java
new file mode 100644
index 0000000..dbe0de4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.stack;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.NotificationHeaderView;
+import android.view.View;
+
+import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.NotificationTestHelper;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class NotificationChildrenContainerTest {
+
+    private Context mContext;
+    private ExpandableNotificationRow mGroup;
+    private int mId;
+    private NotificationTestHelper mNotificationTestHelper;
+
+    @Before
+    @UiThreadTest
+    public void setUp() {
+        mContext = InstrumentationRegistry.getTargetContext();
+        mNotificationTestHelper = new NotificationTestHelper(mContext);
+        mGroup = mNotificationTestHelper.createGroup();
+    }
+
+    @Test
+    public void testLowPriorityHeaderCleared() {
+        mGroup.setIsLowPriority(true);
+        NotificationChildrenContainer childrenContainer = mGroup.getChildrenContainer();
+        NotificationHeaderView lowPriorityHeaderView = childrenContainer.getLowPriorityHeaderView();
+        Assert.assertTrue(lowPriorityHeaderView.getVisibility() == View.VISIBLE);
+        Assert.assertTrue(lowPriorityHeaderView.getParent() == childrenContainer);
+        mGroup.setIsLowPriority(false);
+        Assert.assertTrue(lowPriorityHeaderView.getParent() == null);
+        Assert.assertTrue(childrenContainer.getLowPriorityHeaderView() == null);
+    }
+}
diff --git a/proto/src/ipconnectivity.proto b/proto/src/ipconnectivity.proto
index b5afc40..76c5418 100644
--- a/proto/src/ipconnectivity.proto
+++ b/proto/src/ipconnectivity.proto
@@ -9,6 +9,8 @@
 // NetworkId represents the id given by the system to a physical network on the
 // Android device. It is used to relates events to each other for devices with
 // multiple networks (WiFi, 4G, ...).
+// Deprecated since version 3, replaced by top-level network_id field in
+// IpConnectivityEvent.
 message NetworkId {
   // Every network gets assigned a network_id on creation based on order of
   // creation. Thus network_id N is assigned to the network created directly
@@ -91,7 +93,8 @@
 // This message is associated to android.net.metrics.NetworkEvent.
 message NetworkEvent {
   // The id of the network on which this event happened.
-  optional NetworkId network_id = 1;
+  // Deprecated since version 3.
+  optional NetworkId network_id = 1 [deprecated = true];
 
   // The type of network event, represented by NETWORK_* constants defined in
   // android.net.metrics.NetworkEvent.
@@ -107,7 +110,8 @@
 // This message is associated to android.net.metrics.ValidationProbeEvent.
 message ValidationProbeEvent {
   // The id of the network for which the probe was sent.
-  optional NetworkId network_id = 1;
+  // Deprecated since version 3.
+  optional NetworkId network_id = 1 [deprecated = true];
 
   // The time it took for that probe to complete or time out.
   optional int32 latency_ms = 2;
@@ -167,18 +171,28 @@
 
 // Represents latency and errno statistics of the connect() system call.
 // Since version 2.
+// Next tag: 7
 message ConnectStatistics {
   // The number of connect() operations recorded.
   optional int32 connect_count = 1;
 
+  // The number of connect() operations done in blocking mode.
+  // Since version 3.
+  optional int32 connect_blocking_count = 5;
+
   // The number of connect() operations with IPv6 socket address.
   optional int32 ipv6_addr_count = 2;
 
-  // The time it took for each successful connect() operation to complete.
-  // The number of repeated values can be less than connect_count in case of
-  // event rate-limiting.
+  // The time it took for successful blocking connect() operations to complete
+  // The number of repeated values can be less than connect_blocking_count in
+  // case of event rate-limiting.
   repeated int32 latencies_ms = 3;
 
+  // The time it took for successful connect() operation to complete in
+  // non-blocking mode. The number of repeated values can be less than
+  // connect_count - connect_blocking_count in case of event rate-limiting.
+  repeated int32 non_blocking_latencies_ms = 6;
+
   // Counts of all error values returned by failed connect() operations.
   // The Pair key field is the errno code. The Pair value field is the count
   // for that errno code.
@@ -212,10 +226,15 @@
 
 // Represents the generation of an Android Packet Filter program.
 // Since version 1.
+// Next tag: 8
 message ApfProgramEvent {
-  // Lifetime of the program in seconds.
+  // Maximum lifetime of the program in seconds.
   optional int64 lifetime = 1;
 
+  // Effective lifetime of the program in seconds from the time the
+  // program was installed to the time it was replaced or removed.
+  optional int64 effective_lifetime = 7;
+
   // Number of RAs filtered by the APF program.
   optional int32 filtered_ras = 2;
 
@@ -236,6 +255,7 @@
 // Represents Router Advertisement listening statistics for an interface with
 // Android Packet Filter enabled.
 // Since version 1.
+// Next tag: 12
 message ApfStatistics {
   // The time interval in milliseconds these stastistics cover.
   optional int64 duration_ms = 1;
@@ -261,6 +281,14 @@
 
   // The maximum APF program size in byte advertised by hardware.
   optional int32 max_program_size = 9;
+
+  // The total number of successful APF program updates triggered by any state
+  // change in ApfFilter. Since version 3.
+  optional int32 program_updates_all = 10;
+
+  // The total number of APF program updates triggered when disabling the
+  // multicast filter. Since version 3.
+  optional int32 program_updates_allowing_multicast = 11;
 }
 
 // Represents the reception of a Router Advertisement packet for an interface
@@ -308,7 +336,7 @@
 }
 
 // Represents one of the IP connectivity event defined in this file.
-// Next tag: 16
+// Next tag: 19
 message IpConnectivityEvent {
   // Time in ms when the event was recorded.
   optional int64 time_ms = 1;
@@ -318,7 +346,27 @@
   // Since version 2.
   optional LinkLayer link_layer = 15;
 
-  // Event type.
+  // Represents the id given by the system to a physical network on the device.
+  // Every network gets assigned a unique id on creation from a monotonic
+  // counter. The value 0 is never assigned to a network and means no network.
+  // It is used to correlate different types of events to each other for devices
+  // with multiple networks (WiFi, 4G, ...).
+  // Since version 3.
+  optional int32 network_id = 16;
+
+  // The interface name (wlan, rmnet, lo, ...) on which the event happened.
+  // Present if the link_layer field was not inferred from the if_name on
+  // the device, so that post-processing of the serialized proto can backfill
+  // link_layer. Since version 3.
+  optional string if_name = 17;
+
+  // The transport types of the network on which the event happened, expressed
+  // as a bit field of TRANSPORT_* constants as defined in NetworkCapabilities.
+  // Present if the link_layer field was not inferred from the transport types,
+  // so that post-processing of the serialized proto can backfill link_layer
+  // Since version 3.
+  optional int64 transports = 18;
+
   oneof event {
 
     // An event about the system default network.
@@ -371,9 +419,10 @@
   optional int32 dropped_events = 2;
 
   // The version number of the metrics events being collected.
-  //  nyc-dev: not populated, implicitly 0.
+  //  nyc:     not populated, implicitly 0.
   //  nyc-dr1: not populated, implicitly 1 (sailfish and marlin only).
   //  nyc-mr1: not populated, implicitly 1.
   //  nyc-mr2: 2.
+  //  oc:      3.
   optional int32 version = 3;
 };
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 20aeb11..c45de0d 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -3525,6 +3525,21 @@
     // OPEN: Settings > About device > Model > Hardware info dialog
     DIALOG_SETTINGS_HARDWARE_INFO = 862;
 
+    // ACTION: Checks whether a contact's phone still exists
+    // Value 0: It doesn't exist anymore
+    // Value 1: It still exists
+    // Value 2: A SecurityException was thrown
+    // CATEGORY: SETTINGS
+    // OS: N
+    ACTION_PHONE_EXISTS = 863;
+
+    // ACTION: Retrieves a contact from CP2
+    // Value 0: Contact retrieved without issues
+    // Value 1: An IllegalArgumentException was thrown
+    // CATEGORY: SETTINGS
+    // OS: N
+    ACTION_GET_CONTACT = 864;
+
     // ---- End O Constants, all O constants go above this line ----
 
     // Add new aosp constants above this line.
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
index 40491e91..e943c4c 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
@@ -305,14 +305,23 @@
         }
 
         @Override
+        public void setHasCallback(IBinder activityToken, int userId, boolean hasIt) {
+            synchronized (mLock) {
+                final AutoFillManagerServiceImpl service = getServiceForUserLocked(userId);
+                service.setHasCallback(activityToken, hasIt);
+            }
+        }
+
+        @Override
         public void startSession(IBinder activityToken, IBinder windowToken, IBinder appCallback,
-                AutoFillId autoFillId, Rect bounds, AutoFillValue value, int userId) {
+                AutoFillId autoFillId, Rect bounds, AutoFillValue value, int userId,
+                boolean hasCallback) {
             // TODO(b/33197203): make sure it's called by resumed / focused activity
 
             synchronized (mLock) {
                 final AutoFillManagerServiceImpl service = getServiceForUserLocked(userId);
                 service.startSessionLocked(activityToken, windowToken, appCallback,
-                        autoFillId, bounds, value);
+                        autoFillId, bounds, value, hasCallback);
             }
         }
 
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
index 5e852f1..aa0840c 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
@@ -274,15 +274,25 @@
         }
     }
 
+    void setHasCallback(IBinder activityToken, boolean hasIt) {
+        if (!hasService()) {
+            return;
+        }
+        final Session session = mSessions.get(activityToken);
+        if (session != null) {
+            session.setHasCallback(hasIt);
+        }
+    }
+
     void startSessionLocked(IBinder activityToken, IBinder windowToken, IBinder appCallbackToken,
-            AutoFillId autoFillId,  Rect bounds, AutoFillValue value) {
+            AutoFillId autoFillId,  Rect bounds, AutoFillValue value, boolean hasCallback) {
         if (!hasService()) {
             return;
         }
 
         final String historyItem = "s=" + mInfo.getServiceInfo().packageName
                 + " u=" + mUserId + " a=" + activityToken
-                + " i=" + autoFillId + " b=" + bounds;
+                + " i=" + autoFillId + " b=" + bounds + " hc=" + hasCallback;
         mRequestsHistory.log(historyItem);
 
         // TODO(b/33197203): Handle partitioning
@@ -293,7 +303,7 @@
         }
 
         final Session newSession = createSessionByTokenLocked(activityToken,
-                windowToken, appCallbackToken);
+                windowToken, appCallbackToken, hasCallback);
         newSession.updateLocked(autoFillId, bounds, value, FLAG_START_SESSION);
     }
 
@@ -312,9 +322,9 @@
     }
 
     private Session createSessionByTokenLocked(IBinder activityToken, IBinder windowToken,
-            IBinder appCallbackToken) {
+            IBinder appCallbackToken, boolean hasCallback) {
         final Session newSession = new Session(mContext, activityToken,
-                windowToken, appCallbackToken);
+                windowToken, appCallbackToken, hasCallback);
         mSessions.put(activityToken, newSession);
 
         /*
@@ -599,12 +609,18 @@
         @GuardedBy("mLock")
         private AssistStructure mStructure;
 
+        /**
+         * Whether the client has an {@link android.view.autofill.AutoFillManager.AutofillCallback}.
+         */
+        private boolean mHasCallback;
+
         private Session(Context context, IBinder activityToken, IBinder windowToken,
-                IBinder client) {
+                IBinder client, boolean hasCallback) {
             mRemoteFillService = new RemoteFillService(context,
                     mInfo.getServiceInfo().getComponentName(), mUserId, this);
             mActivityToken = activityToken;
             mWindowToken = windowToken;
+            mHasCallback = hasCallback;
 
             mClient = IAutoFillManagerClient.Stub.asInterface(client);
             try {
@@ -712,6 +728,22 @@
                     .sendToTarget();
         }
 
+        // AutoFillUiCallback
+        @Override
+        public void cancelSave() {
+            mHandlerCaller.getHandler().post(() -> {
+                removeSelf();
+            });
+        }
+
+        // AutoFillUiCallback
+        @Override
+        public void onEvent(AutoFillId id, int event) {
+            mHandlerCaller.getHandler().post(() -> {
+                notifyChangeToClient(id, event);
+            });
+        }
+
         public void setAuthenticationResultLocked(Bundle data) {
             if (mCurrentResponse == null || data == null) {
                 removeSelf();
@@ -731,6 +763,10 @@
             }
         }
 
+        public void setHasCallback(boolean hasIt) {
+            mHasCallback = hasIt;
+        }
+
         /**
          * Show the save UI, when session can be saved.
          */
@@ -814,6 +850,7 @@
                 node.updateAutoFillValue(value);
             }
 
+            // Sanitize structure before it's sent to service.
             mStructure.sanitizeForParceling(false);
 
             if (VERBOSE) {
@@ -871,7 +908,7 @@
             if ((flags & FLAG_FOCUS_GAINED) != 0) {
                 // Remove the UI if the ViewState has changed.
                 if (mCurrentViewState != viewState) {
-                    mUi.hideFillUi();
+                    mUi.hideFillUi(mCurrentViewState != null ? mCurrentViewState.mId : null);
                     mCurrentViewState = viewState;
                 }
 
@@ -888,7 +925,7 @@
 
             if ((flags & FLAG_FOCUS_LOST) != 0) {
                 if (mCurrentViewState == viewState) {
-                    mUi.hideFillUi();
+                    mUi.hideFillUi(viewState.mId);
                     mCurrentViewState = null;
                 }
                 return;
@@ -912,6 +949,15 @@
             getUiForShowing().showFillUi(filledId, response, bounds, filterText);
         }
 
+        private void notifyChangeToClient(AutoFillId id, int event) {
+            if (!mHasCallback) return;
+            try {
+                mClient.onAutofillEvent(mWindowToken, id, event);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Error notifying client on change: id=" + id + ", event=" + event, e);
+            }
+        }
+
         private void processResponseLocked(FillResponse response) {
             if (DEBUG) {
                 Slog.d(TAG, "processResponseLocked(auth=" + response.getAuthentication()
@@ -993,7 +1039,7 @@
                     pw.println("null");
                 }
             }
-
+            pw.print(prefix); pw.print("mHasCallback: "); pw.println(mHasCallback);
             mRemoteFillService.dump(prefix, pw);
         }
 
diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
index 7058248..d9f9721 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
@@ -182,11 +182,8 @@
         if (mDestroyed || mCompleted) {
             return;
         }
-        if (pendingRequest.isFinal()) {
-            mCompleted = true;
-        }
         if (!isBound()) {
-            if (mPendingRequest != null) {
+            if (mPendingRequest != null && mPendingRequest != pendingRequest) {
                 mPendingRequest.cancel();
             }
             mPendingRequest = pendingRequest;
@@ -196,6 +193,9 @@
                 Slog.d(LOG_TAG, "[user: " + mUserId + "] handlePendingRequest()");
             }
             pendingRequest.run();
+            if (pendingRequest.isFinal()) {
+                mCompleted = true;
+            }
         }
     }
 
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index f00d6c5..599bbfe 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -15,6 +15,9 @@
  */
 package com.android.server.autofill.ui;
 
+import static android.view.autofill.AutoFillManager.AutofillCallback.EVENT_INPUT_HIDDEN;
+import static android.view.autofill.AutoFillManager.AutofillCallback.EVENT_INPUT_SHOWN;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
@@ -26,8 +29,8 @@
 import android.service.autofill.FillResponse;
 import android.service.autofill.SaveInfo;
 import android.text.TextUtils;
-import android.util.Slog;
 import android.text.format.DateUtils;
+import android.util.Slog;
 import android.view.autofill.AutoFillId;
 import android.widget.Toast;
 
@@ -62,6 +65,8 @@
         void authenticate(@NonNull IntentSender intent);
         void fill(@NonNull Dataset dataset);
         void save();
+        void cancelSave();
+        void onEvent(AutoFillId id, int event);
     }
 
     public AutoFillUI(@NonNull Context context) {
@@ -97,8 +102,13 @@
     /**
      * Hides the fill UI.
      */
-    public void hideFillUi() {
-        mHandler.post(this::hideFillUiUiThread);
+    public void hideFillUi(AutoFillId id) {
+        mHandler.post(() -> {
+            hideFillUiUiThread();
+            if (mCallback != null) {
+                mCallback.onEvent(id, EVENT_INPUT_HIDDEN);
+            }
+        });
     }
 
     /**
@@ -175,6 +185,7 @@
                     // TODO(b/33197203): add MetricsLogger call
                 }
             });
+            mCallback.onEvent(focusedId, EVENT_INPUT_SHOWN);
         });
     }
 
@@ -210,6 +221,9 @@
                                     + listener, e);
                         }
                     }
+                    if (mCallback != null) {
+                        mCallback.cancelSave();
+                    }
                 }
             }, mSaveTimeoutMs);
         });
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index c26032ce..8f2b428 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -80,6 +80,7 @@
 import android.content.pm.Signature;
 import android.database.ContentObserver;
 import android.net.Uri;
+import android.os.PowerSaveState;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
@@ -122,6 +123,7 @@
 import com.android.server.SystemService;
 import com.android.server.backup.PackageManagerBackupAgent.Metadata;
 
+import com.android.server.power.BatterySaverPolicy.ServiceType;
 import libcore.io.IoUtils;
 
 import java.io.BufferedInputStream;
@@ -5440,7 +5442,9 @@
 
         // Don't run the backup if we're in battery saver mode, but reschedule
         // to try again in the not-so-distant future.
-        if (mPowerManager.isPowerSaveMode()) {
+        final PowerSaveState result =
+                mPowerManager.getPowerSaveState(ServiceType.FULL_BACKUP);
+        if (result.batterySaverEnabled) {
             if (DEBUG) Slog.i(TAG, "Deferring scheduled full backups in battery saver mode");
             FullBackupJob.schedule(mContext, KeyValueBackupJob.BATCH_INTERVAL);
             return false;
@@ -9889,7 +9893,9 @@
     public void backupNow() {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "backupNow");
 
-        if (mPowerManager.isPowerSaveMode()) {
+        final PowerSaveState result =
+                mPowerManager.getPowerSaveState(ServiceType.KEYVALUE_BACKUP);
+        if (result.batterySaverEnabled) {
             if (DEBUG) Slog.v(TAG, "Not running backup while in battery save mode");
             KeyValueBackupJob.schedule(mContext);   // try again in several hours
         } else {
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 81f137e..c9dd116 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -678,7 +678,7 @@
         pw.println("Battery service (battery) commands:");
         pw.println("  help");
         pw.println("    Print this help text.");
-        pw.println("  set [-f] [ac|usb|wireless|status|level|invalid] <value>");
+        pw.println("  set [-f] [ac|usb|wireless|status|level|present|invalid] <value>");
         pw.println("    Force a battery property value, freezing battery state.");
         pw.println("    -f: force a battery change broadcast be sent, prints new sequence.");
         pw.println("  unplug [-f]");
@@ -748,6 +748,9 @@
                     }
                     boolean update = true;
                     switch (key) {
+                        case "present":
+                            mBatteryProps.batteryPresent = Integer.parseInt(value) != 0;
+                            break;
                         case "ac":
                             mBatteryProps.chargerAcOnline = Integer.parseInt(value) != 0;
                             break;
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 8888325..5fe6952 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -25,6 +25,7 @@
 import android.database.ContentObserver;
 import android.hardware.input.InputManager;
 import android.media.AudioManager;
+import android.os.PowerSaveState;
 import android.os.BatteryStats;
 import android.os.Handler;
 import android.os.IVibratorService;
@@ -50,6 +51,7 @@
 
 import com.android.internal.app.IAppOpsService;
 import com.android.internal.app.IBatteryStats;
+import com.android.server.power.BatterySaverPolicy.ServiceType;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -233,10 +235,15 @@
         mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
         mPowerManagerInternal.registerLowPowerModeObserver(
                 new PowerManagerInternal.LowPowerModeListener() {
-            @Override
-            public void onLowPowerModeChanged(boolean enabled) {
-                updateInputDeviceVibrators();
-            }
+                    @Override
+                    public int getServiceType() {
+                        return ServiceType.VIBRATION;
+                    }
+
+                    @Override
+                    public void onLowPowerModeChanged(PowerSaveState result) {
+                        updateInputDeviceVibrators();
+                    }
         });
 
         mContext.getContentResolver().registerContentObserver(
@@ -553,7 +560,8 @@
                 } catch (SettingNotFoundException snfe) {
                 }
 
-                mLowPowerMode = mPowerManagerInternal.getLowPowerModeEnabled();
+                mLowPowerMode = mPowerManagerInternal
+                        .getLowPowerState(ServiceType.VIBRATION).batterySaverEnabled;
 
                 if (mVibrateInputDevicesSetting) {
                     if (!mInputDeviceListenerRegistered) {
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index dc73b63..ea9b651 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -503,10 +503,10 @@
                     UserHandle.getUserId(callingUid));
         } catch (NameNotFoundException e) {
             Log.d(TAG, "Package not found " + e.getMessage());
-            return new HashMap<>();
+            return new LinkedHashMap<>();
         }
 
-        Map<Account, Integer> result = new HashMap<>();
+        Map<Account, Integer> result = new LinkedHashMap<>();
         for (String accountType : accountTypes) {
             synchronized (accounts.cacheLock) {
                 final Account[] accountsOfType = accounts.accountCache.get(accountType);
@@ -1040,7 +1040,7 @@
     private static HashMap<String, Integer> getAuthenticatorTypeAndUIDForUser(
             IAccountAuthenticatorCache authCache,
             int userId) {
-        HashMap<String, Integer> knownAuth = new HashMap<>();
+        HashMap<String, Integer> knownAuth = new LinkedHashMap<>();
         for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> service : authCache
                 .getAllServices(userId)) {
             knownAuth.put(service.type.type, service.uid);
@@ -3927,7 +3927,7 @@
         List<String> visibleAccountTypes = getTypesVisibleToCaller(callingUid, userId,
                 opPackageName);
         if (visibleAccountTypes.isEmpty()) {
-            return new Account[0];
+            return EMPTY_ACCOUNT_ARRAY;
         }
         long identityToken = clearCallingIdentity();
         try {
@@ -4047,7 +4047,7 @@
                 opPackageName);
         if (visibleAccountTypes.isEmpty()
                 || (type != null && !visibleAccountTypes.contains(type))) {
-            return new Account[]{};
+            return EMPTY_ACCOUNT_ARRAY;
         } else if (visibleAccountTypes.contains(type)) {
             // Prune the list down to just the requested type.
             visibleAccountTypes = new ArrayList<>();
@@ -4194,11 +4194,11 @@
             packageUid = mPackageManager.getPackageUidAsUser(packageName, userId);
         } catch (NameNotFoundException re) {
             Slog.e(TAG, "Couldn't determine the packageUid for " + packageName + re);
-            return new Account[0];
+            return EMPTY_ACCOUNT_ARRAY;
         }
         if (!UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
                 && !isAccountManagedByCaller(type, callingUid, userId)) {
-            return new Account[0];
+            return EMPTY_ACCOUNT_ARRAY;
         }
 
         return getAccountsAsUser(type, userId,
@@ -4229,7 +4229,7 @@
         if (!visibleAccountTypes.contains(type)) {
             Bundle result = new Bundle();
             // Need to return just the accounts that are from matching signatures.
-            result.putParcelableArray(AccountManager.KEY_ACCOUNTS, new Account[0]);
+            result.putParcelableArray(AccountManager.KEY_ACCOUNTS, EMPTY_ACCOUNT_ARRAY);
             try {
                 response.onResult(result);
             } catch (RemoteException e) {
@@ -5368,10 +5368,11 @@
         return newAccountsForType[oldLength];
     }
 
+    @NonNull
     private Account[] filterAccounts(UserAccounts accounts, Account[] unfiltered, int callingUid,
             String callingPackage, boolean includeManagedNotVisible) {
         // filter based on visibility.
-        Map<Account, Integer> firstPass = new HashMap<>();
+        Map<Account, Integer> firstPass = new LinkedHashMap<>();
         for (Account account : unfiltered) {
             int visibility = resolveAccountVisibility(account, callingPackage, accounts);
             if ((visibility == AccountManager.VISIBILITY_VISIBLE
@@ -5390,8 +5391,10 @@
         return filtered;
     }
 
+    @NonNull
     private Map<Account, Integer> filterSharedAccounts(UserAccounts userAccounts,
-            Map<Account, Integer> unfiltered, int callingUid, String callingPackage) {
+            @NonNull Map<Account, Integer> unfiltered, int callingUid,
+            String callingPackage) {
         // first part is to filter shared accounts.
         // unfiltered type check is not necessary.
         if (getUserManager() == null || userAccounts == null || userAccounts.userId < 0
@@ -5441,7 +5444,7 @@
             } catch (NameNotFoundException e) {
                 Log.d(TAG, "Package not found " + e.getMessage());
             }
-            Map<Account, Integer> filtered = new HashMap<>();
+            Map<Account, Integer> filtered = new LinkedHashMap<>();
             for (Map.Entry<Account, Integer> entry : unfiltered.entrySet()) {
                 Account account = entry.getKey();
                 if (account.type.equals(requiredAccountType)) {
@@ -5469,6 +5472,7 @@
      * packageName can be null. If not null, it should be used to filter out restricted accounts
      * that the package is not allowed to access.
      */
+    @NonNull
     protected Account[] getAccountsFromCacheLocked(UserAccounts userAccounts, String accountType,
             int callingUid, String callingPackage, boolean includeManagedNotVisible) {
         if (callingPackage == null) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 54ee5dc..10b1f2b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -10088,8 +10088,18 @@
     }
 
     /**
-     * Moves an activity, and all of the other activities within the same task, to the bottom
-     * of the history stack.  The activity's order within the task is unchanged.
+     * Attempts to move a task backwards in z-order (the order of activities within the task is
+     * unchanged).
+     *
+     * There are several possible results of this call:
+     * - if the task is locked, then we will show the lock toast
+     * - if there is a task behind the provided task, then that task is made visible and resumed as
+     *   this task is moved to the back
+     * - otherwise, if there are no other tasks in the stack:
+     *     - if this task is in the pinned stack, then we remove the stack completely, which will
+     *       have the effect of moving the task to the top or bottom of the fullscreen stack
+     *       (depending on whether it is visible)
+     *     - otherwise, we simply return home and hide this task
      *
      * @param token A reference to the activity we wish to move
      * @param nonRoot If false then this only works if the activity is the root
@@ -10105,10 +10115,6 @@
                 int taskId = ActivityRecord.getTaskForActivityLocked(token, !nonRoot);
                 final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
                 if (task != null) {
-                    if (mStackSupervisor.isLockedTask(task)) {
-                        mStackSupervisor.showLockTaskToast();
-                        return false;
-                    }
                     return ActivityRecord.getStackLocked(token).moveTaskToBackLocked(taskId);
                 }
             } finally {
@@ -10367,7 +10373,7 @@
         synchronized (this) {
             if (!mSupportsPictureInPicture) {
                 throw new IllegalStateException("moveTopActivityToPinnedStack:"
-                        + "Device doesn't support picture-in-pciture mode");
+                        + "Device doesn't support picture-in-picture mode");
             }
 
             long ident = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 5d4bff9..a679a31 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -4351,9 +4351,13 @@
             Slog.i(TAG, "moveTaskToBack: bad taskId=" + taskId);
             return false;
         }
-
         Slog.i(TAG, "moveTaskToBack: " + tr);
-        mStackSupervisor.removeLockedTaskLocked(tr);
+
+        // If the task is locked, then show the lock task toast
+        if (mStackSupervisor.isLockedTask(tr)) {
+            mStackSupervisor.showLockTaskToast();
+            return false;
+        }
 
         // If we have a watcher, preflight the move before committing to it.  First check
         // for *other* available tasks, but if none are available, then try again allowing the
@@ -4416,12 +4420,24 @@
                 prevIsHome = true;
             }
         }
-        mTaskHistory.remove(tr);
-        mTaskHistory.add(0, tr);
-        updateTaskMovement(tr, false);
 
-        // There is an assumption that moving a task to the back moves it behind the home activity.
-        // We make sure here that some activity in the stack will launch home.
+        boolean requiresMove = mTaskHistory.indexOf(tr) != 0;
+        if (requiresMove) {
+            mTaskHistory.remove(tr);
+            mTaskHistory.add(0, tr);
+            updateTaskMovement(tr, false);
+
+            mWindowManager.prepareAppTransition(TRANSIT_TASK_TO_BACK, false);
+            mWindowContainerController.positionChildAtBottom(tr.getWindowContainerController());
+        }
+
+        if (mStackId == PINNED_STACK_ID) {
+            mStackSupervisor.removeStackLocked(PINNED_STACK_ID);
+            return true;
+        }
+
+        // Otherwise, there is an assumption that moving a task to the back moves it behind the
+        // home activity. We make sure here that some activity in the stack will launch home.
         int numTasks = mTaskHistory.size();
         for (int taskNdx = numTasks - 1; taskNdx >= 1; --taskNdx) {
             final TaskRecord task = mTaskHistory.get(taskNdx);
@@ -4434,9 +4450,6 @@
             }
         }
 
-        mWindowManager.prepareAppTransition(TRANSIT_TASK_TO_BACK, false);
-        mWindowContainerController.positionChildAtBottom(tr.getWindowContainerController());
-
         final TaskRecord task = mResumedActivity != null ? mResumedActivity.task : null;
         if (prevIsHome || (task == tr && canGoHome) || (numTasks <= 1 && isOnHomeDisplay())) {
             if (!mService.mBooting && !mService.mBooted) {
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 3571302..1712d48 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -24,6 +24,7 @@
 import android.content.pm.PackageManager;
 import android.net.wifi.IWifiManager;
 import android.net.wifi.WifiActivityEnergyInfo;
+import android.os.PowerSaveState;
 import android.os.BatteryStats;
 import android.os.Binder;
 import android.os.Handler;
@@ -60,6 +61,7 @@
 import com.android.internal.os.PowerProfile;
 import com.android.server.LocalServices;
 import com.android.server.ServiceThread;
+import com.android.server.power.BatterySaverPolicy.ServiceType;
 
 import java.io.File;
 import java.io.FileDescriptor;
@@ -232,7 +234,9 @@
     public void initPowerManagement() {
         final PowerManagerInternal powerMgr = LocalServices.getService(PowerManagerInternal.class);
         powerMgr.registerLowPowerModeObserver(this);
-        mStats.notePowerSaveMode(powerMgr.getLowPowerModeEnabled());
+        mStats.notePowerSaveMode(
+                powerMgr.getLowPowerState(ServiceType.BATTERY_STATS)
+                        .batterySaverEnabled);
         (new WakeupReasonThread()).start();
     }
 
@@ -258,9 +262,14 @@
     }
 
     @Override
-    public void onLowPowerModeChanged(boolean enabled) {
+    public int getServiceType() {
+        return ServiceType.BATTERY_STATS;
+    }
+
+    @Override
+    public void onLowPowerModeChanged(PowerSaveState result) {
         synchronized (mStats) {
-            mStats.notePowerSaveMode(enabled);
+            mStats.notePowerSaveMode(result.batterySaverEnabled);
         }
     }
 
diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java
index abdcfe7..b3f1548 100644
--- a/services/core/java/com/android/server/audio/MediaFocusControl.java
+++ b/services/core/java/com/android/server/audio/MediaFocusControl.java
@@ -46,9 +46,9 @@
 
     /**
      * set to true so the framework enforces ducking itself, without communicating to apps
-     * that they lost focus.
+     * that they lost focus for most use cases.
      */
-    static final boolean ENFORCE_DUCKING = false;
+    static final boolean ENFORCE_DUCKING = true;
     /**
      * set to true so the framework enforces muting media/game itself when the device is ringing
      * or in a call.
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index 6932427..82a0ff6 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -309,7 +309,7 @@
                         return false;
                     } else {
                         try {
-                            if (DEBUG) { Log.v(TAG, "ducking player " + piid); }
+                            Log.v(TAG, "ducking player " + piid);
                             apc.getPlayerProxy().applyVolumeShaper(
                                     DUCK_VSHAPE,
                                     PLAY_CREATE_IF_NEEDED);
@@ -339,7 +339,7 @@
                 if (apc != null
                         && winner.hasSameUid(apc.getClientUid())) {
                     try {
-                        if (DEBUG) { Log.v(TAG, "unducking player" + piid); }
+                        Log.v(TAG, "unducking player" + piid);
                         mDuckedPlayers.remove(new Integer(piid));
                         apc.getPlayerProxy().applyVolumeShaper(
                                 DUCK_ID,
@@ -381,11 +381,11 @@
                 }
                 if (mute) {
                     try {
-                        if (DEBUG) { Log.v(TAG, "muting player" + piid); }
+                        Log.v(TAG, "call: muting player" + piid);
                         apc.getPlayerProxy().setVolume(0.0f);
                         mMutedPlayers.add(piid);
                     } catch (Exception e) {
-                        Log.e(TAG, "Error muting player " + piid, e);
+                        Log.e(TAG, "call: error muting player " + piid, e);
                     }
                 }
             }
@@ -405,10 +405,10 @@
                 final AudioPlaybackConfiguration apc = mPlayers.get(piid);
                 if (apc != null) {
                     try {
-                        if (DEBUG) { Log.v(TAG, "unmuting player" + piid); }
+                        Log.v(TAG, "call: unmuting player" + piid);
                         apc.getPlayerProxy().setVolume(1.0f);
                     } catch (Exception e) {
-                        Log.e(TAG, "Error unmuting player " + piid, e);
+                        Log.e(TAG, "call: error unmuting player " + piid, e);
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index fbda901..cf33313 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -790,6 +790,8 @@
             if (userAgent != null) {
                urlConnection.setRequestProperty("User-Agent", userAgent);
             }
+            // cannot read request header after connection
+            String requestHeader = urlConnection.getRequestProperties().toString();
 
             // Time how long it takes to get a response to our request
             long requestTimestamp = SystemClock.elapsedRealtime();
@@ -803,6 +805,7 @@
             validationLog(ValidationProbeEvent.getProbeName(probeType) + " " + url +
                     " time=" + (responseTimestamp - requestTimestamp) + "ms" +
                     " ret=" + httpResponseCode +
+                    " request=" + requestHeader +
                     " headers=" + urlConnection.getHeaderFields());
             // NOTE: We may want to consider an "HTTP/1.0 204" response to be a captive
             // portal.  The only example of this seen so far was a captive portal.  For
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index bed269c..0ef0561 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -705,11 +705,14 @@
             mAppliedDimming = false;
         }
 
-        // If low power mode is enabled, cut the brightness level by half
+        // If low power mode is enabled, scale brightness by screenLowPowerBrightnessFactor
         // as long as it is above the minimum threshold.
         if (mPowerRequest.lowPowerMode) {
             if (brightness > mScreenBrightnessRangeMinimum) {
-                brightness = Math.max(brightness / 2, mScreenBrightnessRangeMinimum);
+                final float brightnessFactor =
+                        Math.min(mPowerRequest.screenLowPowerBrightnessFactor, 1);
+                final int lowPowerBrightness = (int) (brightness * brightnessFactor);
+                brightness = Math.max(lowPowerBrightness, mScreenBrightnessRangeMinimum);
             }
             if (!mAppliedLowPower) {
                 slowChange = false;
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 4c6b832..fc86d68 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -1659,6 +1659,17 @@
         }
 
         @Override
+        public void setStandbyMode(final boolean isStandbyModeOn) {
+            enforceAccessPermission();
+            runOnServiceThread(new Runnable() {
+                @Override
+                public void run() {
+                    HdmiControlService.this.setStandbyMode(isStandbyModeOn);
+                }
+            });
+        }
+
+        @Override
         protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) {
             getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
             final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
@@ -2203,6 +2214,29 @@
         }
     }
 
+    void setStandbyMode(boolean isStandbyModeOn) {
+        assertRunOnServiceThread();
+        if (isPowerOnOrTransient() && isStandbyModeOn) {
+            mPowerManager.goToSleep(SystemClock.uptimeMillis(),
+                    PowerManager.GO_TO_SLEEP_REASON_HDMI, 0);
+            if (playback() != null) {
+                playback().sendStandby(0 /* unused */);
+            }
+        } else if (isPowerStandbyOrTransient() && !isStandbyModeOn) {
+            mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.server.hdmi:WAKE");
+            if (playback() != null) {
+                oneTouchPlay(new IHdmiControlCallback.Stub() {
+                    @Override
+                    public void onComplete(int result) {
+                        if (result != HdmiControlManager.RESULT_SUCCESS) {
+                            Slog.w(TAG, "Failed to complete 'one touch play'. result=" + result);
+                        }
+                    }
+                });
+            }
+        }
+    }
+
     boolean isProhibitMode() {
         synchronized (mLock) {
             return mProhibitMode;
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index fdaba0b..3a1ddd7 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -16,13 +16,6 @@
 
 package com.android.server.location;
 
-import com.android.internal.app.IAppOpsService;
-import com.android.internal.app.IBatteryStats;
-import com.android.internal.location.GpsNetInitiatedHandler;
-import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
-import com.android.internal.location.ProviderProperties;
-import com.android.internal.location.ProviderRequest;
-
 import android.app.AlarmManager;
 import android.app.AppOpsManager;
 import android.app.PendingIntent;
@@ -55,6 +48,7 @@
 import android.net.NetworkRequest;
 import android.net.Uri;
 import android.os.AsyncTask;
+import android.os.PowerSaveState;
 import android.os.BatteryStats;
 import android.os.Binder;
 import android.os.Bundle;
@@ -81,6 +75,17 @@
 import android.util.Log;
 import android.util.NtpTrustedTime;
 
+import com.android.internal.app.IAppOpsService;
+import com.android.internal.app.IBatteryStats;
+import com.android.internal.location.GpsNetInitiatedHandler;
+import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
+import com.android.internal.location.ProviderProperties;
+import com.android.internal.location.ProviderRequest;
+import com.android.server.power.BatterySaverPolicy;
+import com.android.server.power.BatterySaverPolicy.ServiceType;
+
+import libcore.io.IoUtils;
+
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
@@ -96,7 +101,6 @@
 import java.util.Properties;
 import java.util.Map;
 import java.util.HashMap;
-import libcore.io.IoUtils;
 
 /**
  * A GNSS implementation of LocationProvider used by LocationManager.
@@ -243,14 +247,6 @@
     private static final int TCP_MIN_PORT = 0;
     private static final int TCP_MAX_PORT = 0xffff;
 
-    // Value of batterySaverGpsMode such that GPS isn't affected by battery saver mode.
-    private static final int BATTERY_SAVER_MODE_NO_CHANGE = 0;
-    // Value of batterySaverGpsMode such that GPS is disabled when battery saver mode
-    // is enabled and the screen is off.
-    private static final int BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF = 1;
-    // Secure setting for GPS behavior when battery saver mode is on.
-    private static final String BATTERY_SAVER_GPS_MODE = "batterySaverGpsMode";
-
     /** simpler wrapper for ProviderRequest + Worksource */
     private static class GpsRequest {
         public ProviderRequest request;
@@ -548,11 +544,12 @@
     private void updateLowPowerMode() {
         // Disable GPS if we are in device idle mode.
         boolean disableGps = mPowerManager.isDeviceIdleMode();
-        switch (Settings.Secure.getInt(mContext.getContentResolver(), BATTERY_SAVER_GPS_MODE,
-                BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF)) {
-            case BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF:
+        final PowerSaveState result =
+                mPowerManager.getPowerSaveState(ServiceType.GPS);
+        switch (result.gpsMode) {
+            case BatterySaverPolicy.GPS_MODE_DISABLED_WHEN_SCREEN_OFF:
                 // If we are in battery saver mode and the screen is off, disable GPS.
-                disableGps |= mPowerManager.isPowerSaveMode() && !mPowerManager.isInteractive();
+                disableGps |= result.batterySaverEnabled && !mPowerManager.isInteractive();
                 break;
         }
         if (disableGps != mDisableGps) {
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 5078998..4e9d838 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -131,6 +131,7 @@
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
+import android.os.PowerSaveState;
 import android.os.Binder;
 import android.os.Environment;
 import android.os.Handler;
@@ -180,6 +181,7 @@
 import com.android.server.LocalServices;
 import com.android.server.SystemConfig;
 
+import com.android.server.power.BatterySaverPolicy.ServiceType;
 import libcore.io.IoUtils;
 
 import com.google.android.collect.Lists;
@@ -590,18 +592,26 @@
                     mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
                     mPowerManagerInternal.registerLowPowerModeObserver(
                             new PowerManagerInternal.LowPowerModeListener() {
-                        @Override
-                        public void onLowPowerModeChanged(boolean enabled) {
-                            if (LOGD) Slog.d(TAG, "onLowPowerModeChanged(" + enabled + ")");
-                            synchronized (mUidRulesFirstLock) {
-                                if (mRestrictPower != enabled) {
-                                    mRestrictPower = enabled;
-                                    updateRulesForRestrictPowerUL();
+                                @Override
+                                public int getServiceType() {
+                                    return ServiceType.NETWORK_FIREWALL;
                                 }
-                            }
-                        }
+
+                                @Override
+                                public void onLowPowerModeChanged(PowerSaveState result) {
+                                    final boolean enabled = result.batterySaverEnabled;
+                                    if (LOGD) Slog.d(TAG,
+                                            "onLowPowerModeChanged(" + enabled + ")");
+                                    synchronized (mUidRulesFirstLock) {
+                                        if (mRestrictPower != enabled) {
+                                            mRestrictPower = enabled;
+                                            updateRulesForRestrictPowerUL();
+                                        }
+                                    }
+                                }
                     });
-                    mRestrictPower = mPowerManagerInternal.getLowPowerModeEnabled();
+                    mRestrictPower = mPowerManagerInternal.getLowPowerState(
+                            ServiceType.NETWORK_FIREWALL).batterySaverEnabled;
 
                     mSystemReady = true;
 
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index 1af541d..2026c1b 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -504,6 +504,25 @@
         }
 
         @Override
+        public boolean setEnabledExclusive(@Nullable final String packageName, final boolean enable,
+                int userId) throws RemoteException {
+            enforceChangeOverlayPackagesPermission("setEnabled");
+            userId = handleIncomingUser(userId, "setEnabled");
+            if (packageName == null) {
+                return false;
+            }
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    return mImpl.setEnabledExclusive(packageName, enable, userId);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override
         public boolean setPriority(@Nullable final String packageName,
                 @Nullable final String parentPackageName, int userId) throws RemoteException {
             enforceChangeOverlayPackagesPermission("setPriority");
diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
index ed49383..b085179 100644
--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
@@ -301,6 +301,38 @@
         }
     }
 
+    boolean setEnabledExclusive(@NonNull final String packageName, final boolean enable,
+            final int userId) {
+        if (DEBUG) {
+            Slog.d(TAG, String.format("setEnabled packageName=%s enable=%s userId=%d",
+                        packageName, enable, userId));
+        }
+
+        final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
+        if (overlayPackage == null) {
+            return false;
+        }
+
+        try {
+            final OverlayInfo oi = mSettings.getOverlayInfo(packageName, userId);
+            List<OverlayInfo> allOverlays = getOverlayInfosForTarget(oi.targetPackageName, userId);
+
+            // Disable all other overlays.
+            allOverlays.remove(oi);
+            for (int i = 0; i < allOverlays.size(); i++) {
+                mSettings.setEnabled(allOverlays.get(i).packageName, userId, false);
+            }
+
+            final PackageInfo targetPackage =
+                    mPackageManager.getPackageInfo(oi.targetPackageName, userId);
+            mSettings.setEnabled(packageName, userId, enable);
+            updateState(targetPackage, overlayPackage, userId);
+            return true;
+        } catch (OverlayManagerSettings.BadKeyException e) {
+            return false;
+        }
+    }
+
     boolean setPriority(@NonNull final String packageName,
             @NonNull final String newParentPackageName, final int userId) {
         return mSettings.setPriority(packageName, newParentPackageName, userId);
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index fb8429d..36eba8e 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -414,13 +414,6 @@
         final long id = Binder.clearCallingIdentity();
         try {
             switch (key) {
-                case UserManager.DISALLOW_CONFIG_WIFI:
-                    if (newValue) {
-                        android.provider.Settings.Secure.putIntForUser(cr,
-                                android.provider.Settings.Global
-                                        .WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0, userId);
-                    }
-                    break;
                 case UserManager.DISALLOW_DATA_ROAMING:
                     if (newValue) {
                         // DISALLOW_DATA_ROAMING user restriction is set.
diff --git a/services/core/java/com/android/server/power/BatterySaverPolicy.java b/services/core/java/com/android/server/power/BatterySaverPolicy.java
new file mode 100644
index 0000000..8d20531
--- /dev/null
+++ b/services/core/java/com/android/server/power/BatterySaverPolicy.java
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.power;
+
+import android.annotation.IntDef;
+import android.content.ContentResolver;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.provider.Settings;
+import android.util.KeyValueListParser;
+import android.util.Slog;
+import android.os.PowerSaveState;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Class to decide whether to turn on battery saver mode for specific service
+ */
+public class BatterySaverPolicy extends ContentObserver {
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({ServiceType.GPS,
+            ServiceType.VIBRATION,
+            ServiceType.ANIMATION,
+            ServiceType.FULL_BACKUP,
+            ServiceType.KEYVALUE_BACKUP,
+            ServiceType.NETWORK_FIREWALL,
+            ServiceType.SCREEN_BRIGHTNESS,
+            ServiceType.SOUND,
+            ServiceType.BATTERY_STATS})
+    public @interface ServiceType {
+        int NULL = 0;
+        int GPS = 1;
+        int VIBRATION = 2;
+        int ANIMATION = 3;
+        int FULL_BACKUP = 4;
+        int KEYVALUE_BACKUP = 5;
+        int NETWORK_FIREWALL = 6;
+        int SCREEN_BRIGHTNESS = 7;
+        int SOUND = 8;
+        int BATTERY_STATS = 9;
+    }
+
+    private static final String TAG = "BatterySaverPolicy";
+
+    // Value of batterySaverGpsMode such that GPS isn't affected by battery saver mode.
+    public static final int GPS_MODE_NO_CHANGE = 0;
+    // Value of batterySaverGpsMode such that GPS is disabled when battery saver mode
+    // is enabled and the screen is off.
+    public static final int GPS_MODE_DISABLED_WHEN_SCREEN_OFF = 1;
+    // Secure setting for GPS behavior when battery saver mode is on.
+    public static final String SECURE_KEY_GPS_MODE = "batterySaverGpsMode";
+
+    private static final String KEY_GPS_MODE = "gps_mode";
+    private static final String KEY_VIBRATION_DISABLED = "vibration_disabled";
+    private static final String KEY_ANIMATION_DISABLED = "animation_disabled";
+    private static final String KEY_SOUNDTRIGGER_DISABLED = "soundtrigger_disabled";
+    private static final String KEY_FIREWALL_DISABLED = "firewall_disabled";
+    private static final String KEY_ADJUST_BRIGHTNESS_DISABLED = "adjust_brightness_disabled";
+    private static final String KEY_ADJUST_BRIGHTNESS_FACTOR = "adjust_brightness_factor";
+    private static final String KEY_FULLBACKUP_DEFERRED = "fullbackup_deferred";
+    private static final String KEY_KEYVALUE_DEFERRED = "keyvaluebackup_deferred";
+
+    private final KeyValueListParser mParser = new KeyValueListParser(',');
+
+    /**
+     * {@code true} if vibration is disabled in battery saver mode.
+     *
+     * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+     * @see #KEY_VIBRATION_DISABLED
+     */
+    private boolean mVibrationDisabled;
+
+    /**
+     * {@code true} if animation is disabled in battery saver mode.
+     *
+     * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+     * @see #KEY_ANIMATION_DISABLED
+     */
+    private boolean mAnimationDisabled;
+
+    /**
+     * {@code true} if sound trigger is disabled in battery saver mode
+     * in battery saver mode.
+     *
+     * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+     * @see #KEY_SOUNDTRIGGER_DISABLED
+     */
+    private boolean mSoundTriggerDisabled;
+
+    /**
+     * {@code true} if full backup is deferred in battery saver mode.
+     *
+     * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+     * @see #KEY_FULLBACKUP_DEFERRED
+     */
+    private boolean mFullBackupDeferred;
+
+    /**
+     * {@code true} if key value backup is deferred in battery saver mode.
+     *
+     * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+     * @see #KEY_KEYVALUE_DEFERRED
+     */
+    private boolean mKeyValueBackupDeferred;
+
+    /**
+     * {@code true} if network policy firewall is disabled in battery saver mode.
+     *
+     * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+     * @see #KEY_FIREWALL_DISABLED
+     */
+    private boolean mFireWallDisabled;
+
+    /**
+     * {@code true} if adjust brightness is disabled in battery saver mode.
+     *
+     * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+     * @see #KEY_ADJUST_BRIGHTNESS_DISABLED
+     */
+    private boolean mAdjustBrightnessDisabled;
+
+    /**
+     * This is the flag to decide the gps mode in battery saver mode.
+     *
+     * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+     * @see #KEY_GPS_MODE
+     */
+    private int mGpsMode;
+
+    /**
+     * This is the flag to decide the how much to adjust the screen brightness. This is
+     * the float value from 0 to 1 where 1 means don't change brightness.
+     *
+     * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+     * @see #KEY_ADJUST_BRIGHTNESS_FACTOR
+     */
+    private float mAdjustBrightnessFactor;
+
+    private ContentResolver mContentResolver;
+
+    public BatterySaverPolicy(Handler handler) {
+        super(handler);
+    }
+
+    public void start(ContentResolver contentResolver) {
+        mContentResolver = contentResolver;
+
+        mContentResolver.registerContentObserver(Settings.Global.getUriFor(
+                Settings.Global.BATTERY_SAVER_CONSTANTS), false, this);
+        onChange(true, null);
+    }
+
+    @Override
+    public void onChange(boolean selfChange, Uri uri) {
+        final String value = Settings.Global.getString(mContentResolver,
+                Settings.Global.BATTERY_SAVER_CONSTANTS);
+        updateConstants(value);
+    }
+
+    @VisibleForTesting
+    void updateConstants(final String value) {
+        synchronized (BatterySaverPolicy.this) {
+            try {
+                mParser.setString(value);
+            } catch (IllegalArgumentException e) {
+                Slog.e(TAG, "Bad battery saver constants");
+            }
+
+            mVibrationDisabled = mParser.getBoolean(KEY_VIBRATION_DISABLED, true);
+            mAnimationDisabled = mParser.getBoolean(KEY_ANIMATION_DISABLED, true);
+            mSoundTriggerDisabled = mParser.getBoolean(KEY_SOUNDTRIGGER_DISABLED, true);
+            mFullBackupDeferred = mParser.getBoolean(KEY_FULLBACKUP_DEFERRED, true);
+            mKeyValueBackupDeferred = mParser.getBoolean(KEY_KEYVALUE_DEFERRED, true);
+            mFireWallDisabled = mParser.getBoolean(KEY_FIREWALL_DISABLED, false);
+            mAdjustBrightnessDisabled = mParser.getBoolean(KEY_ADJUST_BRIGHTNESS_DISABLED, false);
+            mAdjustBrightnessFactor = mParser.getFloat(KEY_ADJUST_BRIGHTNESS_FACTOR, 0.5f);
+
+            // Get default value from Settings.Secure
+            final int defaultGpsMode = Settings.Secure.getInt(mContentResolver, SECURE_KEY_GPS_MODE,
+                    GPS_MODE_DISABLED_WHEN_SCREEN_OFF);
+            mGpsMode = mParser.getInt(KEY_GPS_MODE, defaultGpsMode);
+        }
+    }
+
+    /**
+     * Get the {@link PowerSaveState} based on {@paramref type} and {@paramref realMode}.
+     * The result will have {@link PowerSaveState#batterySaverEnabled} and some other
+     * parameters when necessary.
+     *
+     * @param type     type of the service, one of {@link ServiceType}
+     * @param realMode whether the battery saver is on by default
+     * @return State data that contains battery saver data
+     */
+    public PowerSaveState getBatterySaverPolicy(@ServiceType int type, boolean realMode) {
+        synchronized (BatterySaverPolicy.this) {
+            final PowerSaveState.Builder builder = new PowerSaveState.Builder();
+            if (!realMode) {
+                return builder.setBatterySaverEnabled(realMode)
+                        .build();
+            }
+            switch (type) {
+                case ServiceType.GPS:
+                    return builder.setBatterySaverEnabled(realMode)
+                            .setGpsMode(mGpsMode)
+                            .build();
+                case ServiceType.ANIMATION:
+                    return builder.setBatterySaverEnabled(mAnimationDisabled)
+                            .build();
+                case ServiceType.FULL_BACKUP:
+                    return builder.setBatterySaverEnabled(mFullBackupDeferred)
+                            .build();
+                case ServiceType.KEYVALUE_BACKUP:
+                    return builder.setBatterySaverEnabled(mKeyValueBackupDeferred)
+                            .build();
+                case ServiceType.NETWORK_FIREWALL:
+                    return builder.setBatterySaverEnabled(!mFireWallDisabled)
+                            .build();
+                case ServiceType.SCREEN_BRIGHTNESS:
+                    return builder.setBatterySaverEnabled(!mAdjustBrightnessDisabled)
+                            .setBrightnessFactor(mAdjustBrightnessFactor)
+                            .build();
+                case ServiceType.SOUND:
+                    return builder.setBatterySaverEnabled(mSoundTriggerDisabled)
+                            .build();
+                case ServiceType.VIBRATION:
+                    return builder.setBatterySaverEnabled(mVibrationDisabled)
+                            .build();
+                default:
+                    return builder.setBatterySaverEnabled(realMode)
+                            .build();
+            }
+        }
+    }
+
+    public void dump(PrintWriter pw) {
+        pw.println();
+        pw.println("Battery saver policy");
+        pw.println("  Settings " + Settings.Global.BATTERY_SAVER_CONSTANTS);
+        pw.println("  value: " + Settings.Global.getString(mContentResolver,
+                Settings.Global.BATTERY_SAVER_CONSTANTS));
+
+        pw.println();
+        pw.println("  " + KEY_VIBRATION_DISABLED + "=" + mVibrationDisabled);
+        pw.println("  " + KEY_ANIMATION_DISABLED + "=" + mAnimationDisabled);
+        pw.println("  " + KEY_FULLBACKUP_DEFERRED + "=" + mFullBackupDeferred);
+        pw.println("  " + KEY_KEYVALUE_DEFERRED + "=" + mKeyValueBackupDeferred);
+        pw.println("  " + KEY_FIREWALL_DISABLED + "=" + mFireWallDisabled);
+        pw.println("  " + KEY_ADJUST_BRIGHTNESS_DISABLED + "=" + mAdjustBrightnessDisabled);
+        pw.println("  " + KEY_ADJUST_BRIGHTNESS_FACTOR + "=" + mAdjustBrightnessFactor);
+        pw.println("  " + KEY_GPS_MODE + "=" + mGpsMode);
+
+    }
+}
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index d3931fb..c58b527 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -43,6 +43,7 @@
 import android.os.Message;
 import android.os.PowerManager;
 import android.os.PowerManagerInternal;
+import android.os.PowerSaveState;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
@@ -68,6 +69,7 @@
 import android.util.proto.ProtoOutputStream;
 import android.view.Display;
 import android.view.WindowManagerPolicy;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IAppOpsService;
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.os.BackgroundThread;
@@ -80,7 +82,7 @@
 import com.android.server.am.BatteryStatsService;
 import com.android.server.lights.Light;
 import com.android.server.lights.LightsManager;
-
+import com.android.server.power.BatterySaverPolicy.ServiceType;
 import libcore.util.Objects;
 
 import java.io.FileDescriptor;
@@ -192,6 +194,7 @@
     private final Context mContext;
     private final ServiceThread mHandlerThread;
     private final PowerManagerHandler mHandler;
+    private final BatterySaverPolicy mBatterySaverPolicy;
 
     private LightsManager mLightsManager;
     private BatteryManagerInternal mBatteryManagerInternal;
@@ -605,6 +608,7 @@
         mHandlerThread.start();
         mHandler = new PowerManagerHandler(mHandlerThread.getLooper());
         mConstants = new Constants(mHandler);
+        mBatterySaverPolicy = new BatterySaverPolicy(mHandler);
 
         synchronized (mLock) {
             mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");
@@ -625,6 +629,21 @@
         }
     }
 
+    @VisibleForTesting
+    PowerManagerService(Context context, BatterySaverPolicy batterySaverPolicy) {
+        super(context);
+
+        mBatterySaverPolicy = batterySaverPolicy;
+        mContext = context;
+        mHandlerThread = new ServiceThread(TAG,
+                Process.THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
+        mHandlerThread.start();
+        mHandler = new PowerManagerHandler(mHandlerThread.getLooper());
+        mConstants = new Constants(mHandler);
+        mDisplaySuspendBlocker = null;
+        mWakeLockSuspendBlocker = null;
+    }
+
     @Override
     public void onStart() {
         publishBinderService(Context.POWER_SERVICE, new BinderService());
@@ -704,6 +723,7 @@
 
         final ContentResolver resolver = mContext.getContentResolver();
         mConstants.start(resolver);
+        mBatterySaverPolicy.start(resolver);
 
         // Register for settings changes.
         resolver.registerContentObserver(Settings.Secure.getUriFor(
@@ -939,8 +959,12 @@
                         listeners = new ArrayList<PowerManagerInternal.LowPowerModeListener>(
                                 mLowPowerModeListeners);
                     }
-                    for (int i=0; i<listeners.size(); i++) {
-                        listeners.get(i).onLowPowerModeChanged(lowPowerModeEnabled);
+                    for (int i = 0; i < listeners.size(); i++) {
+                        final PowerManagerInternal.LowPowerModeListener listener = listeners.get(i);
+                        final PowerSaveState result =
+                                mBatterySaverPolicy.getBatterySaverPolicy(
+                                        listener.getServiceType(), lowPowerModeEnabled);
+                        listener.onLowPowerModeChanged(result);
                     }
                     intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
                     intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
@@ -2252,9 +2276,10 @@
             mDisplayPowerRequest.brightnessSetByUser = brightnessSetByUser;
             mDisplayPowerRequest.useAutoBrightness = autoBrightness;
             mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
-            mDisplayPowerRequest.lowPowerMode = mLowPowerModeEnabled;
             mDisplayPowerRequest.boostScreenBrightness = shouldBoostScreenBrightness();
 
+            updatePowerRequestFromBatterySaverPolicy(mDisplayPowerRequest);
+
             if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {
                 mDisplayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager;
                 if (mDisplayPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND
@@ -2671,6 +2696,14 @@
         }
     }
 
+    @VisibleForTesting
+    void updatePowerRequestFromBatterySaverPolicy(DisplayPowerRequest displayPowerRequest) {
+        PowerSaveState state = mBatterySaverPolicy.
+                getBatterySaverPolicy(ServiceType.SCREEN_BRIGHTNESS, mLowPowerModeEnabled);
+        displayPowerRequest.lowPowerMode = state.batterySaverEnabled;
+        displayPowerRequest.screenLowPowerBrightnessFactor = state.brightnessFactor;
+    }
+
     void setStayOnSettingInternal(int val) {
         Settings.Global.putInt(mContext.getContentResolver(),
                 Settings.Global.STAY_ON_WHILE_PLUGGED_IN, val);
@@ -3245,6 +3278,8 @@
             pw.println();
             pw.println("Display Power: " + mDisplayPowerCallbacks);
 
+            mBatterySaverPolicy.dump(pw);
+
             wcd = mWirelessChargerDetector;
         }
 
@@ -4201,6 +4236,19 @@
             }
         }
 
+        // Binder call
+        public PowerSaveState getPowerSaveState(@ServiceType int serviceType) {
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    return mBatterySaverPolicy.getBatterySaverPolicy(
+                            serviceType, isLowPowerModeInternal());
+                }
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
         @Override // Binder call
         public boolean setPowerSaveMode(boolean mode) {
             mContext.enforceCallingOrSelfPermission(
@@ -4519,9 +4567,9 @@
         }
 
         @Override
-        public boolean getLowPowerModeEnabled() {
+        public PowerSaveState getLowPowerState(@ServiceType int serviceType) {
             synchronized (mLock) {
-                return mLowPowerModeEnabled;
+                return mBatterySaverPolicy.getBatterySaverPolicy(serviceType, mLowPowerModeEnabled);
             }
         }
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 8b62236..8b859d1 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -129,6 +129,7 @@
 import android.hardware.display.DisplayManagerInternal;
 import android.hardware.input.InputManager;
 import android.net.Uri;
+import android.os.PowerSaveState;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
@@ -219,6 +220,7 @@
 import com.android.server.UiThread;
 import com.android.server.Watchdog;
 import com.android.server.input.InputManagerService;
+import com.android.server.power.BatterySaverPolicy.ServiceType;
 import com.android.server.power.ShutdownThread;
 
 import java.io.BufferedWriter;
@@ -1009,15 +1011,26 @@
         mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
 
         if (mPowerManagerInternal != null) {
-            mPowerManagerInternal.registerLowPowerModeObserver((enabled) -> {
-                synchronized (mWindowMap) {
-                    if (mAnimationsDisabled != enabled && !mAllowAnimationsInLowPowerMode) {
-                        mAnimationsDisabled = enabled;
-                        dispatchNewAnimatorScaleLocked(null);
+            mPowerManagerInternal.registerLowPowerModeObserver(
+                    new PowerManagerInternal.LowPowerModeListener() {
+                @Override
+                public int getServiceType() {
+                    return ServiceType.ANIMATION;
+                }
+
+                @Override
+                public void onLowPowerModeChanged(PowerSaveState result) {
+                    synchronized (mWindowMap) {
+                        final boolean enabled = result.batterySaverEnabled;
+                        if (mAnimationsDisabled != enabled && !mAllowAnimationsInLowPowerMode) {
+                            mAnimationsDisabled = enabled;
+                            dispatchNewAnimatorScaleLocked(null);
+                        }
                     }
                 }
             });
-            mAnimationsDisabled = mPowerManagerInternal.getLowPowerModeEnabled();
+            mAnimationsDisabled = mPowerManagerInternal
+                    .getLowPowerState(ServiceType.ANIMATION).batterySaverEnabled;
         }
         mScreenFrozenLock = mPowerManager.newWakeLock(
                 PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN");
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 36ae94b..78d8b53 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -1175,7 +1175,7 @@
     }
 
     sp<IGnssNiCallback> gnssNiCbIface = new GnssNiCallback();
-    if (gnssNiCbIface != nullptr) {
+    if (gnssNiIface != nullptr) {
         gnssNiIface->setCallback(gnssNiCbIface);
     } else {
         ALOGE("Unable to initialize GNSS NI interface\n");
diff --git a/services/tests/servicestests/src/com/android/server/power/BatterySaverPolicyTest.java b/services/tests/servicestests/src/com/android/server/power/BatterySaverPolicyTest.java
new file mode 100644
index 0000000..7282b3e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/power/BatterySaverPolicyTest.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.power;
+
+import android.os.PowerSaveState;
+import android.os.Handler;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import com.android.server.power.BatterySaverPolicy.ServiceType;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import static com.google.common.truth.Truth.assertThat;
+
+/**
+ * Tests for {@link com.android.server.power.BatterySaverPolicy}
+ */
+public class BatterySaverPolicyTest extends AndroidTestCase {
+    private static final boolean BATTERY_SAVER_ON = true;
+    private static final boolean BATTERY_SAVER_OFF = false;
+    private static final float BRIGHTNESS_FACTOR = 0.7f;
+    private static final float DEFAULT_BRIGHTNESS_FACTOR = 0.5f;
+    private static final float PRECISION = 0.001f;
+    private static final int GPS_MODE = 0;
+    private static final int DEFAULT_GPS_MODE = 1;
+    private static final String BATTERY_SAVER_CONSTANTS = "vibration_disabled=true,"
+            + "animation_disabled=false,"
+            + "soundtrigger_disabled=true,"
+            + "firewall_disabled=false,"
+            + "adjust_brightness_disabled=true,"
+            + "adjust_brightness_factor=0.7,"
+            + "fullbackup_deferred=true,"
+            + "keyvaluebackup_deferred=false,"
+            + "gps_mode=0";
+    private static final String BATTERY_SAVER_INCORRECT_CONSTANTS = "vi*,!=,,true";
+
+    @Mock
+    Handler mHandler;
+    private BatterySaverPolicy mBatterySaverPolicy;
+
+    public void setUp() throws Exception {
+        super.setUp();
+        MockitoAnnotations.initMocks(this);
+        mBatterySaverPolicy = new BatterySaverPolicy(mHandler);
+        mBatterySaverPolicy.start(getContext().getContentResolver());
+    }
+
+    @SmallTest
+    public void testGetBatterySaverPolicy_PolicyNull_DefaultValueCorrect() {
+        testServiceDefaultValue(ServiceType.NULL);
+    }
+
+    @SmallTest
+    public void testGetBatterySaverPolicy_PolicyVibration_DefaultValueCorrect() {
+        testServiceDefaultValue(ServiceType.VIBRATION);
+    }
+
+    @SmallTest
+    public void testGetBatterySaverPolicy_PolicySound_DefaultValueCorrect() {
+        testServiceDefaultValue(ServiceType.SOUND);
+    }
+
+    @SmallTest
+    public void testGetBatterySaverPolicy_PolicyFullBackup_DefaultValueCorrect() {
+        testServiceDefaultValue(ServiceType.FULL_BACKUP);
+    }
+
+    @SmallTest
+    public void testGetBatterySaverPolicy_PolicyKeyValueBackup_DefaultValueCorrect() {
+        testServiceDefaultValue(ServiceType.KEYVALUE_BACKUP);
+    }
+
+    @SmallTest
+    public void testGetBatterySaverPolicy_PolicyAnimation_DefaultValueCorrect() {
+        testServiceDefaultValue(ServiceType.ANIMATION);
+    }
+
+    @SmallTest
+    public void testGetBatterySaverPolicy_PolicyBatteryStats_DefaultValueCorrect() {
+        testServiceDefaultValue(ServiceType.BATTERY_STATS);
+    }
+
+    @SmallTest
+    public void testGetBatterySaverPolicy_PolicyNetworkFirewall_DefaultValueCorrect() {
+        testServiceDefaultValue(ServiceType.NETWORK_FIREWALL);
+    }
+
+    @SmallTest
+    public void testGetBatterySaverPolicy_PolicyScreenBrightness_DefaultValueCorrect() {
+        testServiceDefaultValue(ServiceType.SCREEN_BRIGHTNESS);
+
+        PowerSaveState stateOn =
+                mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.SCREEN_BRIGHTNESS, true);
+        assertThat(stateOn.brightnessFactor).isWithin(PRECISION).of(DEFAULT_BRIGHTNESS_FACTOR);
+    }
+
+    @SmallTest
+    public void testGetBatterySaverPolicy_PolicyGps_DefaultValueCorrect() {
+        testServiceDefaultValue(ServiceType.GPS);
+
+        PowerSaveState stateOn =
+                mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.GPS, true);
+        assertThat(stateOn.gpsMode).isEqualTo(DEFAULT_GPS_MODE);
+    }
+
+    @SmallTest
+    public void testUpdateConstants_getCorrectData() {
+        mBatterySaverPolicy.updateConstants(BATTERY_SAVER_CONSTANTS);
+
+        final PowerSaveState vibrationState =
+                mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.VIBRATION, BATTERY_SAVER_ON);
+        assertThat(vibrationState.batterySaverEnabled).isTrue();
+
+        final PowerSaveState animationState =
+                mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.ANIMATION, BATTERY_SAVER_ON);
+        assertThat(animationState.batterySaverEnabled).isFalse();
+
+        final PowerSaveState soundState =
+                mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.SOUND, BATTERY_SAVER_ON);
+        assertThat(soundState.batterySaverEnabled).isTrue();
+
+        final PowerSaveState networkState = mBatterySaverPolicy.getBatterySaverPolicy(
+                ServiceType.NETWORK_FIREWALL, BATTERY_SAVER_ON);
+        assertThat(networkState.batterySaverEnabled).isTrue();
+
+        final PowerSaveState screenState =
+                mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.SCREEN_BRIGHTNESS, BATTERY_SAVER_ON);
+        assertThat(screenState.batterySaverEnabled).isFalse();
+        assertThat(screenState.brightnessFactor).isWithin(PRECISION).of(BRIGHTNESS_FACTOR);
+
+        final PowerSaveState fullBackupState = mBatterySaverPolicy.getBatterySaverPolicy(
+                ServiceType.FULL_BACKUP, BATTERY_SAVER_ON);
+        assertThat(fullBackupState.batterySaverEnabled).isTrue();
+
+        final PowerSaveState keyValueBackupState = mBatterySaverPolicy.getBatterySaverPolicy(
+                ServiceType.KEYVALUE_BACKUP, BATTERY_SAVER_ON);
+        assertThat(keyValueBackupState.batterySaverEnabled).isFalse();
+
+        final PowerSaveState gpsState =
+                mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.GPS, BATTERY_SAVER_ON);
+        assertThat(gpsState.batterySaverEnabled).isTrue();
+        assertThat(gpsState.gpsMode).isEqualTo(GPS_MODE);
+    }
+
+    @SmallTest
+    public void testUpdateConstants_IncorrectData_NotCrash() {
+        //Should not crash
+        mBatterySaverPolicy.updateConstants(BATTERY_SAVER_INCORRECT_CONSTANTS);
+        mBatterySaverPolicy.updateConstants(null);
+    }
+
+    private void testServiceDefaultValue(@ServiceType int type) {
+        mBatterySaverPolicy.updateConstants("");
+        final PowerSaveState batterySaverStateOn =
+                mBatterySaverPolicy.getBatterySaverPolicy(type, BATTERY_SAVER_ON);
+        assertThat(batterySaverStateOn.batterySaverEnabled).isTrue();
+
+        final PowerSaveState batterySaverStateOff =
+                mBatterySaverPolicy.getBatterySaverPolicy(type, BATTERY_SAVER_OFF);
+        assertThat(batterySaverStateOff.batterySaverEnabled).isFalse();
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
new file mode 100644
index 0000000..967b0a4
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.power;
+
+import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
+import android.os.PowerSaveState;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.when;
+
+/**
+ * Tests for {@link com.android.server.power.PowerManagerService}
+ */
+public class PowerManagerServiceTest extends AndroidTestCase {
+    private static final float PRECISION = 0.001f;
+    private static final float BRIGHTNESS_FACTOR = 0.7f;
+    private static final boolean BATTERY_SAVER_ENABLED = true;
+
+    private @Mock BatterySaverPolicy mBatterySaverPolicy;
+    private PowerManagerService mService;
+    private PowerSaveState mPowerSaveState;
+    private DisplayPowerRequest mDisplayPowerRequest;
+
+    public void setUp() throws Exception {
+        super.setUp();
+        MockitoAnnotations.initMocks(this);
+
+        mPowerSaveState = new PowerSaveState.Builder()
+                .setBatterySaverEnabled(BATTERY_SAVER_ENABLED)
+                .setBrightnessFactor(BRIGHTNESS_FACTOR)
+                .build();
+        when(mBatterySaverPolicy.getBatterySaverPolicy(
+                eq(BatterySaverPolicy.ServiceType.SCREEN_BRIGHTNESS), anyBoolean()))
+                .thenReturn(mPowerSaveState);
+        mDisplayPowerRequest = new DisplayPowerRequest();
+        mService = new PowerManagerService(getContext(), mBatterySaverPolicy);
+    }
+
+    @SmallTest
+    public void testUpdatePowerScreenPolicy_UpdateDisplayPowerRequest() {
+        mService.updatePowerRequestFromBatterySaverPolicy(mDisplayPowerRequest);
+        assertThat(mDisplayPowerRequest.lowPowerMode).isEqualTo(BATTERY_SAVER_ENABLED);
+        assertThat(mDisplayPowerRequest.screenLowPowerBrightnessFactor)
+                .isWithin(PRECISION).of(BRIGHTNESS_FACTOR);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index dd45d9b..c8b73f1 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -17,9 +17,13 @@
 package com.android.server.wm;
 
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.doAnswer;
+
+import android.os.PowerSaveState;
 import org.mockito.invocation.InvocationOnMock;
 
 import android.annotation.Nullable;
@@ -67,6 +71,10 @@
             if (LocalServices.getService(PowerManagerInternal.class) == null) {
                 LocalServices.addService(PowerManagerInternal.class,
                         mock(PowerManagerInternal.class));
+                final PowerManagerInternal pm =
+                        LocalServices.getService(PowerManagerInternal.class);
+                PowerSaveState state = new PowerSaveState.Builder().build();
+                doReturn(state).when(pm).getLowPowerState(anyInt());
             }
             if (LocalServices.getService(ActivityManagerInternal.class) == null) {
                 LocalServices.addService(ActivityManagerInternal.class,
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
index 058de05..40bdaa5 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
@@ -497,6 +497,7 @@
     //
     // Devices List
     //
+/*
     public ArrayList<UsbAudioDevice> getConnectedDevices() {
         ArrayList<UsbAudioDevice> devices = new ArrayList<UsbAudioDevice>(mAudioDevices.size());
         for (HashMap.Entry<UsbDevice,UsbAudioDevice> entry : mAudioDevices.entrySet()) {
@@ -504,6 +505,7 @@
         }
         return devices;
     }
+*/
 
     //
     // Logging
@@ -519,6 +521,7 @@
         }
     }
 
+/*
     public void logDevicesList(String title) {
       if (DEBUG) {
           for (HashMap.Entry<UsbDevice,UsbAudioDevice> entry : mAudioDevices.entrySet()) {
@@ -528,15 +531,19 @@
               Slog.i(TAG, "" + entry.getValue());
           }
       }
-  }
+    }
+*/
 
-  // This logs a more terse (and more readable) version of the devices list
-  public void logDevices(String title) {
+    // This logs a more terse (and more readable) version of the devices list
+/*
+    public void logDevices(String title) {
       if (DEBUG) {
           Slog.i(TAG, title);
           for (HashMap.Entry<UsbDevice,UsbAudioDevice> entry : mAudioDevices.entrySet()) {
               Slog.i(TAG, entry.getValue().toShortString());
           }
       }
-  }
+    }
+*/
+
 }
diff --git a/services/usb/java/com/android/server/usb/UsbAudioDevice.java b/services/usb/java/com/android/server/usb/UsbAudioDevice.java
index bdd28e4..70d1fc6 100644
--- a/services/usb/java/com/android/server/usb/UsbAudioDevice.java
+++ b/services/usb/java/com/android/server/usb/UsbAudioDevice.java
@@ -20,10 +20,10 @@
     private static final String TAG = "UsbAudioDevice";
     protected static final boolean DEBUG = false;
 
-    public int mCard;
-    public int mDevice;
-    public boolean mHasPlayback;
-    public boolean mHasCapture;
+    public final int mCard;
+    public final int mDevice;
+    public final boolean mHasPlayback;
+    public final boolean mHasCapture;
 
     // Device "class" flags
     public static final int kAudioDeviceClassMask = 0x00FFFFFF;
@@ -34,7 +34,7 @@
     public static final int kAudioDeviceMetaMask = 0xFF000000;
     public static final int kAudioDeviceMeta_Alsa = 0x80000000;
     // This member is a combination of the above bit-flags
-    public int mDeviceClass;
+    public final int mDeviceClass;
 
     public String mDeviceName = "";
     public String mDeviceDescription = "";
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index b1df0af..a17676a 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -749,7 +749,7 @@
                         mMidiCard = scanner.nextInt();
                         mMidiDevice = scanner.nextInt();
                     } catch (FileNotFoundException e) {
-                        Slog.e(TAG, "could not open MIDI PCM file", e);
+                        Slog.e(TAG, "could not open MIDI file", e);
                         enabled = false;
                     } finally {
                         if (scanner != null) {
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
index e89585c..ca37631 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
@@ -16,8 +16,6 @@
 
 package com.android.server.soundtrigger;
 
-import static android.hardware.soundtrigger.SoundTrigger.STATUS_ERROR;
-
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -42,6 +40,7 @@
 import android.telephony.TelephonyManager;
 import android.util.Slog;
 import com.android.internal.logging.MetricsLogger;
+import com.android.server.power.BatterySaverPolicy.ServiceType;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -841,7 +840,8 @@
             if (!PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(intent.getAction())) {
                 return;
             }
-            boolean active = mPowerManager.isPowerSaveMode();
+            boolean active = mPowerManager.getPowerSaveState(ServiceType.SOUND)
+                    .batterySaverEnabled;
             if (DBG) Slog.d(TAG, "onPowerSaveModeChanged: " + active);
             synchronized (mLock) {
                 onPowerSaveModeChangedLocked(active);
@@ -874,7 +874,8 @@
             mContext.registerReceiver(mPowerSaveModeListener,
                     new IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED));
         }
-        mIsPowerSaveMode = mPowerManager.isPowerSaveMode();
+        mIsPowerSaveMode = mPowerManager.getPowerSaveState(ServiceType.SOUND)
+                .batterySaverEnabled;
     }
 
     // Sends an error callback to all models with a valid registered callback.
diff --git a/telephony/java/android/telephony/ims/ImsServiceBase.java b/telephony/java/android/telephony/ims/ImsServiceBase.java
index 0878db8..bb36862 100644
--- a/telephony/java/android/telephony/ims/ImsServiceBase.java
+++ b/telephony/java/android/telephony/ims/ImsServiceBase.java
@@ -19,6 +19,7 @@
 import android.annotation.SystemApi;
 import android.app.Service;
 import android.content.Intent;
+import android.os.Binder;
 import android.os.IBinder;
 
 /**
@@ -30,8 +31,15 @@
 @SystemApi
 public class ImsServiceBase extends Service {
 
+    /**
+     * Binder connection that does nothing but keep the connection between this Service and the
+     * framework active. If this service crashes, the framework will be notified.
+     */
+    private IBinder mConnection = new Binder();
+
     @Override
     public IBinder onBind(Intent intent) {
-        return null;
+        return mConnection;
     }
+
 }
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PathDestructionActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/PathDestructionActivity.java
index 4177725..5cede65 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/PathDestructionActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/PathDestructionActivity.java
@@ -25,6 +25,8 @@
 import android.util.MathUtils;
 import android.view.View;
 
+import java.util.Random;
+
 /**
  * The point of this test is to ensure that we can cause many paths to be created, drawn,
  * and destroyed without causing hangs or crashes. This tests the native reference counting
@@ -57,10 +59,11 @@
 
         private Path getRandomPath() {
             float left, top, right, bottom;
-            left = MathUtils.random(getWidth() - MIN_SIZE);
-            top = MathUtils.random(getHeight() - MIN_SIZE);
-            right = left + MathUtils.random(getWidth() - left);
-            bottom = top + MathUtils.random(getHeight() - top);
+            Random r = new Random();
+            left = r.nextFloat() * (getWidth() - MIN_SIZE);
+            top = r.nextFloat() * (getHeight() - MIN_SIZE);
+            right = left + r.nextFloat() * (getWidth() - left);
+            bottom = top + r.nextFloat() * (getHeight() - top);
             Path path = new Path();
             path.moveTo(left, top);
             path.lineTo(right, top);
@@ -71,9 +74,10 @@
         }
 
         private int getRandomColor() {
-            int red = MathUtils.random(255);
-            int green = MathUtils.random(255);
-            int blue = MathUtils.random(255);
+            Random r = new Random();
+            int red = r.nextInt(255);
+            int green = r.nextInt(255);
+            int blue = r.nextInt(255);
             return 0xff000000 | red << 16 | green << 8 | blue;
         }
 
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
index 415911e..11105d6 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
@@ -43,6 +43,7 @@
 import java.util.Arrays;
 import junit.framework.TestCase;
 
+// TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto.
 public class IpConnectivityEventBuilderTest extends TestCase {
 
     @SmallTest
@@ -58,8 +59,11 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 1",
+                "  transports: 0",
                 "  default_network_event <",
                 "    network_id <",
                 "      network_id: 102",
@@ -89,8 +93,11 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 1",
+                "  transports: 0",
                 "  dhcp_event <",
                 "    duration_ms: 192",
                 "    if_name: \"wlan0\"",
@@ -112,8 +119,11 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 1",
+                "  transports: 0",
                 "  dhcp_event <",
                 "    duration_ms: 0",
                 "    if_name: \"wlan0\"",
@@ -137,8 +147,11 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 1",
+                "  transports: 0",
                 "  dns_lookup_batch <",
                 "    event_types: 1",
                 "    event_types: 1",
@@ -185,8 +198,11 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 1",
+                "  transports: 0",
                 "  ip_provisioning_event <",
                 "    event_type: 1",
                 "    if_name: \"wlan0\"",
@@ -208,8 +224,11 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 1",
+                "  transports: 0",
                 "  ip_reachability_event <",
                 "    event_type: 512",
                 "    if_name: \"wlan0\"",
@@ -231,8 +250,11 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 1",
+                "  transports: 0",
                 "  network_event <",
                 "    event_type: 5",
                 "    latency_ms: 20410",
@@ -258,8 +280,11 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 1",
+                "  transports: 0",
                 "  validation_probe_event <",
                 "    latency_ms: 40730",
                 "    network_id <",
@@ -287,11 +312,15 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 1",
+                "  transports: 0",
                 "  apf_program_event <",
                 "    current_ras: 9",
                 "    drop_multicast: true",
+                "    effective_lifetime: 0",
                 "    filtered_ras: 7",
                 "    has_ipv4_addr: true",
                 "    lifetime: 200",
@@ -319,8 +348,11 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 1",
+                "  transports: 0",
                 "  apf_statistics <",
                 "    dropped_ras: 2",
                 "    duration_ms: 45000",
@@ -328,6 +360,8 @@
                 "    max_program_size: 2048",
                 "    parse_errors: 2",
                 "    program_updates: 4",
+                "    program_updates_all: 0",
+                "    program_updates_allowing_multicast: 0",
                 "    received_ras: 10",
                 "    zero_lifetime_ras: 1",
                 "  >",
@@ -351,8 +385,11 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 1",
+                "  transports: 0",
                 "  ra_event <",
                 "    dnssl_lifetime: -1",
                 "    prefix_preferred_lifetime: 300",
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
index f56f3f8..1f7c5f4 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
@@ -139,6 +139,7 @@
 
     @SmallTest
     public void testEndToEndLogging() {
+        // TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto.
         IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
 
         Parcelable[] events = {
@@ -158,16 +159,22 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 100",
+                "  transports: 0",
                 "  ip_reachability_event <",
                 "    event_type: 512",
                 "    if_name: \"wlan0\"",
                 "  >",
                 ">",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 200",
+                "  transports: 0",
                 "  dhcp_event <",
                 "    duration_ms: 192",
                 "    if_name: \"wlan0\"",
@@ -175,8 +182,11 @@
                 "  >",
                 ">",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 300",
+                "  transports: 0",
                 "  default_network_event <",
                 "    network_id <",
                 "      network_id: 102",
@@ -191,8 +201,11 @@
                 "  >",
                 ">",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 400",
+                "  transports: 0",
                 "  ip_provisioning_event <",
                 "    event_type: 1",
                 "    if_name: \"wlan0\"",
@@ -200,8 +213,11 @@
                 "  >",
                 ">",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 500",
+                "  transports: 0",
                 "  validation_probe_event <",
                 "    latency_ms: 40730",
                 "    network_id <",
@@ -212,8 +228,11 @@
                 "  >",
                 ">",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 600",
+                "  transports: 0",
                 "  apf_statistics <",
                 "    dropped_ras: 2",
                 "    duration_ms: 45000",
@@ -221,13 +240,18 @@
                 "    max_program_size: 2048",
                 "    parse_errors: 2",
                 "    program_updates: 4",
+                "    program_updates_all: 0",
+                "    program_updates_allowing_multicast: 0",
                 "    received_ras: 10",
                 "    zero_lifetime_ras: 1",
                 "  >",
                 ">",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 700",
+                "  transports: 0",
                 "  ra_event <",
                 "    dnssl_lifetime: -1",
                 "    prefix_preferred_lifetime: 300",
diff --git a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
index cfd5598..637eaa3 100644
--- a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
+++ b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
@@ -213,9 +213,13 @@
 
         IpConnectivityEvent got = events.get(0);
         String want = String.join("\n",
+                "if_name: \"\"",
                 "link_layer: 0",
+                "network_id: 0",
                 "time_ms: 0",
+                "transports: 0",
                 "connect_statistics <",
+                "  connect_blocking_count: 0",
                 "  connect_count: 12",
                 "  errnos_counters <",
                 "    key: 1",
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index ff306ce..60f0d56 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -4764,6 +4764,7 @@
                                         const sp<XMLNode>& root) {
     const String16 vector16("vector");
     const String16 animatedVector16("animated-vector");
+    const String16 pathInterpolator16("pathInterpolator");
 
     const int minSdk = getMinSdkVersion(bundle);
     if (minSdk >= SDK_LOLLIPOP_MR1) {
@@ -4789,7 +4790,8 @@
         nodesToVisit.pop();
 
         if (bundle->getNoVersionVectors() && (node->getElementName() == vector16 ||
-                    node->getElementName() == animatedVector16)) {
+                    node->getElementName() == animatedVector16 ||
+                    node->getElementName() == pathInterpolator16)) {
             // We were told not to version vector tags, so skip the children here.
             continue;
         }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
index 9f73d79..339019d 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
@@ -18,6 +18,7 @@
 
 import android.os.IBinder;
 import android.os.IPowerManager;
+import android.os.PowerSaveState;
 import android.os.RemoteException;
 import android.os.WorkSource;
 
@@ -42,6 +43,10 @@
         return false;
     }
 
+    public PowerSaveState getPowerSaveState(int serviceType) {
+        return null;
+    }
+
     @Override
     public IBinder asBinder() {
         // pass for now.