Merge "MathUtils: Remove static Random field."
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 cb0d7b1..6ee593c 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
@@ -47046,6 +47049,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 {
@@ -48511,8 +48515,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();
@@ -48556,6 +48561,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();
@@ -48685,6 +48691,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();
@@ -48867,6 +48874,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);
@@ -48970,6 +48978,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
@@ -49027,6 +49040,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
@@ -49639,8 +49655,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);
@@ -50899,17 +50916,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();
@@ -51374,9 +51401,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/QueuedWork.java b/core/java/android/app/QueuedWork.java
index 9c5c338..56338f5 100644
--- a/core/java/android/app/QueuedWork.java
+++ b/core/java/android/app/QueuedWork.java
@@ -25,6 +25,7 @@
 import android.util.Log;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.ExponentiallyBucketedHistogram;
 
 import java.util.LinkedList;
 
@@ -47,11 +48,14 @@
  */
 public class QueuedWork {
     private static final String LOG_TAG = QueuedWork.class.getSimpleName();
-    private static final boolean DEBUG = true;
+    private static final boolean DEBUG = false;
 
     /** Delay for delayed runnables, as big as possible but low enough to be barely perceivable */
     private static final long DELAY = 100;
 
+    /** If a {@link #waitToFinish()} takes more than {@value #MAX_WAIT_TIME_MILLIS} ms, warn */
+    private static final long MAX_WAIT_TIME_MILLIS = 512;
+
     /** Lock for this class */
     private static final Object sLock = new Object();
 
@@ -80,6 +84,13 @@
     @GuardedBy("sLock")
     private static boolean sCanDelay = true;
 
+    /** Time (and number of instances) waited for work to get processed */
+    @GuardedBy("sLock")
+    private final static ExponentiallyBucketedHistogram
+            mWaitTimes = new ExponentiallyBucketedHistogram(
+            16);
+    private static int mNumWaits = 0;
+
     /**
      * Lazily create a handler on a separate thread.
      *
@@ -136,13 +147,9 @@
      * after Service command handling, etc. (so async work is never lost)
      */
     public static void waitToFinish() {
-        long startTime = 0;
+        long startTime = System.currentTimeMillis();
         boolean hadMessages = false;
 
-        if (DEBUG) {
-            startTime = System.currentTimeMillis();
-        }
-
         Handler handler = getHandler();
 
         synchronized (sLock) {
@@ -185,11 +192,16 @@
             sCanDelay = true;
         }
 
-        if (DEBUG) {
+        synchronized (sLock) {
             long waitTime = System.currentTimeMillis() - startTime;
 
             if (waitTime > 0 || hadMessages) {
-                Log.d(LOG_TAG, "waited " + waitTime + " ms");
+                mWaitTimes.add(Long.valueOf(waitTime).intValue());
+                mNumWaits++;
+
+                if (DEBUG || mNumWaits % 1024 == 0 || waitTime > MAX_WAIT_TIME_MILLIS) {
+                    mWaitTimes.log(LOG_TAG, "waited: ");
+                }
             }
         }
     }
diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java
index 11ba7ee..063ad24 100644
--- a/core/java/android/app/SharedPreferencesImpl.java
+++ b/core/java/android/app/SharedPreferencesImpl.java
@@ -28,6 +28,7 @@
 import com.google.android.collect.Maps;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.ExponentiallyBucketedHistogram;
 import com.android.internal.util.XmlUtils;
 
 import dalvik.system.BlockGuard;
@@ -53,9 +54,12 @@
 
 final class SharedPreferencesImpl implements SharedPreferences {
     private static final String TAG = "SharedPreferencesImpl";
-    private static final boolean DEBUG = true;
+    private static final boolean DEBUG = false;
     private static final Object CONTENT = new Object();
 
+    /** If a fsync takes more than {@value #MAX_FSYNC_DURATION_MILLIS} ms, warn */
+    private static final long MAX_FSYNC_DURATION_MILLIS = 256;
+
     // Lock ordering rules:
     //  - acquire SharedPreferencesImpl.mLock before EditorImpl.mLock
     //  - acquire mWritingToDiskLock before EditorImpl.mLock
@@ -93,6 +97,11 @@
     @GuardedBy("mWritingToDiskLock")
     private long mDiskStateGeneration;
 
+    /** Time (and number of instances) of file-system sync requests */
+    @GuardedBy("mWritingToDiskLock")
+    private final ExponentiallyBucketedHistogram mSyncTimes = new ExponentiallyBucketedHistogram(16);
+    private int mNumSync = 0;
+
     SharedPreferencesImpl(File file, int mode) {
         mFile = file;
         mBackupFile = makeBackupFile(file);
@@ -139,8 +148,8 @@
                     str = new BufferedInputStream(
                             new FileInputStream(mFile), 16*1024);
                     map = XmlUtils.readMapXml(str);
-                } catch (XmlPullParserException | IOException e) {
-                    Log.w(TAG, "getSharedPreferences", e);
+                } catch (Exception e) {
+                    Log.w(TAG, "Cannot read " + mFile.getAbsolutePath(), e);
                 } finally {
                     IoUtils.closeQuietly(str);
                 }
@@ -719,15 +728,11 @@
             }
             XmlUtils.writeMapXml(mcr.mapToWriteToDisk, str);
 
-            if (DEBUG) {
-                writeTime = System.currentTimeMillis();
-            }
+            writeTime = System.currentTimeMillis();
 
             FileUtils.sync(str);
 
-            if (DEBUG) {
-                fsyncTime = System.currentTimeMillis();
-            }
+            fsyncTime = System.currentTimeMillis();
 
             str.close();
             ContextImpl.setFilePermissionsFromMode(mFile.getPath(), mMode, 0);
@@ -761,14 +766,24 @@
 
             mcr.setDiskWriteResult(true, true);
 
-            Log.d(TAG, "write: " + (existsTime - startTime) + "/"
-                    + (backupExistsTime - startTime) + "/"
-                    + (outputStreamCreateTime - startTime) + "/"
-                    + (writeTime - startTime) + "/"
-                    + (fsyncTime - startTime) + "/"
-                    + (setPermTime - startTime) + "/"
-                    + (fstatTime - startTime) + "/"
-                    + (deleteTime - startTime));
+            if (DEBUG) {
+                Log.d(TAG, "write: " + (existsTime - startTime) + "/"
+                        + (backupExistsTime - startTime) + "/"
+                        + (outputStreamCreateTime - startTime) + "/"
+                        + (writeTime - startTime) + "/"
+                        + (fsyncTime - startTime) + "/"
+                        + (setPermTime - startTime) + "/"
+                        + (fstatTime - startTime) + "/"
+                        + (deleteTime - startTime));
+            }
+
+            long fsyncDuration = fsyncTime - writeTime;
+            mSyncTimes.add(Long.valueOf(fsyncDuration).intValue());
+            mNumSync++;
+
+            if (DEBUG || mNumSync % 1024 == 0 || fsyncDuration > MAX_FSYNC_DURATION_MILLIS) {
+                mSyncTimes.log(TAG, "Time required to fsync " + mFile + ": ");
+            }
 
             return;
         } catch (XmlPullParserException e) {
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/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/MapCollections.java b/core/java/android/util/MapCollections.java
index 28b788b..80ab23c 100644
--- a/core/java/android/util/MapCollections.java
+++ b/core/java/android/util/MapCollections.java
@@ -22,6 +22,7 @@
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.NoSuchElementException;
 import java.util.Set;
 
 /**
@@ -52,6 +53,7 @@
 
         @Override
         public T next() {
+            if (!hasNext()) throw new NoSuchElementException();
             Object res = colGetEntry(mIndex, mOffset);
             mIndex++;
             mCanRemove = true;
@@ -87,6 +89,7 @@
 
         @Override
         public Map.Entry<K, V> next() {
+            if (!hasNext()) throw new NoSuchElementException();
             mIndex++;
             mEntryValid = true;
             return this;
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 1e7cddf..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");
         }
@@ -2784,6 +2790,10 @@
      * package that was used to load it. Otherwise, the package that would be used if the WebView
      * was loaded right now will be returned; this does not cause WebView to be loaded, so this
      * information may become outdated at any time.
+     * The WebView package changes either when the current WebView package is updated, disabled, or
+     * uninstalled. It can also be changed through a Developer Setting.
+     * If the WebView package changes, any app process that has loaded WebView will be killed. The
+     * next time the app starts and loads WebView it will use the new WebView package instead.
      * @return the current WebView package, or null if there is none.
      */
     public static PackageInfo getCurrentWebViewPackage() {
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/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/internal/util/ExponentiallyBucketedHistogram.java b/core/java/com/android/internal/util/ExponentiallyBucketedHistogram.java
new file mode 100644
index 0000000..dc9f3f4
--- /dev/null
+++ b/core/java/com/android/internal/util/ExponentiallyBucketedHistogram.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.util;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.util.Log;
+
+import java.util.Arrays;
+
+/**
+ * A histogram for positive integers where each bucket is twice the size of the previous one.
+ */
+public class ExponentiallyBucketedHistogram {
+    @NonNull
+    private final int[] mData;
+
+    /**
+     * Create a new histogram.
+     *
+     * @param numBuckets The number of buckets. The highest bucket is for all value >=
+     *                   2<sup>numBuckets - 1</sup>
+     */
+    public ExponentiallyBucketedHistogram(@IntRange(from = 1, to = 31) int numBuckets) {
+        numBuckets = Preconditions.checkArgumentInRange(numBuckets, 1, 31, "numBuckets");
+
+        mData = new int[numBuckets];
+    }
+
+    /**
+     * Add a new value to the histogram.
+     *
+     * All values <= 0 are in the first bucket. The last bucket contains all values >=
+     * 2<sup>numBuckets - 1</sup>
+     *
+     * @param value The value to add
+     */
+    public void add(int value) {
+        if (value <= 0) {
+            mData[0]++;
+        } else {
+            mData[Math.min(mData.length - 1, 32 - Integer.numberOfLeadingZeros(value))]++;
+        }
+    }
+
+    /**
+     * Clear all data from the histogram
+     */
+    public void reset() {
+        Arrays.fill(mData, 0);
+    }
+
+    /**
+     * Write the histogram to the log.
+     *
+     * @param tag    The tag to use when logging
+     * @param prefix A custom prefix that is printed in front of the histogram
+     */
+    public void log(@NonNull String tag, @Nullable CharSequence prefix) {
+        StringBuilder builder = new StringBuilder(prefix);
+        builder.append('[');
+
+        for (int i = 0; i < mData.length; i++) {
+            if (i != 0) {
+                builder.append(", ");
+            }
+
+            if (i < mData.length - 1) {
+                builder.append("<");
+                builder.append(1 << i);
+            } else {
+                builder.append(">=");
+                builder.append(1 << (i - 1));
+            }
+
+            builder.append(": ");
+            builder.append(mData[i]);
+        }
+        builder.append("]");
+
+        Log.d(tag, builder.toString());
+    }
+}
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItem.java b/core/java/com/android/internal/view/menu/ActionMenuItem.java
index ace0cce..ac226dd 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItem.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItem.java
@@ -145,12 +145,12 @@
     }
 
     public MenuItem setAlphabeticShortcut(char alphaChar) {
-        mShortcutAlphabeticChar = alphaChar;
+        mShortcutAlphabeticChar = Character.toLowerCase(alphaChar);
         return this;
     }
 
     public MenuItem setAlphabeticShortcut(char alphachar, int alphaModifiers) {
-        mShortcutAlphabeticChar = alphachar;
+        mShortcutAlphabeticChar = Character.toLowerCase(alphachar);
         mShortcutAlphabeticModifiers = KeyEvent.normalizeMetaState(alphaModifiers);
         return this;
     }
@@ -210,7 +210,7 @@
 
     public MenuItem setShortcut(char numericChar, char alphaChar) {
         mShortcutNumericChar = numericChar;
-        mShortcutAlphabeticChar = alphaChar;
+        mShortcutAlphabeticChar = Character.toLowerCase(alphaChar);
         return this;
     }
 
@@ -218,7 +218,7 @@
             int alphaModifiers) {
         mShortcutNumericChar = numericChar;
         mShortcutNumericModifiers = KeyEvent.normalizeMetaState(numericModifiers);
-        mShortcutAlphabeticChar = alphaChar;
+        mShortcutAlphabeticChar = Character.toLowerCase(alphaChar);
         mShortcutAlphabeticModifiers = KeyEvent.normalizeMetaState(alphaModifiers);
         return this;
     }
diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java
index 4c3118d..9310d14 100644
--- a/core/java/com/android/internal/view/menu/MenuItemImpl.java
+++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java
@@ -255,7 +255,7 @@
             return this;
         }
 
-        mShortcutAlphabeticChar = alphaChar;
+        mShortcutAlphabeticChar = Character.toLowerCase(alphaChar);
         mShortcutAlphabeticModifiers = KeyEvent.normalizeMetaState(alphaModifiers);
 
         mMenu.onItemsChanged(false);
@@ -307,7 +307,7 @@
             int alphaModifiers) {
         mShortcutNumericChar = numericChar;
         mShortcutNumericModifiers = KeyEvent.normalizeMetaState(numericModifiers);
-        mShortcutAlphabeticChar = alphaChar;
+        mShortcutAlphabeticChar = Character.toLowerCase(alphaChar);
         mShortcutAlphabeticModifiers = KeyEvent.normalizeMetaState(alphaModifiers);
 
         mMenu.onItemsChanged(false);
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_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/Android.mk b/core/tests/coretests/Android.mk
index ef09c35..1a16b3b 100644
--- a/core/tests/coretests/Android.mk
+++ b/core/tests/coretests/Android.mk
@@ -29,7 +29,6 @@
     frameworks-core-util-lib \
     mockwebserver \
     guava \
-    littlemock \
     android-support-test \
     mockito-target-minus-junit4 \
     espresso-core \
diff --git a/core/tests/coretests/src/android/net/SSLSessionCacheTest.java b/core/tests/coretests/src/android/net/SSLSessionCacheTest.java
index be19303..ec130e0 100644
--- a/core/tests/coretests/src/android/net/SSLSessionCacheTest.java
+++ b/core/tests/coretests/src/android/net/SSLSessionCacheTest.java
@@ -19,7 +19,7 @@
 import com.android.org.conscrypt.ClientSessionContext;
 import com.android.org.conscrypt.SSLClientSessionCache;
 
-import com.google.testing.littlemock.LittleMock;
+import org.mockito.Mockito;
 
 import junit.framework.TestCase;
 
@@ -39,25 +39,25 @@
 
     public void testInstall_compatibleContext() throws Exception {
         final SSLContext ctx = SSLContext.getDefault();
-        final SSLClientSessionCache mock = LittleMock.mock(SSLClientSessionCache.class);
+        final SSLClientSessionCache mock = Mockito.mock(SSLClientSessionCache.class);
         final ClientSessionContext clientCtx = (ClientSessionContext) ctx.getClientSessionContext();
 
         try {
             SSLSessionCache.install(new SSLSessionCache(mock), ctx);
             clientCtx.getSession("www.foogle.com", 443);
-            LittleMock.verify(mock).getSessionData(LittleMock.anyString(), LittleMock.anyInt());
+            Mockito.verify(mock).getSessionData(Mockito.anyString(), Mockito.anyInt());
         } finally {
             // Restore cacheless behaviour.
             SSLSessionCache.install(null, ctx);
             clientCtx.getSession("www.foogle.com", 443);
-            LittleMock.verifyNoMoreInteractions(mock);
+            Mockito.verifyNoMoreInteractions(mock);
         }
     }
 
     public void testInstall_incompatibleContext() {
         try {
             SSLSessionCache.install(
-                    new SSLSessionCache(LittleMock.mock(SSLClientSessionCache.class)),
+                    new SSLSessionCache(Mockito.mock(SSLClientSessionCache.class)),
                     new FakeSSLContext());
             fail();
         } catch (IllegalArgumentException expected) {}
@@ -102,7 +102,7 @@
 
         @Override
         protected SSLSessionContext engineGetClientSessionContext() {
-            return LittleMock.mock(SSLSessionContext.class);
+            return Mockito.mock(SSLSessionContext.class);
         }
     }
 }
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/core/tests/coretests/src/android/view/PopupWindowVisibility.java b/core/tests/coretests/src/android/view/PopupWindowVisibility.java
index 7eb0468..6e11ede 100644
--- a/core/tests/coretests/src/android/view/PopupWindowVisibility.java
+++ b/core/tests/coretests/src/android/view/PopupWindowVisibility.java
@@ -82,7 +82,7 @@
         "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
         "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
         "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
-        "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
+        "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czechia",
         "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
         "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
         "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
diff --git a/core/tests/coretests/src/android/widget/focus/RequestFocusTest.java b/core/tests/coretests/src/android/widget/focus/RequestFocusTest.java
index f2eba23..cdfa217 100644
--- a/core/tests/coretests/src/android/widget/focus/RequestFocusTest.java
+++ b/core/tests/coretests/src/android/widget/focus/RequestFocusTest.java
@@ -16,8 +16,8 @@
 
 package android.widget.focus;
 
-import static com.google.testing.littlemock.LittleMock.inOrder;
-import static com.google.testing.littlemock.LittleMock.mock;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
 
 import android.os.Handler;
 import android.test.ActivityInstrumentationTestCase2;
@@ -31,7 +31,7 @@
 import android.widget.Button;
 
 import com.android.frameworks.coretests.R;
-import com.google.testing.littlemock.LittleMock.InOrder;
+import org.mockito.InOrder;
 
 /**
  * {@link RequestFocusTest} is set up to exercise cases where the views that
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/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..4dc593b 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/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/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/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/ListActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java
index db6421e..0defe92 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java
@@ -42,7 +42,7 @@
             "Burkina Faso", "Burundi", "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
             "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
             "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
-            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
+            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czechia",
             "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
             "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
             "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java
index 535f865..ffb8689 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java
@@ -42,7 +42,7 @@
             "Burkina Faso", "Burundi", "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
             "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
             "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
-            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
+            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czechia",
             "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
             "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
             "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity.java
index 0ddd7fd..7168478 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity.java
@@ -126,7 +126,7 @@
             "Burkina Faso", "Burundi", "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
             "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
             "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
-            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
+            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czechia",
             "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
             "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
             "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity2.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity2.java
index e795f02..a037d70 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity2.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity2.java
@@ -76,7 +76,7 @@
             "Burkina Faso", "Burundi", "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
             "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
             "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
-            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
+            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czechia",
             "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
             "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
             "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity3.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity3.java
index c8ae75b..e65dd63 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity3.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity3.java
@@ -73,7 +73,7 @@
             "Burkina Faso", "Burundi", "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
             "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
             "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
-            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
+            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czechia",
             "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
             "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
             "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity4.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity4.java
index 6072c6e..17f78af 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity4.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity4.java
@@ -80,7 +80,7 @@
             "Burkina Faso", "Burundi", "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
             "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
             "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
-            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
+            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czechia",
             "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
             "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
             "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java
index cbbb7ef..2dd7b6a 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java
@@ -145,7 +145,7 @@
             "Burkina Faso", "Burundi", "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
             "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
             "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
-            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
+            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czechia",
             "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
             "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
             "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
diff --git a/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityLandscape.java b/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityLandscape.java
index 7a4fddf..292bbd2 100644
--- a/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityLandscape.java
+++ b/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityLandscape.java
@@ -65,7 +65,7 @@
    "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
    "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
    "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
-   "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
+   "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czechia",
    "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
    "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
    "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
diff --git a/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityPortrait.java b/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityPortrait.java
index 5bfe456..570cb6b 100644
--- a/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityPortrait.java
+++ b/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityPortrait.java
@@ -60,7 +60,7 @@
    "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
    "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
    "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
-   "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
+   "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czechia",
    "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
    "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
    "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
diff --git a/tests/TtsTests/Android.mk b/tests/TtsTests/Android.mk
index ed63e12..3c3cd77 100644
--- a/tests/TtsTests/Android.mk
+++ b/tests/TtsTests/Android.mk
@@ -20,7 +20,7 @@
 
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
-LOCAL_STATIC_JAVA_LIBRARIES := littlemock junit legacy-android-test
+LOCAL_STATIC_JAVA_LIBRARIES := mockito-target legacy-android-test
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
 LOCAL_PACKAGE_NAME := TtsTests
diff --git a/tests/TtsTests/src/com/android/speech/tts/TextToSpeechTests.java b/tests/TtsTests/src/com/android/speech/tts/TextToSpeechTests.java
index faf6827..918873b 100644
--- a/tests/TtsTests/src/com/android/speech/tts/TextToSpeechTests.java
+++ b/tests/TtsTests/src/com/android/speech/tts/TextToSpeechTests.java
@@ -22,9 +22,12 @@
 import android.test.InstrumentationTestCase;
 
 import com.android.speech.tts.MockableTextToSpeechService.IDelegate;
-import com.google.testing.littlemock.ArgumentCaptor;
-import com.google.testing.littlemock.Behaviour;
-import com.google.testing.littlemock.LittleMock;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+import org.mockito.internal.stubbing.StubberImpl;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.Stubber;
 import junit.framework.Assert;
 
 import java.util.Locale;
@@ -40,16 +43,16 @@
 
     @Override
     public void setUp() throws Exception {
-        IDelegate passThrough = LittleMock.mock(IDelegate.class);
+        IDelegate passThrough = Mockito.mock(IDelegate.class);
         MockableTextToSpeechService.setMocker(passThrough);
 
         // For the default voice selection
-        LittleMock.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).when(passThrough)
+        Mockito.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).when(passThrough)
             .onIsLanguageAvailable(
-                    LittleMock.anyString(), LittleMock.anyString(), LittleMock.anyString());
-        LittleMock.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).when(passThrough)
+                    Mockito.anyString(), Mockito.anyString(), Mockito.anyString());
+        Mockito.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).when(passThrough)
             .onLoadLanguage(
-                    LittleMock.anyString(), LittleMock.anyString(), LittleMock.anyString());
+                    Mockito.anyString(), Mockito.anyString(), Mockito.anyString());
 
         blockingInitAndVerify(MOCK_ENGINE, TextToSpeech.SUCCESS);
         assertEquals(MOCK_ENGINE, mTts.getCurrentEngine());
@@ -71,42 +74,42 @@
     }
 
     public void testSetLanguage_delegation() {
-        IDelegate delegate = LittleMock.mock(IDelegate.class);
+        IDelegate delegate = Mockito.mock(IDelegate.class);
         MockableTextToSpeechService.setMocker(delegate);
 
-        LittleMock.doReturn(TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE).when(delegate).onIsLanguageAvailable(
+        Mockito.doReturn(TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE).when(delegate).onIsLanguageAvailable(
                 "eng", "USA", "variant");
-        LittleMock.doReturn(TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE).when(delegate).onLoadLanguage(
+        Mockito.doReturn(TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE).when(delegate).onLoadLanguage(
                 "eng", "USA", "variant");
 
         // Test 1 :Tests that calls to onLoadLanguage( ) are delegated through to the
         // service without any caching or intermediate steps.
         assertEquals(TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE, mTts.setLanguage(new Locale("eng", "USA", "variant")));
-        LittleMock.verify(delegate, LittleMock.anyTimes()).onIsLanguageAvailable(
+        Mockito.verify(delegate, Mockito.atLeast(0)).onIsLanguageAvailable(
             "eng", "USA", "variant");
-        LittleMock.verify(delegate, LittleMock.anyTimes()).onLoadLanguage(
+        Mockito.verify(delegate, Mockito.atLeast(0)).onLoadLanguage(
             "eng", "USA", "variant");
     }
 
     public void testSetLanguage_availableLanguage() throws Exception {
-        IDelegate delegate = LittleMock.mock(IDelegate.class);
+        IDelegate delegate = Mockito.mock(IDelegate.class);
         MockableTextToSpeechService.setMocker(delegate);
 
         // ---------------------------------------------------------
         // Test 2 : Tests that when the language is successfully set
         // like above (returns LANG_COUNTRY_AVAILABLE). That the
         // request language changes from that point on.
-        LittleMock.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).when(delegate).onIsLanguageAvailable(
+        Mockito.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).when(delegate).onIsLanguageAvailable(
                 "eng", "USA", "variant");
-        LittleMock.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).when(delegate).onIsLanguageAvailable(
+        Mockito.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).when(delegate).onIsLanguageAvailable(
                 "eng", "USA", "");
-        LittleMock.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).when(delegate).onLoadLanguage(
+        Mockito.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).when(delegate).onLoadLanguage(
                 "eng", "USA", "");
         mTts.setLanguage(new Locale("eng", "USA", "variant"));
         blockingCallSpeak("foo bar", delegate);
-        ArgumentCaptor<SynthesisRequest> req = LittleMock.createCaptor();
-        LittleMock.verify(delegate, LittleMock.times(1)).onSynthesizeText(req.capture(),
-                LittleMock.<SynthesisCallback>anyObject());
+        ArgumentCaptor<SynthesisRequest> req = ArgumentCaptor.forClass(SynthesisRequest.class);
+        Mockito.verify(delegate, Mockito.times(1)).onSynthesizeText(req.capture(),
+                Mockito.<SynthesisCallback>anyObject());
 
         assertEquals("eng", req.getValue().getLanguage());
         assertEquals("USA", req.getValue().getCountry());
@@ -115,21 +118,21 @@
     }
 
     public void testSetLanguage_unavailableLanguage() throws Exception {
-        IDelegate delegate = LittleMock.mock(IDelegate.class);
+        IDelegate delegate = Mockito.mock(IDelegate.class);
         MockableTextToSpeechService.setMocker(delegate);
 
         // ---------------------------------------------------------
         // TEST 3 : Tests that the language that is set does not change when the
         // engine reports it could not load the specified language.
-        LittleMock.doReturn(TextToSpeech.LANG_NOT_SUPPORTED).when(
+        Mockito.doReturn(TextToSpeech.LANG_NOT_SUPPORTED).when(
                 delegate).onIsLanguageAvailable("fra", "FRA", "");
-        LittleMock.doReturn(TextToSpeech.LANG_NOT_SUPPORTED).when(
+        Mockito.doReturn(TextToSpeech.LANG_NOT_SUPPORTED).when(
                 delegate).onLoadLanguage("fra", "FRA", "");
         mTts.setLanguage(Locale.FRANCE);
         blockingCallSpeak("le fou barre", delegate);
-        ArgumentCaptor<SynthesisRequest> req2 = LittleMock.createCaptor();
-        LittleMock.verify(delegate, LittleMock.times(1)).onSynthesizeText(req2.capture(),
-                        LittleMock.<SynthesisCallback>anyObject());
+        ArgumentCaptor<SynthesisRequest> req2 = ArgumentCaptor.forClass(SynthesisRequest.class);
+        Mockito.verify(delegate, Mockito.times(1)).onSynthesizeText(req2.capture(),
+                        Mockito.<SynthesisCallback>anyObject());
 
         // The params are basically unchanged.
         assertEquals("eng", req2.getValue().getLanguage());
@@ -139,41 +142,41 @@
     }
 
     public void testIsLanguageAvailable() {
-        IDelegate delegate = LittleMock.mock(IDelegate.class);
+        IDelegate delegate = Mockito.mock(IDelegate.class);
         MockableTextToSpeechService.setMocker(delegate);
 
         // Test1: Simple end to end test.
-        LittleMock.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).when(
+        Mockito.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).when(
                 delegate).onIsLanguageAvailable("eng", "USA", "");
 
         assertEquals(TextToSpeech.LANG_COUNTRY_AVAILABLE, mTts.isLanguageAvailable(Locale.US));
-        LittleMock.verify(delegate, LittleMock.times(1)).onIsLanguageAvailable(
+        Mockito.verify(delegate, Mockito.times(1)).onIsLanguageAvailable(
                 "eng", "USA", "");
     }
 
     public void testDefaultLanguage_setsVoiceName() throws Exception {
-        IDelegate delegate = LittleMock.mock(IDelegate.class);
+        IDelegate delegate = Mockito.mock(IDelegate.class);
         MockableTextToSpeechService.setMocker(delegate);
         Locale defaultLocale = Locale.getDefault();
 
         // ---------------------------------------------------------
         // Test that default language also sets the default voice
         // name
-        LittleMock.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).
+        Mockito.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).
             when(delegate).onIsLanguageAvailable(
                 defaultLocale.getISO3Language(),
                 defaultLocale.getISO3Country().toUpperCase(),
                 defaultLocale.getVariant());
-        LittleMock.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).
+        Mockito.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).
             when(delegate).onLoadLanguage(
                 defaultLocale.getISO3Language(),
                 defaultLocale.getISO3Country(),
                 defaultLocale.getVariant());
 
         blockingCallSpeak("foo bar", delegate);
-        ArgumentCaptor<SynthesisRequest> req = LittleMock.createCaptor();
-        LittleMock.verify(delegate, LittleMock.times(1)).onSynthesizeText(req.capture(),
-                LittleMock.<SynthesisCallback>anyObject());
+        ArgumentCaptor<SynthesisRequest> req = ArgumentCaptor.forClass(SynthesisRequest.class);
+        Mockito.verify(delegate, Mockito.times(1)).onSynthesizeText(req.capture(),
+                Mockito.<SynthesisCallback>anyObject());
 
         assertEquals(defaultLocale.getISO3Language(), req.getValue().getLanguage());
         assertEquals(defaultLocale.getISO3Country(), req.getValue().getCountry());
@@ -185,8 +188,8 @@
     private void blockingCallSpeak(String speech, IDelegate mock) throws
             InterruptedException {
         final CountDownLatch latch = new CountDownLatch(1);
-        doCountDown(latch).when(mock).onSynthesizeText(LittleMock.<SynthesisRequest>anyObject(),
-                LittleMock.<SynthesisCallback>anyObject());
+        doCountDown(latch).when(mock).onSynthesizeText(Mockito.<SynthesisRequest>anyObject(),
+                Mockito.<SynthesisCallback>anyObject());
         mTts.speak(speech, TextToSpeech.QUEUE_ADD, null);
 
         awaitCountDown(latch, 5, TimeUnit.SECONDS);
@@ -194,7 +197,7 @@
 
     private void blockingInitAndVerify(final String engine, int errorCode) throws
             InterruptedException {
-        TextToSpeech.OnInitListener listener = LittleMock.mock(
+        TextToSpeech.OnInitListener listener = Mockito.mock(
                 TextToSpeech.OnInitListener.class);
 
         final CountDownLatch latch = new CountDownLatch(1);
@@ -206,18 +209,18 @@
         awaitCountDown(latch, 5, TimeUnit.SECONDS);
     }
 
-    public interface CountDownBehaviour extends Behaviour {
+    public static abstract class CountDownBehaviour extends StubberImpl {
         /** Used to mock methods that return a result. */
-        Behaviour andReturn(Object result);
+        public abstract Stubber andReturn(Object result);
     }
 
     public static CountDownBehaviour doCountDown(final CountDownLatch latch) {
         return new CountDownBehaviour() {
             @Override
             public <T> T when(T mock) {
-                return LittleMock.doAnswer(new Callable<Void>() {
+                return Mockito.doAnswer(new Answer<Void>() {
                     @Override
-                    public Void call() throws Exception {
+                    public Void answer(InvocationOnMock invocation) throws Exception {
                         latch.countDown();
                         return null;
                     }
@@ -225,13 +228,13 @@
             }
 
             @Override
-            public Behaviour andReturn(final Object result) {
-                return new Behaviour() {
+            public Stubber andReturn(final Object result) {
+                return new StubberImpl() {
                     @Override
                     public <T> T when(T mock) {
-                        return LittleMock.doAnswer(new Callable<Object>() {
+                        return Mockito.doAnswer(new Answer<Object>() {
                             @Override
-                            public Object call() throws Exception {
+                            public Object answer(InvocationOnMock invocation) throws Exception {
                                 latch.countDown();
                                 return result;
                             }
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/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
index 8c6740c..43c95f4 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
@@ -650,6 +650,20 @@
         return null;
     }
 
+    @LayoutlibDelegate
+    /*package*/ static boolean nativeIsSRGB(long nativeBitmap) {
+        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
+                "Color spaces are not supported", null /*data*/);
+        return false;
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static boolean nativeGetColorSpace(long nativePtr, float[] xyz, float[] params) {
+        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
+                "Color spaces are not supported", null /*data*/);
+        return false;
+    }
+
     // ---- Private delegate/helper methods ----
 
     private Bitmap_Delegate(BufferedImage image, Config config) {
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.
diff --git a/wifi/java/android/net/wifi/aware/DiscoverySession.java b/wifi/java/android/net/wifi/aware/DiscoverySession.java
index 59fe1ee..156c3fd 100644
--- a/wifi/java/android/net/wifi/aware/DiscoverySession.java
+++ b/wifi/java/android/net/wifi/aware/DiscoverySession.java
@@ -116,6 +116,7 @@
             Log.w(TAG, "terminate: already terminated.");
             return;
         }
+
         mTerminated = true;
         mMgr.clear();
         mCloseGuard.close();
@@ -172,15 +173,15 @@
         if (mTerminated) {
             Log.w(TAG, "sendMessage: called on terminated session");
             return;
-        } else {
-            WifiAwareManager mgr = mMgr.get();
-            if (mgr == null) {
-                Log.w(TAG, "sendMessage: called post GC on WifiAwareManager");
-                return;
-            }
-
-            mgr.sendMessage(mClientId, mSessionId, peerHandle, message, messageId, retryCount);
         }
+
+        WifiAwareManager mgr = mMgr.get();
+        if (mgr == null) {
+            Log.w(TAG, "sendMessage: called post GC on WifiAwareManager");
+            return;
+        }
+
+        mgr.sendMessage(mClientId, mSessionId, peerHandle, message, messageId, retryCount);
     }
 
     /**
@@ -235,15 +236,15 @@
         if (mTerminated) {
             Log.w(TAG, "startRanging: called on terminated session");
             return;
-        } else {
-            WifiAwareManager mgr = mMgr.get();
-            if (mgr == null) {
-                Log.w(TAG, "startRanging: called post GC on WifiAwareManager");
-                return;
-            }
-
-            mgr.startRanging(mClientId, mSessionId, params, listener);
         }
+
+        WifiAwareManager mgr = mMgr.get();
+        if (mgr == null) {
+            Log.w(TAG, "startRanging: called post GC on WifiAwareManager");
+            return;
+        }
+
+        mgr.startRanging(mClientId, mSessionId, params, listener);
     }
 
     /**
@@ -261,6 +262,9 @@
      * <p>
      * Note: per the Wi-Fi Aware specification the roles are fixed - a Subscriber is an INITIATOR
      * and a Publisher is a RESPONDER.
+     * <p>
+     * To set up an encrypted link use the {@link #createNetworkSpecifierPmk(PeerHandle, byte[])}
+     * or {@link #createNetworkSpecifierPassphrase(PeerHandle, String)} APIs.
      *
      * @param peerHandle The peer's handle obtained through
      * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, byte[], java.util.List)}
@@ -282,19 +286,19 @@
         if (mTerminated) {
             Log.w(TAG, "createNetworkSpecifierOpen: called on terminated session");
             return null;
-        } else {
-            WifiAwareManager mgr = mMgr.get();
-            if (mgr == null) {
-                Log.w(TAG, "createNetworkSpecifierOpen: called post GC on WifiAwareManager");
-                return null;
-            }
-
-            int role = this instanceof SubscribeDiscoverySession
-                    ? WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
-                    : WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER;
-
-            return mgr.createNetworkSpecifier(mClientId, role, mSessionId, peerHandle, null);
         }
+
+        WifiAwareManager mgr = mMgr.get();
+        if (mgr == null) {
+            Log.w(TAG, "createNetworkSpecifierOpen: called post GC on WifiAwareManager");
+            return null;
+        }
+
+        int role = this instanceof SubscribeDiscoverySession
+                ? WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
+                : WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER;
+
+        return mgr.createNetworkSpecifier(mClientId, role, mSessionId, peerHandle, null, null);
     }
 
     /**
@@ -307,8 +311,70 @@
      * discovery or communication (in such scenarios the MAC address of the peer is shielded by
      * an opaque peer ID handle). If a Aware connection is needed to a peer discovered using other
      * OOB (out-of-band) mechanism then use the alternative
-     * {@link WifiAwareSession#createNetworkSpecifierPmk(int, byte[], byte[])} method - which uses the
-     * peer's MAC address.
+     * {@link WifiAwareSession#createNetworkSpecifierPassphrase(int, byte[], String)} method -
+     * which uses the peer's MAC address.
+     * <p>
+     * Note: per the Wi-Fi Aware specification the roles are fixed - a Subscriber is an INITIATOR
+     * and a Publisher is a RESPONDER.
+     *
+     * @param peerHandle The peer's handle obtained through
+     * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
+     * byte[], java.util.List)} or
+     * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
+     * byte[])}. On a RESPONDER this value is used to gate the acceptance of a connection request
+     *                   from only that peer. A RESPONDER may specify a null - indicating that
+     *                   it will accept connection requests from any device.
+     * @param passphrase The passphrase to be used to encrypt the link. The PMK is generated from
+     *                   the passphrase. Use the
+     *                   {@link #createNetworkSpecifierPmk(PeerHandle, byte[])} to specify the
+     *                   PMK directly or {@link #createNetworkSpecifierOpen(PeerHandle)} to
+     *                   specify an open (unencrypted) link.
+     *
+     * @return A string to be used to construct
+     * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
+     * {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
+     * android.net.ConnectivityManager.NetworkCallback)}
+     * [or other varieties of that API].
+     *
+     * * @hide
+     */
+    public String createNetworkSpecifierPassphrase(@Nullable PeerHandle peerHandle,
+            @NonNull String passphrase) {
+        if (passphrase == null || passphrase.length() == 0) {
+            throw new IllegalArgumentException("Passphrase must not be null or empty");
+        }
+
+        if (mTerminated) {
+            Log.w(TAG, "createNetworkSpecifierPassphrase: called on terminated session");
+            return null;
+        }
+
+        WifiAwareManager mgr = mMgr.get();
+        if (mgr == null) {
+            Log.w(TAG, "createNetworkSpecifierPassphrase: called post GC on WifiAwareManager");
+            return null;
+        }
+
+        int role = this instanceof SubscribeDiscoverySession
+                ? WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
+                : WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER;
+
+        return mgr.createNetworkSpecifier(mClientId, role, mSessionId, peerHandle, null,
+                passphrase);
+    }
+
+    /**
+     * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for an
+     * encrypted WiFi Aware connection (link) to the specified peer. The
+     * {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
+     * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
+     * <p>
+     * This method should be used when setting up a connection with a peer discovered through Aware
+     * discovery or communication (in such scenarios the MAC address of the peer is shielded by
+     * an opaque peer ID handle). If a Aware connection is needed to a peer discovered using other
+     * OOB (out-of-band) mechanism then use the alternative
+     * {@link WifiAwareSession#createNetworkSpecifierPmk(int, byte[], byte[])} method - which uses
+     * the peer's MAC address.
      * <p>
      * Note: per the Wi-Fi Aware specification the roles are fixed - a Subscriber is an INITIATOR
      * and a Publisher is a RESPONDER.
@@ -322,8 +388,9 @@
      *                   it will accept connection requests from any device.
      * @param pmk A PMK (pairwise master key, see IEEE 802.11i) specifying the key to use for
      *            encrypting the data-path. Use the
-     *            {@link #createNetworkSpecifierOpen(PeerHandle)} to specify an open (unencrypted)
-     *            link.
+     *            {@link #createNetworkSpecifierPassphrase(PeerHandle, String)} to specify a
+     *            Passphrase or {@link #createNetworkSpecifierOpen(PeerHandle)} to specify an
+     *            open (unencrypted) link.
      *
      * @return A string to be used to construct
      * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
@@ -342,19 +409,19 @@
         if (mTerminated) {
             Log.w(TAG, "createNetworkSpecifierPmk: called on terminated session");
             return null;
-        } else {
-            WifiAwareManager mgr = mMgr.get();
-            if (mgr == null) {
-                Log.w(TAG, "createNetworkSpecifierPmk: called post GC on WifiAwareManager");
-                return null;
-            }
-
-            int role = this instanceof SubscribeDiscoverySession
-                    ? WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
-                    : WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER;
-
-            return mgr.createNetworkSpecifier(mClientId, role, mSessionId, peerHandle, pmk);
         }
+
+        WifiAwareManager mgr = mMgr.get();
+        if (mgr == null) {
+            Log.w(TAG, "createNetworkSpecifierPmk: called post GC on WifiAwareManager");
+            return null;
+        }
+
+        int role = this instanceof SubscribeDiscoverySession
+                ? WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
+                : WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER;
+
+        return mgr.createNetworkSpecifier(mClientId, role, mSessionId, peerHandle, pmk, null);
     }
 
     /**
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
index 3d784ba..7b6805c 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -130,26 +130,26 @@
      */
 
     /**
-     * TYPE: in band, specific peer: role, client_id, session_id, peer_id, pmk optional
+     * TYPE: in band, specific peer: role, client_id, session_id, peer_id, pmk/passphrase optional
      * @hide
      */
     public static final int NETWORK_SPECIFIER_TYPE_IB = 0;
 
     /**
-     * TYPE: in band, any peer: role, client_id, session_id, pmk optional
+     * TYPE: in band, any peer: role, client_id, session_id, pmk/passphrase optional
      * [only permitted for RESPONDER]
      * @hide
      */
     public static final int NETWORK_SPECIFIER_TYPE_IB_ANY_PEER = 1;
 
     /**
-     * TYPE: out-of-band: role, client_id, peer_mac, pmk optional
+     * TYPE: out-of-band: role, client_id, peer_mac, pmk/passphrase optional
      * @hide
      */
     public static final int NETWORK_SPECIFIER_TYPE_OOB = 2;
 
     /**
-     * TYPE: out-of-band, any peer: role, client_id, pmk optional
+     * TYPE: out-of-band, any peer: role, client_id, pmk/passphrase optional
      * [only permitted for RESPONDER]
      * @hide
      */
@@ -180,6 +180,9 @@
     /** @hide */
     public static final String NETWORK_SPECIFIER_KEY_PMK = "pmk";
 
+    /** @hide */
+    public static final String NETWORK_SPECIFIER_KEY_PASSPHRASE = "passphrase";
+
     /**
      * Broadcast intent action to indicate that the state of Wi-Fi Aware availability has changed.
      * Use the {@link #isAvailable()} to query the current status.
@@ -473,11 +476,12 @@
 
     /** @hide */
     public String createNetworkSpecifier(int clientId, int role, int sessionId,
-            PeerHandle peerHandle, @Nullable byte[] pmk) {
+            PeerHandle peerHandle, @Nullable byte[] pmk, @Nullable String passphrase) {
         if (VDBG) {
             Log.v(TAG, "createNetworkSpecifier: role=" + role + ", sessionId=" + sessionId
                     + ", peerHandle=" + ((peerHandle == null) ? peerHandle : peerHandle.peerId)
-                    + ", pmk=" + ((pmk == null) ? "null" : "non-null"));
+                    + ", pmk=" + ((pmk == null) ? "null" : "non-null")
+                    + ", passphrase=" + ((passphrase == null) ? "null" : "non-null"));
         }
 
         int type = (peerHandle == null) ? NETWORK_SPECIFIER_TYPE_IB_ANY_PEER
@@ -512,6 +516,11 @@
             }
             json.put(NETWORK_SPECIFIER_KEY_PMK,
                     Base64.encodeToString(pmk, 0, pmk.length, Base64.DEFAULT));
+            if (passphrase == null) {
+                passphrase = new String();
+            }
+            json.put(NETWORK_SPECIFIER_KEY_PASSPHRASE, passphrase);
+
         } catch (JSONException e) {
             return "";
         }
@@ -521,10 +530,11 @@
 
     /** @hide */
     public String createNetworkSpecifier(int clientId, @DataPathRole int role,
-            @Nullable byte[] peer, @Nullable byte[] pmk) {
+            @Nullable byte[] peer, @Nullable byte[] pmk, @Nullable String passphrase) {
         if (VDBG) {
             Log.v(TAG, "createNetworkSpecifier: role=" + role
-                    + ", pmk=" + ((pmk == null) ? "null" : "non-null"));
+                    + ", pmk=" + ((pmk == null) ? "null" : "non-null")
+                    + ", passphrase=" + ((passphrase == null) ? "null" : "non-null"));
         }
 
         int type = (peer == null) ?
@@ -560,6 +570,10 @@
             }
             json.put(NETWORK_SPECIFIER_KEY_PMK,
                     Base64.encodeToString(pmk, 0, pmk.length, Base64.DEFAULT));
+            if (passphrase == null) {
+                passphrase = new String();
+            }
+            json.put(NETWORK_SPECIFIER_KEY_PASSPHRASE, passphrase);
         } catch (JSONException e) {
             return "";
         }
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareSession.java b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
index 856066e..f48f641 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareSession.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
@@ -192,6 +192,9 @@
      *     (out-of-band) discovery. Aware discovery does not provide the MAC address of the peer -
      *     when using Aware discovery use the alternative network specifier method -
      *     {@link DiscoverySession#createNetworkSpecifierOpen(PeerHandle)}.
+     * <p>
+     * To set up an encrypted link use the {@link #createNetworkSpecifierPmk(int, byte[], byte[])}
+     * or {@link #createNetworkSpecifierPassphrase(int, byte[], String)} APIs.
      *
      * @param role  The role of this device:
      *              {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_INITIATOR} or
@@ -220,7 +223,7 @@
             Log.e(TAG, "createNetworkSpecifierOpen: called after termination");
             return "";
         }
-        return mgr.createNetworkSpecifier(mClientId, role, peer, null);
+        return mgr.createNetworkSpecifier(mClientId, role, peer, null, null);
     }
 
     /**
@@ -232,7 +235,56 @@
      *     This API is targeted for applications which can obtain the peer MAC address using OOB
      *     (out-of-band) discovery. Aware discovery does not provide the MAC address of the peer -
      *     when using Aware discovery use the alternative network specifier method -
-     *     {@link DiscoverySession#createNetworkSpecifierPmk(PeerHandle, byte[])}}.
+     *     {@link DiscoverySession#createNetworkSpecifierPassphrase(PeerHandle, String)}.
+     *
+     * @param role  The role of this device:
+     *              {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_INITIATOR} or
+     *              {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_RESPONDER}
+     * @param peer  The MAC address of the peer's Aware discovery interface. On a RESPONDER this
+     *              value is used to gate the acceptance of a connection request from only that
+     *              peer. A RESPONDER may specify a null - indicating that it will accept
+     *              connection requests from any device.
+     * @param passphrase The passphrase to be used to encrypt the link. The PMK is generated from
+     *                   the passphrase. Use the
+     *                   {@link #createNetworkSpecifierPmk(int, byte[], byte[])} to specify the
+     *                   PMK directly or {@link #createNetworkSpecifierOpen(int, byte[])} to
+     *                   specify an open (unencrypted) link.
+     *
+     * @return A string to be used to construct
+     * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
+     * {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
+     * android.net.ConnectivityManager.NetworkCallback)}
+     * [or other varieties of that API].
+     *
+     * @hide
+     */
+    public String createNetworkSpecifierPassphrase(@WifiAwareManager.DataPathRole int role,
+            @Nullable byte[] peer, @NonNull String passphrase) {
+        WifiAwareManager mgr = mMgr.get();
+        if (mgr == null) {
+            Log.e(TAG, "createNetworkSpecifierPassphrase: called post GC on WifiAwareManager");
+            return "";
+        }
+        if (mTerminated) {
+            Log.e(TAG, "createNetworkSpecifierPassphrase: called after termination");
+            return "";
+        }
+        if (passphrase == null || passphrase.length() == 0) {
+            throw new IllegalArgumentException("Passphrase must not be null or empty");
+        }
+        return mgr.createNetworkSpecifier(mClientId, role, peer, null, passphrase);
+    }
+
+    /**
+     * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for an
+     * encrypted WiFi Aware connection (link) to the specified peer. The
+     * {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
+     * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
+     * <p>
+     *     This API is targeted for applications which can obtain the peer MAC address using OOB
+     *     (out-of-band) discovery. Aware discovery does not provide the MAC address of the peer -
+     *     when using Aware discovery use the alternative network specifier method -
+     *     {@link DiscoverySession#createNetworkSpecifierPassphrase(PeerHandle, String)}.
      *
      * @param role  The role of this device:
      *              {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_INITIATOR} or
@@ -242,8 +294,10 @@
      *              peer. A RESPONDER may specify a null - indicating that it will accept
      *              connection requests from any device.
      * @param pmk A PMK (pairwise master key, see IEEE 802.11i) specifying the key to use for
-     *            encrypting the data-path. Use the {@link #createNetworkSpecifierOpen(int, byte[])}
-     *            to specify an open (unencrypted) link.
+     *            encrypting the data-path. Use the
+     *            {@link #createNetworkSpecifierPassphrase(int, byte[], String)} to specify a
+     *            Passphrase or {@link #createNetworkSpecifierOpen(int, byte[])} to specify an
+     *            open (unencrypted) link.
      *
      * @return A string to be used to construct
      * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
@@ -267,7 +321,7 @@
         if (pmk == null || pmk.length == 0) {
             throw new IllegalArgumentException("PMK must not be null or empty");
         }
-        return mgr.createNetworkSpecifier(mClientId, role, peer, pmk);
+        return mgr.createNetworkSpecifier(mClientId, role, peer, pmk, null);
     }
 
     /**
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
index 992958b..eceb365 100644
--- a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
@@ -974,6 +974,7 @@
         final PeerHandle peerHandle = new PeerHandle(123412);
         final int role = WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER;
         final byte[] pmk = "Some arbitrary byte array".getBytes();
+        final String passphrase = "A really bad password";
         final ConfigRequest configRequest = new ConfigRequest.Builder().build();
         final PublishConfig publishConfig = new PublishConfig.Builder().build();
 
@@ -1038,6 +1039,23 @@
         collector.checkThat("pmk", pmkB64 ,
                 equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PMK)));
 
+        // (5) request an encrypted (Passphrase) network specifier from the session
+        networkSpecifier = publishSession.getValue().createNetworkSpecifierPassphrase(peerHandle,
+                passphrase);
+
+        // validate format
+        jsonObject = new JSONObject(networkSpecifier);
+        collector.checkThat("role", role,
+                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE)));
+        collector.checkThat("client_id", clientId,
+                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID)));
+        collector.checkThat("session_id", sessionId,
+                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_SESSION_ID)));
+        collector.checkThat("peer_id", peerHandle.peerId,
+                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_ID)));
+        collector.checkThat("passphrase", passphrase,
+                equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PASSPHRASE)));
+
         verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService,
                 mockPublishSession, mockRttListener);
     }
@@ -1053,6 +1071,7 @@
         final byte[] someMac = HexEncoding.decode("000102030405".toCharArray(), false);
         final int role = WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR;
         final byte[] pmk = "Some arbitrary pmk data".getBytes();
+        final String passphrase = "A really bad password";
 
         String pmkB64 = Base64.encodeToString(pmk, Base64.DEFAULT);
 
@@ -1101,6 +1120,21 @@
         collector.checkThat("pmk", pmkB64,
                 equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PMK)));
 
+        // (4) request an encrypted (Passphrase) direct network specifier
+        networkSpecifier = session.createNetworkSpecifierPassphrase(role, someMac, passphrase);
+
+        // validate format
+        jsonObject = new JSONObject(networkSpecifier);
+        collector.checkThat("role", role,
+                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE)));
+        collector.checkThat("client_id", clientId,
+                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID)));
+        collector.checkThat("peer_mac", someMac, equalTo(HexEncoding.decode(
+                jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_MAC).toCharArray(),
+                false)));
+        collector.checkThat("passphrase", passphrase,
+                equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PASSPHRASE)));
+
         verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService,
                 mockPublishSession, mockRttListener);
     }