Merge "Fix ModelFile.isPreferredTo method"
diff --git a/Android.bp b/Android.bp
index 092f548..abeeb43 100644
--- a/Android.bp
+++ b/Android.bp
@@ -570,7 +570,6 @@
         "telephony/java/com/android/internal/telephony/IOnSubscriptionsChangedListener.aidl",
         "telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl",
         "telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl",
-        "telephony/java/com/android/internal/telephony/IRcs.aidl",
         "telephony/java/com/android/internal/telephony/ISms.aidl",
         "telephony/java/com/android/internal/telephony/ISub.aidl",
         "telephony/java/com/android/internal/telephony/IAns.aidl",
@@ -601,6 +600,7 @@
         "telephony/java/com/android/internal/telephony/euicc/ISetDefaultSmdpAddressCallback.aidl",
         "telephony/java/com/android/internal/telephony/euicc/ISetNicknameCallback.aidl",
         "telephony/java/com/android/internal/telephony/euicc/ISwitchToProfileCallback.aidl",
+        "telephony/java/com/android/internal/telephony/rcs/IRcs.aidl",
         "wifi/java/android/net/wifi/INetworkRequestMatchCallback.aidl",
         "wifi/java/android/net/wifi/INetworkRequestUserSelectionCallback.aidl",
         "wifi/java/android/net/wifi/ISoftApCallback.aidl",
diff --git a/api/current.txt b/api/current.txt
index 83b08a7..cde7499 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -740,6 +740,7 @@
     field public static final int immersive = 16843456; // 0x10102c0
     field public static final int importantForAccessibility = 16843690; // 0x10103aa
     field public static final int importantForAutofill = 16844120; // 0x1010558
+    field public static final int importantForContentCapture = 16844182; // 0x1010596
     field public static final int inAnimation = 16843127; // 0x1010177
     field public static final int includeFontPadding = 16843103; // 0x101015f
     field public static final int includeInGlobalSearch = 16843374; // 0x101026e
@@ -7580,6 +7581,8 @@
     method public java.lang.String getShortcutId();
     method public long getTimeStamp();
     field public static final int CONFIGURATION_CHANGE = 5; // 0x5
+    field public static final int FOREGROUND_SERVICE_START = 19; // 0x13
+    field public static final int FOREGROUND_SERVICE_STOP = 20; // 0x14
     field public static final int KEYGUARD_HIDDEN = 18; // 0x12
     field public static final int KEYGUARD_SHOWN = 17; // 0x11
     field public static final int MOVE_TO_BACKGROUND = 2; // 0x2
@@ -7597,9 +7600,11 @@
     method public void add(android.app.usage.UsageStats);
     method public int describeContents();
     method public long getFirstTimeStamp();
+    method public long getLastTimeForegroundServiceUsed();
     method public long getLastTimeStamp();
     method public long getLastTimeUsed();
     method public java.lang.String getPackageName();
+    method public long getTotalTimeForegroundServiceUsed();
     method public long getTotalTimeInForeground();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.app.usage.UsageStats> CREATOR;
@@ -9470,6 +9475,7 @@
 
   public abstract class Context {
     ctor public Context();
+    method public abstract boolean bindIsolatedService(android.content.Intent, android.content.ServiceConnection, int, java.lang.String);
     method public abstract boolean bindService(android.content.Intent, android.content.ServiceConnection, int);
     method public abstract int checkCallingOrSelfPermission(java.lang.String);
     method public abstract int checkCallingOrSelfUriPermission(android.net.Uri, int);
@@ -9681,6 +9687,7 @@
   public class ContextWrapper extends android.content.Context {
     ctor public ContextWrapper(android.content.Context);
     method protected void attachBaseContext(android.content.Context);
+    method public boolean bindIsolatedService(android.content.Intent, android.content.ServiceConnection, int, java.lang.String);
     method public boolean bindService(android.content.Intent, android.content.ServiceConnection, int);
     method public int checkCallingOrSelfPermission(java.lang.String);
     method public int checkCallingOrSelfUriPermission(android.net.Uri, int);
@@ -16628,6 +16635,8 @@
     field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR = 3; // 0x3
     field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG = 2; // 0x2
     field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG = 1; // 0x1
+    field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_MONO = 5; // 0x5
+    field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_NIR = 6; // 0x6
     field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB = 4; // 0x4
     field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB = 0; // 0x0
     field public static final int SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME = 1; // 0x1
@@ -20712,6 +20721,51 @@
     enum_constant public static final android.icu.text.TimeZoneNames.NameType SHORT_STANDARD;
   }
 
+  public abstract class Transliterator {
+    method public static final android.icu.text.Transliterator createFromRules(java.lang.String, java.lang.String, int);
+    method public void filteredTransliterate(android.icu.text.Replaceable, android.icu.text.Transliterator.Position, boolean);
+    method public final void finishTransliteration(android.icu.text.Replaceable, android.icu.text.Transliterator.Position);
+    method public static final java.util.Enumeration<java.lang.String> getAvailableIDs();
+    method public static final java.util.Enumeration<java.lang.String> getAvailableSources();
+    method public static final java.util.Enumeration<java.lang.String> getAvailableTargets(java.lang.String);
+    method public static final java.util.Enumeration<java.lang.String> getAvailableVariants(java.lang.String, java.lang.String);
+    method public static final java.lang.String getDisplayName(java.lang.String);
+    method public static java.lang.String getDisplayName(java.lang.String, java.util.Locale);
+    method public static java.lang.String getDisplayName(java.lang.String, android.icu.util.ULocale);
+    method public android.icu.text.Transliterator[] getElements();
+    method public final android.icu.text.UnicodeFilter getFilter();
+    method public final java.lang.String getID();
+    method public static final android.icu.text.Transliterator getInstance(java.lang.String);
+    method public static android.icu.text.Transliterator getInstance(java.lang.String, int);
+    method public final android.icu.text.Transliterator getInverse();
+    method public final int getMaximumContextLength();
+    method public final android.icu.text.UnicodeSet getSourceSet();
+    method public android.icu.text.UnicodeSet getTargetSet();
+    method public void setFilter(android.icu.text.UnicodeFilter);
+    method public java.lang.String toRules(boolean);
+    method public final int transliterate(android.icu.text.Replaceable, int, int);
+    method public final void transliterate(android.icu.text.Replaceable);
+    method public final java.lang.String transliterate(java.lang.String);
+    method public final void transliterate(android.icu.text.Replaceable, android.icu.text.Transliterator.Position, java.lang.String);
+    method public final void transliterate(android.icu.text.Replaceable, android.icu.text.Transliterator.Position, int);
+    method public final void transliterate(android.icu.text.Replaceable, android.icu.text.Transliterator.Position);
+    field public static final int FORWARD = 0; // 0x0
+    field public static final int REVERSE = 1; // 0x1
+  }
+
+  public static class Transliterator.Position {
+    ctor public Transliterator.Position();
+    ctor public Transliterator.Position(int, int, int);
+    ctor public Transliterator.Position(int, int, int, int);
+    ctor public Transliterator.Position(android.icu.text.Transliterator.Position);
+    method public void set(android.icu.text.Transliterator.Position);
+    method public final void validate(int);
+    field public int contextLimit;
+    field public int contextStart;
+    field public int limit;
+    field public int start;
+  }
+
   public abstract class UCharacterIterator implements java.lang.Cloneable {
     ctor protected UCharacterIterator();
     method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
@@ -42089,7 +42143,7 @@
     field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000
     field public static final int CAPABILITY_CAN_PULL_CALL = 16777216; // 0x1000000
     field public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 4194304; // 0x400000
-    field public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 524288; // 0x80000
+    field public static final deprecated int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 524288; // 0x80000
     field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000
     field public static final int CAPABILITY_HOLD = 1; // 0x1
     field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80
@@ -42509,6 +42563,7 @@
     method public android.telecom.PhoneAccount getPhoneAccount(android.telecom.PhoneAccountHandle);
     method public java.util.List<android.telecom.PhoneAccountHandle> getSelfManagedPhoneAccounts();
     method public android.telecom.PhoneAccountHandle getSimCallManager();
+    method public java.lang.String getSystemDialerPackage();
     method public java.lang.String getVoiceMailNumber(android.telecom.PhoneAccountHandle);
     method public boolean handleMmi(java.lang.String);
     method public boolean handleMmi(java.lang.String, android.telecom.PhoneAccountHandle);
@@ -43271,6 +43326,7 @@
 
   public class PhoneStateListener {
     ctor public PhoneStateListener();
+    ctor public PhoneStateListener(java.util.concurrent.Executor);
     method public void onCallForwardingIndicatorChanged(boolean);
     method public void onCallStateChanged(int, java.lang.String);
     method public void onCellInfoChanged(java.util.List<android.telephony.CellInfo>);
@@ -43629,6 +43685,7 @@
     method public int getNetworkType();
     method public int getPhoneCount();
     method public int getPhoneType();
+    method public int getPreferredOpportunisticDataSubscription();
     method public android.telephony.ServiceState getServiceState();
     method public android.telephony.SignalStrength getSignalStrength();
     method public int getSimCarrierId();
@@ -43678,6 +43735,7 @@
     method public boolean setNetworkSelectionModeManual(java.lang.String, boolean);
     method public boolean setOperatorBrandOverride(java.lang.String);
     method public boolean setPreferredNetworkTypeToGlobal();
+    method public boolean setPreferredOpportunisticDataSubscription(int);
     method public void setVisualVoicemailSmsFilterSettings(android.telephony.VisualVoicemailSmsFilterSettings);
     method public boolean setVoiceMailNumber(java.lang.String, java.lang.String);
     method public deprecated void setVoicemailRingtoneUri(android.telecom.PhoneAccountHandle, android.net.Uri);
@@ -48791,6 +48849,7 @@
     method public int getId();
     method public int getImportantForAccessibility();
     method public int getImportantForAutofill();
+    method public int getImportantForContentCapture();
     method public boolean getKeepScreenOn();
     method public android.view.KeyEvent.DispatcherState getKeyDispatcherState();
     method public int getLabelFor();
@@ -48924,6 +48983,7 @@
     method public boolean isHovered();
     method public boolean isImportantForAccessibility();
     method public final boolean isImportantForAutofill();
+    method public final boolean isImportantForContentCapture();
     method public boolean isInEditMode();
     method public boolean isInLayout();
     method public boolean isInTouchMode();
@@ -48998,6 +49058,7 @@
     method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
     method public void onProvideAutofillStructure(android.view.ViewStructure, int);
     method public void onProvideAutofillVirtualStructure(android.view.ViewStructure, int);
+    method public boolean onProvideContentCaptureStructure(android.view.ViewStructure, int);
     method public void onProvideStructure(android.view.ViewStructure);
     method public void onProvideVirtualStructure(android.view.ViewStructure);
     method public android.view.PointerIcon onResolvePointerIcon(android.view.MotionEvent, int);
@@ -49116,6 +49177,7 @@
     method public void setId(int);
     method public void setImportantForAccessibility(int);
     method public void setImportantForAutofill(int);
+    method public void setImportantForContentCapture(int);
     method public void setKeepScreenOn(boolean);
     method public void setKeyboardNavigationCluster(boolean);
     method public void setLabelFor(int);
@@ -49286,6 +49348,11 @@
     field public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 8; // 0x8
     field public static final int IMPORTANT_FOR_AUTOFILL_YES = 1; // 0x1
     field public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 4; // 0x4
+    field public static final int IMPORTANT_FOR_CONTENT_CAPTURE_AUTO = 0; // 0x0
+    field public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO = 2; // 0x2
+    field public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS = 8; // 0x8
+    field public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES = 1; // 0x1
+    field public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS = 4; // 0x4
     field public static final int INVISIBLE = 4; // 0x4
     field public static final int KEEP_SCREEN_ON = 67108864; // 0x4000000
     field public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
@@ -51740,6 +51807,10 @@
     method public void disableContentCapture();
     method public android.content.ComponentName getIntelligenceServiceComponentName();
     method public boolean isContentCaptureEnabled();
+    method public android.view.ViewStructure newVirtualViewStructure(android.view.autofill.AutofillId, int);
+    method public void notifyViewAppeared(android.view.ViewStructure);
+    method public void notifyViewDisappeared(android.view.autofill.AutofillId);
+    method public void notifyViewTextChanged(android.view.autofill.AutofillId, java.lang.CharSequence, int);
     field public static final int FLAG_USER_INPUT = 1; // 0x1
   }
 
@@ -52053,6 +52124,7 @@
   public final class TextLinks implements android.os.Parcelable {
     method public int apply(android.text.Spannable, int, java.util.function.Function<android.view.textclassifier.TextLinks.TextLink, android.view.textclassifier.TextLinks.TextLinkSpan>);
     method public int describeContents();
+    method public android.os.Bundle getExtras();
     method public java.util.Collection<android.view.textclassifier.TextLinks.TextLink> getLinks();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int APPLY_STRATEGY_IGNORE = 0; // 0x0
@@ -52069,12 +52141,14 @@
     method public android.view.textclassifier.TextLinks.Builder addLink(int, int, java.util.Map<java.lang.String, java.lang.Float>);
     method public android.view.textclassifier.TextLinks build();
     method public android.view.textclassifier.TextLinks.Builder clearTextLinks();
+    method public android.view.textclassifier.TextLinks.Builder setExtras(android.os.Bundle);
   }
 
   public static final class TextLinks.Request implements android.os.Parcelable {
     method public int describeContents();
     method public android.os.LocaleList getDefaultLocales();
     method public android.view.textclassifier.TextClassifier.EntityConfig getEntityConfig();
+    method public android.os.Bundle getExtras();
     method public java.lang.CharSequence getText();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.view.textclassifier.TextLinks.Request> CREATOR;
@@ -52085,6 +52159,7 @@
     method public android.view.textclassifier.TextLinks.Request build();
     method public android.view.textclassifier.TextLinks.Request.Builder setDefaultLocales(android.os.LocaleList);
     method public android.view.textclassifier.TextLinks.Request.Builder setEntityConfig(android.view.textclassifier.TextClassifier.EntityConfig);
+    method public android.view.textclassifier.TextLinks.Request.Builder setExtras(android.os.Bundle);
   }
 
   public static final class TextLinks.TextLink implements android.os.Parcelable {
@@ -52109,6 +52184,7 @@
     method public float getConfidenceScore(java.lang.String);
     method public java.lang.String getEntity(int);
     method public int getEntityCount();
+    method public android.os.Bundle getExtras();
     method public java.lang.String getId();
     method public int getSelectionEndIndex();
     method public int getSelectionStartIndex();
@@ -52120,6 +52196,7 @@
     ctor public TextSelection.Builder(int, int);
     method public android.view.textclassifier.TextSelection build();
     method public android.view.textclassifier.TextSelection.Builder setEntityType(java.lang.String, float);
+    method public android.view.textclassifier.TextSelection.Builder setExtras(android.os.Bundle);
     method public android.view.textclassifier.TextSelection.Builder setId(java.lang.String);
   }
 
@@ -52127,6 +52204,7 @@
     method public int describeContents();
     method public android.os.LocaleList getDefaultLocales();
     method public int getEndIndex();
+    method public android.os.Bundle getExtras();
     method public int getStartIndex();
     method public java.lang.CharSequence getText();
     method public void writeToParcel(android.os.Parcel, int);
@@ -52137,6 +52215,7 @@
     ctor public TextSelection.Request.Builder(java.lang.CharSequence, int, int);
     method public android.view.textclassifier.TextSelection.Request build();
     method public android.view.textclassifier.TextSelection.Request.Builder setDefaultLocales(android.os.LocaleList);
+    method public android.view.textclassifier.TextSelection.Request.Builder setExtras(android.os.Bundle);
   }
 
 }
@@ -54271,6 +54350,7 @@
     method public int getSourceWidth();
     method public int getWidth();
     method public float getZoom();
+    method public boolean isForcePositionWithinWindowSystemInsetsBounds();
     method public void setZoom(float);
     method public void show(float, float);
     method public void show(float, float, float, float);
@@ -54283,6 +54363,7 @@
     method public android.widget.Magnifier.Builder setCornerRadius(float);
     method public android.widget.Magnifier.Builder setDefaultSourceToMagnifierOffset(int, int);
     method public android.widget.Magnifier.Builder setElevation(float);
+    method public android.widget.Magnifier.Builder setForcePositionWithinWindowSystemInsetsBounds(boolean);
     method public android.widget.Magnifier.Builder setSize(int, int);
     method public android.widget.Magnifier.Builder setZoom(float);
   }
diff --git a/api/system-current.txt b/api/system-current.txt
index e0c58b4..2c2df81 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4109,8 +4109,12 @@
   }
 
   public final class PowerManager {
+    method public int getPowerSaveMode();
+    method public boolean setDynamicPowerSavings(boolean, int);
     method public boolean setPowerSaveMode(boolean);
     method public void userActivity(long, int, int);
+    field public static final int POWER_SAVER_MODE_DYNAMIC = 1; // 0x1
+    field public static final int POWER_SAVER_MODE_PERCENTAGE = 0; // 0x0
     field public static final int USER_ACTIVITY_EVENT_ACCESSIBILITY = 3; // 0x3
     field public static final int USER_ACTIVITY_EVENT_BUTTON = 1; // 0x1
     field public static final int USER_ACTIVITY_EVENT_OTHER = 0; // 0x0
@@ -4541,10 +4545,6 @@
   public final class Settings {
     field public static final java.lang.String ACTION_ENTERPRISE_PRIVACY_SETTINGS = "android.settings.ENTERPRISE_PRIVACY_SETTINGS";
     field public static final java.lang.String ACTION_SHOW_ADMIN_SUPPORT_DETAILS = "android.settings.SHOW_ADMIN_SUPPORT_DETAILS";
-    field public static final int USER_SETUP_PERSONALIZATION_COMPLETE = 10; // 0xa
-    field public static final int USER_SETUP_PERSONALIZATION_NOT_STARTED = 0; // 0x0
-    field public static final int USER_SETUP_PERSONALIZATION_PAUSED = 2; // 0x2
-    field public static final int USER_SETUP_PERSONALIZATION_STARTED = 1; // 0x1
   }
 
   public static final class Settings.Global extends android.provider.Settings.NameValueTable {
@@ -4588,6 +4588,10 @@
     field public static final java.lang.String LOCK_SCREEN_SHOW_NOTIFICATIONS = "lock_screen_show_notifications";
     field public static final java.lang.String MANUAL_RINGER_TOGGLE_COUNT = "manual_ringer_toggle_count";
     field public static final java.lang.String USER_SETUP_COMPLETE = "user_setup_complete";
+    field public static final int USER_SETUP_PERSONALIZATION_COMPLETE = 10; // 0xa
+    field public static final int USER_SETUP_PERSONALIZATION_NOT_STARTED = 0; // 0x0
+    field public static final int USER_SETUP_PERSONALIZATION_PAUSED = 2; // 0x2
+    field public static final int USER_SETUP_PERSONALIZATION_STARTED = 1; // 0x1
     field public static final java.lang.String USER_SETUP_PERSONALIZATION_STATE = "user_setup_personalization_state";
     field public static final java.lang.String VOLUME_HUSH_GESTURE = "volume_hush_gesture";
   }
@@ -5427,15 +5431,21 @@
     method public int getAllPhoneAccountsCount();
     method public int getCallState();
     method public android.telecom.PhoneAccountHandle getConnectionManager();
+    method public int getCurrentTtyMode();
     method public deprecated android.content.ComponentName getDefaultPhoneApp();
     method public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsForPackage();
     method public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsSupportingScheme(java.lang.String);
     method public boolean isInEmergencyCall();
     method public boolean isRinging();
     method public boolean isTtySupported();
+    method public boolean setDefaultDialer(java.lang.String);
     field public static final java.lang.String EXTRA_CALL_BACK_INTENT = "android.telecom.extra.CALL_BACK_INTENT";
     field public static final java.lang.String EXTRA_CLEAR_MISSED_CALLS_INTENT = "android.telecom.extra.CLEAR_MISSED_CALLS_INTENT";
     field public static final java.lang.String EXTRA_CONNECTION_SERVICE = "android.telecom.extra.CONNECTION_SERVICE";
+    field public static final int TTY_MODE_FULL = 1; // 0x1
+    field public static final int TTY_MODE_HCO = 2; // 0x2
+    field public static final int TTY_MODE_OFF = 0; // 0x0
+    field public static final int TTY_MODE_VCO = 3; // 0x3
   }
 
 }
@@ -6999,8 +7009,8 @@
     field public static final int TYPE_ACTIVITY_RESUMED = 2; // 0x2
     field public static final int TYPE_ACTIVITY_STARTED = 1; // 0x1
     field public static final int TYPE_ACTIVITY_STOPPED = 4; // 0x4
-    field public static final int TYPE_VIEW_ADDED = 5; // 0x5
-    field public static final int TYPE_VIEW_REMOVED = 6; // 0x6
+    field public static final int TYPE_VIEW_APPEARED = 5; // 0x5
+    field public static final int TYPE_VIEW_DISAPPEARED = 6; // 0x6
     field public static final int TYPE_VIEW_TEXT_CHANGED = 7; // 0x7
   }
 
@@ -7400,6 +7410,7 @@
     method public default void onMovedToDisplay(int, android.content.res.Configuration);
     method public abstract void onOverScrolled(int, int, boolean, boolean);
     method public default void onProvideAutofillVirtualStructure(android.view.ViewStructure, int);
+    method public default boolean onProvideContentCaptureStructure(android.view.ViewStructure, int);
     method public abstract void onProvideVirtualStructure(android.view.ViewStructure);
     method public abstract void onScrollChanged(int, int, int, int);
     method public abstract void onSizeChanged(int, int, int, int);
diff --git a/api/test-current.txt b/api/test-current.txt
index 8b8c542..5531014 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -25,6 +25,10 @@
 
 package android.app {
 
+  public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.view.View.OnCreateContextMenuListener android.view.Window.Callback {
+    method public void onMovedToDisplay(int, android.content.res.Configuration);
+  }
+
   public class ActivityManager {
     method public void addOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener, int);
     method public void alwaysShowUnsupportedCompileSdkWarning(android.content.ComponentName);
@@ -710,6 +714,7 @@
 
   public class Environment {
     method public static java.io.File buildPath(java.io.File, java.lang.String...);
+    method public static java.io.File getProductDirectory();
     method public static java.io.File getStorageDirectory();
   }
 
@@ -739,7 +744,11 @@
   }
 
   public final class PowerManager {
+    method public int getPowerSaveMode();
+    method public boolean setDynamicPowerSavings(boolean, int);
     method public boolean setPowerSaveMode(boolean);
+    field public static final int POWER_SAVER_MODE_DYNAMIC = 1; // 0x1
+    field public static final int POWER_SAVER_MODE_PERCENTAGE = 0; // 0x0
   }
 
   public class Process {
@@ -976,6 +985,9 @@
 
   public static final class Settings.Global extends android.provider.Settings.NameValueTable {
     field public static final java.lang.String AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES = "autofill_compat_mode_allowed_packages";
+    field public static final java.lang.String AUTOMATIC_POWER_SAVER_MODE = "automatic_power_saver_mode";
+    field public static final java.lang.String DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD = "dynamic_power_savings_disable_threshold";
+    field public static final java.lang.String DYNAMIC_POWER_SAVINGS_ENABLED = "dynamic_power_savings_enabled";
     field public static final java.lang.String HIDDEN_API_BLACKLIST_EXEMPTIONS = "hidden_api_blacklist_exemptions";
     field public static final java.lang.String LOCATION_GLOBAL_KILL_SWITCH = "location_global_kill_switch";
     field public static final java.lang.String LOW_POWER_MODE = "low_power";
@@ -1591,6 +1603,7 @@
 
   public class KeyEvent extends android.view.InputEvent implements android.os.Parcelable {
     method public static java.lang.String actionToString(int);
+    method public final void setDisplayId(int);
     field public static final int LAST_KEYCODE = 288; // 0x120
   }
 
@@ -1637,9 +1650,9 @@
   }
 
   public abstract interface WindowManager implements android.view.ViewManager {
-    method public abstract void setShouldShowIme(int, boolean);
-    method public abstract void setShouldShowWithInsecureKeyguard(int, boolean);
-    method public abstract void setShouldShowSystemDecors(int, boolean);
+    method public default void setShouldShowIme(int, boolean);
+    method public default void setShouldShowSystemDecors(int, boolean);
+    method public default void setShouldShowWithInsecureKeyguard(int, boolean);
   }
 
   public static class WindowManager.LayoutParams extends android.view.ViewGroup.LayoutParams implements android.os.Parcelable {
diff --git a/cmds/idmap2/idmap2/Scan.cpp b/cmds/idmap2/idmap2/Scan.cpp
index 33c274e..00c49e3 100644
--- a/cmds/idmap2/idmap2/Scan.cpp
+++ b/cmds/idmap2/idmap2/Scan.cpp
@@ -138,7 +138,8 @@
   std::stringstream stream;
   for (auto iter = interesting_apks.cbegin(); iter != interesting_apks.cend(); ++iter) {
     const std::string idmap_path = Idmap::CanonicalIdmapPathFor(output_directory, *iter);
-    if (!Verify(std::vector<std::string>({"--idmap-path", idmap_path}), out_error) &&
+    std::stringstream dev_null;
+    if (!Verify(std::vector<std::string>({"--idmap-path", idmap_path}), dev_null) &&
         !Create(std::vector<std::string>({
                     "--target-apk-path",
                     target_apk_path,
diff --git a/cmds/sm/src/com/android/commands/sm/Sm.java b/cmds/sm/src/com/android/commands/sm/Sm.java
index c6d717a..783c8c4 100644
--- a/cmds/sm/src/com/android/commands/sm/Sm.java
+++ b/cmds/sm/src/com/android/commands/sm/Sm.java
@@ -127,6 +127,8 @@
             filterType = VolumeInfo.TYPE_PRIVATE;
         } else if ("emulated".equals(filter)) {
             filterType = VolumeInfo.TYPE_EMULATED;
+        } else if ("stub".equals(filter)) {
+            filterType = VolumeInfo.TYPE_STUB;
         } else {
             filterType = -1;
         }
@@ -314,7 +316,7 @@
 
     private static int showUsage() {
         System.err.println("usage: sm list-disks [adoptable]");
-        System.err.println("       sm list-volumes [public|private|emulated|all]");
+        System.err.println("       sm list-volumes [public|private|emulated|stub|all]");
         System.err.println("       sm has-adoptable");
         System.err.println("       sm get-primary-storage-uuid");
         System.err.println("       sm set-force-adoptable [on|off|default]");
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index a3cd8a3..0114ff4 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -72,6 +72,7 @@
         "src/external/StatsPuller.cpp",
         "src/external/StatsCompanionServicePuller.cpp",
         "src/external/SubsystemSleepStatePuller.cpp",
+        "src/external/PowerStatsPuller.cpp",
         "src/external/ResourceHealthManagerPuller.cpp",
         "src/external/ResourceThermalManagerPuller.cpp",
         "src/external/StatsPullerManager.cpp",
@@ -134,6 +135,7 @@
         "android.hardware.health@2.0",
         "android.hardware.power@1.0",
         "android.hardware.power@1.1",
+        "android.hardware.power.stats@1.0",
         "android.hardware.thermal@1.0",
         "libpackagelistparser",
         "libsysutils",
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index eb498f5..a981997 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -370,11 +370,9 @@
     // This skips the uid map if it's an empty config.
     if (it->second->getNumMetrics() > 0) {
         uint64_t uidMapToken = proto->start(FIELD_TYPE_MESSAGE | FIELD_ID_UID_MAP);
-        if (it->second->hashStringInReport()) {
-            mUidMap->appendUidMap(dumpTimeStampNs, key, &str_set, proto);
-        } else {
-            mUidMap->appendUidMap(dumpTimeStampNs, key, nullptr, proto);
-        }
+        mUidMap->appendUidMap(
+                dumpTimeStampNs, key, it->second->hashStringInReport() ? &str_set : nullptr,
+                it->second->versionStringsInReport(), it->second->installerInReport(), proto);
         proto->end(uidMapToken);
     }
 
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 27685fc..7fa05be 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -787,21 +787,24 @@
 }
 
 Status StatsService::informAllUidData(const vector<int32_t>& uid, const vector<int64_t>& version,
-                                      const vector<String16>& app) {
+                                      const vector<String16>& version_string,
+                                      const vector<String16>& app,
+                                      const vector<String16>& installer) {
     ENFORCE_UID(AID_SYSTEM);
 
     VLOG("StatsService::informAllUidData was called");
-    mUidMap->updateMap(getElapsedRealtimeNs(), uid, version, app);
+    mUidMap->updateMap(getElapsedRealtimeNs(), uid, version, version_string, app, installer);
     VLOG("StatsService::informAllUidData succeeded");
 
     return Status::ok();
 }
 
-Status StatsService::informOnePackage(const String16& app, int32_t uid, int64_t version) {
+Status StatsService::informOnePackage(const String16& app, int32_t uid, int64_t version,
+                                      const String16& version_string, const String16& installer) {
     ENFORCE_UID(AID_SYSTEM);
 
     VLOG("StatsService::informOnePackage was called");
-    mUidMap->updateApp(getElapsedRealtimeNs(), app, uid, version);
+    mUidMap->updateApp(getElapsedRealtimeNs(), app, uid, version, version_string, installer);
     return Status::ok();
 }
 
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index 4a5f05f..cd4d601 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -73,8 +73,10 @@
     virtual Status informAlarmForSubscriberTriggeringFired();
 
     virtual Status informAllUidData(const vector<int32_t>& uid, const vector<int64_t>& version,
-                                    const vector<String16>& app);
-    virtual Status informOnePackage(const String16& app, int32_t uid, int64_t version);
+                                    const vector<String16>& version_string,
+                                    const vector<String16>& app, const vector<String16>& installer);
+    virtual Status informOnePackage(const String16& app, int32_t uid, int64_t version,
+                                    const String16& version_string, const String16& installer);
     virtual Status informOnePackageRemoved(const String16& app, int32_t uid);
     virtual Status informDeviceShutdown();
 
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 5620184..53d9673 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -147,6 +147,7 @@
         PhoneStateChanged phone_state_changed = 95;
         UserRestrictionChanged user_restriction_changed = 96;
         SettingsUIChanged settings_ui_changed = 97;
+        ConnectivityStateChanged connectivity_state_changed = 98;
     }
 
     // Pulled events will start at field 10000.
@@ -190,6 +191,7 @@
         ProcessCpuTime process_cpu_time = 10035;
         NativeProcessMemoryState native_process_memory_state = 10036;
         CpuTimePerThreadFreq cpu_time_per_thread_freq = 10037;
+        OnDevicePowerMeasurement on_device_power_measurement = 10038;
     }
 
     // DO NOT USE field numbers above 100,000 in AOSP.
@@ -2128,6 +2130,22 @@
     optional int64 visible_millis = 16;
 }
 
+/*
+ * Logs when a connection becomes available and lost.
+ * Logged in StatsCompanionService.java
+ */
+message ConnectivityStateChanged {
+    // Id of the network.
+    optional int32 net_id = 1;
+
+    enum State {
+        UNKNOWN = 0;
+        CONNECTED = 1;
+        DISCONNECTED = 2;
+    }
+    // Connected state of a network.
+    optional State state = 2;
+}
 
 //////////////////////////////////////////////////////////////////////
 // Pulled atoms below this line //
@@ -2262,6 +2280,27 @@
 }
 
 /**
+ * Pulls on-device power measurement information.
+ * Data defined by hardware/interfaces/power/stats/1.0/types.hal.
+ * Pulled from:
+ *   frameworks/base/cmds/statsd/src/external/PowerStatsPuller.cpp
+ */
+message OnDevicePowerMeasurement {
+    // Name of the subsystem (to which the rail belongs).
+    optional string subsystem_name = 1;
+
+    // Rail name. The rail lies within the subsystem.
+    optional string rail_name = 2;
+
+    // Time (in ms since boot) at which the rail energy value was measured.
+    // This may differ slightly from the time that statsd logs this information.
+    optional uint64 measurement_timestamp_millis = 3;
+
+    // Accumulated energy used via the rail since device boot in uWs.
+    optional uint64 energy_microwatt_secs = 4;
+}
+
+/**
  * Pulls Cpu time per frequency.
  * Pulls the time the cpu spend on the frequency index. Frequency index
  * starts from highest to lowest. The value should be monotonically
diff --git a/cmds/statsd/src/external/PowerStatsPuller.cpp b/cmds/statsd/src/external/PowerStatsPuller.cpp
new file mode 100644
index 0000000..71e5fa0
--- /dev/null
+++ b/cmds/statsd/src/external/PowerStatsPuller.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#define DEBUG false  // STOPSHIP if true
+#include "Log.h"
+
+#include <android/hardware/power/stats/1.0/IPowerStats.h>
+
+#include <vector>
+
+#include "PowerStatsPuller.h"
+#include "stats_log_util.h"
+
+using android::hardware::hidl_vec;
+using android::hardware::power::stats::V1_0::IPowerStats;
+using android::hardware::power::stats::V1_0::EnergyData;
+using android::hardware::power::stats::V1_0::RailInfo;
+using android::hardware::power::stats::V1_0::Status;
+using android::hardware::Return;
+using android::hardware::Void;
+
+using std::make_shared;
+using std::shared_ptr;
+
+namespace android {
+namespace os {
+namespace statsd {
+
+sp<android::hardware::power::stats::V1_0::IPowerStats> gPowerStatsHal = nullptr;
+std::mutex gPowerStatsHalMutex;
+bool gPowerStatsExist = true; // Initialized to ensure making a first attempt.
+std::vector<RailInfo> gRailInfo;
+
+bool getPowerStatsHal() {
+    if (gPowerStatsHal == nullptr && gPowerStatsExist) {
+        gPowerStatsHal = android::hardware::power::stats::V1_0::IPowerStats::getService();
+        if (gPowerStatsHal == nullptr) {
+            ALOGW("Couldn't load power.stats HAL service");
+            gPowerStatsExist = false;
+        }
+    }
+    return gPowerStatsHal != nullptr;
+}
+
+PowerStatsPuller::PowerStatsPuller() : StatsPuller(android::util::ON_DEVICE_POWER_MEASUREMENT) {
+}
+
+bool PowerStatsPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) {
+    std::lock_guard<std::mutex> lock(gPowerStatsHalMutex);
+
+    if (!getPowerStatsHal()) {
+        ALOGE("power.stats Hal not loaded");
+        return false;
+    }
+
+    int64_t wallClockTimestampNs = getWallClockNs();
+    int64_t elapsedTimestampNs = getElapsedRealtimeNs();
+
+    data->clear();
+
+    // Pull getRailInfo if necessary
+    if (gRailInfo.empty()) {
+        bool resultSuccess = true;
+        Return<void> ret = gPowerStatsHal->getRailInfo(
+                [&resultSuccess](const hidl_vec<RailInfo> &list, Status status) {
+                    resultSuccess = (status == Status::SUCCESS || status == Status::NOT_SUPPORTED);
+                    if (status != Status::SUCCESS) return;
+
+                    gRailInfo.reserve(list.size());
+                    for (size_t i = 0; i < list.size(); ++i) {
+                        gRailInfo.push_back(list[i]);
+                    }
+                });
+        if (!resultSuccess || !ret.isOk()) {
+            ALOGE("power.stats getRailInfo() failed. Description: %s", ret.description().c_str());
+            gPowerStatsHal = nullptr;
+            return false;
+        }
+        // If SUCCESS but empty, or if NOT_SUPPORTED, then never try again.
+        if (gRailInfo.empty()) {
+            ALOGE("power.stats has no rail information");
+            gPowerStatsExist = false; // No rail info, so never try again.
+            return false;
+        }
+    }
+
+    // Pull getEnergyData and write the data out
+    const hidl_vec<uint32_t> desiredRailIndices; // Empty vector indicates we want all.
+    bool resultSuccess = true;
+    Return<void> ret = gPowerStatsHal->getEnergyData(desiredRailIndices,
+                [&data, wallClockTimestampNs, elapsedTimestampNs, &resultSuccess]
+                (hidl_vec<EnergyData> energyDataList, Status status) {
+                    resultSuccess = (status == Status::SUCCESS);
+                    if (!resultSuccess) return;
+
+                    for (size_t i = 0; i < energyDataList.size(); i++) {
+                        const EnergyData& energyData = energyDataList[i];
+
+                        if (energyData.index >= gRailInfo.size()) {
+                            ALOGE("power.stats getEnergyData() returned an invalid rail index %u.",
+                                    energyData.index);
+                            resultSuccess = false;
+                            return;
+                        }
+                        const RailInfo& rail = gRailInfo[energyData.index];
+
+                        auto ptr = make_shared<LogEvent>(android::util::ON_DEVICE_POWER_MEASUREMENT,
+                              wallClockTimestampNs, elapsedTimestampNs);
+                        ptr->write(rail.subsysName);
+                        ptr->write(rail.railName);
+                        ptr->write(energyData.timestamp);
+                        ptr->write(energyData.energy);
+                        ptr->init();
+                        data->push_back(ptr);
+
+                        VLOG("power.stat: %s.%s: %llu, %llu",
+                             rail.subsysName.c_str(),
+                             rail.railName.c_str(),
+                             (unsigned long long)energyData.timestamp,
+                             (unsigned long long)energyData.energy);
+                    }
+                });
+    if (!resultSuccess || !ret.isOk()) {
+        ALOGE("power.stats getEnergyData() failed. Description: %s", ret.description().c_str());
+        gPowerStatsHal = nullptr;
+        return false;
+    }
+    return true;
+}
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
diff --git a/telephony/java/com/android/internal/telephony/IRcs.aidl b/cmds/statsd/src/external/PowerStatsPuller.h
similarity index 63%
copy from telephony/java/com/android/internal/telephony/IRcs.aidl
copy to cmds/statsd/src/external/PowerStatsPuller.h
index ede8695..dd5ff8f 100644
--- a/telephony/java/com/android/internal/telephony/IRcs.aidl
+++ b/cmds/statsd/src/external/PowerStatsPuller.h
@@ -14,8 +14,23 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony;
+#pragma once
 
-interface IRcs {
-    void deleteThread(int threadId);
-}
\ No newline at end of file
+#include "StatsPuller.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+/**
+ * Reads hal for power.stats
+ */
+class PowerStatsPuller : public StatsPuller {
+public:
+    PowerStatsPuller();
+    bool PullInternal(vector<std::shared_ptr<LogEvent>>* data) override;
+};
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 9633980..8378ae1 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -26,6 +26,7 @@
 #include "../logd/LogEvent.h"
 #include "../stats_log_util.h"
 #include "../statscompanion_util.h"
+#include "PowerStatsPuller.h"
 #include "ResourceHealthManagerPuller.h"
 #include "ResourceThermalManagerPuller.h"
 #include "StatsCompanionServicePuller.h"
@@ -86,6 +87,9 @@
         // subsystem_sleep_state
         {android::util::SUBSYSTEM_SLEEP_STATE,
          {{}, {}, 1 * NS_PER_SEC, new SubsystemSleepStatePuller()}},
+        // on_device_power_measurement
+        {android::util::ON_DEVICE_POWER_MEASUREMENT,
+         {{}, {}, 1 * NS_PER_SEC, new PowerStatsPuller()}},
         // cpu_time_per_freq
         {android::util::CPU_TIME_PER_FREQ,
          {{3},
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index febb922..625294c 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -156,9 +156,6 @@
             FieldValue(Field(mTagId, getSimpleField(1)), Value(speakerImpedance.speakerLocation)));
     mValues.push_back(
             FieldValue(Field(mTagId, getSimpleField(2)), Value(speakerImpedance.milliOhms)));
-    if (!mValues.empty()) {
-        mValues.back().mField.decorateLastPos(1);
-    }
 }
 
 LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
@@ -173,9 +170,6 @@
             FieldValue(Field(mTagId, getSimpleField(2)), Value(hardwareFailed.hardwareLocation)));
     mValues.push_back(
             FieldValue(Field(mTagId, getSimpleField(3)), Value(int32_t(hardwareFailed.errorCode))));
-    if (!mValues.empty()) {
-        mValues.back().mField.decorateLastPos(1);
-    }
 }
 
 LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
@@ -190,9 +184,6 @@
             FieldValue(Field(mTagId, getSimpleField(2)), Value(physicalDropDetected.accelPeak)));
     mValues.push_back(FieldValue(Field(mTagId, getSimpleField(3)),
                                  Value(physicalDropDetected.freefallDuration)));
-    if (!mValues.empty()) {
-        mValues.back().mField.decorateLastPos(1);
-    }
 }
 
 LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
@@ -205,10 +196,6 @@
         mValues.push_back(FieldValue(Field(mTagId, getSimpleField(i + 1)),
                                      Value(chargeCycles.cycleBucket[i])));
     }
-
-    if (!mValues.empty()) {
-        mValues.back().mField.decorateLastPos(1);
-    }
 }
 
 LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
@@ -231,10 +218,6 @@
                                  Value(batteryHealthSnapshotArgs.resistanceMicroOhm)));
     mValues.push_back(FieldValue(Field(mTagId, getSimpleField(7)),
                                  Value(batteryHealthSnapshotArgs.levelPercent)));
-
-    if (!mValues.empty()) {
-        mValues.back().mField.decorateLastPos(1);
-    }
 }
 
 LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs, const SlowIo& slowIo) {
@@ -247,10 +230,6 @@
             FieldValue(Field(mTagId, getSimpleField(1)), Value(int32_t(slowIo.operation))));
     pos[0]++;
     mValues.push_back(FieldValue(Field(mTagId, getSimpleField(2)), Value(slowIo.count)));
-
-    if (!mValues.empty()) {
-        mValues.back().mField.decorateLastPos(1);
-    }
 }
 
 LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
@@ -261,10 +240,6 @@
 
     mValues.push_back(FieldValue(Field(mTagId, getSimpleField(1)),
                                  Value(batteryCausedShutdown.voltageMicroV)));
-
-    if (!mValues.empty()) {
-        mValues.back().mField.decorateLastPos(1);
-    }
 }
 
 LogEvent::LogEvent(int32_t tagId, int64_t timestampNs) : LogEvent(tagId, timestampNs, 0) {}
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 05103a9..461ad28 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -140,7 +140,7 @@
 
     // Adjust start for partial bucket
     mCurrentBucketStartTimeNs = startTimeNs;
-    if (mIsPulled) {
+    if (mIsPulled && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
         pullAndMatchEventsLocked(startTimeNs);
     }
 
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index 5866139..6e3530b 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -80,7 +80,7 @@
         }
         flushCurrentBucketLocked(eventTimeNs);
         mCurrentBucketStartTimeNs = eventTimeNs;
-        if (mIsPulled) {
+        if (mIsPulled && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
             pullAndMatchEventsLocked(eventTimeNs);
         }
     };
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index 4244d5b..ac34f47 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -77,6 +77,8 @@
             mActivationAtomTrackerToMetricMap, mMetricIndexesWithActivation, mNoReportMetricIds);
 
     mHashStringsInReport = config.hash_strings_in_metric_report();
+    mVersionStringsInReport = config.version_strings_in_metric_report();
+    mInstallerInReport = config.installer_in_metric_report();
 
     if (config.allowed_log_source_size() == 0) {
         mConfigValid = false;
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index a4672b6..a31efbd 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -83,6 +83,14 @@
         return mHashStringsInReport;
     };
 
+    inline bool versionStringsInReport() const {
+        return mVersionStringsInReport;
+    };
+
+    inline bool installerInReport() const {
+        return mInstallerInReport;
+    };
+
     void refreshTtl(const int64_t currentTimestampNs) {
         if (mTtlNs > 0) {
             mTtlEndNs = currentTimestampNs + mTtlNs;
@@ -126,6 +134,8 @@
     bool mConfigValid = false;
 
     bool mHashStringsInReport = false;
+    bool mVersionStringsInReport = false;
+    bool mInstallerInReport = false;
 
     const int64_t mTtlNs;
     int64_t mTtlEndNs;
diff --git a/cmds/statsd/src/packages/UidMap.cpp b/cmds/statsd/src/packages/UidMap.cpp
index 37a0067..59f3f04 100644
--- a/cmds/statsd/src/packages/UidMap.cpp
+++ b/cmds/statsd/src/packages/UidMap.cpp
@@ -49,6 +49,10 @@
 const int FIELD_ID_SNAPSHOT_PACKAGE_UID = 3;
 const int FIELD_ID_SNAPSHOT_PACKAGE_DELETED = 4;
 const int FIELD_ID_SNAPSHOT_PACKAGE_NAME_HASH = 5;
+const int FIELD_ID_SNAPSHOT_PACKAGE_VERSION_STRING = 6;
+const int FIELD_ID_SNAPSHOT_PACKAGE_VERSION_STRING_HASH = 7;
+const int FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER = 8;
+const int FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER_HASH = 9;
 const int FIELD_ID_SNAPSHOT_TIMESTAMP = 1;
 const int FIELD_ID_SNAPSHOT_PACKAGE_INFO = 2;
 const int FIELD_ID_SNAPSHOTS = 1;
@@ -60,6 +64,10 @@
 const int FIELD_ID_CHANGE_NEW_VERSION = 5;
 const int FIELD_ID_CHANGE_PREV_VERSION = 6;
 const int FIELD_ID_CHANGE_PACKAGE_HASH = 7;
+const int FIELD_ID_CHANGE_NEW_VERSION_STRING = 8;
+const int FIELD_ID_CHANGE_PREV_VERSION_STRING = 9;
+const int FIELD_ID_CHANGE_NEW_VERSION_STRING_HASH = 10;
+const int FIELD_ID_CHANGE_PREV_VERSION_STRING_HASH = 11;
 
 UidMap::UidMap() : mBytesUsed(0) {}
 
@@ -104,7 +112,8 @@
 }
 
 void UidMap::updateMap(const int64_t& timestamp, const vector<int32_t>& uid,
-                       const vector<int64_t>& versionCode, const vector<String16>& packageName) {
+                       const vector<int64_t>& versionCode, const vector<String16>& versionString,
+                       const vector<String16>& packageName, const vector<String16>& installer) {
     vector<wp<PackageInfoListener>> broadcastList;
     {
         lock_guard<mutex> lock(mMutex);  // Exclusively lock for updates.
@@ -121,7 +130,9 @@
         mMap.clear();
         for (size_t j = 0; j < uid.size(); j++) {
             string package = string(String8(packageName[j]).string());
-            mMap[std::make_pair(uid[j], package)] = AppData(versionCode[j]);
+            mMap[std::make_pair(uid[j], package)] =
+                    AppData(versionCode[j], string(String8(versionString[j]).string()),
+                            string(String8(installer[j]).string()));
         }
 
         for (const auto& kv : deletedApps) {
@@ -150,23 +161,30 @@
 }
 
 void UidMap::updateApp(const int64_t& timestamp, const String16& app_16, const int32_t& uid,
-                       const int64_t& versionCode) {
+                       const int64_t& versionCode, const String16& versionString,
+                       const String16& installer) {
     vector<wp<PackageInfoListener>> broadcastList;
     string appName = string(String8(app_16).string());
     {
         lock_guard<mutex> lock(mMutex);
         int32_t prevVersion = 0;
+        string prevVersionString = "";
+        string newVersionString = string(String8(versionString).string());
         bool found = false;
         auto it = mMap.find(std::make_pair(uid, appName));
         if (it != mMap.end()) {
             found = true;
             prevVersion = it->second.versionCode;
+            prevVersionString = it->second.versionString;
             it->second.versionCode = versionCode;
+            it->second.versionString = newVersionString;
+            it->second.installer = string(String8(installer).string());
             it->second.deleted = false;
         }
         if (!found) {
             // Otherwise, we need to add an app at this uid.
-            mMap[std::make_pair(uid, appName)] = AppData(versionCode);
+            mMap[std::make_pair(uid, appName)] =
+                    AppData(versionCode, newVersionString, string(String8(installer).string()));
         } else {
             // Only notify the listeners if this is an app upgrade. If this app is being installed
             // for the first time, then we don't notify the listeners.
@@ -174,7 +192,8 @@
             // app after deletion.
             getListenerListCopyLocked(&broadcastList);
         }
-        mChanges.emplace_back(false, timestamp, appName, uid, versionCode, prevVersion);
+        mChanges.emplace_back(false, timestamp, appName, uid, versionCode, newVersionString,
+                              prevVersion, prevVersionString);
         mBytesUsed += kBytesChangeRecord;
         ensureBytesUsedBelowLimit();
         StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
@@ -226,10 +245,12 @@
         lock_guard<mutex> lock(mMutex);
 
         int64_t prevVersion = 0;
+        string prevVersionString = "";
         auto key = std::make_pair(uid, app);
         auto it = mMap.find(key);
         if (it != mMap.end() && !it->second.deleted) {
             prevVersion = it->second.versionCode;
+            prevVersionString = it->second.versionString;
             it->second.deleted = true;
             mDeletedApps.push_back(key);
         }
@@ -240,7 +261,7 @@
             mMap.erase(oldest);
             StatsdStats::getInstance().noteUidMapAppDeletionDropped();
         }
-        mChanges.emplace_back(true, timestamp, app, uid, 0, prevVersion);
+        mChanges.emplace_back(true, timestamp, app, uid, 0, "", prevVersion, prevVersionString);
         mBytesUsed += kBytesChangeRecord;
         ensureBytesUsedBelowLimit();
         StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
@@ -315,8 +336,9 @@
     return mBytesUsed;
 }
 
-void UidMap::appendUidMap(const int64_t& timestamp, const ConfigKey& key,
-                          std::set<string> *str_set, ProtoOutputStream* proto) {
+void UidMap::appendUidMap(const int64_t& timestamp, const ConfigKey& key, std::set<string>* str_set,
+                          bool includeVersionStrings, bool includeInstaller,
+                          ProtoOutputStream* proto) {
     lock_guard<mutex> lock(mMutex);  // Lock for updates
 
     for (const ChangeRecord& record : mChanges) {
@@ -330,8 +352,22 @@
                 str_set->insert(record.package);
                 proto->write(FIELD_TYPE_UINT64 | FIELD_ID_CHANGE_PACKAGE_HASH,
                              (long long)Hash64(record.package));
+                if (includeVersionStrings) {
+                    str_set->insert(record.versionString);
+                    proto->write(FIELD_TYPE_UINT64 | FIELD_ID_CHANGE_NEW_VERSION_STRING_HASH,
+                                 (long long)Hash64(record.versionString));
+                    str_set->insert(record.prevVersionString);
+                    proto->write(FIELD_TYPE_UINT64 | FIELD_ID_CHANGE_PREV_VERSION_STRING_HASH,
+                                 (long long)Hash64(record.prevVersionString));
+                }
             } else {
                 proto->write(FIELD_TYPE_STRING | FIELD_ID_CHANGE_PACKAGE, record.package);
+                if (includeVersionStrings) {
+                    proto->write(FIELD_TYPE_STRING | FIELD_ID_CHANGE_NEW_VERSION_STRING,
+                                 record.versionString);
+                    proto->write(FIELD_TYPE_STRING | FIELD_ID_CHANGE_PREV_VERSION_STRING,
+                                 record.prevVersionString);
+                }
             }
 
             proto->write(FIELD_TYPE_INT32 | FIELD_ID_CHANGE_UID, (int)record.uid);
@@ -354,8 +390,26 @@
             str_set->insert(kv.first.second);
             proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_NAME_HASH,
                          (long long)Hash64(kv.first.second));
+            if (includeVersionStrings) {
+                str_set->insert(kv.second.versionString);
+                proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_VERSION_STRING_HASH,
+                             (long long)Hash64(kv.second.versionString));
+            }
+            if (includeInstaller) {
+                str_set->insert(kv.second.installer);
+                proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER_HASH,
+                             (long long)Hash64(kv.second.installer));
+            }
         } else {
             proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_NAME, kv.first.second);
+            if (includeVersionStrings) {
+                proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_VERSION_STRING,
+                             kv.second.versionString);
+            }
+            if (includeInstaller) {
+                proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER,
+                             kv.second.installer);
+            }
         }
 
         proto->write(FIELD_TYPE_INT64 | FIELD_ID_SNAPSHOT_PACKAGE_VERSION,
@@ -391,8 +445,9 @@
 
     for (const auto& kv : mMap) {
         if (!kv.second.deleted) {
-            dprintf(out, "%s, v%" PRId64 " (%i)\n", kv.first.second.c_str(), kv.second.versionCode,
-                    kv.first.first);
+            dprintf(out, "%s, v%" PRId64 ", %s, %s (%i)\n", kv.first.second.c_str(),
+                    kv.second.versionCode, kv.second.versionString.c_str(),
+                    kv.second.installer.c_str(), kv.first.first);
         }
     }
 }
diff --git a/cmds/statsd/src/packages/UidMap.h b/cmds/statsd/src/packages/UidMap.h
index 4598369..75ff507 100644
--- a/cmds/statsd/src/packages/UidMap.h
+++ b/cmds/statsd/src/packages/UidMap.h
@@ -44,12 +44,16 @@
 
 struct AppData {
     int64_t versionCode;
+    string versionString;
+    string installer;
     bool deleted;
 
     // Empty constructor needed for unordered map.
     AppData() {
     }
-    AppData(const int64_t v) : versionCode(v), deleted(false){};
+
+    AppData(const int64_t v, const string& versionString, const string& installer)
+        : versionCode(v), versionString(versionString), installer(installer), deleted(false){};
 };
 
 // When calling appendUidMap, we retrieve all the ChangeRecords since the last
@@ -61,15 +65,20 @@
     const int32_t uid;
     const int64_t version;
     const int64_t prevVersion;
+    const string versionString;
+    const string prevVersionString;
 
     ChangeRecord(const bool isDeletion, const int64_t timestampNs, const string& package,
-                 const int32_t uid, const int64_t version, const int64_t prevVersion)
+                 const int32_t uid, const int64_t version, const string versionString,
+                 const int64_t prevVersion, const string prevVersionString)
         : deletion(isDeletion),
           timestampNs(timestampNs),
           package(package),
           uid(uid),
           version(version),
-          prevVersion(prevVersion) {
+          prevVersion(prevVersion),
+          versionString(versionString),
+          prevVersionString(prevVersionString) {
     }
 };
 
@@ -87,10 +96,12 @@
      * tuple, ie. uid[j] corresponds to packageName[j] with versionCode[j].
      */
     void updateMap(const int64_t& timestamp, const vector<int32_t>& uid,
-                   const vector<int64_t>& versionCode, const vector<String16>& packageName);
+                   const vector<int64_t>& versionCode, const vector<String16>& versionString,
+                   const vector<String16>& packageName, const vector<String16>& installer);
 
     void updateApp(const int64_t& timestamp, const String16& packageName, const int32_t& uid,
-                   const int64_t& versionCode);
+                   const int64_t& versionCode, const String16& versionString,
+                   const String16& installer);
     void removeApp(const int64_t& timestamp, const String16& packageName, const int32_t& uid);
 
     // Returns true if the given uid contains the specified app (eg. com.google.android.gms).
@@ -127,8 +138,9 @@
     // Gets all snapshots and changes that have occurred since the last output.
     // If every config key has received a change or snapshot record, then this
     // record is deleted.
-    void appendUidMap(const int64_t& timestamp, const ConfigKey& key,
-                      std::set<string> *str_set, util::ProtoOutputStream* proto);
+    void appendUidMap(const int64_t& timestamp, const ConfigKey& key, std::set<string>* str_set,
+                      bool includeVersionStrings, bool includeInstaller,
+                      util::ProtoOutputStream* proto);
 
     // Forces the output to be cleared. We still generate a snapshot based on the current state.
     // This results in extra data uploaded but helps us reconstruct the uid mapping on the server
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 5d0f3d1..32ee5af 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -233,6 +233,14 @@
             optional bool deleted = 4;
 
             optional uint64 name_hash = 5;
+
+            optional string version_string = 6;
+
+            optional uint64 version_string_hash = 7;
+
+            optional string installer = 8;
+
+            optional uint64 installer_hash = 9;
         }
         optional int64 elapsed_timestamp_nanos = 1;
 
@@ -250,6 +258,10 @@
         optional int64 new_version = 5;
         optional int64 prev_version = 6;
         optional uint64 app_hash = 7;
+        optional string new_version_string = 8;
+        optional string prev_version_string = 9;
+        optional uint64 new_version_string_hash = 10;
+        optional uint64 prev_version_string_hash = 11;
     }
     repeated Change changes = 2;
 }
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index 5c46a29..f955df2 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -274,6 +274,7 @@
   optional bool use_diff = 12;
 
   enum ValueDirection {
+      UNKNOWN = 0;
       INCREASING = 1;
       DECREASING = 2;
       ANY = 3;
@@ -408,6 +409,10 @@
 
   repeated MetricActivation metric_activation = 17;
 
+  optional bool version_strings_in_metric_report = 18;
+
+  optional bool installer_in_metric_report = 19;
+
   // Field number 1000 is reserved for later use.
   reserved 1000;
 }
diff --git a/cmds/statsd/tests/LogEntryMatcher_test.cpp b/cmds/statsd/tests/LogEntryMatcher_test.cpp
index 4c6671d..2b9528f 100644
--- a/cmds/statsd/tests/LogEntryMatcher_test.cpp
+++ b/cmds/statsd/tests/LogEntryMatcher_test.cpp
@@ -148,8 +148,12 @@
 
     uidMap.updateMap(
             1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
+            {android::String16("v1"), android::String16("v1"), android::String16("v2"),
+             android::String16("v1"), android::String16("v2")},
             {android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
-             android::String16("Pkg2"), android::String16("PkG3")} /* package name list */);
+             android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
+            {android::String16(""), android::String16(""), android::String16(""),
+             android::String16(""), android::String16("")});
 
     EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
     attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
@@ -297,8 +301,12 @@
     UidMap uidMap;
     uidMap.updateMap(
             1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
+            {android::String16("v1"), android::String16("v1"), android::String16("v2"),
+             android::String16("v1"), android::String16("v2")},
             {android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
-             android::String16("Pkg2"), android::String16("PkG3")} /* package name list */);
+             android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
+            {android::String16(""), android::String16(""), android::String16(""),
+             android::String16(""), android::String16("")});
 
     AttributionNodeInternal attribution_node1;
     attribution_node1.set_uid(1111);
@@ -372,8 +380,12 @@
     UidMap uidMap;
     uidMap.updateMap(
             1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
+            {android::String16("v1"), android::String16("v1"), android::String16("v2"),
+             android::String16("v1"), android::String16("v2")},
             {android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
-             android::String16("Pkg2"), android::String16("PkG3")} /* package name list */);
+             android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
+            {android::String16(""), android::String16(""), android::String16(""),
+             android::String16(""), android::String16("")});
 
     AttributionNodeInternal attribution_node1;
     attribution_node1.set_uid(1067);
diff --git a/cmds/statsd/tests/StatsLogProcessor_test.cpp b/cmds/statsd/tests/StatsLogProcessor_test.cpp
index 8864252..355df29 100644
--- a/cmds/statsd/tests/StatsLogProcessor_test.cpp
+++ b/cmds/statsd/tests/StatsLogProcessor_test.cpp
@@ -153,7 +153,8 @@
     // Setup simple config key corresponding to empty config.
     sp<UidMap> m = new UidMap();
     sp<StatsPullerManager> pullerManager = new StatsPullerManager();
-    m->updateMap(1, {1, 2}, {1, 2}, {String16("p1"), String16("p2")});
+    m->updateMap(1, {1, 2}, {1, 2}, {String16("v1"), String16("v2")},
+                 {String16("p1"), String16("p2")}, {String16(""), String16("")});
     sp<AlarmMonitor> anomalyAlarmMonitor;
     sp<AlarmMonitor> subscriberAlarmMonitor;
     int broadcastCount = 0;
@@ -182,7 +183,8 @@
     // Setup simple config key corresponding to empty config.
     sp<UidMap> m = new UidMap();
     sp<StatsPullerManager> pullerManager = new StatsPullerManager();
-    m->updateMap(1, {1, 2}, {1, 2}, {String16("p1"), String16("p2")});
+    m->updateMap(1, {1, 2}, {1, 2}, {String16("v1"), String16("v2")},
+                 {String16("p1"), String16("p2")}, {String16(""), String16("")});
     sp<AlarmMonitor> anomalyAlarmMonitor;
     sp<AlarmMonitor> subscriberAlarmMonitor;
     int broadcastCount = 0;
diff --git a/cmds/statsd/tests/UidMap_test.cpp b/cmds/statsd/tests/UidMap_test.cpp
index 99082cc..f0d9cf1 100644
--- a/cmds/statsd/tests/UidMap_test.cpp
+++ b/cmds/statsd/tests/UidMap_test.cpp
@@ -71,14 +71,20 @@
     vector<int32_t> uids;
     vector<int64_t> versions;
     vector<String16> apps;
+    vector<String16> versionStrings;
+    vector<String16> installers;
 
     uids.push_back(1000);
     uids.push_back(1000);
+    versionStrings.push_back(String16("v1"));
+    versionStrings.push_back(String16("v1"));
+    installers.push_back(String16(""));
+    installers.push_back(String16(""));
     apps.push_back(String16(kApp1.c_str()));
     apps.push_back(String16(kApp2.c_str()));
     versions.push_back(4);
     versions.push_back(5);
-    m.updateMap(1, uids, versions, apps);
+    m.updateMap(1, uids, versions, versionStrings, apps, installers);
     EXPECT_TRUE(m.hasApp(1000, kApp1));
     EXPECT_TRUE(m.hasApp(1000, kApp2));
     EXPECT_FALSE(m.hasApp(1000, "not.app"));
@@ -97,14 +103,20 @@
     vector<int32_t> uids;
     vector<int64_t> versions;
     vector<String16> apps;
+    vector<String16> versionStrings;
+    vector<String16> installers;
 
     uids.push_back(1000);
     uids.push_back(1000);
+    versionStrings.push_back(String16("v1"));
+    versionStrings.push_back(String16("v1"));
+    installers.push_back(String16(""));
+    installers.push_back(String16(""));
     apps.push_back(String16(kApp1.c_str()));
     apps.push_back(String16(kApp2.c_str()));
     versions.push_back(4);
     versions.push_back(5);
-    m.updateMap(1, uids, versions, apps);
+    m.updateMap(1, uids, versions, versionStrings, apps, installers);
 
     std::set<string> name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
     EXPECT_EQ(name_set.size(), 2u);
@@ -112,7 +124,7 @@
     EXPECT_TRUE(name_set.find(kApp2) != name_set.end());
 
     // Update the app1 version.
-    m.updateApp(2, String16(kApp1.c_str()), 1000, 40);
+    m.updateApp(2, String16(kApp1.c_str()), 1000, 40, String16("v40"), String16(""));
     EXPECT_EQ(40, m.getAppVersion(1000, kApp1));
 
     name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
@@ -138,14 +150,15 @@
 
 TEST(UidMapTest, TestUpdateApp) {
     UidMap m;
-    m.updateMap(1, {1000, 1000}, {4, 5}, {String16(kApp1.c_str()), String16(kApp2.c_str())});
+    m.updateMap(1, {1000, 1000}, {4, 5}, {String16("v4"), String16("v5")},
+                {String16(kApp1.c_str()), String16(kApp2.c_str())}, {String16(""), String16("")});
     std::set<string> name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
     EXPECT_EQ(name_set.size(), 2u);
     EXPECT_TRUE(name_set.find(kApp1) != name_set.end());
     EXPECT_TRUE(name_set.find(kApp2) != name_set.end());
 
     // Adds a new name for uid 1000.
-    m.updateApp(2, String16("NeW_aPP1_NAmE"), 1000, 40);
+    m.updateApp(2, String16("NeW_aPP1_NAmE"), 1000, 40, String16("v40"), String16(""));
     name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
     EXPECT_EQ(name_set.size(), 3u);
     EXPECT_TRUE(name_set.find(kApp1) != name_set.end());
@@ -154,7 +167,7 @@
     EXPECT_TRUE(name_set.find("new_app1_name") != name_set.end());
 
     // This name is also reused by another uid 2000.
-    m.updateApp(3, String16("NeW_aPP1_NAmE"), 2000, 1);
+    m.updateApp(3, String16("NeW_aPP1_NAmE"), 2000, 1, String16("v1"), String16(""));
     name_set = m.getAppNamesFromUid(2000, true /* returnNormalized */);
     EXPECT_EQ(name_set.size(), 1u);
     EXPECT_TRUE(name_set.find("NeW_aPP1_NAmE") == name_set.end());
@@ -185,21 +198,26 @@
     vector<int32_t> uids;
     vector<int64_t> versions;
     vector<String16> apps;
+    vector<String16> versionStrings;
+    vector<String16> installers;
     uids.push_back(1000);
     apps.push_back(String16(kApp2.c_str()));
+    versionStrings.push_back(String16("v1"));
+    installers.push_back(String16(""));
     versions.push_back(5);
-    m.updateMap(1, uids, versions, apps);
+    m.updateMap(1, uids, versions, versionStrings, apps, installers);
 
     // Set the last timestamp for this config key to be newer.
     m.mLastUpdatePerConfigKey[config1] = 2;
 
     ProtoOutputStream proto;
-    m.appendUidMap(3, config1, nullptr, &proto);
+    m.appendUidMap(3, config1, nullptr, true, true, &proto);
 
     // Check there's still a uidmap attached this one.
     UidMapping results;
     protoOutputStreamToUidMapping(&proto, &results);
     EXPECT_EQ(1, results.snapshots_size());
+    EXPECT_EQ("v1", results.snapshots(0).package_info(0).version_string());
 }
 
 TEST(UidMapTest, TestRemovedAppRetained) {
@@ -209,15 +227,19 @@
     m.OnConfigUpdated(config1);
     vector<int32_t> uids;
     vector<int64_t> versions;
+    vector<String16> versionStrings;
+    vector<String16> installers;
     vector<String16> apps;
     uids.push_back(1000);
     apps.push_back(String16(kApp2.c_str()));
     versions.push_back(5);
-    m.updateMap(1, uids, versions, apps);
+    versionStrings.push_back(String16("v5"));
+    installers.push_back(String16(""));
+    m.updateMap(1, uids, versions, versionStrings, apps, installers);
     m.removeApp(2, String16(kApp2.c_str()), 1000);
 
     ProtoOutputStream proto;
-    m.appendUidMap(3, config1, nullptr, &proto);
+    m.appendUidMap(3, config1, nullptr, true, true, &proto);
 
     // Snapshot should still contain this item as deleted.
     UidMapping results;
@@ -233,30 +255,34 @@
     m.OnConfigUpdated(config1);
     vector<int32_t> uids;
     vector<int64_t> versions;
+    vector<String16> versionStrings;
+    vector<String16> installers;
     vector<String16> apps;
     const int maxDeletedApps = StatsdStats::kMaxDeletedAppsInUidMap;
     for (int j = 0; j < maxDeletedApps + 10; j++) {
         uids.push_back(j);
         apps.push_back(String16(kApp1.c_str()));
         versions.push_back(j);
+        versionStrings.push_back(String16("v"));
+        installers.push_back(String16(""));
     }
-    m.updateMap(1, uids, versions, apps);
+    m.updateMap(1, uids, versions, versionStrings, apps, installers);
 
     // First, verify that we have the expected number of items.
     UidMapping results;
     ProtoOutputStream proto;
-    m.appendUidMap(3, config1, nullptr, &proto);
+    m.appendUidMap(3, config1, nullptr, true, true, &proto);
     protoOutputStreamToUidMapping(&proto, &results);
     EXPECT_EQ(maxDeletedApps + 10, results.snapshots(0).package_info_size());
 
     // Now remove all the apps.
-    m.updateMap(1, uids, versions, apps);
+    m.updateMap(1, uids, versions, versionStrings, apps, installers);
     for (int j = 0; j < maxDeletedApps + 10; j++) {
         m.removeApp(4, String16(kApp1.c_str()), j);
     }
 
     proto.clear();
-    m.appendUidMap(5, config1, nullptr, &proto);
+    m.appendUidMap(5, config1, nullptr, true, true, &proto);
     // Snapshot drops the first nine items.
     protoOutputStreamToUidMapping(&proto, &results);
     EXPECT_EQ(maxDeletedApps, results.snapshots(0).package_info_size());
@@ -272,6 +298,8 @@
 
     vector<int32_t> uids;
     vector<int64_t> versions;
+    vector<String16> versionStrings;
+    vector<String16> installers;
     vector<String16> apps;
     uids.push_back(1000);
     uids.push_back(1000);
@@ -279,45 +307,49 @@
     apps.push_back(String16(kApp2.c_str()));
     versions.push_back(4);
     versions.push_back(5);
-    m.updateMap(1, uids, versions, apps);
+    versionStrings.push_back(String16("v4"));
+    versionStrings.push_back(String16("v5"));
+    installers.push_back(String16(""));
+    installers.push_back(String16(""));
+    m.updateMap(1, uids, versions, versionStrings, apps, installers);
 
     ProtoOutputStream proto;
-    m.appendUidMap(2, config1, nullptr, &proto);
+    m.appendUidMap(2, config1, nullptr, true, true, &proto);
     UidMapping results;
     protoOutputStreamToUidMapping(&proto, &results);
     EXPECT_EQ(1, results.snapshots_size());
 
     // We have to keep at least one snapshot in memory at all times.
     proto.clear();
-    m.appendUidMap(2, config1, nullptr, &proto);
+    m.appendUidMap(2, config1, nullptr, true, true, &proto);
     protoOutputStreamToUidMapping(&proto, &results);
     EXPECT_EQ(1, results.snapshots_size());
 
     // Now add another configuration.
     m.OnConfigUpdated(config2);
-    m.updateApp(5, String16(kApp1.c_str()), 1000, 40);
+    m.updateApp(5, String16(kApp1.c_str()), 1000, 40, String16("v40"), String16(""));
     EXPECT_EQ(1U, m.mChanges.size());
     proto.clear();
-    m.appendUidMap(6, config1, nullptr, &proto);
+    m.appendUidMap(6, config1, nullptr, true, true, &proto);
     protoOutputStreamToUidMapping(&proto, &results);
     EXPECT_EQ(1, results.snapshots_size());
     EXPECT_EQ(1, results.changes_size());
     EXPECT_EQ(1U, m.mChanges.size());
 
     // Add another delta update.
-    m.updateApp(7, String16(kApp2.c_str()), 1001, 41);
+    m.updateApp(7, String16(kApp2.c_str()), 1001, 41, String16("v41"), String16(""));
     EXPECT_EQ(2U, m.mChanges.size());
 
     // We still can't remove anything.
     proto.clear();
-    m.appendUidMap(8, config1, nullptr, &proto);
+    m.appendUidMap(8, config1, nullptr, true, true, &proto);
     protoOutputStreamToUidMapping(&proto, &results);
     EXPECT_EQ(1, results.snapshots_size());
     EXPECT_EQ(1, results.changes_size());
     EXPECT_EQ(2U, m.mChanges.size());
 
     proto.clear();
-    m.appendUidMap(9, config2, nullptr, &proto);
+    m.appendUidMap(9, config2, nullptr, true, true, &proto);
     protoOutputStreamToUidMapping(&proto, &results);
     EXPECT_EQ(1, results.snapshots_size());
     EXPECT_EQ(2, results.changes_size());
@@ -335,19 +367,23 @@
     vector<int32_t> uids;
     vector<int64_t> versions;
     vector<String16> apps;
+    vector<String16> versionStrings;
+    vector<String16> installers;
     uids.push_back(1000);
     apps.push_back(String16(kApp1.c_str()));
     versions.push_back(1);
-    m.updateMap(1, uids, versions, apps);
+    versionStrings.push_back(String16("v1"));
+    installers.push_back(String16(""));
+    m.updateMap(1, uids, versions, versionStrings, apps, installers);
 
-    m.updateApp(3, String16(kApp1.c_str()), 1000, 40);
+    m.updateApp(3, String16(kApp1.c_str()), 1000, 40, String16("v40"), String16(""));
 
     ProtoOutputStream proto;
     vector<uint8_t> bytes;
-    m.appendUidMap(2, config1, nullptr, &proto);
+    m.appendUidMap(2, config1, nullptr, true, true, &proto);
     size_t prevBytes = m.mBytesUsed;
 
-    m.appendUidMap(4, config1, nullptr, &proto);
+    m.appendUidMap(4, config1, nullptr, true, true, &proto);
     EXPECT_TRUE(m.mBytesUsed < prevBytes);
 }
 
@@ -361,21 +397,27 @@
     size_t startBytes = m.mBytesUsed;
     vector<int32_t> uids;
     vector<int64_t> versions;
+    vector<String16> versionStrings;
+    vector<String16> installers;
     vector<String16> apps;
     for (int i = 0; i < 100; i++) {
         uids.push_back(1);
         buf = "EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY." + to_string(i);
         apps.push_back(String16(buf.c_str()));
         versions.push_back(1);
+        versionStrings.push_back(String16("v1"));
+        installers.push_back(String16(""));
     }
-    m.updateMap(1, uids, versions, apps);
+    m.updateMap(1, uids, versions, versionStrings, apps, installers);
 
-    m.updateApp(3, String16("EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY.0"), 1000, 2);
+    m.updateApp(3, String16("EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY.0"), 1000, 2,
+                String16("v2"), String16(""));
     EXPECT_EQ(1U, m.mChanges.size());
 
     // Now force deletion by limiting the memory to hold one delta change.
-    m.maxBytesOverride = 80; // Since the app string alone requires >45 characters.
-    m.updateApp(5, String16("EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY.0"), 1000, 4);
+    m.maxBytesOverride = 120; // Since the app string alone requires >45 characters.
+    m.updateApp(5, String16("EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY.0"), 1000, 4,
+                String16("v4"), String16(""));
     EXPECT_EQ(1U, m.mChanges.size());
 }
 
diff --git a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
index 5c47af7..a9841c9 100644
--- a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
@@ -69,8 +69,10 @@
     // Here it assumes that GMS core has two uids.
     processor->getUidMap()->updateMap(
             1, {222, 444, 111, 333}, {1, 1, 2, 2},
+            {String16("v1"), String16("v1"), String16("v2"), String16("v2")},
             {String16("com.android.gmscore"), String16("com.android.gmscore"), String16("app1"),
-             String16("APP3")});
+             String16("APP3")},
+            {String16(""), String16(""), String16(""), String16("")});
 
     // GMS core node is in the middle.
     std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
@@ -215,8 +217,10 @@
     // Here it assumes that GMS core has two uids.
     processor->getUidMap()->updateMap(
             1, {222, 444, 111, 333}, {1, 1, 2, 2},
+            {String16("v1"), String16("v1"), String16("v2"), String16("v2")},
             {String16("com.android.gmscore"), String16("com.android.gmscore"), String16("app1"),
-             String16("APP3")});
+             String16("APP3")},
+            {String16(""), String16(""), String16(""), String16("")});
 
     // GMS core node is in the middle.
     std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
diff --git a/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp b/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
index 3cb553f..2b0285b 100644
--- a/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
@@ -132,7 +132,8 @@
     service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
     // This is a new installation, so there shouldn't be a split (should be same as the without
     // split case).
-    service.mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2);
+    service.mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
+                               String16(""));
     // Goes into the second bucket.
     service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
 
@@ -145,11 +146,13 @@
     SendConfig(service, MakeConfig());
     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
                                              // initialized with.
-    service.mUidMap->updateMap(start, {1}, {1}, {String16(kApp1.c_str())});
+    service.mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
+                               {String16("")});
 
     // Force the uidmap to update at timestamp 2.
     service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
-    service.mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2);
+    service.mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
+                               String16(""));
     // Goes into the second bucket.
     service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
 
@@ -168,7 +171,8 @@
     SendConfig(service, MakeConfig());
     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
                                              // initialized with.
-    service.mUidMap->updateMap(start, {1}, {1}, {String16(kApp1.c_str())});
+    service.mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
+                               {String16("")});
 
     // Force the uidmap to update at timestamp 2.
     service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
@@ -189,13 +193,14 @@
 TEST(PartialBucketE2eTest, TestValueMetricWithoutMinPartialBucket) {
     StatsService service(nullptr);
     // Partial buckets don't occur when app is first installed.
-    service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1);
+    service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""));
     SendConfig(service, MakeValueMetricConfig(0));
     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
                                              // initialized with.
 
     service.mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
-    service.mUidMap->updateApp(5 * 60 * NS_PER_SEC + start + 2, String16(kApp1.c_str()), 1, 2);
+    service.mUidMap->updateApp(5 * 60 * NS_PER_SEC + start + 2, String16(kApp1.c_str()), 1, 2,
+                               String16("v2"), String16(""));
 
     ConfigMetricsReport report =
             GetReports(service.mProcessor, 5 * 60 * NS_PER_SEC + start + 100, true);
@@ -206,14 +211,15 @@
 TEST(PartialBucketE2eTest, TestValueMetricWithMinPartialBucket) {
     StatsService service(nullptr);
     // Partial buckets don't occur when app is first installed.
-    service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1);
+    service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""));
     SendConfig(service, MakeValueMetricConfig(60 * NS_PER_SEC /* One minute */));
     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
                                              // initialized with.
 
     const int64_t endSkipped = 5 * 60 * NS_PER_SEC + start + 2;
     service.mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
-    service.mUidMap->updateApp(endSkipped, String16(kApp1.c_str()), 1, 2);
+    service.mUidMap->updateApp(endSkipped, String16(kApp1.c_str()), 1, 2, String16("v2"),
+                               String16(""));
 
     ConfigMetricsReport report =
             GetReports(service.mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC, true);
@@ -229,13 +235,14 @@
 TEST(PartialBucketE2eTest, TestGaugeMetricWithoutMinPartialBucket) {
     StatsService service(nullptr);
     // Partial buckets don't occur when app is first installed.
-    service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1);
+    service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""));
     SendConfig(service, MakeGaugeMetricConfig(0));
     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
                                              // initialized with.
 
     service.mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
-    service.mUidMap->updateApp(5 * 60 * NS_PER_SEC + start + 2, String16(kApp1.c_str()), 1, 2);
+    service.mUidMap->updateApp(5 * 60 * NS_PER_SEC + start + 2, String16(kApp1.c_str()), 1, 2,
+                               String16("v2"), String16(""));
 
     ConfigMetricsReport report =
             GetReports(service.mProcessor, 5 * 60 * NS_PER_SEC + start + 100, true);
@@ -246,14 +253,15 @@
 TEST(PartialBucketE2eTest, TestGaugeMetricWithMinPartialBucket) {
     StatsService service(nullptr);
     // Partial buckets don't occur when app is first installed.
-    service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1);
+    service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""));
     SendConfig(service, MakeGaugeMetricConfig(60 * NS_PER_SEC /* One minute */));
     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
                                              // initialized with.
 
     const int64_t endSkipped = 5 * 60 * NS_PER_SEC + start + 2;
     service.mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
-    service.mUidMap->updateApp(endSkipped, String16(kApp1.c_str()), 1, 2);
+    service.mUidMap->updateApp(endSkipped, String16(kApp1.c_str()), 1, 2, String16("v2"),
+                               String16(""));
 
     ConfigMetricsReport report =
             GetReports(service.mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC, true);
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 0997566..39b327c 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -441,6 +441,8 @@
 Landroid/hardware/location/IContextHubService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/location/IContextHubService;
 Landroid/hardware/usb/IUsbManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/hardware/usb/IUsbManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/usb/IUsbManager;
+Landroid/inputmethodservice/IInputMethodSessionWrapper;->mCaller:Lcom/android/internal/os/HandlerCaller;
+Landroid/inputmethodservice/IInputMethodWrapper;->mCaller:Lcom/android/internal/os/HandlerCaller;
 Landroid/location/ICountryDetector$Stub;->asInterface(Landroid/os/IBinder;)Landroid/location/ICountryDetector;
 Landroid/location/ICountryListener$Stub;-><init>()V
 Landroid/location/IGeocodeProvider$Stub;-><init>()V
@@ -1318,18 +1320,6 @@
 Landroid/security/Credentials;->convertToPem([Ljava/security/cert/Certificate;)[B
 Landroid/security/IKeyChainService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/IKeyChainService;
 Landroid/security/IKeyChainService;->requestPrivateKey(Ljava/lang/String;)Ljava/lang/String;
-Landroid/security/IKeystoreService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/IKeystoreService;
-Landroid/security/IKeystoreService;->clear_uid(J)I
-Landroid/security/IKeystoreService;->del(Ljava/lang/String;I)I
-Landroid/security/IKeystoreService;->exist(Ljava/lang/String;I)I
-Landroid/security/IKeystoreService;->generateKey(Ljava/lang/String;Landroid/security/keymaster/KeymasterArguments;[BIILandroid/security/keymaster/KeyCharacteristics;)I
-Landroid/security/IKeystoreService;->get(Ljava/lang/String;I)[B
-Landroid/security/IKeystoreService;->getState(I)I
-Landroid/security/IKeystoreService;->insert(Ljava/lang/String;[BII)I
-Landroid/security/IKeystoreService;->is_hardware_backed(Ljava/lang/String;)I
-Landroid/security/IKeystoreService;->list(Ljava/lang/String;I)[Ljava/lang/String;
-Landroid/security/IKeystoreService;->reset()I
-Landroid/security/IKeystoreService;->ungrant(Ljava/lang/String;I)I
 Landroid/security/keymaster/KeymasterBlobArgument;-><init>(ILandroid/os/Parcel;)V
 Landroid/security/keymaster/KeymasterBlobArgument;-><init>(I[B)V
 Landroid/security/keymaster/KeymasterBlobArgument;->blob:[B
@@ -1341,6 +1331,17 @@
 Landroid/security/keymaster/KeymasterLongArgument;-><init>(IJ)V
 Landroid/security/keymaster/KeymasterLongArgument;-><init>(ILandroid/os/Parcel;)V
 Landroid/security/keymaster/KeymasterLongArgument;->value:J
+Landroid/security/keystore/IKeystoreService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/keystore/IKeystoreService;
+Landroid/security/keystore/IKeystoreService;->clear_uid(J)I
+Landroid/security/keystore/IKeystoreService;->del(Ljava/lang/String;I)I
+Landroid/security/keystore/IKeystoreService;->exist(Ljava/lang/String;I)I
+Landroid/security/keystore/IKeystoreService;->get(Ljava/lang/String;I)[B
+Landroid/security/keystore/IKeystoreService;->getState(I)I
+Landroid/security/keystore/IKeystoreService;->insert(Ljava/lang/String;[BII)I
+Landroid/security/keystore/IKeystoreService;->is_hardware_backed(Ljava/lang/String;)I
+Landroid/security/keystore/IKeystoreService;->list(Ljava/lang/String;I)[Ljava/lang/String;
+Landroid/security/keystore/IKeystoreService;->reset()I
+Landroid/security/keystore/IKeystoreService;->ungrant(Ljava/lang/String;I)I
 Landroid/service/carrier/ICarrierMessagingCallback$Stub;-><init>()V
 Landroid/service/carrier/ICarrierMessagingService;->filterSms(Landroid/service/carrier/MessagePdu;Ljava/lang/String;IILandroid/service/carrier/ICarrierMessagingCallback;)V
 Landroid/service/dreams/IDreamManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/dreams/IDreamManager;
@@ -4210,170 +4211,6 @@
 Lcom/android/okhttp/Response;->message:Ljava/lang/String;
 Lcom/android/okhttp/Response;->networkResponse:Lcom/android/okhttp/Response;
 Lcom/android/okhttp/Response;->protocol:Lcom/android/okhttp/Protocol;
-Lcom/android/org/bouncycastle/asn1/ASN1EncodableVector;-><init>()V
-Lcom/android/org/bouncycastle/asn1/ASN1EncodableVector;->add(Lcom/android/org/bouncycastle/asn1/ASN1Encodable;)V
-Lcom/android/org/bouncycastle/asn1/ASN1InputStream;-><init>(Ljava/io/InputStream;)V
-Lcom/android/org/bouncycastle/asn1/ASN1InputStream;-><init>([B)V
-Lcom/android/org/bouncycastle/asn1/ASN1InputStream;->readObject()Lcom/android/org/bouncycastle/asn1/ASN1Primitive;
-Lcom/android/org/bouncycastle/asn1/ASN1Integer;-><init>(Ljava/math/BigInteger;)V
-Lcom/android/org/bouncycastle/asn1/DERBitString;-><init>([B)V
-Lcom/android/org/bouncycastle/asn1/DEREncodableVector;-><init>()V
-Lcom/android/org/bouncycastle/asn1/DERInteger;-><init>(J)V
-Lcom/android/org/bouncycastle/asn1/DERInteger;-><init>(Ljava/math/BigInteger;)V
-Lcom/android/org/bouncycastle/asn1/DERNull;->INSTANCE:Lcom/android/org/bouncycastle/asn1/DERNull;
-Lcom/android/org/bouncycastle/asn1/DERObjectIdentifier;-><init>(Ljava/lang/String;)V
-Lcom/android/org/bouncycastle/asn1/DEROctetString;-><init>([B)V
-Lcom/android/org/bouncycastle/asn1/DEROutputStream;-><init>(Ljava/io/OutputStream;)V
-Lcom/android/org/bouncycastle/asn1/DERSequence;-><init>()V
-Lcom/android/org/bouncycastle/asn1/DERSequence;-><init>(Lcom/android/org/bouncycastle/asn1/ASN1EncodableVector;)V
-Lcom/android/org/bouncycastle/asn1/DERSet;-><init>(Lcom/android/org/bouncycastle/asn1/ASN1EncodableVector;)V
-Lcom/android/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers;->sha256WithRSAEncryption:Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;
-Lcom/android/org/bouncycastle/asn1/x509/AlgorithmIdentifier;-><init>(Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;)V
-Lcom/android/org/bouncycastle/asn1/x509/AlgorithmIdentifier;-><init>(Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;Lcom/android/org/bouncycastle/asn1/ASN1Encodable;)V
-Lcom/android/org/bouncycastle/asn1/x509/Certificate;->getInstance(Ljava/lang/Object;)Lcom/android/org/bouncycastle/asn1/x509/Certificate;
-Lcom/android/org/bouncycastle/asn1/x509/DigestInfo;-><init>(Lcom/android/org/bouncycastle/asn1/x509/AlgorithmIdentifier;[B)V
-Lcom/android/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo;->getInstance(Ljava/lang/Object;)Lcom/android/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo;
-Lcom/android/org/bouncycastle/asn1/x509/Time;-><init>(Ljava/util/Date;)V
-Lcom/android/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator;-><init>()V
-Lcom/android/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator;->generateTBSCertificate()Lcom/android/org/bouncycastle/asn1/x509/TBSCertificate;
-Lcom/android/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator;->setEndDate(Lcom/android/org/bouncycastle/asn1/x509/Time;)V
-Lcom/android/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator;->setIssuer(Lcom/android/org/bouncycastle/asn1/x509/X509Name;)V
-Lcom/android/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator;->setSerialNumber(Lcom/android/org/bouncycastle/asn1/ASN1Integer;)V
-Lcom/android/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator;->setSignature(Lcom/android/org/bouncycastle/asn1/x509/AlgorithmIdentifier;)V
-Lcom/android/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator;->setStartDate(Lcom/android/org/bouncycastle/asn1/x509/Time;)V
-Lcom/android/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator;->setSubject(Lcom/android/org/bouncycastle/asn1/x509/X509Name;)V
-Lcom/android/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator;->setSubjectPublicKeyInfo(Lcom/android/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo;)V
-Lcom/android/org/bouncycastle/asn1/x509/X509Name;-><init>(Lcom/android/org/bouncycastle/asn1/ASN1Sequence;)V
-Lcom/android/org/bouncycastle/asn1/x509/X509Name;-><init>(Ljava/lang/String;)V
-Lcom/android/org/bouncycastle/asn1/x509/X509Name;->CN:Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;
-Lcom/android/org/bouncycastle/asn1/x509/X509Name;->getOIDs()Ljava/util/Vector;
-Lcom/android/org/bouncycastle/asn1/x509/X509Name;->getValues()Ljava/util/Vector;
-Lcom/android/org/bouncycastle/asn1/x9/X9ObjectIdentifiers;->ecdsa_with_SHA256:Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;
-Lcom/android/org/bouncycastle/jce/provider/BouncyCastleProvider;-><init>()V
-Lcom/android/org/bouncycastle/jce/provider/X509CertificateObject;-><init>(Lcom/android/org/bouncycastle/asn1/x509/Certificate;)V
-Lcom/android/org/bouncycastle/jce/X509Principal;-><init>([B)V
-Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;-><init>()V
-Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;->generate(Ljava/security/PrivateKey;)Ljava/security/cert/X509Certificate;
-Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;->setIssuerDN(Lcom/android/org/bouncycastle/asn1/x509/X509Name;)V
-Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;->setIssuerDN(Ljavax/security/auth/x500/X500Principal;)V
-Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;->setNotAfter(Ljava/util/Date;)V
-Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;->setNotBefore(Ljava/util/Date;)V
-Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;->setPublicKey(Ljava/security/PublicKey;)V
-Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;->setSerialNumber(Ljava/math/BigInteger;)V
-Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;->setSignatureAlgorithm(Ljava/lang/String;)V
-Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;->setSubjectDN(Lcom/android/org/bouncycastle/asn1/x509/X509Name;)V
-Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;->setSubjectDN(Ljavax/security/auth/x500/X500Principal;)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getAlpnSelectedProtocol()[B
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getApplicationProtocols()[Ljava/lang/String;
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getChannelId()[B
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getHostname()Ljava/lang/String;
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getHostnameOrIP()Ljava/lang/String;
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getNpnSelectedProtocol()[B
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getSoWriteTimeout()I
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setAlpnProtocols([B)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setAlpnProtocols([Ljava/lang/String;)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setApplicationProtocols([Ljava/lang/String;)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setChannelIdEnabled(Z)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setChannelIdPrivateKey(Ljava/security/PrivateKey;)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setHandshakeTimeout(I)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setHostname(Ljava/lang/String;)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setNpnProtocols([B)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setSoWriteTimeout(I)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setUseSessionTickets(Z)V
-Lcom/android/org/conscrypt/ClientSessionContext;->getSession(Ljava/lang/String;I)Lcom/android/org/conscrypt/NativeSslSession;
-Lcom/android/org/conscrypt/ClientSessionContext;->setPersistentCache(Lcom/android/org/conscrypt/SSLClientSessionCache;)V
-Lcom/android/org/conscrypt/ConscryptFileDescriptorSocket;->setHostname(Ljava/lang/String;)V
-Lcom/android/org/conscrypt/ConscryptFileDescriptorSocket;->setUseSessionTickets(Z)V
-Lcom/android/org/conscrypt/FileClientSessionCache$Impl;->getSessionData(Ljava/lang/String;I)[B
-Lcom/android/org/conscrypt/FileClientSessionCache;->usingDirectory(Ljava/io/File;)Lcom/android/org/conscrypt/SSLClientSessionCache;
-Lcom/android/org/conscrypt/NativeCrypto;->ASN1_seq_pack_X509([J)[B
-Lcom/android/org/conscrypt/NativeCrypto;->ASN1_seq_unpack_X509_bio(J)[J
-Lcom/android/org/conscrypt/NativeCrypto;->ASN1_TIME_to_Calendar(JLjava/util/Calendar;)V
-Lcom/android/org/conscrypt/NativeCrypto;->BIO_free_all(J)V
-Lcom/android/org/conscrypt/NativeCrypto;->create_BIO_InputStream(Lcom/android/org/conscrypt/OpenSSLBIOInputStream;Z)J
-Lcom/android/org/conscrypt/NativeCrypto;->create_BIO_OutputStream(Ljava/io/OutputStream;)J
-Lcom/android/org/conscrypt/NativeCrypto;->d2i_PKCS7_bio(JI)[J
-Lcom/android/org/conscrypt/NativeCrypto;->d2i_SSL_SESSION([B)J
-Lcom/android/org/conscrypt/NativeCrypto;->d2i_X509([B)J
-Lcom/android/org/conscrypt/NativeCrypto;->d2i_X509_bio(J)J
-Lcom/android/org/conscrypt/NativeCrypto;->d2i_X509_CRL_bio(J)J
-Lcom/android/org/conscrypt/NativeCrypto;->EC_GROUP_clear_free(J)V
-Lcom/android/org/conscrypt/NativeCrypto;->EC_GROUP_new_by_curve_name(Ljava/lang/String;)J
-Lcom/android/org/conscrypt/NativeCrypto;->EC_POINT_clear_free(J)V
-Lcom/android/org/conscrypt/NativeCrypto;->EVP_CIPHER_CTX_new()J
-Lcom/android/org/conscrypt/NativeCrypto;->EVP_CIPHER_iv_length(J)I
-Lcom/android/org/conscrypt/NativeCrypto;->EVP_get_cipherbyname(Ljava/lang/String;)J
-Lcom/android/org/conscrypt/NativeCrypto;->EVP_get_digestbyname(Ljava/lang/String;)J
-Lcom/android/org/conscrypt/NativeCrypto;->EVP_MD_CTX_create()J
-Lcom/android/org/conscrypt/NativeCrypto;->EVP_MD_CTX_destroy(J)V
-Lcom/android/org/conscrypt/NativeCrypto;->EVP_MD_size(J)I
-Lcom/android/org/conscrypt/NativeCrypto;->EVP_PKEY_free(J)V
-Lcom/android/org/conscrypt/NativeCrypto;->EVP_PKEY_new_RSA([B[B[B[B[B[B[B[B)J
-Lcom/android/org/conscrypt/NativeCrypto;->get_X509_REVOKED_ext_oids(JI)[Ljava/lang/String;
-Lcom/android/org/conscrypt/NativeCrypto;->get_X509_REVOKED_revocationDate(J)J
-Lcom/android/org/conscrypt/NativeCrypto;->i2d_PKCS7([J)[B
-Lcom/android/org/conscrypt/NativeCrypto;->i2d_SSL_SESSION(J)[B
-Lcom/android/org/conscrypt/NativeCrypto;->i2d_X509_REVOKED(J)[B
-Lcom/android/org/conscrypt/NativeCrypto;->PEM_read_bio_PKCS7(JI)[J
-Lcom/android/org/conscrypt/NativeCrypto;->PEM_read_bio_X509(J)J
-Lcom/android/org/conscrypt/NativeCrypto;->PEM_read_bio_X509_CRL(J)J
-Lcom/android/org/conscrypt/NativeCrypto;->RAND_bytes([B)V
-Lcom/android/org/conscrypt/NativeCrypto;->RSA_generate_key_ex(I[B)J
-Lcom/android/org/conscrypt/NativeCrypto;->SSL_CTX_new()J
-Lcom/android/org/conscrypt/NativeCrypto;->SSL_SESSION_cipher(J)Ljava/lang/String;
-Lcom/android/org/conscrypt/NativeCrypto;->SSL_SESSION_free(J)V
-Lcom/android/org/conscrypt/NativeCrypto;->SSL_SESSION_get_time(J)J
-Lcom/android/org/conscrypt/NativeCrypto;->SSL_SESSION_get_version(J)Ljava/lang/String;
-Lcom/android/org/conscrypt/NativeCrypto;->SSL_SESSION_session_id(J)[B
-Lcom/android/org/conscrypt/NativeCrypto;->X509_REVOKED_dup(J)J
-Lcom/android/org/conscrypt/NativeCrypto;->X509_REVOKED_get_ext(JLjava/lang/String;)J
-Lcom/android/org/conscrypt/NativeCrypto;->X509_REVOKED_get_ext_oid(JLjava/lang/String;)[B
-Lcom/android/org/conscrypt/NativeCrypto;->X509_REVOKED_get_serialNumber(J)[B
-Lcom/android/org/conscrypt/NativeCrypto;->X509_REVOKED_print(JJ)V
-Lcom/android/org/conscrypt/NativeCrypto;->X509_supported_extension(J)I
-Lcom/android/org/conscrypt/OpenSSLBIOInputStream;-><init>(Ljava/io/InputStream;Z)V
-Lcom/android/org/conscrypt/OpenSSLBIOInputStream;->getBioContext()J
-Lcom/android/org/conscrypt/OpenSSLBIOInputStream;->release()V
-Lcom/android/org/conscrypt/OpenSSLContextImpl$TLSv12;-><init>()V
-Lcom/android/org/conscrypt/OpenSSLContextImpl;-><init>()V
-Lcom/android/org/conscrypt/OpenSSLContextImpl;->engineGetClientSessionContext()Lcom/android/org/conscrypt/ClientSessionContext;
-Lcom/android/org/conscrypt/OpenSSLContextImpl;->getPreferred()Lcom/android/org/conscrypt/OpenSSLContextImpl;
-Lcom/android/org/conscrypt/OpenSSLKey;-><init>(J)V
-Lcom/android/org/conscrypt/OpenSSLKey;->fromPrivateKey(Ljava/security/PrivateKey;)Lcom/android/org/conscrypt/OpenSSLKey;
-Lcom/android/org/conscrypt/OpenSSLKey;->getNativeRef()Lcom/android/org/conscrypt/NativeRef$EVP_PKEY;
-Lcom/android/org/conscrypt/OpenSSLKey;->getPublicKey()Ljava/security/PublicKey;
-Lcom/android/org/conscrypt/OpenSSLKeyHolder;->getOpenSSLKey()Lcom/android/org/conscrypt/OpenSSLKey;
-Lcom/android/org/conscrypt/OpenSSLProvider;-><init>()V
-Lcom/android/org/conscrypt/OpenSSLRandom;-><init>()V
-Lcom/android/org/conscrypt/OpenSSLSocketFactoryImpl;-><init>()V
-Lcom/android/org/conscrypt/OpenSSLSocketFactoryImpl;->sslParameters:Lcom/android/org/conscrypt/SSLParametersImpl;
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getAlpnSelectedProtocol()[B
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getChannelId()[B
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getHostname()Ljava/lang/String;
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getHostnameOrIP()Ljava/lang/String;
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getNpnSelectedProtocol()[B
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getSoWriteTimeout()I
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setAlpnProtocols([B)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setAlpnProtocols([Ljava/lang/String;)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setChannelIdEnabled(Z)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setChannelIdPrivateKey(Ljava/security/PrivateKey;)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setHandshakeTimeout(I)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setHostname(Ljava/lang/String;)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setNpnProtocols([B)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setSoWriteTimeout(I)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setUseSessionTickets(Z)V
-Lcom/android/org/conscrypt/OpenSSLX509Certificate;->fromX509PemInputStream(Ljava/io/InputStream;)Lcom/android/org/conscrypt/OpenSSLX509Certificate;
-Lcom/android/org/conscrypt/OpenSSLX509Certificate;->mContext:J
-Lcom/android/org/conscrypt/SSLParametersImpl;->getDefault()Lcom/android/org/conscrypt/SSLParametersImpl;
-Lcom/android/org/conscrypt/SSLParametersImpl;->getDefaultX509TrustManager()Ljavax/net/ssl/X509TrustManager;
-Lcom/android/org/conscrypt/SSLParametersImpl;->getX509TrustManager()Ljavax/net/ssl/X509TrustManager;
-Lcom/android/org/conscrypt/SSLParametersImpl;->setEnabledProtocols([Ljava/lang/String;)V
-Lcom/android/org/conscrypt/SSLParametersImpl;->x509TrustManager:Ljavax/net/ssl/X509TrustManager;
-Lcom/android/org/conscrypt/TrustedCertificateStore;-><init>()V
-Lcom/android/org/conscrypt/TrustedCertificateStore;->getCertificateChain(Ljava/security/cert/X509Certificate;)Ljava/util/List;
-Lcom/android/org/conscrypt/TrustManagerImpl;-><init>(Ljava/security/KeyStore;)V
-Lcom/android/org/conscrypt/TrustManagerImpl;->checkServerTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;Ljava/lang/String;)Ljava/util/List;
-Lcom/android/org/conscrypt/X509PublicKey;-><init>(Ljava/lang/String;[B)V
 Lcom/android/server/net/BaseNetworkObserver;-><init>()V
 Lcom/android/server/net/NetlinkTracker;-><init>(Ljava/lang/String;Lcom/android/server/net/NetlinkTracker$Callback;)V
 Lcom/android/server/net/NetlinkTracker;->clearLinkProperties()V
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index fade574..553acc8 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -31,6 +31,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.StyleRes;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.app.VoiceInteractor.Request;
 import android.app.admin.DevicePolicyManager;
@@ -2346,6 +2347,7 @@
      * @see View#onMovedToDisplay(int, Configuration)
      * @hide
      */
+    @TestApi
     public void onMovedToDisplay(int displayId, Configuration config) {
     }
 
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 45d68fa..0e5b976 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -161,13 +161,6 @@
     public abstract List<ProcessMemoryState> getMemoryStateForProcesses();
 
     /**
-     * Returns a list that contains the memory stats for monitored native processes.
-     *
-     * The list of the monitored processes is defined in MemoryStatUtil class.
-     */
-    public abstract List<ProcessMemoryState> getMemoryStateForNativeProcesses();
-
-    /**
      * Checks to see if the calling pid is allowed to handle the user. Returns adjusted user id as
      * needed.
      */
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 2be5dc9..9e109c5 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1625,9 +1625,6 @@
             case AppOpsManager.OP_READ_CALL_LOG:
             case AppOpsManager.OP_WRITE_CALL_LOG:
             case AppOpsManager.OP_PROCESS_OUTGOING_CALLS: {
-                if (sSmsAndCallLogRestrictionEnabled.get() < 0) {
-                    startWatchingSmsRestrictionEnabled();
-                }
                 if (sSmsAndCallLogRestrictionEnabled.get() == 1) {
                     return AppOpsManager.MODE_DEFAULT;
                 }
@@ -1640,26 +1637,24 @@
     private static final AtomicInteger sSmsAndCallLogRestrictionEnabled = new AtomicInteger(-1);
 
     // STOPSHIP b/118520006: Hardcode the default values once the feature is stable.
-    private static void startWatchingSmsRestrictionEnabled() {
+    static {
         final Context context = ActivityThread.currentApplication();
-        if (context == null) {
-            // Should never happen
-            return;
+        if (context != null) {
+            sSmsAndCallLogRestrictionEnabled.set(ActivityThread.currentActivityThread()
+                        .getIntCoreSetting(Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, 0));
+
+            final Uri uri =
+                    Settings.Global.getUriFor(Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED);
+            context.getContentResolver().registerContentObserver(uri, false, new ContentObserver(
+                    context.getMainThreadHandler()) {
+                @Override
+                public void onChange(boolean selfChange) {
+                    sSmsAndCallLogRestrictionEnabled.set(Settings.Global.getInt(
+                            context.getContentResolver(),
+                            Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, 0));
+                }
+            });
         }
-
-        sSmsAndCallLogRestrictionEnabled.set(ActivityThread.currentActivityThread()
-                    .getIntCoreSetting(Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, 0));
-
-        final Uri uri = Settings.Global.getUriFor(Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED);
-        context.getContentResolver().registerContentObserver(uri, false, new ContentObserver(
-                context.getMainThreadHandler()) {
-            @Override
-            public void onChange(boolean selfChange) {
-                sSmsAndCallLogRestrictionEnabled.set(Settings.Global.getInt(
-                        context.getContentResolver(),
-                        Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, 0));
-            }
-        });
     }
 
     /**
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index dc707e8..9837deb 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -140,6 +140,13 @@
         throw new ReceiverCallNotAllowedException(
                 "BroadcastReceiver components are not allowed to bind to services");
     }
+
+    @Override
+    public boolean bindIsolatedService(Intent service, ServiceConnection conn, int flags,
+            String instanceName) {
+        throw new ReceiverCallNotAllowedException(
+                "BroadcastReceiver components are not allowed to bind to services");
+    }
 }
 
 /**
@@ -1630,14 +1637,25 @@
     public boolean bindService(Intent service, ServiceConnection conn,
             int flags) {
         warnIfCallingFromSystemProcess();
-        return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), getUser());
+        return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), getUser());
+    }
+
+    @Override
+    public boolean bindIsolatedService(Intent service, ServiceConnection conn,
+            int flags, String instanceName) {
+        warnIfCallingFromSystemProcess();
+        if (instanceName == null) {
+            throw new NullPointerException("null instanceName");
+        }
+        return bindServiceCommon(service, conn, flags, instanceName, mMainThread.getHandler(),
+                getUser());
     }
 
     /** @hide */
     @Override
     public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
             UserHandle user) {
-        return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), user);
+        return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), user);
     }
 
     /** @hide */
@@ -1647,7 +1665,7 @@
         if (handler == null) {
             throw new IllegalArgumentException("handler must not be null.");
         }
-        return bindServiceCommon(service, conn, flags, handler, user);
+        return bindServiceCommon(service, conn, flags, null, handler, user);
     }
 
     /** @hide */
@@ -1669,7 +1687,8 @@
         return mMainThread.getHandler();
     }
 
-    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
+    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
+            String instanceName, Handler
             handler, UserHandle user) {
         // Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser.
         IServiceConnection sd;
@@ -1690,10 +1709,10 @@
                 flags |= BIND_WAIVE_PRIORITY;
             }
             service.prepareToLeaveProcess(this);
-            int res = ActivityManager.getService().bindService(
+            int res = ActivityManager.getService().bindIsolatedService(
                 mMainThread.getApplicationThread(), getActivityToken(), service,
                 service.resolveTypeIfNeeded(getContentResolver()),
-                sd, flags, getOpPackageName(), user.getIdentifier());
+                sd, flags, instanceName, getOpPackageName(), user.getIdentifier());
             if (res < 0) {
                 throw new SecurityException(
                         "Not allowed to bind to service " + service);
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index e2312a5..f27c667 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -133,9 +133,13 @@
             in String resolvedType, boolean requireForeground, in String callingPackage, int userId);
     int stopService(in IApplicationThread caller, in Intent service,
             in String resolvedType, int userId);
+    // Currently keeping old bindService because it is on the greylist
     int bindService(in IApplicationThread caller, in IBinder token, in Intent service,
             in String resolvedType, in IServiceConnection connection, int flags,
             in String callingPackage, int userId);
+    int bindIsolatedService(in IApplicationThread caller, in IBinder token, in Intent service,
+            in String resolvedType, in IServiceConnection connection, int flags,
+            in String instanceName, in String callingPackage, int userId);
     boolean unbindService(in IServiceConnection connection);
     void publishService(in IBinder token, in Intent intent, in IBinder service);
     void setDebugApp(in String packageName, boolean waitForDebugger, boolean persistent);
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index ac16442..015bc6c 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -1009,7 +1009,7 @@
      * from its event processing, though it may <em>not</em> have completely
      * finished reacting from the event -- for example, if it needs to update
      * its display as a result, it may still be in the process of doing that.
-     * 
+     *
      * @param event The event to send to the current focus.
      */
     public void sendKeySync(KeyEvent event) {
@@ -1017,14 +1017,7 @@
 
         long downTime = event.getDownTime();
         long eventTime = event.getEventTime();
-        int action = event.getAction();
-        int code = event.getKeyCode();
-        int repeatCount = event.getRepeatCount();
-        int metaState = event.getMetaState();
-        int deviceId = event.getDeviceId();
-        int scancode = event.getScanCode();
         int source = event.getSource();
-        int flags = event.getFlags();
         if (source == InputDevice.SOURCE_UNKNOWN) {
             source = InputDevice.SOURCE_KEYBOARD;
         }
@@ -1034,12 +1027,14 @@
         if (downTime == 0) {
             downTime = eventTime;
         }
-        KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState,
-                deviceId, scancode, flags | KeyEvent.FLAG_FROM_SYSTEM, source);
+        KeyEvent newEvent = new KeyEvent(event);
+        newEvent.setTime(downTime, eventTime);
+        newEvent.setSource(source);
+        newEvent.setFlags(event.getFlags() | KeyEvent.FLAG_FROM_SYSTEM);
         InputManager.getInstance().injectInputEvent(newEvent,
                 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
     }
-    
+
     /**
      * Sends an up and down key event sync to the currently focused window.
      * 
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 5850540..0123551 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -153,6 +153,7 @@
 import android.telephony.TelephonyManager;
 import android.telephony.euicc.EuiccCardManager;
 import android.telephony.euicc.EuiccManager;
+import android.telephony.rcs.RcsManager;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.view.ContextThemeWrapper;
@@ -547,6 +548,14 @@
                 return new SubscriptionManager(ctx.getOuterContext());
             }});
 
+        registerService(Context.TELEPHONY_RCS_SERVICE, RcsManager.class,
+                new CachedServiceFetcher<RcsManager>() {
+                    @Override
+                    public RcsManager createService(ContextImpl ctx) {
+                        return new RcsManager();
+                    }
+                });
+
         registerService(Context.CARRIER_CONFIG_SERVICE, CarrierConfigManager.class,
                 new CachedServiceFetcher<CarrierConfigManager>() {
             @Override
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index 308b39e..3a5975a 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -50,12 +50,20 @@
         public static final int NONE = 0;
 
         /**
-         * An event type denoting that a component moved to the foreground.
+         * An event type denoting that an {@link android.app.Activity} moved to the foreground.
+         * This event has a package name and class name associated with it and can be retrieved
+         * using {@link #getPackageName()} and {@link #getClassName()}.
+         * If a package has multiple activities, this event is reported for each activity that moves
+         * to foreground.
          */
         public static final int MOVE_TO_FOREGROUND = 1;
 
         /**
-         * An event type denoting that a component moved to the background.
+         * An event type denoting that an {@link android.app.Activity} moved to the background.
+         * This event has a package name and class name associated with it and can be retrieved
+         * using {@link #getPackageName()} and {@link #getClassName()}.
+         * If a package has multiple activities, this event is reported for each activity that moves
+         * to background.
          */
         public static final int MOVE_TO_BACKGROUND = 2;
 
@@ -166,10 +174,43 @@
         public static final int KEYGUARD_HIDDEN = 18;
 
         /**
+         * An event type denoting start of a foreground service.
+         * This event has a package name and class name associated with it and can be retrieved
+         * using {@link #getPackageName()} and {@link #getClassName()}.
+         * If a package has multiple foreground services, this event is reported for each service
+         * that is started.
+         */
+        public static final int FOREGROUND_SERVICE_START = 19;
+
+        /**
+         * An event type denoting stop of a foreground service.
+         * This event has a package name and class name associated with it and can be retrieved
+         * using {@link #getPackageName()} and {@link #getClassName()}.
+         * If a package has multiple foreground services, this event is reported for each service
+         * that is stopped.
+         */
+        public static final int FOREGROUND_SERVICE_STOP = 20;
+
+        /**
+         * An event type denoting that a foreground service is at started state at beginning of a
+         * time interval.
+         * This is effectively treated as a {@link #FOREGROUND_SERVICE_START}.
+         * {@hide}
+         */
+        public static final int CONTINUING_FOREGROUND_SERVICE = 21;
+
+        /**
+         * An event type denoting that a foreground service is at started state when the stats
+         * rolled-over at the end of a time interval.
+         * {@hide}
+         */
+        public static final int ROLLOVER_FOREGROUND_SERVICE = 22;
+
+        /**
          * Keep in sync with the greatest event type value.
          * @hide
          */
-        public static final int MAX_EVENT_TYPE = 18;
+        public static final int MAX_EVENT_TYPE = 22;
 
         /** @hide */
         public static final int FLAG_IS_PACKAGE_INSTANT_APP = 1 << 0;
diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java
index 0659a23..73426e4 100644
--- a/core/java/android/app/usage/UsageStats.java
+++ b/core/java/android/app/usage/UsageStats.java
@@ -16,6 +16,15 @@
 
 package android.app.usage;
 
+import static android.app.usage.UsageEvents.Event.CONTINUE_PREVIOUS_DAY;
+import static android.app.usage.UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE;
+import static android.app.usage.UsageEvents.Event.END_OF_DAY;
+import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_START;
+import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_STOP;
+import static android.app.usage.UsageEvents.Event.MOVE_TO_BACKGROUND;
+import static android.app.usage.UsageEvents.Event.MOVE_TO_FOREGROUND;
+import static android.app.usage.UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE;
+
 import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
@@ -48,19 +57,32 @@
     public long mEndTimeStamp;
 
     /**
-     * Last time used by the user with an explicit action (notification, activity launch).
+     * Last time used by the user with an explicit action (notification, activity launch)
      * {@hide}
      */
     @UnsupportedAppUsage
     public long mLastTimeUsed;
 
     /**
+     * Total time this package's activity is in foreground.
      * {@hide}
      */
     @UnsupportedAppUsage
     public long mTotalTimeInForeground;
 
     /**
+     * Last time foreground service is started.
+     * {@hide}
+     */
+    public long mLastTimeForegroundServiceUsed;
+
+    /**
+     * Total time this package's foreground service is started.
+     * {@hide}
+     */
+    public long mTotalTimeForegroundServiceUsed;
+
+    /**
      * {@hide}
      */
     @UnsupportedAppUsage
@@ -71,16 +93,36 @@
      */
     public int mAppLaunchCount;
 
-    /**
+    /** Last activity MOVE_TO_FOREGROUND or MOVE_TO_BACKGROUND event.
      * {@hide}
+     * @deprecated use {@link #mLastForegroundActivityEventMap} instead.
      */
     @UnsupportedAppUsage
+    @Deprecated
     public int mLastEvent;
 
     /**
+     * If an activity is in foreground, it has one entry in this map.
+     * When activity moves to background, it is removed from this map.
+     * Key is activity class name.
+     * Value is last time this activity MOVE_TO_FOREGROUND or MOVE_TO_BACKGROUND event.
+     * {@hide}
+     */
+    public ArrayMap<String, Integer> mLastForegroundActivityEventMap = new ArrayMap<>();
+
+    /**
+     * If a foreground service is started, it has one entry in this map.
+     * When a foreground service is stopped, it is removed from this map.
+     * Key is foreground service class name.
+     * Value is last foreground service FOREGROUND_SERVICE_START ot FOREGROUND_SERVICE_STOP event.
+     * {@hide}
+     */
+    public ArrayMap<String, Integer> mLastForegroundServiceEventMap = new ArrayMap<>();
+
+    /**
      * {@hide}
      */
-    public ArrayMap<String, ArrayMap<String, Integer>> mChooserCounts;
+    public ArrayMap<String, ArrayMap<String, Integer>> mChooserCounts = new ArrayMap<>();
 
     /**
      * {@hide}
@@ -93,10 +135,14 @@
         mBeginTimeStamp = stats.mBeginTimeStamp;
         mEndTimeStamp = stats.mEndTimeStamp;
         mLastTimeUsed = stats.mLastTimeUsed;
+        mLastTimeForegroundServiceUsed = stats.mLastTimeForegroundServiceUsed;
         mTotalTimeInForeground = stats.mTotalTimeInForeground;
+        mTotalTimeForegroundServiceUsed = stats.mTotalTimeForegroundServiceUsed;
         mLaunchCount = stats.mLaunchCount;
         mAppLaunchCount = stats.mAppLaunchCount;
         mLastEvent = stats.mLastEvent;
+        mLastForegroundActivityEventMap = stats.mLastForegroundActivityEventMap;
+        mLastForegroundServiceEventMap = stats.mLastForegroundServiceEventMap;
         mChooserCounts = stats.mChooserCounts;
     }
 
@@ -136,7 +182,7 @@
     }
 
     /**
-     * Get the last time this package was used, measured in milliseconds since the epoch.
+     * Get the last time this package's activity was used, measured in milliseconds since the epoch.
      * <p/>
      * See {@link System#currentTimeMillis()}.
      */
@@ -152,6 +198,23 @@
     }
 
     /**
+     * Get the last time this package's foreground service was used, measured in milliseconds since
+     * the epoch.
+     * <p/>
+     * See {@link System#currentTimeMillis()}.
+     */
+    public long getLastTimeForegroundServiceUsed() {
+        return mLastTimeForegroundServiceUsed;
+    }
+
+    /**
+     * Get the total time this package's foreground services are started, measured in milliseconds.
+     */
+    public long getTotalTimeForegroundServiceUsed() {
+        return mTotalTimeForegroundServiceUsed;
+    }
+
+    /**
      * Returns the number of times the app was launched as an activity from outside of the app.
      * Excludes intra-app activity transitions.
      * @hide
@@ -161,6 +224,19 @@
         return mAppLaunchCount;
     }
 
+    private void mergeEventMap(ArrayMap<String, Integer> left, ArrayMap<String, Integer> right) {
+        final int size = right.size();
+        for (int i = 0; i < size; i++) {
+            final String className = right.keyAt(i);
+            final Integer event = right.valueAt(i);
+            if (left.containsKey(className)) {
+                left.put(className, Math.max(left.get(className), event));
+            } else {
+                left.put(className, event);
+            }
+        }
+    }
+
     /**
      * Add the statistics from the right {@link UsageStats} to the left. The package name for
      * both {@link UsageStats} objects must be the same.
@@ -179,12 +255,16 @@
         if (right.mBeginTimeStamp > mBeginTimeStamp) {
             // Even though incoming UsageStat begins after this one, its last time used fields
             // may somehow be empty or chronologically preceding the older UsageStat.
-            mLastEvent = Math.max(mLastEvent, right.mLastEvent);
+            mergeEventMap(mLastForegroundActivityEventMap, right.mLastForegroundActivityEventMap);
+            mergeEventMap(mLastForegroundServiceEventMap, right.mLastForegroundServiceEventMap);
             mLastTimeUsed = Math.max(mLastTimeUsed, right.mLastTimeUsed);
+            mLastTimeForegroundServiceUsed = Math.max(mLastTimeForegroundServiceUsed,
+                    right.mLastTimeForegroundServiceUsed);
         }
         mBeginTimeStamp = Math.min(mBeginTimeStamp, right.mBeginTimeStamp);
         mEndTimeStamp = Math.max(mEndTimeStamp, right.mEndTimeStamp);
         mTotalTimeInForeground += right.mTotalTimeInForeground;
+        mTotalTimeForegroundServiceUsed += right.mTotalTimeForegroundServiceUsed;
         mLaunchCount += right.mLaunchCount;
         mAppLaunchCount += right.mAppLaunchCount;
         if (mChooserCounts == null) {
@@ -209,6 +289,161 @@
         }
     }
 
+    /**
+     * Tell if an event indicate activity is in foreground or not.
+     * @param event the activity event.
+     * @return true if activity is in foreground, false otherwise.
+     * @hide
+     */
+    private boolean isActivityInForeground(int event) {
+        return event == MOVE_TO_FOREGROUND
+                || event == CONTINUE_PREVIOUS_DAY;
+    }
+
+    /**
+     * Tell if an event indicate foreground sevice is started or not.
+     * @param event the foreground service event.
+     * @return true if foreground service is started, false if stopped.
+     * @hide
+     */
+    private boolean isForegroundServiceStarted(int event) {
+        return event == FOREGROUND_SERVICE_START
+                || event == CONTINUING_FOREGROUND_SERVICE;
+    }
+
+    /**
+     * If any activity in foreground or any foreground service is started, the app is considered in
+     * use.
+     * @return true if in use, false otherwise.
+     * @hide
+     */
+    private boolean isAppInUse() {
+        return !mLastForegroundActivityEventMap.isEmpty()
+                || !mLastForegroundServiceEventMap.isEmpty();
+    }
+
+    /**
+     * Update by an event of an activity.
+     * @param className className of the activity.
+     * @param timeStamp timeStamp of the event.
+     * @param eventType type of the event.
+     * @hide
+     */
+    private void updateForegroundActivity(String className, long timeStamp, int eventType) {
+        if (eventType != MOVE_TO_BACKGROUND
+                && eventType != MOVE_TO_FOREGROUND
+                && eventType != END_OF_DAY) {
+            return;
+        }
+
+        final Integer lastEvent = mLastForegroundActivityEventMap.get(className);
+        if (lastEvent != null) {
+            if (isActivityInForeground(lastEvent)) {
+                if (timeStamp > mLastTimeUsed) {
+                    mTotalTimeInForeground += timeStamp - mLastTimeUsed;
+                    mLastTimeUsed = timeStamp;
+                }
+            }
+            if (eventType == MOVE_TO_BACKGROUND) {
+                mLastForegroundActivityEventMap.remove(className);
+            } else {
+                mLastForegroundActivityEventMap.put(className, eventType);
+            }
+        } else if (eventType == MOVE_TO_FOREGROUND) {
+            if (!isAppInUse()) {
+                mLastTimeUsed = timeStamp;
+            }
+            mLastForegroundActivityEventMap.put(className, eventType);
+        }
+    }
+
+    /**
+     * Update by an event of an foreground service.
+     * @param className className of the foreground service.
+     * @param timeStamp timeStamp of the event.
+     * @param eventType type of the event.
+     * @hide
+     */
+    private void updateForegroundService(String className, long timeStamp, int eventType) {
+        if (eventType != FOREGROUND_SERVICE_STOP
+                && eventType != FOREGROUND_SERVICE_START
+                && eventType != ROLLOVER_FOREGROUND_SERVICE) {
+            return;
+        }
+        final Integer lastEvent = mLastForegroundServiceEventMap.get(className);
+        if (lastEvent != null) {
+            if (isForegroundServiceStarted(lastEvent)) {
+                if (timeStamp > mLastTimeForegroundServiceUsed) {
+                    mTotalTimeForegroundServiceUsed +=
+                            timeStamp - mLastTimeForegroundServiceUsed;
+                    mLastTimeForegroundServiceUsed = timeStamp;
+                }
+            }
+            if (eventType == FOREGROUND_SERVICE_STOP) {
+                mLastForegroundServiceEventMap.remove(className);
+            } else {
+                mLastForegroundServiceEventMap.put(className, eventType);
+            }
+        } else if (eventType == FOREGROUND_SERVICE_START) {
+            if (!isAppInUse()) {
+                mLastTimeForegroundServiceUsed = timeStamp;
+            }
+            mLastForegroundServiceEventMap.put(className, eventType);
+        }
+    }
+
+    /**
+     * Update the UsageStats by a activity or foreground service event.
+     * @param className class name of a activity or foreground service, could be null to mark
+     *                  END_OF_DAY or rollover.
+     * @param timeStamp Epoch timestamp in milliseconds.
+     * @param eventType event type as in {@link UsageEvents.Event}
+     * @hide
+     */
+    public void update(String className, long timeStamp, int eventType) {
+        switch(eventType) {
+            case MOVE_TO_BACKGROUND:
+            case MOVE_TO_FOREGROUND:
+                updateForegroundActivity(className, timeStamp, eventType);
+                break;
+            case END_OF_DAY:
+                // END_OF_DAY means updating all activities.
+                final int size = mLastForegroundActivityEventMap.size();
+                for (int i = 0; i < size; i++) {
+                    final String name = mLastForegroundActivityEventMap.keyAt(i);
+                    updateForegroundActivity(name, timeStamp, eventType);
+                }
+                break;
+            case CONTINUE_PREVIOUS_DAY:
+                mLastTimeUsed = timeStamp;
+                mLastForegroundActivityEventMap.put(className, eventType);
+                break;
+            case FOREGROUND_SERVICE_STOP:
+            case FOREGROUND_SERVICE_START:
+                updateForegroundService(className, timeStamp, eventType);
+                break;
+            case ROLLOVER_FOREGROUND_SERVICE:
+                // ROLLOVER_FOREGROUND_SERVICE means updating all foreground services.
+                final int size2 = mLastForegroundServiceEventMap.size();
+                for (int i = 0; i < size2; i++) {
+                    final String name = mLastForegroundServiceEventMap.keyAt(i);
+                    updateForegroundService(name, timeStamp, eventType);
+                }
+                break;
+            case CONTINUING_FOREGROUND_SERVICE:
+                mLastTimeForegroundServiceUsed = timeStamp;
+                mLastForegroundServiceEventMap.put(className, eventType);
+                break;
+            default:
+                break;
+        }
+        mEndTimeStamp = timeStamp;
+
+        if (eventType == MOVE_TO_FOREGROUND) {
+            mLaunchCount += 1;
+        }
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -220,7 +455,9 @@
         dest.writeLong(mBeginTimeStamp);
         dest.writeLong(mEndTimeStamp);
         dest.writeLong(mLastTimeUsed);
+        dest.writeLong(mLastTimeForegroundServiceUsed);
         dest.writeLong(mTotalTimeInForeground);
+        dest.writeLong(mTotalTimeForegroundServiceUsed);
         dest.writeInt(mLaunchCount);
         dest.writeInt(mAppLaunchCount);
         dest.writeInt(mLastEvent);
@@ -239,6 +476,22 @@
             }
         }
         dest.writeBundle(allCounts);
+
+        final Bundle foregroundActivityEventBundle = new Bundle();
+        final int foregroundEventSize = mLastForegroundActivityEventMap.size();
+        for (int i = 0; i < foregroundEventSize; i++) {
+            foregroundActivityEventBundle.putInt(mLastForegroundActivityEventMap.keyAt(i),
+                    mLastForegroundActivityEventMap.valueAt(i));
+        }
+        dest.writeBundle(foregroundActivityEventBundle);
+
+        final Bundle foregroundServiceEventBundle = new Bundle();
+        final int foregroundServiceEventSize = mLastForegroundServiceEventMap.size();
+        for (int i = 0; i < foregroundServiceEventSize; i++) {
+            foregroundServiceEventBundle.putInt(mLastForegroundServiceEventMap.keyAt(i),
+                    mLastForegroundServiceEventMap.valueAt(i));
+        }
+        dest.writeBundle(foregroundServiceEventBundle);
     }
 
     public static final Creator<UsageStats> CREATOR = new Creator<UsageStats>() {
@@ -249,7 +502,9 @@
             stats.mBeginTimeStamp = in.readLong();
             stats.mEndTimeStamp = in.readLong();
             stats.mLastTimeUsed = in.readLong();
+            stats.mLastTimeForegroundServiceUsed = in.readLong();
             stats.mTotalTimeInForeground = in.readLong();
+            stats.mTotalTimeForegroundServiceUsed = in.readLong();
             stats.mLaunchCount = in.readInt();
             stats.mAppLaunchCount = in.readInt();
             stats.mLastEvent = in.readInt();
@@ -272,9 +527,20 @@
                     }
                 }
             }
+            readBundleToEventMap(stats.mLastForegroundActivityEventMap, in.readBundle());
+            readBundleToEventMap(stats.mLastForegroundServiceEventMap, in.readBundle());
             return stats;
         }
 
+        private void readBundleToEventMap(ArrayMap<String, Integer> eventMap, Bundle bundle) {
+            if (bundle != null) {
+                for (String className : bundle.keySet()) {
+                    final int event = bundle.getInt(className);
+                    eventMap.put(className, event);
+                }
+            }
+        }
+
         @Override
         public UsageStats[] newArray(int size) {
             return new UsageStats[size];
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 6d7400e..5514851 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -192,7 +192,10 @@
     public static final int REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_DOZE = 0x000C;
     /** @hide */
     public static final int REASON_SUB_USAGE_EXEMPTED_SYNC_START = 0x000D;
-
+    /** @hide */
+    public static final int REASON_SUB_USAGE_FOREGROUND_SERVICE_START = 0x000E;
+    /** @hide */
+    public static final int REASON_SUB_USAGE_FOREGROUND_SERVICE_STOP = 0x000F;
     /** @hide */
     public static final int REASON_SUB_PREDICTED_RESTORED       = 0x0001;
 
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 2aa32c4..03eba7e 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2906,8 +2906,9 @@
      * @param flags Operation options for the binding.  May be 0,
      *          {@link #BIND_AUTO_CREATE}, {@link #BIND_DEBUG_UNBIND},
      *          {@link #BIND_NOT_FOREGROUND}, {@link #BIND_ABOVE_CLIENT},
-     *          {@link #BIND_ALLOW_OOM_MANAGEMENT}, or
-     *          {@link #BIND_WAIVE_PRIORITY}.
+     *          {@link #BIND_ALLOW_OOM_MANAGEMENT}, {@link #BIND_WAIVE_PRIORITY}.
+     *          {@link #BIND_IMPORTANT}, or
+     *          {@link #BIND_ADJUST_WITH_ACTIVITY}.
      * @return {@code true} if the system is in the process of bringing up a
      *         service that your client has permission to bind to; {@code false}
      *         if the system couldn't find the service or if your client doesn't
@@ -2923,11 +2924,38 @@
      * @see #BIND_AUTO_CREATE
      * @see #BIND_DEBUG_UNBIND
      * @see #BIND_NOT_FOREGROUND
+     * @see #BIND_ABOVE_CLIENT
+     * @see #BIND_ALLOW_OOM_MANAGEMENT
+     * @see #BIND_WAIVE_PRIORITY
+     * @see #BIND_IMPORTANT
+     * @see #BIND_ADJUST_WITH_ACTIVITY
      */
     public abstract boolean bindService(@RequiresPermission Intent service,
             @NonNull ServiceConnection conn, @BindServiceFlags int flags);
 
     /**
+     * Variation of {@link #bindService} that, in the specific case of isolated
+     * services, allows the caller to generate multiple instances of a service
+     * from a single component declaration.
+     *
+     * @param service Identifies the service to connect to.  The Intent must
+     *      specify an explicit component name.
+     * @param conn Receives information as the service is started and stopped.
+     *      This must be a valid ServiceConnection object; it must not be null.
+     * @param flags Operation options for the binding as per {@link #bindService}.
+     * @param instanceName Unique identifier for the service instance.  Each unique
+     *      name here will result in a different service instance being created.
+     * @return Returns success of binding as per {@link #bindService}.
+     *
+     * @throws SecurityException If the caller does not have permission to access the service
+     *
+     * @see #bindService
+     */
+    public abstract boolean bindIsolatedService(@RequiresPermission Intent service,
+            @NonNull ServiceConnection conn, @BindServiceFlags int flags,
+            @NonNull String instanceName);
+
+    /**
      * Same as {@link #bindService(Intent, ServiceConnection, int)}, but with an explicit userHandle
      * argument for use by system server and other multi-user aware code.
      * @hide
@@ -2941,7 +2969,7 @@
     }
 
     /**
-     * Same as {@link #bindService(Intent, ServiceConnection, int, UserHandle)}, but with an
+     * Same as {@link #bindServiceAsUser(Intent, ServiceConnection, int, UserHandle)}, but with an
      * explicit non-null Handler to run the ServiceConnection callbacks on.
      *
      * @hide
@@ -4367,6 +4395,13 @@
     public static final String APP_BINDING_SERVICE = "app_binding";
 
     /**
+     * Use with {@link #getSystemService(String)} to retrieve an
+     * {@link android.telephony.rcs.RcsManager}.
+     * @hide
+     */
+    public static final String TELEPHONY_RCS_SERVICE = "ircs";
+
+    /**
      * Determine whether the given permission is allowed for a particular
      * process and user ID running in the system.
      *
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index bfad2b4..88696b0 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -705,6 +705,12 @@
         return mBase.bindService(service, conn, flags);
     }
 
+    @Override
+    public boolean bindIsolatedService(Intent service, ServiceConnection conn,
+            int flags, String instanceName) {
+        return mBase.bindIsolatedService(service, conn, flags, instanceName);
+    }
+
     /** @hide */
     @Override
     public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 02f38a7..e9b2404 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -7508,7 +7508,7 @@
      *
      * @see #putExtra(String, String)
      */
-    public String getStringExtra(String name) {
+    public @Nullable String getStringExtra(String name) {
         return mExtras == null ? null : mExtras.getString(name);
     }
 
@@ -7522,7 +7522,7 @@
      *
      * @see #putExtra(String, CharSequence)
      */
-    public CharSequence getCharSequenceExtra(String name) {
+    public @Nullable CharSequence getCharSequenceExtra(String name) {
         return mExtras == null ? null : mExtras.getCharSequence(name);
     }
 
@@ -7536,7 +7536,7 @@
      *
      * @see #putExtra(String, Parcelable)
      */
-    public <T extends Parcelable> T getParcelableExtra(String name) {
+    public @Nullable <T extends Parcelable> T getParcelableExtra(String name) {
         return mExtras == null ? null : mExtras.<T>getParcelable(name);
     }
 
@@ -7550,7 +7550,7 @@
      *
      * @see #putExtra(String, Parcelable[])
      */
-    public Parcelable[] getParcelableArrayExtra(String name) {
+    public @Nullable Parcelable[] getParcelableArrayExtra(String name) {
         return mExtras == null ? null : mExtras.getParcelableArray(name);
     }
 
@@ -7565,7 +7565,7 @@
      *
      * @see #putParcelableArrayListExtra(String, ArrayList)
      */
-    public <T extends Parcelable> ArrayList<T> getParcelableArrayListExtra(String name) {
+    public @Nullable <T extends Parcelable> ArrayList<T> getParcelableArrayListExtra(String name) {
         return mExtras == null ? null : mExtras.<T>getParcelableArrayList(name);
     }
 
@@ -7579,7 +7579,7 @@
      *
      * @see #putExtra(String, Serializable)
      */
-    public Serializable getSerializableExtra(String name) {
+    public @Nullable Serializable getSerializableExtra(String name) {
         return mExtras == null ? null : mExtras.getSerializable(name);
     }
 
@@ -7594,7 +7594,7 @@
      *
      * @see #putIntegerArrayListExtra(String, ArrayList)
      */
-    public ArrayList<Integer> getIntegerArrayListExtra(String name) {
+    public @Nullable ArrayList<Integer> getIntegerArrayListExtra(String name) {
         return mExtras == null ? null : mExtras.getIntegerArrayList(name);
     }
 
@@ -7609,7 +7609,7 @@
      *
      * @see #putStringArrayListExtra(String, ArrayList)
      */
-    public ArrayList<String> getStringArrayListExtra(String name) {
+    public @Nullable ArrayList<String> getStringArrayListExtra(String name) {
         return mExtras == null ? null : mExtras.getStringArrayList(name);
     }
 
@@ -7624,7 +7624,7 @@
      *
      * @see #putCharSequenceArrayListExtra(String, ArrayList)
      */
-    public ArrayList<CharSequence> getCharSequenceArrayListExtra(String name) {
+    public @Nullable ArrayList<CharSequence> getCharSequenceArrayListExtra(String name) {
         return mExtras == null ? null : mExtras.getCharSequenceArrayList(name);
     }
 
@@ -7638,7 +7638,7 @@
      *
      * @see #putExtra(String, boolean[])
      */
-    public boolean[] getBooleanArrayExtra(String name) {
+    public @Nullable boolean[] getBooleanArrayExtra(String name) {
         return mExtras == null ? null : mExtras.getBooleanArray(name);
     }
 
@@ -7652,7 +7652,7 @@
      *
      * @see #putExtra(String, byte[])
      */
-    public byte[] getByteArrayExtra(String name) {
+    public @Nullable byte[] getByteArrayExtra(String name) {
         return mExtras == null ? null : mExtras.getByteArray(name);
     }
 
@@ -7666,7 +7666,7 @@
      *
      * @see #putExtra(String, short[])
      */
-    public short[] getShortArrayExtra(String name) {
+    public @Nullable short[] getShortArrayExtra(String name) {
         return mExtras == null ? null : mExtras.getShortArray(name);
     }
 
@@ -7680,7 +7680,7 @@
      *
      * @see #putExtra(String, char[])
      */
-    public char[] getCharArrayExtra(String name) {
+    public @Nullable char[] getCharArrayExtra(String name) {
         return mExtras == null ? null : mExtras.getCharArray(name);
     }
 
@@ -7694,7 +7694,7 @@
      *
      * @see #putExtra(String, int[])
      */
-    public int[] getIntArrayExtra(String name) {
+    public @Nullable int[] getIntArrayExtra(String name) {
         return mExtras == null ? null : mExtras.getIntArray(name);
     }
 
@@ -7708,7 +7708,7 @@
      *
      * @see #putExtra(String, long[])
      */
-    public long[] getLongArrayExtra(String name) {
+    public @Nullable long[] getLongArrayExtra(String name) {
         return mExtras == null ? null : mExtras.getLongArray(name);
     }
 
@@ -7722,7 +7722,7 @@
      *
      * @see #putExtra(String, float[])
      */
-    public float[] getFloatArrayExtra(String name) {
+    public @Nullable float[] getFloatArrayExtra(String name) {
         return mExtras == null ? null : mExtras.getFloatArray(name);
     }
 
@@ -7736,7 +7736,7 @@
      *
      * @see #putExtra(String, double[])
      */
-    public double[] getDoubleArrayExtra(String name) {
+    public @Nullable double[] getDoubleArrayExtra(String name) {
         return mExtras == null ? null : mExtras.getDoubleArray(name);
     }
 
@@ -7750,7 +7750,7 @@
      *
      * @see #putExtra(String, String[])
      */
-    public String[] getStringArrayExtra(String name) {
+    public @Nullable String[] getStringArrayExtra(String name) {
         return mExtras == null ? null : mExtras.getStringArray(name);
     }
 
@@ -7764,7 +7764,7 @@
      *
      * @see #putExtra(String, CharSequence[])
      */
-    public CharSequence[] getCharSequenceArrayExtra(String name) {
+    public @Nullable CharSequence[] getCharSequenceArrayExtra(String name) {
         return mExtras == null ? null : mExtras.getCharSequenceArray(name);
     }
 
@@ -7778,7 +7778,7 @@
      *
      * @see #putExtra(String, Bundle)
      */
-    public Bundle getBundleExtra(String name) {
+    public @Nullable Bundle getBundleExtra(String name) {
         return mExtras == null ? null : mExtras.getBundle(name);
     }
 
@@ -8584,7 +8584,7 @@
      * @see #removeExtra
      * @see #getStringExtra(String)
      */
-    public @NonNull Intent putExtra(String name, String value) {
+    public @NonNull Intent putExtra(String name, @Nullable String value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8607,7 +8607,7 @@
      * @see #removeExtra
      * @see #getCharSequenceExtra(String)
      */
-    public @NonNull Intent putExtra(String name, CharSequence value) {
+    public @NonNull Intent putExtra(String name, @Nullable CharSequence value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8630,7 +8630,7 @@
      * @see #removeExtra
      * @see #getParcelableExtra(String)
      */
-    public @NonNull Intent putExtra(String name, Parcelable value) {
+    public @NonNull Intent putExtra(String name, @Nullable Parcelable value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8653,7 +8653,7 @@
      * @see #removeExtra
      * @see #getParcelableArrayExtra(String)
      */
-    public @NonNull Intent putExtra(String name, Parcelable[] value) {
+    public @NonNull Intent putExtra(String name, @Nullable Parcelable[] value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8677,7 +8677,7 @@
      * @see #getParcelableArrayListExtra(String)
      */
     public @NonNull Intent putParcelableArrayListExtra(String name,
-            ArrayList<? extends Parcelable> value) {
+            @Nullable ArrayList<? extends Parcelable> value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8700,7 +8700,8 @@
      * @see #removeExtra
      * @see #getIntegerArrayListExtra(String)
      */
-    public @NonNull Intent putIntegerArrayListExtra(String name, ArrayList<Integer> value) {
+    public @NonNull Intent putIntegerArrayListExtra(String name,
+            @Nullable ArrayList<Integer> value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8723,7 +8724,7 @@
      * @see #removeExtra
      * @see #getStringArrayListExtra(String)
      */
-    public @NonNull Intent putStringArrayListExtra(String name, ArrayList<String> value) {
+    public @NonNull Intent putStringArrayListExtra(String name, @Nullable ArrayList<String> value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8747,7 +8748,7 @@
      * @see #getCharSequenceArrayListExtra(String)
      */
     public @NonNull Intent putCharSequenceArrayListExtra(String name,
-            ArrayList<CharSequence> value) {
+            @Nullable ArrayList<CharSequence> value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8770,7 +8771,7 @@
      * @see #removeExtra
      * @see #getSerializableExtra(String)
      */
-    public @NonNull Intent putExtra(String name, Serializable value) {
+    public @NonNull Intent putExtra(String name, @Nullable Serializable value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8793,7 +8794,7 @@
      * @see #removeExtra
      * @see #getBooleanArrayExtra(String)
      */
-    public @NonNull Intent putExtra(String name, boolean[] value) {
+    public @NonNull Intent putExtra(String name, @Nullable boolean[] value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8816,7 +8817,7 @@
      * @see #removeExtra
      * @see #getByteArrayExtra(String)
      */
-    public @NonNull Intent putExtra(String name, byte[] value) {
+    public @NonNull Intent putExtra(String name, @Nullable byte[] value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8839,7 +8840,7 @@
      * @see #removeExtra
      * @see #getShortArrayExtra(String)
      */
-    public @NonNull Intent putExtra(String name, short[] value) {
+    public @NonNull Intent putExtra(String name, @Nullable short[] value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8862,7 +8863,7 @@
      * @see #removeExtra
      * @see #getCharArrayExtra(String)
      */
-    public @NonNull Intent putExtra(String name, char[] value) {
+    public @NonNull Intent putExtra(String name, @Nullable char[] value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8885,7 +8886,7 @@
      * @see #removeExtra
      * @see #getIntArrayExtra(String)
      */
-    public @NonNull Intent putExtra(String name, int[] value) {
+    public @NonNull Intent putExtra(String name, @Nullable int[] value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8908,7 +8909,7 @@
      * @see #removeExtra
      * @see #getLongArrayExtra(String)
      */
-    public @NonNull Intent putExtra(String name, long[] value) {
+    public @NonNull Intent putExtra(String name, @Nullable long[] value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8931,7 +8932,7 @@
      * @see #removeExtra
      * @see #getFloatArrayExtra(String)
      */
-    public @NonNull Intent putExtra(String name, float[] value) {
+    public @NonNull Intent putExtra(String name, @Nullable float[] value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8954,7 +8955,7 @@
      * @see #removeExtra
      * @see #getDoubleArrayExtra(String)
      */
-    public @NonNull Intent putExtra(String name, double[] value) {
+    public @NonNull Intent putExtra(String name, @Nullable double[] value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8977,7 +8978,7 @@
      * @see #removeExtra
      * @see #getStringArrayExtra(String)
      */
-    public @NonNull Intent putExtra(String name, String[] value) {
+    public @NonNull Intent putExtra(String name, @Nullable String[] value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -9000,7 +9001,7 @@
      * @see #removeExtra
      * @see #getCharSequenceArrayExtra(String)
      */
-    public @NonNull Intent putExtra(String name, CharSequence[] value) {
+    public @NonNull Intent putExtra(String name, @Nullable CharSequence[] value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -9023,7 +9024,7 @@
      * @see #removeExtra
      * @see #getBundleExtra(String)
      */
-    public @NonNull Intent putExtra(String name, Bundle value) {
+    public @NonNull Intent putExtra(String name, @Nullable Bundle value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
diff --git a/core/java/android/content/MimeTypeFilter.java b/core/java/android/content/MimeTypeFilter.java
new file mode 100644
index 0000000..1c26fd9
--- /dev/null
+++ b/core/java/android/content/MimeTypeFilter.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2018 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.content;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import java.util.ArrayList;
+
+/**
+ * Provides utility methods for matching MIME type filters used in ContentProvider.
+ *
+ * <p>Wildcards are allowed only instead of the entire type or subtype with a tree prefix.
+ * Eg. image\/*, *\/* is a valid filter and will match image/jpeg, but image/j* is invalid and
+ * it will not match image/jpeg. Suffixes and parameters are not supported, and they are treated
+ * as part of the subtype during matching. Neither type nor subtype can be empty.
+ *
+ * <p><em>Note: MIME type matching in the Android framework is case-sensitive, unlike the formal
+ * RFC definitions. As a result, you should always write these elements with lower case letters,
+ * or use {@link android.content.Intent#normalizeMimeType} to ensure that they are converted to
+ * lower case.</em>
+ *
+ * <p>MIME types can be null or ill-formatted. In such case they won't match anything.
+ *
+ * <p>MIME type filters must be correctly formatted, or an exception will be thrown.
+ * Copied from support library.
+ * {@hide}
+ */
+public final class MimeTypeFilter {
+
+    private MimeTypeFilter() {
+    }
+
+    private static boolean mimeTypeAgainstFilter(
+            @NonNull String[] mimeTypeParts, @NonNull String[] filterParts) {
+        if (filterParts.length != 2) {
+            throw new IllegalArgumentException(
+                    "Ill-formatted MIME type filter. Must be type/subtype.");
+        }
+        if (filterParts[0].isEmpty() || filterParts[1].isEmpty()) {
+            throw new IllegalArgumentException(
+                    "Ill-formatted MIME type filter. Type or subtype empty.");
+        }
+        if (mimeTypeParts.length != 2) {
+            return false;
+        }
+        if (!"*".equals(filterParts[0])
+                && !filterParts[0].equals(mimeTypeParts[0])) {
+            return false;
+        }
+        if (!"*".equals(filterParts[1])
+                && !filterParts[1].equals(mimeTypeParts[1])) {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Matches one nullable MIME type against one MIME type filter.
+     * @return True if the {@code mimeType} matches the {@code filter}.
+     */
+    public static boolean matches(@Nullable String mimeType, @NonNull String filter) {
+        if (mimeType == null) {
+            return false;
+        }
+
+        final String[] mimeTypeParts = mimeType.split("/");
+        final String[] filterParts = filter.split("/");
+
+        return mimeTypeAgainstFilter(mimeTypeParts, filterParts);
+    }
+
+    /**
+     * Matches one nullable MIME type against an array of MIME type filters.
+     * @return The first matching filter, or null if nothing matches.
+     */
+    @Nullable
+    public static String matches(
+            @Nullable String mimeType, @NonNull String[] filters) {
+        if (mimeType == null) {
+            return null;
+        }
+
+        final String[] mimeTypeParts = mimeType.split("/");
+        for (String filter : filters) {
+            final String[] filterParts = filter.split("/");
+            if (mimeTypeAgainstFilter(mimeTypeParts, filterParts)) {
+                return filter;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Matches multiple MIME types against an array of MIME type filters.
+     * @return The first matching MIME type, or null if nothing matches.
+     */
+    @Nullable
+    public static String matches(
+            @Nullable String[] mimeTypes, @NonNull String filter) {
+        if (mimeTypes == null) {
+            return null;
+        }
+
+        final String[] filterParts = filter.split("/");
+        for (String mimeType : mimeTypes) {
+            final String[] mimeTypeParts = mimeType.split("/");
+            if (mimeTypeAgainstFilter(mimeTypeParts, filterParts)) {
+                return mimeType;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Matches multiple MIME types against an array of MIME type filters.
+     * @return The list of matching MIME types, or empty array if nothing matches.
+     */
+    @NonNull
+    public static String[] matchesMany(
+            @Nullable String[] mimeTypes, @NonNull String filter) {
+        if (mimeTypes == null) {
+            return new String[] {};
+        }
+
+        final ArrayList<String> list = new ArrayList<>();
+        final String[] filterParts = filter.split("/");
+        for (String mimeType : mimeTypes) {
+            final String[] mimeTypeParts = mimeType.split("/");
+            if (mimeTypeAgainstFilter(mimeTypeParts, filterParts)) {
+                list.add(mimeType);
+            }
+        }
+
+        return list.toArray(new String[list.size()]);
+    }
+}
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 6b5c659..48240db 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -27,7 +27,6 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
-import android.os.Build;
 import android.os.Environment;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -1171,11 +1170,11 @@
      * system apps.
      * @hide
      */
-    public static final int HIDDEN_API_ENFORCEMENT_NONE = 0;
+    public static final int HIDDEN_API_ENFORCEMENT_DISABLED = 0;
     /**
      * No API enforcement, but enable the detection logic and warnings. Observed behaviour is the
-     * same as {@link #HIDDEN_API_ENFORCEMENT_NONE} but you may see warnings in the log when APIs
-     * are accessed.
+     * same as {@link #HIDDEN_API_ENFORCEMENT_DISABLED} but you may see warnings in the log when
+     * APIs are accessed.
      * @hide
      * */
     public static final int HIDDEN_API_ENFORCEMENT_JUST_WARN = 1;
@@ -1183,14 +1182,10 @@
      * Dark grey list enforcement. Enforces the dark grey and black lists
      * @hide
      */
-    public static final int HIDDEN_API_ENFORCEMENT_DARK_GREY_AND_BLACK = 2;
-    /**
-     * Blacklist enforcement only.
-     * @hide
-     */
-    public static final int HIDDEN_API_ENFORCEMENT_BLACK = 3;
+    public static final int HIDDEN_API_ENFORCEMENT_ENABLED = 2;
 
-    private static final int HIDDEN_API_ENFORCEMENT_MAX = HIDDEN_API_ENFORCEMENT_BLACK;
+    private static final int HIDDEN_API_ENFORCEMENT_MIN = HIDDEN_API_ENFORCEMENT_DEFAULT;
+    private static final int HIDDEN_API_ENFORCEMENT_MAX = HIDDEN_API_ENFORCEMENT_ENABLED;
 
     /**
      * Values in this IntDef MUST be kept in sync with enum hiddenapi::EnforcementPolicy in
@@ -1199,17 +1194,16 @@
      */
     @IntDef(prefix = { "HIDDEN_API_ENFORCEMENT_" }, value = {
             HIDDEN_API_ENFORCEMENT_DEFAULT,
-            HIDDEN_API_ENFORCEMENT_NONE,
+            HIDDEN_API_ENFORCEMENT_DISABLED,
             HIDDEN_API_ENFORCEMENT_JUST_WARN,
-            HIDDEN_API_ENFORCEMENT_DARK_GREY_AND_BLACK,
-            HIDDEN_API_ENFORCEMENT_BLACK,
+            HIDDEN_API_ENFORCEMENT_ENABLED,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface HiddenApiEnforcementPolicy {}
 
     /** @hide */
     public static boolean isValidHiddenApiEnforcementPolicy(int policy) {
-        return policy >= HIDDEN_API_ENFORCEMENT_DEFAULT && policy <= HIDDEN_API_ENFORCEMENT_MAX;
+        return policy >= HIDDEN_API_ENFORCEMENT_MIN && policy <= HIDDEN_API_ENFORCEMENT_MAX;
     }
 
     private int mHiddenApiPolicy = HIDDEN_API_ENFORCEMENT_DEFAULT;
@@ -1749,16 +1743,12 @@
      */
     public @HiddenApiEnforcementPolicy int getHiddenApiEnforcementPolicy() {
         if (isAllowedToUseHiddenApis()) {
-            return HIDDEN_API_ENFORCEMENT_NONE;
+            return HIDDEN_API_ENFORCEMENT_DISABLED;
         }
         if (mHiddenApiPolicy != HIDDEN_API_ENFORCEMENT_DEFAULT) {
             return mHiddenApiPolicy;
         }
-        if (targetSdkVersion < Build.VERSION_CODES.P) {
-            return HIDDEN_API_ENFORCEMENT_BLACK;
-        } else {
-            return HIDDEN_API_ENFORCEMENT_DARK_GREY_AND_BLACK;
-        }
+        return HIDDEN_API_ENFORCEMENT_ENABLED;
     }
 
     /**
@@ -1777,23 +1767,15 @@
      * This will have no effect if this app is not subject to hidden API enforcement, i.e. if it
      * is on the package whitelist.
      *
-     * @param policyPreP configured policy for pre-P apps, or {@link
-     *        #HIDDEN_API_ENFORCEMENT_DEFAULT} if nothing configured.
-     * @param policyP configured policy for apps targeting P or later, or {@link
-     *        #HIDDEN_API_ENFORCEMENT_DEFAULT} if nothing configured.
+     * @param policy configured policy for this app, or {@link #HIDDEN_API_ENFORCEMENT_DEFAULT}
+     *               if nothing configured.
      * @hide
      */
-    public void maybeUpdateHiddenApiEnforcementPolicy(
-            @HiddenApiEnforcementPolicy int policyPreP, @HiddenApiEnforcementPolicy int policyP) {
+    public void maybeUpdateHiddenApiEnforcementPolicy(@HiddenApiEnforcementPolicy int policy) {
         if (isPackageWhitelistedForHiddenApis()) {
             return;
         }
-        if (targetSdkVersion < Build.VERSION_CODES.P) {
-            setHiddenApiEnforcementPolicy(policyPreP);
-        } else if (targetSdkVersion >= Build.VERSION_CODES.P) {
-            setHiddenApiEnforcementPolicy(policyP);
-        }
-
+        setHiddenApiEnforcementPolicy(policy);
     }
 
     /**
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index 7952c41..bd149fd 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -426,6 +426,31 @@
     }
 
     /**
+     * Authenticates for the given user.
+     * @param cancel An object that can be used to cancel authentication
+     * @param executor An executor to handle callback events
+     * @param callback An object to receive authentication events
+     * @param userId The user to authenticate
+     * @hide
+     */
+    @RequiresPermission(USE_BIOMETRIC_INTERNAL)
+    public void authenticateUser(@NonNull CancellationSignal cancel,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull AuthenticationCallback callback,
+            int userId) {
+        if (cancel == null) {
+            throw new IllegalArgumentException("Must supply a cancellation signal");
+        }
+        if (executor == null) {
+            throw new IllegalArgumentException("Must supply an executor");
+        }
+        if (callback == null) {
+            throw new IllegalArgumentException("Must supply a callback");
+        }
+        authenticateInternal(null /* crypto */, cancel, executor, callback, userId);
+    }
+
+    /**
      * This call warms up the biometric hardware, displays a system-provided dialog, and starts
      * scanning for a biometric. It terminates when {@link
      * AuthenticationCallback#onAuthenticationError(int, CharSequence)} is called, when {@link
@@ -465,7 +490,7 @@
         if (callback == null) {
             throw new IllegalArgumentException("Must supply a callback");
         }
-        authenticateInternal(crypto, cancel, executor, callback);
+        authenticateInternal(crypto, cancel, executor, callback, mContext.getUserId());
     }
 
     /**
@@ -502,7 +527,7 @@
         if (callback == null) {
             throw new IllegalArgumentException("Must supply a callback");
         }
-        authenticateInternal(null /* crypto */, cancel, executor, callback);
+        authenticateInternal(null /* crypto */, cancel, executor, callback, mContext.getUserId());
     }
 
     private void cancelAuthentication() {
@@ -518,7 +543,8 @@
     private void authenticateInternal(@Nullable CryptoObject crypto,
             @NonNull CancellationSignal cancel,
             @NonNull @CallbackExecutor Executor executor,
-            @NonNull AuthenticationCallback callback) {
+            @NonNull AuthenticationCallback callback,
+            int userId) {
         try {
             if (cancel.isCanceled()) {
                 Log.w(TAG, "Authentication already canceled");
@@ -531,7 +557,7 @@
             mExecutor = executor;
             mAuthenticationCallback = callback;
             final long sessionId = crypto != null ? crypto.getOpId() : 0;
-            mService.authenticate(mToken, sessionId, mContext.getUserId(),
+            mService.authenticate(mToken, sessionId, userId,
                     mBiometricServiceReceiver, 0 /* flags */, mContext.getOpPackageName(),
                     mBundle, mDialogReceiver);
         } catch (RemoteException e) {
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 444ca87..7148b12 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -28,8 +28,8 @@
 import android.hardware.camera2.utils.TypeReference;
 import android.util.Rational;
 
-import java.util.Arrays;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
@@ -2668,7 +2668,8 @@
     /**
      * <p>The arrangement of color filters on sensor;
      * represents the colors in the top-left 2x2 section of
-     * the sensor, in reading order.</p>
+     * the sensor, in reading order, for a Bayer camera, or the
+     * light spectrum it captures for MONOCHROME camera.</p>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB RGGB}</li>
@@ -2676,6 +2677,8 @@
      *   <li>{@link #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG GBRG}</li>
      *   <li>{@link #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR BGGR}</li>
      *   <li>{@link #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB RGB}</li>
+     *   <li>{@link #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_MONO MONO}</li>
+     *   <li>{@link #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_NIR NIR}</li>
      * </ul></p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      * <p><b>Full capability</b> -
@@ -2688,6 +2691,8 @@
      * @see #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG
      * @see #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR
      * @see #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB
+     * @see #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_MONO
+     * @see #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_NIR
      */
     @PublicKey
     public static final Key<Integer> SENSOR_INFO_COLOR_FILTER_ARRANGEMENT =
@@ -2919,6 +2924,8 @@
      * <p>Some devices may choose to provide a second set of calibration
      * information for improved quality, including
      * {@link CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT2 android.sensor.referenceIlluminant2} and its corresponding matrices.</p>
+     * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+     * the camera device has RAW capability.</p>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #SENSOR_REFERENCE_ILLUMINANT1_DAYLIGHT DAYLIGHT}</li>
@@ -2981,6 +2988,8 @@
      * <p>If this key is present, then {@link CameraCharacteristics#SENSOR_COLOR_TRANSFORM2 android.sensor.colorTransform2},
      * {@link CameraCharacteristics#SENSOR_CALIBRATION_TRANSFORM2 android.sensor.calibrationTransform2}, and
      * {@link CameraCharacteristics#SENSOR_FORWARD_MATRIX2 android.sensor.forwardMatrix2} will also be present.</p>
+     * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+     * the camera device has RAW capability.</p>
      * <p><b>Range of valid values:</b><br>
      * Any value listed in {@link CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1 android.sensor.referenceIlluminant1}</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
@@ -3006,6 +3015,8 @@
      * colorspace) into this camera device's native sensor color
      * space under the first reference illuminant
      * ({@link CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1 android.sensor.referenceIlluminant1}).</p>
+     * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+     * the camera device has RAW capability.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
@@ -3029,6 +3040,8 @@
      * ({@link CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT2 android.sensor.referenceIlluminant2}).</p>
      * <p>This matrix will only be present if the second reference
      * illuminant is present.</p>
+     * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+     * the camera device has RAW capability.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
@@ -3053,6 +3066,8 @@
      * and the CIE XYZ colorspace when calculating this transform will
      * match the standard white point for the first reference illuminant
      * (i.e. no chromatic adaptation will be applied by this transform).</p>
+     * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+     * the camera device has RAW capability.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
@@ -3079,6 +3094,8 @@
      * (i.e. no chromatic adaptation will be applied by this transform).</p>
      * <p>This matrix will only be present if the second reference
      * illuminant is present.</p>
+     * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+     * the camera device has RAW capability.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
@@ -3101,6 +3118,8 @@
      * this matrix is chosen so that the standard white point for this reference
      * illuminant in the reference sensor colorspace is mapped to D50 in the
      * CIE XYZ colorspace.</p>
+     * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+     * the camera device has RAW capability.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
@@ -3125,6 +3144,8 @@
      * CIE XYZ colorspace.</p>
      * <p>This matrix will only be present if the second reference
      * illuminant is present.</p>
+     * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+     * the camera device has RAW capability.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
@@ -3153,6 +3174,7 @@
      * level values. For raw capture in particular, it is recommended to use
      * pixels from {@link CameraCharacteristics#SENSOR_OPTICAL_BLACK_REGIONS android.sensor.opticalBlackRegions} to calculate black
      * level values for each frame.</p>
+     * <p>For a MONOCHROME camera device, all of the 2x2 channels must have the same values.</p>
      * <p><b>Range of valid values:</b><br>
      * &gt;= 0 for each.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index ac00f14..dc6cffc 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -357,7 +357,7 @@
      * </p>
      *
      * <p>MONOCHROME-capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES}
-     * includes {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME MONOCHROME})
+     * includes {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME MONOCHROME}) devices
      * supporting {@link android.graphics.ImageFormat#Y8 Y8} support substituting {@code YUV}
      * streams with {@code Y8} in all guaranteed stream combinations for the device's hardware level
      * and capabilities.</p>
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index ffc2264..402472a 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -880,11 +880,15 @@
 
     /**
      * <p>The camera device is a monochrome camera that doesn't contain a color filter array,
-     * and the pixel values on U and V planes are all 128.</p>
+     * and for YUV_420_888 stream, the pixel values on U and V planes are all 128.</p>
      * <p>A MONOCHROME camera must support the guaranteed stream combinations required for
      * its device level and capabilities. Additionally, if the monochrome camera device
      * supports Y8 format, all mandatory stream combination requirements related to {@link android.graphics.ImageFormat#YUV_420_888 YUV_420_888} apply
-     * to {@link android.graphics.ImageFormat#Y8 Y8} as well.</p>
+     * to {@link android.graphics.ImageFormat#Y8 Y8} as well. There are no
+     * mandatory stream combination requirements with regard to
+     * {@link android.graphics.ImageFormat#Y8 Y8} for Bayer camera devices.</p>
+     * <p>Starting from Android Q, the SENSOR_INFO_COLOR_FILTER_ARRANGEMENT of a MONOCHROME
+     * camera will be either MONO or NIR.</p>
      * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
      */
     public static final int REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME = 12;
@@ -937,6 +941,23 @@
      */
     public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB = 4;
 
+    /**
+     * <p>Sensor doesn't have any Bayer color filter.
+     * Such sensor captures visible light in monochrome. The exact weighting and
+     * wavelengths captured is not specified, but generally only includes the visible
+     * frequencies. This value implies a MONOCHROME camera.</p>
+     * @see CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
+     */
+    public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_MONO = 5;
+
+    /**
+     * <p>Sensor has a near infrared filter capturing light with wavelength between
+     * roughly 750nm and 1400nm, and the same filter covers the whole sensor array. This
+     * value implies a MONOCHROME camera.</p>
+     * @see CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
+     */
+    public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_NIR = 6;
+
     //
     // Enumeration values for CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE
     //
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 2744e91..8ebaf2f 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -24,8 +24,8 @@
 import android.hardware.camera2.impl.SyntheticKey;
 import android.hardware.camera2.params.OutputConfiguration;
 import android.hardware.camera2.utils.HashCodeHelpers;
-import android.hardware.camera2.utils.TypeReference;
 import android.hardware.camera2.utils.SurfaceUtils;
+import android.hardware.camera2.utils.TypeReference;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.ArraySet;
@@ -2947,8 +2947,8 @@
      * of points can be less than max (that is, the request doesn't have to
      * always provide a curve with number of points equivalent to
      * {@link CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS android.tonemap.maxCurvePoints}).</p>
-     * <p>For devices with MONOCHROME capability, only red channel is used. Green and blue channels
-     * are ignored.</p>
+     * <p>For devices with MONOCHROME capability, all three channels must have the same set of
+     * control points.</p>
      * <p>A few examples, and their corresponding graphical mappings; these
      * only specify the red channel and the precision is limited to 4
      * digits, for conciseness.</p>
@@ -3011,8 +3011,8 @@
      * of points can be less than max (that is, the request doesn't have to
      * always provide a curve with number of points equivalent to
      * {@link CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS android.tonemap.maxCurvePoints}).</p>
-     * <p>For devices with MONOCHROME capability, only red channel is used. Green and blue channels
-     * are ignored.</p>
+     * <p>For devices with MONOCHROME capability, all three channels must have the same set of
+     * control points.</p>
      * <p>A few examples, and their corresponding graphical mappings; these
      * only specify the red channel and the precision is limited to 4
      * digits, for conciseness.</p>
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 2b67f3e..3d70c51 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -3417,6 +3417,8 @@
      * used to interpolate between the provided color transforms when
      * processing raw sensor data.</p>
      * <p>The order of the values is R, G, B; where R is in the lowest index.</p>
+     * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+     * the camera device has RAW capability.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      */
     @PublicKey
@@ -3442,6 +3444,8 @@
      * that channel.</p>
      * <p>A more detailed description of the noise model can be found in the
      * Adobe DNG specification for the NoiseProfile tag.</p>
+     * <p>For a MONOCHROME camera, there is only one color channel. So the noise model coefficients
+     * will only contain one S and one O.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      *
      * @see CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
@@ -3482,6 +3486,8 @@
      * <li>R &gt; 1.20 will require strong software correction to produce
      * a usuable image (&gt;20% divergence).</li>
      * </ul>
+     * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+     * the camera device has RAW capability.</p>
      * <p><b>Range of valid values:</b><br></p>
      * <p>&gt;= 0</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
@@ -3592,6 +3598,7 @@
      * layout key (see {@link CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT android.sensor.info.colorFilterArrangement}), i.e. the
      * nth value given corresponds to the black level offset for the nth
      * color channel listed in the CFA.</p>
+     * <p>For a MONOCHROME camera, all of the 2x2 channels must have the same values.</p>
      * <p>This key will be available if {@link CameraCharacteristics#SENSOR_OPTICAL_BLACK_REGIONS android.sensor.opticalBlackRegions} is available or the
      * camera device advertises this key via {@link android.hardware.camera2.CameraCharacteristics#getAvailableCaptureResultKeys }.</p>
      * <p><b>Range of valid values:</b><br>
@@ -3852,6 +3859,17 @@
      * <p>As a visualization only, inverting the full-color map to recover an
      * image of a gray wall (using bicubic interpolation for visual quality) as captured by the sensor gives:</p>
      * <p><img alt="Image of a uniform white wall (inverse shading map)" src="/reference/images/camera2/metadata/android.statistics.lensShadingMap/inv_shading.png" /></p>
+     * <p>For a MONOCHROME camera, all of the 2x2 channels must have the same values. An example
+     * shading map for such a camera is defined as:</p>
+     * <pre><code>android.lens.info.shadingMapSize = [ 4, 3 ]
+     * android.statistics.lensShadingMap =
+     * [ 1.3, 1.3, 1.3, 1.3,  1.2, 1.2, 1.2, 1.2,
+     *     1.1, 1.1, 1.1, 1.1,  1.3, 1.3, 1.3, 1.3,
+     *   1.2, 1.2, 1.2, 1.2,  1.1, 1.1, 1.1, 1.1,
+     *     1.0, 1.0, 1.0, 1.0,  1.2, 1.2, 1.2, 1.2,
+     *   1.3, 1.3, 1.3, 1.3,   1.2, 1.2, 1.2, 1.2,
+     *     1.2, 1.2, 1.2, 1.2,  1.3, 1.3, 1.3, 1.3 ]
+     * </code></pre>
      * <p><b>Range of valid values:</b><br>
      * Each gain factor is &gt;= 1</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
@@ -3894,13 +3912,13 @@
      * (x,y) ϵ (0 ... N-1, 0 ... M-1) is the value of the shading map at
      * pixel ( ((W-1)/(N-1)) * x, ((H-1)/(M-1)) * y) for the four color channels.
      * The map is assumed to be bilinearly interpolated between the sample points.</p>
-     * <p>The channel order is [R, Geven, Godd, B], where Geven is the green
-     * channel for the even rows of a Bayer pattern, and Godd is the odd rows.
+     * <p>For a Bayer camera, the channel order is [R, Geven, Godd, B], where Geven is
+     * the green channel for the even rows of a Bayer pattern, and Godd is the odd rows.
      * The shading map is stored in a fully interleaved format, and its size
      * is provided in the camera static metadata by android.lens.info.shadingMapSize.</p>
      * <p>The shading map will generally have on the order of 30-40 rows and columns,
      * and will be smaller than 64x64.</p>
-     * <p>As an example, given a very small map defined as:</p>
+     * <p>As an example, given a very small map for a Bayer camera defined as:</p>
      * <pre><code>android.lens.info.shadingMapSize = [ 4, 3 ]
      * android.statistics.lensShadingMap =
      * [ 1.3, 1.2, 1.15, 1.2,  1.2, 1.2, 1.15, 1.2,
@@ -3920,6 +3938,17 @@
      * image of a gray wall (using bicubic interpolation for visual quality)
      * as captured by the sensor gives:</p>
      * <p><img alt="Image of a uniform white wall (inverse shading map)" src="/reference/images/camera2/metadata/android.statistics.lensShadingMap/inv_shading.png" /></p>
+     * <p>For a MONOCHROME camera, all of the 2x2 channels must have the same values. An example
+     * shading map for such a camera is defined as:</p>
+     * <pre><code>android.lens.info.shadingMapSize = [ 4, 3 ]
+     * android.statistics.lensShadingMap =
+     * [ 1.3, 1.3, 1.3, 1.3,  1.2, 1.2, 1.2, 1.2,
+     *     1.1, 1.1, 1.1, 1.1,  1.3, 1.3, 1.3, 1.3,
+     *   1.2, 1.2, 1.2, 1.2,  1.1, 1.1, 1.1, 1.1,
+     *     1.0, 1.0, 1.0, 1.0,  1.2, 1.2, 1.2, 1.2,
+     *   1.3, 1.3, 1.3, 1.3,   1.2, 1.2, 1.2, 1.2,
+     *     1.2, 1.2, 1.2, 1.2,  1.3, 1.3, 1.3, 1.3 ]
+     * </code></pre>
      * <p>Note that the RAW image data might be subject to lens shading
      * correction not reported on this map. Query
      * {@link CameraCharacteristics#SENSOR_INFO_LENS_SHADING_APPLIED android.sensor.info.lensShadingApplied} to see if RAW image data has subject
@@ -4250,8 +4279,8 @@
      * of points can be less than max (that is, the request doesn't have to
      * always provide a curve with number of points equivalent to
      * {@link CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS android.tonemap.maxCurvePoints}).</p>
-     * <p>For devices with MONOCHROME capability, only red channel is used. Green and blue channels
-     * are ignored.</p>
+     * <p>For devices with MONOCHROME capability, all three channels must have the same set of
+     * control points.</p>
      * <p>A few examples, and their corresponding graphical mappings; these
      * only specify the red channel and the precision is limited to 4
      * digits, for conciseness.</p>
@@ -4314,8 +4343,8 @@
      * of points can be less than max (that is, the request doesn't have to
      * always provide a curve with number of points equivalent to
      * {@link CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS android.tonemap.maxCurvePoints}).</p>
-     * <p>For devices with MONOCHROME capability, only red channel is used. Green and blue channels
-     * are ignored.</p>
+     * <p>For devices with MONOCHROME capability, all three channels must have the same set of
+     * control points.</p>
      * <p>A few examples, and their corresponding graphical mappings; these
      * only specify the red channel and the precision is limited to 4
      * digits, for conciseness.</p>
diff --git a/core/java/android/hardware/camera2/params/BlackLevelPattern.java b/core/java/android/hardware/camera2/params/BlackLevelPattern.java
index 6d6c094..283977f 100644
--- a/core/java/android/hardware/camera2/params/BlackLevelPattern.java
+++ b/core/java/android/hardware/camera2/params/BlackLevelPattern.java
@@ -16,13 +16,17 @@
 
 package android.hardware.camera2.params;
 
-import java.util.Arrays;
-
 import static com.android.internal.util.Preconditions.checkNotNull;
 
+import java.util.Arrays;
+
 /**
  * Immutable class to store a 4-element vector of integers corresponding to a 2x2 pattern
  * of color channel offsets used for the black level offsets of each color channel.
+ *
+ * For a camera device with
+ * {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME
+ * MONOCHROME} capability, all 4 elements of the pattern will have the same value.
  */
 public final class BlackLevelPattern {
 
@@ -133,6 +137,12 @@
      * {@link android.hardware.camera2.CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT}).
      * </p>
      *
+     * <p>A {@link
+     * android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME
+     * MONOCHROME} camera only has one channel. As a result, the returned string will contain 4
+     * identical values.
+     * </p>
+     *
      * @return string representation of {@link BlackLevelPattern}
      *
      * @see android.hardware.camera2.CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
diff --git a/core/java/android/hardware/camera2/params/TonemapCurve.java b/core/java/android/hardware/camera2/params/TonemapCurve.java
index 71e68a5..90e6355 100644
--- a/core/java/android/hardware/camera2/params/TonemapCurve.java
+++ b/core/java/android/hardware/camera2/params/TonemapCurve.java
@@ -34,6 +34,10 @@
  * use as the tonemapping/contrast/gamma curve when {@link CaptureRequest#TONEMAP_MODE} is
  * set to {@link CameraMetadata#TONEMAP_MODE_CONTRAST_CURVE}.</p>
  *
+ * <p>For a camera device with
+ * {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME
+ * MONOCHROME} capability, all 3 channels will contain the same set of control points.
+ *
  * <p>The total number of points {@code (Pin, Pout)} for each color channel can be no more than
  * {@link CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS}.</p>
  *
diff --git a/core/java/android/hardware/display/ColorDisplayManager.java b/core/java/android/hardware/display/ColorDisplayManager.java
new file mode 100644
index 0000000..0a76c2b
--- /dev/null
+++ b/core/java/android/hardware/display/ColorDisplayManager.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 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.hardware.display;
+
+import android.content.Context;
+
+import com.android.internal.R;
+
+/**
+ * Manages the display's color transforms and modes.
+ * @hide
+ */
+public final class ColorDisplayManager {
+
+    /**
+     * Returns {@code true} if Night Display is supported by the device.
+     */
+    public static boolean isNightDisplayAvailable(Context context) {
+        return context.getResources().getBoolean(R.bool.config_nightDisplayAvailable);
+    }
+}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 9cf7de5..c437dde 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -2421,7 +2421,7 @@
 
     public static final IntToString[] HISTORY_EVENT_INT_FORMATTERS = new IntToString[] {
             sUidToString, sUidToString, sUidToString, sUidToString, sUidToString, sUidToString,
-            sUidToString, sUidToString, sUidToString, sUidToString, sUidToString, sUidToString,
+            sUidToString, sUidToString, sUidToString, sUidToString, sUidToString, sIntToString,
             sUidToString, sUidToString, sUidToString, sUidToString, sUidToString, sUidToString,
             sUidToString, sUidToString, sUidToString, sIntToString
     };
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 1bae3f7..0c1aae8 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -199,6 +199,7 @@
      * @hide
      */
     @SystemApi
+    @TestApi
     public static File getProductDirectory() {
         return DIR_PRODUCT_ROOT;
     }
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 1f47f93..28ea553 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -1390,3 +1390,4 @@
         }
     }
 }
+
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 7ceeb52..ca5b233 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -48,6 +48,8 @@
     boolean isPowerSaveMode();
     PowerSaveState getPowerSaveState(int serviceType);
     boolean setPowerSaveMode(boolean mode);
+    boolean setDynamicPowerSavings(boolean dynamicPowerSavingsEnabled, int disableThreshold);
+    int getPowerSaveMode();
     boolean isDeviceIdleMode();
     boolean isLightDeviceIdleMode();
 
diff --git a/core/java/android/os/IStatsManager.aidl b/core/java/android/os/IStatsManager.aidl
index 124f207..74d434c 100644
--- a/core/java/android/os/IStatsManager.aidl
+++ b/core/java/android/os/IStatsManager.aidl
@@ -62,12 +62,15 @@
      * Inform statsd what the version and package are for each uid. Note that each array should
      * have the same number of elements, and version[i] and package[i] correspond to uid[i].
      */
-    oneway void informAllUidData(in int[] uid, in long[] version, in String[] app);
+    oneway void informAllUidData(in int[] uid, in long[] version, in String[] version_string,
+        in String[] app, in String[] installer);
 
     /**
-     * Inform statsd what the uid and version are for one app that was updated.
+     * Inform statsd what the uid, version, version_string, and installer are for one app that was
+     * updated.
      */
-    oneway void informOnePackage(in String app, in int uid, in long version);
+    oneway void informOnePackage(in String app, in int uid, in long version,
+        in String version_string, in String installer);
 
     /**
      * Inform stats that an app was removed.
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 126588a..44b9e311 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -1056,6 +1056,9 @@
     /**
      * Internal class representing a remote status read by
      * {@link ParcelFileDescriptor#readCommStatus(FileDescriptor, byte[])}.
+     *
+     * Warning: this must be kept in sync with ParcelFileDescriptorStatus at
+     * frameworks/native/libs/binder/Parcel.cpp
      */
     private static class Status {
         /** Special value indicating remote side died. */
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 27c281d..a307cd8 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import android.Manifest.permission;
 import android.annotation.IntDef;
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
@@ -1185,6 +1186,105 @@
     }
 
     /**
+     * Updates the current state of dynamic power savings and disable threshold. This is
+     * a signal to the system which an app can update to serve as an indicator that
+     * the user will be in a battery critical situation before being able to plug in.
+     * Only apps with the {@link android.Manifest.permission#POWER_SAVER} permission may do this.
+     * This is a device global state, not a per user setting.
+     *
+     * <p>When enabled, the system may enact various measures for reducing power consumption in
+     * order to help ensure that the user will make it to their next charging point. The most
+     * visible of these will be the automatic enabling of battery saver if the user has set
+     * their battery saver mode to "automatic". Note
+     * that this is NOT simply an on/off switch for features, but rather a hint for the
+     * system to consider enacting these power saving features, some of which have additional
+     * logic around when to activate based on this signal.
+     *
+     * <p>The provided threshold is the percentage the system should consider itself safe at given
+     * the current state of the device. The value is an integer representing a battery level.
+     *
+     * <p>The threshold is meant to set an explicit stopping point for dynamic power savings
+     * functionality so that the dynamic power savings itself remains a signal rather than becoming
+     * an on/off switch for a subset of features.
+     * @hide
+     *
+     * @param dynamicPowerSavingsEnabled A signal indicating to the system if it believes the
+     * dynamic power savings behaviors should be activated.
+     * @param disableThreshold When the suggesting app believes it would be safe to disable dynamic
+     * power savings behaviors.
+     * @return True if the update was allowed and succeeded.
+     *
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    @RequiresPermission(permission.POWER_SAVER)
+    public boolean setDynamicPowerSavings(boolean dynamicPowerSavingsEnabled,
+            int disableThreshold) {
+        try {
+            return mService.setDynamicPowerSavings(dynamicPowerSavingsEnabled, disableThreshold);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Indicates automatic battery saver toggling by the system will be based on percentage.
+     *
+     * @see PowerManager#getPowerSaveMode()
+     *
+     *  @hide
+     */
+    @SystemApi
+    @TestApi
+    public static final int POWER_SAVER_MODE_PERCENTAGE = 0;
+
+    /**
+     * Indicates automatic battery saver toggling by the system will be based on the state
+     * of the dynamic power savings signal.
+     *
+     * @see PowerManager#setDynamicPowerSavings(boolean, int)
+     * @see PowerManager#getPowerSaveMode()
+     *
+     *  @hide
+     */
+    @SystemApi
+    @TestApi
+    public static final int POWER_SAVER_MODE_DYNAMIC = 1;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(value = {
+        POWER_SAVER_MODE_PERCENTAGE,
+        POWER_SAVER_MODE_DYNAMIC
+
+    })
+    public @interface AutoPowerSaverMode{}
+
+
+    /**
+     * Returns the current battery saver control mode. Values it may return are defined in
+     * AutoPowerSaverMode. Note that this is a global device state, not a per user setting.
+     *
+     * @return The current value power saver mode for the system.
+     *
+     * @see AutoPowerSaverMode
+     * @see PowerManager#getPowerSaveMode()
+     * @hide
+     */
+    @AutoPowerSaverMode
+    @SystemApi
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.POWER_SAVER)
+    public int getPowerSaveMode() {
+        try {
+            return mService.getPowerSaveMode();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Get data about the battery saver mode for a specific service
      * @param serviceType unique key for the service, one of {@link ServiceType}
      * @return Battery saver state data.
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 8a36a78..423ce77 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -268,6 +268,9 @@
     public static final int ENCRYPTION_STATE_ERROR_CORRUPT =
             IVold.ENCRYPTION_STATE_ERROR_CORRUPT;
 
+    /** @hide Prefix used in sandboxIds for apps with sharedUserIds */
+    public static final String SHARED_SANDBOX_PREFIX = "shared-";
+
     private static volatile IStorageManager sStorageManager = null;
 
     private final Context mContext;
@@ -801,7 +804,7 @@
         try {
             for (VolumeInfo vol : mStorageManager.getVolumes(0)) {
                 if (vol.path != null && FileUtils.contains(vol.path, pathString)
-                        && vol.type != VolumeInfo.TYPE_PUBLIC) {
+                        && vol.type != VolumeInfo.TYPE_PUBLIC && vol.type != VolumeInfo.TYPE_STUB) {
                     // TODO: verify that emulated adopted devices have UUID of
                     // underlying volume
                     try {
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index e55afb6..8c3aa17 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -84,6 +84,7 @@
     public static final int TYPE_EMULATED = IVold.VOLUME_TYPE_EMULATED;
     public static final int TYPE_ASEC = IVold.VOLUME_TYPE_ASEC;
     public static final int TYPE_OBB = IVold.VOLUME_TYPE_OBB;
+    public static final int TYPE_STUB = IVold.VOLUME_TYPE_STUB;
 
     public static final int STATE_UNMOUNTED = IVold.VOLUME_STATE_UNMOUNTED;
     public static final int STATE_CHECKING = IVold.VOLUME_STATE_CHECKING;
@@ -295,7 +296,7 @@
     }
 
     public boolean isVisibleForUser(int userId) {
-        if (type == TYPE_PUBLIC && mountUserId == userId) {
+        if ((type == TYPE_PUBLIC || type == TYPE_STUB) && mountUserId == userId) {
             return isVisible();
         } else if (type == TYPE_EMULATED) {
             return isVisible();
@@ -327,7 +328,7 @@
     public File getPathForUser(int userId) {
         if (path == null) {
             return null;
-        } else if (type == TYPE_PUBLIC) {
+        } else if (type == TYPE_PUBLIC || type == TYPE_STUB) {
             return new File(path);
         } else if (type == TYPE_EMULATED) {
             return new File(path, Integer.toString(userId));
@@ -344,7 +345,7 @@
     public File getInternalPathForUser(int userId) {
         if (path == null) {
             return null;
-        } else if (type == TYPE_PUBLIC) {
+        } else if (type == TYPE_PUBLIC || type == TYPE_STUB) {
             // TODO: plumb through cleaner path from vold
             return new File(path.replace("/storage/", "/mnt/media_rw/"));
         } else {
@@ -390,7 +391,7 @@
                 removable = true;
             }
 
-        } else if (type == TYPE_PUBLIC) {
+        } else if (type == TYPE_PUBLIC || type == TYPE_STUB) {
             emulated = false;
             removable = true;
 
@@ -447,7 +448,8 @@
 
     public @Nullable Intent buildBrowseIntentForUser(int userId) {
         final Uri uri;
-        if (type == VolumeInfo.TYPE_PUBLIC && mountUserId == userId) {
+        if ((type == VolumeInfo.TYPE_PUBLIC || type == VolumeInfo.TYPE_STUB)
+                && mountUserId == userId) {
             uri = DocumentsContract.buildRootUri(DOCUMENT_AUTHORITY, fsUuid);
         } else if (type == VolumeInfo.TYPE_EMULATED && isPrimary()) {
             uri = DocumentsContract.buildRootUri(DOCUMENT_AUTHORITY,
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 67e52aa..16d454d 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -16,12 +16,11 @@
 
 package android.provider;
 
-import static android.system.OsConstants.SEEK_SET;
-
 import static com.android.internal.util.Preconditions.checkArgument;
 import static com.android.internal.util.Preconditions.checkCollectionElementsNotNull;
 import static com.android.internal.util.Preconditions.checkCollectionNotEmpty;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
 import android.content.ContentProviderClient;
@@ -29,13 +28,12 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
+import android.content.MimeTypeFilter;
 import android.content.pm.ResolveInfo;
 import android.content.res.AssetFileDescriptor;
 import android.database.Cursor;
 import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
 import android.graphics.ImageDecoder;
-import android.graphics.Matrix;
 import android.graphics.Point;
 import android.media.ExifInterface;
 import android.net.Uri;
@@ -50,20 +48,13 @@
 import android.os.ParcelableException;
 import android.os.RemoteException;
 import android.os.storage.StorageVolume;
-import android.system.ErrnoException;
-import android.system.Os;
 import android.util.DataUnit;
 import android.util.Log;
-import android.util.Size;
 
-import libcore.io.IoUtils;
-
-import java.io.BufferedInputStream;
 import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
 
@@ -113,6 +104,54 @@
     public static final String EXTRA_TARGET_URI = "android.content.extra.TARGET_URI";
 
     /**
+     * Key for {@link DocumentsProvider} to query display name is matched.
+     * The match of display name is partial matching and case-insensitive.
+     * Ex: The value is "o", the display name of the results will contain
+     * both "foo" and "Open".
+     *
+     * @see DocumentsProvider#querySearchDocuments(String, String[],
+     *      Bundle)
+     * {@hide}
+     */
+    public static final String QUERY_ARG_DISPLAY_NAME = "android:query-arg-display-name";
+
+    /**
+     * Key for {@link DocumentsProvider} to query mime types is matched.
+     * The value is a string array, it can support different mime types.
+     * Each items will be treated as "OR" condition. Ex: {"image/*" ,
+     * "video/*"}. The mime types of the results will contain both image
+     * type and video type.
+     *
+     * @see DocumentsProvider#querySearchDocuments(String, String[],
+     *      Bundle)
+     * {@hide}
+     */
+    public static final String QUERY_ARG_MIME_TYPES = "android:query-arg-mime-types";
+
+    /**
+     * Key for {@link DocumentsProvider} to query the file size in bytes is
+     * larger than the value.
+     *
+     * @see DocumentsProvider#querySearchDocuments(String, String[],
+     *      Bundle)
+     * {@hide}
+     */
+    public static final String QUERY_ARG_FILE_SIZE_OVER = "android:query-arg-file-size-over";
+
+    /**
+     * Key for {@link DocumentsProvider} to query the last modified time
+     * is newer than the value. The unit is in milliseconds since
+     * January 1, 1970 00:00:00.0 UTC.
+     *
+     * @see DocumentsProvider#querySearchDocuments(String, String[],
+     *      Bundle)
+     * @see Document#COLUMN_LAST_MODIFIED
+     * {@hide}
+     */
+    public static final String QUERY_ARG_LAST_MODIFIED_AFTER =
+            "android:query-arg-last-modified-after";
+
+    /**
      * Sets the desired initial location visible to user when file chooser is shown.
      *
      * <p>Applicable to {@link Intent} with actions:
@@ -929,6 +968,89 @@
     }
 
     /**
+     * Check if the values match the query arguments.
+     *
+     * @param queryArgs the query arguments
+     * @param displayName the display time to check against
+     * @param mimeType the mime type to check against
+     * @param lastModified the last modified time to check against
+     * @param size the size to check against
+     * @hide
+     */
+    public static boolean matchSearchQueryArguments(Bundle queryArgs, String displayName,
+            String mimeType, long lastModified, long size) {
+        if (queryArgs == null) {
+            return true;
+        }
+
+        final String argDisplayName = queryArgs.getString(QUERY_ARG_DISPLAY_NAME, "");
+        if (!argDisplayName.isEmpty()) {
+            // TODO (118795812) : Enhance the search string handled in DocumentsProvider
+            if (!displayName.toLowerCase().contains(argDisplayName.toLowerCase())) {
+                return false;
+            }
+        }
+
+        final long argFileSize = queryArgs.getLong(QUERY_ARG_FILE_SIZE_OVER, -1 /* defaultValue */);
+        if (argFileSize != -1 && size < argFileSize) {
+            return false;
+        }
+
+        final long argLastModified = queryArgs.getLong(QUERY_ARG_LAST_MODIFIED_AFTER,
+                -1 /* defaultValue */);
+        if (argLastModified != -1 && lastModified < argLastModified) {
+            return false;
+        }
+
+        final String[] argMimeTypes = queryArgs.getStringArray(QUERY_ARG_MIME_TYPES);
+        if (argMimeTypes != null && argMimeTypes.length > 0) {
+            mimeType = Intent.normalizeMimeType(mimeType);
+            for (String type : argMimeTypes) {
+                if (MimeTypeFilter.matches(mimeType, Intent.normalizeMimeType(type))) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Get the handled query arguments from the query bundle. The handled arguments are
+     * {@link DocumentsContract#QUERY_ARG_DISPLAY_NAME},
+     * {@link DocumentsContract#QUERY_ARG_MIME_TYPES},
+     * {@link DocumentsContract#QUERY_ARG_FILE_SIZE_OVER} and
+     * {@link DocumentsContract#QUERY_ARG_LAST_MODIFIED_AFTER}.
+     *
+     * @param queryArgs the query arguments to be parsed.
+     * @return the handled query arguments
+     * @hide
+     */
+    public static String[] getHandledQueryArguments(Bundle queryArgs) {
+        if (queryArgs == null) {
+            return new String[0];
+        }
+
+        final ArrayList<String> args = new ArrayList<>();
+        if (queryArgs.keySet().contains(QUERY_ARG_DISPLAY_NAME)) {
+            args.add(QUERY_ARG_DISPLAY_NAME);
+        }
+
+        if (queryArgs.keySet().contains(QUERY_ARG_FILE_SIZE_OVER)) {
+            args.add(QUERY_ARG_FILE_SIZE_OVER);
+        }
+
+        if (queryArgs.keySet().contains(QUERY_ARG_LAST_MODIFIED_AFTER)) {
+            args.add(QUERY_ARG_LAST_MODIFIED_AFTER);
+        }
+
+        if (queryArgs.keySet().contains(QUERY_ARG_MIME_TYPES)) {
+            args.add(QUERY_ARG_MIME_TYPES);
+        }
+        return args.toArray(new String[0]);
+    }
+
+    /**
      * Test if the given URI represents a {@link Document} backed by a
      * {@link DocumentsProvider}.
      *
@@ -1052,6 +1174,15 @@
         return searchDocumentsUri.getQueryParameter(PARAM_QUERY);
     }
 
+    /**
+     * Extract the search query from a Bundle
+     * {@link #QUERY_ARG_DISPLAY_NAME}.
+     * {@hide}
+     */
+    public static String getSearchDocumentsQuery(@NonNull Bundle bundle) {
+        return bundle.getString(QUERY_ARG_DISPLAY_NAME, "" /* defaultValue */);
+    }
+
     /** {@hide} */
     @UnsupportedAppUsage
     public static Uri setManageMode(Uri uri) {
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index 68f8acd..58f8213 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -32,7 +32,6 @@
 import static android.provider.DocumentsContract.buildTreeDocumentUri;
 import static android.provider.DocumentsContract.getDocumentId;
 import static android.provider.DocumentsContract.getRootId;
-import static android.provider.DocumentsContract.getSearchDocumentsQuery;
 import static android.provider.DocumentsContract.getTreeDocumentId;
 import static android.provider.DocumentsContract.isTreeUri;
 
@@ -47,6 +46,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
+import android.content.MimeTypeFilter;
 import android.content.UriMatcher;
 import android.content.pm.PackageManager;
 import android.content.pm.ProviderInfo;
@@ -651,6 +651,55 @@
     }
 
     /**
+     * Return documents that match the given query under the requested
+     * root. The returned documents should be sorted by relevance in descending
+     * order. How documents are matched against the query string is an
+     * implementation detail left to each provider, but it's suggested that at
+     * least {@link Document#COLUMN_DISPLAY_NAME} be matched in a
+     * case-insensitive fashion.
+     * <p>
+     * If your provider is cloud-based, and you have some data cached or pinned
+     * locally, you may return the local data immediately, setting
+     * {@link DocumentsContract#EXTRA_LOADING} on the Cursor to indicate that
+     * you are still fetching additional data. Then, when the network data is
+     * available, you can send a change notification to trigger a requery and
+     * return the complete contents.
+     * <p>
+     * To support change notifications, you must
+     * {@link Cursor#setNotificationUri(ContentResolver, Uri)} with a relevant
+     * Uri, such as {@link DocumentsContract#buildSearchDocumentsUri(String,
+     * String, String)}. Then you can call {@link ContentResolver#notifyChange(Uri,
+     * android.database.ContentObserver, boolean)} with that Uri to send change
+     * notifications.
+     *
+     * @param rootId the root to search under.
+     * @param projection list of {@link Document} columns to put into the
+     *            cursor. If {@code null} all supported columns should be
+     *            included.
+     * @param queryArgs the query arguments.
+     *            {@link DocumentsContract#QUERY_ARG_DISPLAY_NAME},
+     *            {@link DocumentsContract#QUERY_ARG_MIME_TYPES},
+     *            {@link DocumentsContract#QUERY_ARG_FILE_SIZE_OVER},
+     *            {@link DocumentsContract#QUERY_ARG_LAST_MODIFIED_AFTER}.
+     * @return cursor containing search result. Include
+     *         {@link ContentResolver#EXTRA_HONORED_ARGS} in {@link Cursor}
+     *         extras {@link Bundle} when any QUERY_ARG_* value was honored
+     *         during the preparation of the results.
+     *
+     * @see ContentResolver#EXTRA_HONORED_ARGS
+     * @see DocumentsContract#EXTRA_LOADING
+     * @see DocumentsContract#EXTRA_INFO
+     * @see DocumentsContract#EXTRA_ERROR
+     * {@hide}
+     */
+    @SuppressWarnings("unused")
+    public Cursor querySearchDocuments(String rootId, String[] projection, Bundle queryArgs)
+            throws FileNotFoundException {
+        return querySearchDocuments(rootId, DocumentsContract.getSearchDocumentsQuery(queryArgs),
+                projection);
+    }
+
+    /**
      * Ejects the root. Throws {@link IllegalStateException} if ejection failed.
      *
      * @param rootId the root to be ejected.
@@ -795,7 +844,7 @@
      *      {@link #queryDocument(String, String[])},
      *      {@link #queryRecentDocuments(String, String[])},
      *      {@link #queryRoots(String[])}, and
-     *      {@link #querySearchDocuments(String, String, String[])}.
+     *      {@link #querySearchDocuments(String, String[], Bundle)}.
      */
     @Override
     public Cursor query(Uri uri, String[] projection, String selection,
@@ -812,7 +861,7 @@
      * @see #queryRecentDocuments(String, String[], Bundle, CancellationSignal)
      * @see #queryDocument(String, String[])
      * @see #queryChildDocuments(String, String[], String)
-     * @see #querySearchDocuments(String, String, String[])
+     * @see #querySearchDocuments(String, String[], Bundle)
      */
     @Override
     public final Cursor query(
@@ -825,8 +874,7 @@
                     return queryRecentDocuments(
                             getRootId(uri), projection, queryArgs, cancellationSignal);
                 case MATCH_SEARCH:
-                    return querySearchDocuments(
-                            getRootId(uri), getSearchDocumentsQuery(uri), projection);
+                    return querySearchDocuments(getRootId(uri), projection, queryArgs);
                 case MATCH_DOCUMENT:
                 case MATCH_DOCUMENT_TREE:
                     enforceTree(uri);
@@ -1301,7 +1349,7 @@
                 final long flags =
                     cursor.getLong(cursor.getColumnIndexOrThrow(Document.COLUMN_FLAGS));
                 if ((flags & Document.FLAG_VIRTUAL_DOCUMENT) == 0 && mimeType != null &&
-                        mimeTypeMatches(mimeTypeFilter, mimeType)) {
+                        MimeTypeFilter.matches(mimeType, mimeTypeFilter)) {
                     return new String[] { mimeType };
                 }
             }
@@ -1354,21 +1402,4 @@
         // For any other yet unhandled case, let the provider subclass handle it.
         return openTypedDocument(documentId, mimeTypeFilter, opts, signal);
     }
-
-    /**
-     * @hide
-     */
-    public static boolean mimeTypeMatches(String filter, String test) {
-        if (test == null) {
-            return false;
-        } else if (filter == null || "*/*".equals(filter)) {
-            return true;
-        } else if (filter.equals(test)) {
-            return true;
-        } else if (filter.endsWith("/*")) {
-            return filter.regionMatches(0, test, 0, filter.indexOf('/'));
-        } else {
-            return false;
-        }
-    }
 }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 0aa3a7b..e3401e7 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1825,53 +1825,6 @@
     })
     public @interface ResetMode{}
 
-
-    /**
-     * Indicates that the user has not started setup personalization.
-     * One of the possible states for {@link Secure#USER_SETUP_PERSONALIZATION_STATE}.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int USER_SETUP_PERSONALIZATION_NOT_STARTED = 0;
-
-    /**
-     * Indicates that the user has not yet completed setup personalization.
-     * One of the possible states for {@link Secure#USER_SETUP_PERSONALIZATION_STATE}.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int USER_SETUP_PERSONALIZATION_STARTED = 1;
-
-    /**
-     * Indicates that the user has snoozed personalization and will complete it later.
-     * One of the possible states for {@link Secure#USER_SETUP_PERSONALIZATION_STATE}.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int USER_SETUP_PERSONALIZATION_PAUSED = 2;
-
-    /**
-     * Indicates that the user has completed setup personalization.
-     * One of the possible states for {@link Secure#USER_SETUP_PERSONALIZATION_STATE}.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int USER_SETUP_PERSONALIZATION_COMPLETE = 10;
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({
-            USER_SETUP_PERSONALIZATION_NOT_STARTED,
-            USER_SETUP_PERSONALIZATION_STARTED,
-            USER_SETUP_PERSONALIZATION_PAUSED,
-            USER_SETUP_PERSONALIZATION_COMPLETE
-    })
-    public @interface UserSetupPersonalization {}
-
     /**
      * Activity Extra: Number of certificates
      * <p>
@@ -5650,6 +5603,52 @@
         public static final String USER_SETUP_COMPLETE = "user_setup_complete";
 
         /**
+         * Indicates that the user has not started setup personalization.
+         * One of the possible states for {@link #USER_SETUP_PERSONALIZATION_STATE}.
+         *
+         * @hide
+         */
+        @SystemApi
+        public static final int USER_SETUP_PERSONALIZATION_NOT_STARTED = 0;
+
+        /**
+         * Indicates that the user has not yet completed setup personalization.
+         * One of the possible states for {@link #USER_SETUP_PERSONALIZATION_STATE}.
+         *
+         * @hide
+         */
+        @SystemApi
+        public static final int USER_SETUP_PERSONALIZATION_STARTED = 1;
+
+        /**
+         * Indicates that the user has snoozed personalization and will complete it later.
+         * One of the possible states for {@link #USER_SETUP_PERSONALIZATION_STATE}.
+         *
+         * @hide
+         */
+        @SystemApi
+        public static final int USER_SETUP_PERSONALIZATION_PAUSED = 2;
+
+        /**
+         * Indicates that the user has completed setup personalization.
+         * One of the possible states for {@link #USER_SETUP_PERSONALIZATION_STATE}.
+         *
+         * @hide
+         */
+        @SystemApi
+        public static final int USER_SETUP_PERSONALIZATION_COMPLETE = 10;
+
+        /** @hide */
+        @Retention(RetentionPolicy.SOURCE)
+        @IntDef({
+                USER_SETUP_PERSONALIZATION_NOT_STARTED,
+                USER_SETUP_PERSONALIZATION_STARTED,
+                USER_SETUP_PERSONALIZATION_PAUSED,
+                USER_SETUP_PERSONALIZATION_COMPLETE
+        })
+        public @interface UserSetupPersonalization {}
+
+        /**
          * Defines the user's current state of device personalization.
          * The possible states are defined in {@link UserSetupPersonalization}.
          *
@@ -11811,14 +11810,54 @@
 
         /**
          * Battery level [1-100] at which low power mode automatically turns on.
-         * If 0, it will not automatically turn on.
+         * Pre-Q If 0, it will not automatically turn on. Q and newer it will only automatically
+         * turn on if the {@link #AUTOMATIC_POWER_SAVER_MODE} setting is also set to
+         * {@link android.os.PowerManager.AutoPowerSaverMode#POWER_SAVER_MODE_PERCENTAGE}.
+         *
+         * @see #AUTOMATIC_POWER_SAVER_MODE
+         * @see android.os.PowerManager#getPowerSaveMode()
          * @hide
          */
         public static final String LOW_POWER_MODE_TRIGGER_LEVEL = "low_power_trigger_level";
 
+
         private static final Validator LOW_POWER_MODE_TRIGGER_LEVEL_VALIDATOR =
                 new SettingsValidators.InclusiveIntegerRangeValidator(0, 100);
 
+        /**
+         * Whether battery saver is currently set to trigger based on percentage, dynamic power
+         * savings trigger, or none. See {@link android.os.PowerManager.AutoPowerSaverMode} for
+         * accepted values.
+         *
+         *  @hide
+         */
+        @TestApi
+        public static final String AUTOMATIC_POWER_SAVER_MODE = "automatic_power_saver_mode";
+
+        private static final Validator AUTOMATIC_POWER_SAVER_MODE_VALIDATOR =
+                new SettingsValidators.DiscreteValueValidator(new String[] {"0", "1"});
+
+        /**
+         * The setting that backs the disable threshold for the setPowerSavingsWarning api in
+         * PowerManager
+         *
+         * @see android.os.PowerManager#setDynamicPowerSavings(boolean, int)
+         * @hide
+         */
+        @TestApi
+        public static final String DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD =
+                "dynamic_power_savings_disable_threshold";
+        private static final Validator DYNAMIC_POWER_SAVINGS_VALIDATOR =
+                new SettingsValidators.InclusiveIntegerRangeValidator(0, 100);
+
+        /**
+         * The setting which backs the setDynamicPowerSavings api in PowerManager.
+         *
+         * @see android.os.PowerManager#setDynamicPowerSavings(boolean, int)
+         * @hide
+         */
+        @TestApi
+        public static final String DYNAMIC_POWER_SAVINGS_ENABLED = "dynamic_power_savings_enabled";
 
         /**
          * The max value for {@link #LOW_POWER_MODE_TRIGGER_LEVEL}. If this setting is not set
@@ -12636,27 +12675,14 @@
                 "hidden_api_access_log_sampling_rate";
 
         /**
-         * Hidden API enforcement policy for apps targeting SDK versions prior to the latest
-         * version.
+         * Hidden API enforcement policy for apps.
          *
          * Values correspond to @{@link
          * android.content.pm.ApplicationInfo.HiddenApiEnforcementPolicy}
          *
          * @hide
          */
-        public static final String HIDDEN_API_POLICY_PRE_P_APPS =
-                "hidden_api_policy_pre_p_apps";
-
-        /**
-         * Hidden API enforcement policy for apps targeting the current SDK version.
-         *
-         * Values correspond to @{@link
-         * android.content.pm.ApplicationInfo.HiddenApiEnforcementPolicy}
-         *
-         * @hide
-         */
-        public static final String HIDDEN_API_POLICY_P_APPS =
-                "hidden_api_policy_p_apps";
+        public static final String HIDDEN_API_POLICY = "hidden_api_policy";
 
         /**
          * Timeout for a single {@link android.media.soundtrigger.SoundTriggerDetectionService}
@@ -12755,6 +12781,9 @@
             VALIDATORS.put(LOW_POWER_MODE_TRIGGER_LEVEL, LOW_POWER_MODE_TRIGGER_LEVEL_VALIDATOR);
             VALIDATORS.put(LOW_POWER_MODE_TRIGGER_LEVEL_MAX,
                     LOW_POWER_MODE_TRIGGER_LEVEL_VALIDATOR);
+            VALIDATORS.put(AUTOMATIC_POWER_SAVER_MODE, AUTOMATIC_POWER_SAVER_MODE_VALIDATOR);
+            VALIDATORS.put(DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD,
+                    DYNAMIC_POWER_SAVINGS_VALIDATOR);
             VALIDATORS.put(BLUETOOTH_ON, BLUETOOTH_ON_VALIDATOR);
             VALIDATORS.put(PRIVATE_DNS_MODE, PRIVATE_DNS_MODE_VALIDATOR);
             VALIDATORS.put(PRIVATE_DNS_SPECIFIER, PRIVATE_DNS_SPECIFIER_VALIDATOR);
diff --git a/core/java/android/security/keymaster/ExportResult.java b/core/java/android/security/keymaster/ExportResult.java
index c104671..1ab79fb 100644
--- a/core/java/android/security/keymaster/ExportResult.java
+++ b/core/java/android/security/keymaster/ExportResult.java
@@ -28,6 +28,11 @@
     public final int resultCode;
     public final byte[] exportData;
 
+    public ExportResult(int resultCode) {
+        this.resultCode = resultCode;
+        this.exportData = new byte[0];
+    }
+
     @UnsupportedAppUsage
     public static final Parcelable.Creator<ExportResult> CREATOR = new
             Parcelable.Creator<ExportResult>() {
diff --git a/core/java/android/security/keymaster/KeyCharacteristics.java b/core/java/android/security/keymaster/KeyCharacteristics.java
index 555863e..a4fe75d 100644
--- a/core/java/android/security/keymaster/KeyCharacteristics.java
+++ b/core/java/android/security/keymaster/KeyCharacteristics.java
@@ -52,6 +52,14 @@
         readFromParcel(in);
     }
 
+    /**
+     * Makes a shallow copy of other by copying the other's references to the KeymasterArguments
+     */
+    public void shallowCopyFrom(KeyCharacteristics other) {
+        this.swEnforced = other.swEnforced;
+        this.hwEnforced = other.hwEnforced;
+    }
+
     @Override
     public int describeContents() {
         return 0;
diff --git a/core/java/android/security/keymaster/KeymasterCertificateChain.java b/core/java/android/security/keymaster/KeymasterCertificateChain.java
index 243b9fe..00a1a1c 100644
--- a/core/java/android/security/keymaster/KeymasterCertificateChain.java
+++ b/core/java/android/security/keymaster/KeymasterCertificateChain.java
@@ -54,6 +54,14 @@
         readFromParcel(in);
     }
 
+    /**
+     * Makes a shallow copy of other by copying the reference to the certificate chain list.
+     * @param other
+     */
+    public void shallowCopyFrom(KeymasterCertificateChain other) {
+        this.mCertificates = other.mCertificates;
+    }
+
     public List<byte[]> getCertificates() {
         return mCertificates;
     }
diff --git a/core/java/android/security/keymaster/OperationResult.java b/core/java/android/security/keymaster/OperationResult.java
index 2943211..bc4f360 100644
--- a/core/java/android/security/keymaster/OperationResult.java
+++ b/core/java/android/security/keymaster/OperationResult.java
@@ -59,6 +59,10 @@
         this.outParams = outParams;
     }
 
+    public OperationResult(int resultCode) {
+        this(resultCode, null, 0, 0, null, null);
+    }
+
     protected OperationResult(Parcel in) {
         resultCode = in.readInt();
         token = in.readStrongBinder();
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index e5fd292..c8e0dd2 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -2360,6 +2360,52 @@
         public Directions(int[] dirs) {
             mDirections = dirs;
         }
+
+        /**
+         * Returns number of BiDi runs.
+         *
+         * @hide
+         */
+        public @IntRange(from = 0) int getRunCount() {
+            return mDirections.length / 2;
+        }
+
+        /**
+         * Returns the start offset of the BiDi run.
+         *
+         * @param runIndex the index of the BiDi run
+         * @return the start offset of the BiDi run.
+         * @hide
+         */
+        public @IntRange(from = 0) int getRunStart(@IntRange(from = 0) int runIndex) {
+            return mDirections[runIndex * 2];
+        }
+
+        /**
+         * Returns the length of the BiDi run.
+         *
+         * Note that this method may return too large number due to reducing the number of object
+         * allocations. The too large number means the remaining part is assigned to this run. The
+         * caller must clamp the returned value.
+         *
+         * @param runIndex the index of the BiDi run
+         * @return the length of the BiDi run.
+         * @hide
+         */
+        public @IntRange(from = 0) int getRunLength(@IntRange(from = 0) int runIndex) {
+            return mDirections[runIndex * 2 + 1] & RUN_LENGTH_MASK;
+        }
+
+        /**
+         * Returns true if the BiDi run is RTL.
+         *
+         * @param runIndex the index of the BiDi run
+         * @return true if the BiDi run is RTL.
+         * @hide
+         */
+        public boolean isRunRtl(int runIndex) {
+            return (mDirections[runIndex * 2 + 1] & RUN_RTL_FLAG) != 0;
+        }
     }
 
     /**
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 44dfd11..7b638b4 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -16,6 +16,7 @@
 
 package android.text;
 
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
@@ -51,6 +52,8 @@
 public class TextLine {
     private static final boolean DEBUG = false;
 
+    private static final char TAB_CHAR = '\t';
+
     private TextPaint mPaint;
     @UnsupportedAppUsage
     private CharSequence mText;
@@ -232,6 +235,10 @@
         mEllipsisEnd = ellipsisStart != ellipsisEnd ? ellipsisEnd : 0;
     }
 
+    private char charAt(int i) {
+        return mCharsValid ? mChars[i] : mText.charAt(i + mStart);
+    }
+
     /**
      * Justify the line to the given width.
      */
@@ -261,51 +268,23 @@
      * @param bottom the bottom of the line
      */
     void draw(Canvas c, float x, int top, int y, int bottom) {
-        if (!mHasTabs) {
-            if (mDirections == Layout.DIRS_ALL_LEFT_TO_RIGHT) {
-                drawRun(c, 0, mLen, false, x, top, y, bottom, false);
-                return;
-            }
-            if (mDirections == Layout.DIRS_ALL_RIGHT_TO_LEFT) {
-                drawRun(c, 0, mLen, true, x, top, y, bottom, false);
-                return;
-            }
-        }
-
         float h = 0;
-        int[] runs = mDirections.mDirections;
+        final int runCount = mDirections.getRunCount();
+        for (int runIndex = 0; runIndex < runCount; runIndex++) {
+            final int runStart = mDirections.getRunStart(runIndex);
+            final int runLimit = Math.min(runStart + mDirections.getRunLength(runIndex), mLen);
+            final boolean runIsRtl = mDirections.isRunRtl(runIndex);
 
-        int lastRunIndex = runs.length - 2;
-        for (int i = 0; i < runs.length; i += 2) {
-            int runStart = runs[i];
-            int runLimit = runStart + (runs[i+1] & Layout.RUN_LENGTH_MASK);
-            if (runLimit > mLen) {
-                runLimit = mLen;
-            }
-            boolean runIsRtl = (runs[i+1] & Layout.RUN_RTL_FLAG) != 0;
-
-            int segstart = runStart;
+            int segStart = runStart;
             for (int j = mHasTabs ? runStart : runLimit; j <= runLimit; j++) {
-                int codept = 0;
-                if (mHasTabs && j < runLimit) {
-                    codept = mChars[j];
-                    if (codept >= 0xD800 && codept < 0xDC00 && j + 1 < runLimit) {
-                        codept = Character.codePointAt(mChars, j);
-                        if (codept > 0xFFFF) {
-                            ++j;
-                            continue;
-                        }
-                    }
-                }
+                if (j == runLimit || charAt(j) == TAB_CHAR) {
+                    h += drawRun(c, segStart, j, runIsRtl, x + h, top, y, bottom,
+                            runIndex != (runCount - 1) || j != mLen);
 
-                if (j == runLimit || codept == '\t') {
-                    h += drawRun(c, segstart, j, runIsRtl, x+h, top, y, bottom,
-                            i != lastRunIndex || j != mLen);
-
-                    if (codept == '\t') {
+                    if (j != runLimit) {  // charAt(j) == TAB_CHAR
                         h = mDir * nextTab(h * mDir);
                     }
-                    segstart = j + 1;
+                    segStart = j + 1;
                 }
             }
         }
@@ -323,75 +302,81 @@
     }
 
     /**
-     * Returns information about a position on the line.
+     * Returns the signed graphical offset from the leading margin.
      *
-     * @param offset the line-relative character offset, between 0 and the
-     * line length, inclusive
-     * @param trailing true to measure the trailing edge of the character
-     * before offset, false to measure the leading edge of the character
-     * at offset.
-     * @param fmi receives metrics information about the requested
-     * character, can be null.
-     * @return the signed offset from the leading margin to the requested
-     * character edge.
+     * Following examples are all for measuring offset=3. LX(e.g. L0, L1, ...) denotes a
+     * character which has LTR BiDi property. On the other hand, RX(e.g. R0, R1, ...) denotes a
+     * character which has RTL BiDi property. Assuming all character has 1em width.
+     *
+     * Example 1: All LTR chars within LTR context
+     *   Input Text (logical)  :   L0 L1 L2 L3 L4 L5 L6 L7 L8
+     *   Input Text (visual)   :   L0 L1 L2 L3 L4 L5 L6 L7 L8
+     *   Output(trailing=true) :  |--------| (Returns 3em)
+     *   Output(trailing=false):  |--------| (Returns 3em)
+     *
+     * Example 2: All RTL chars within RTL context.
+     *   Input Text (logical)  :   R0 R1 R2 R3 R4 R5 R6 R7 R8
+     *   Input Text (visual)   :   R8 R7 R6 R5 R4 R3 R2 R1 R0
+     *   Output(trailing=true) :                    |--------| (Returns -3em)
+     *   Output(trailing=false):                    |--------| (Returns -3em)
+     *
+     * Example 3: BiDi chars within LTR context.
+     *   Input Text (logical)  :   L0 L1 L2 R3 R4 R5 L6 L7 L8
+     *   Input Text (visual)   :   L0 L1 L2 R5 R4 R3 L6 L7 L8
+     *   Output(trailing=true) :  |-----------------| (Returns 6em)
+     *   Output(trailing=false):  |--------| (Returns 3em)
+     *
+     * Example 4: BiDi chars within RTL context.
+     *   Input Text (logical)  :   L0 L1 L2 R3 R4 R5 L6 L7 L8
+     *   Input Text (visual)   :   L6 L7 L8 R5 R4 R3 L0 L1 L2
+     *   Output(trailing=true) :           |-----------------| (Returns -6em)
+     *   Output(trailing=false):                    |--------| (Returns -3em)
+     *
+     * @param offset the line-relative character offset, between 0 and the line length, inclusive
+     * @param trailing no effect if the offset is not on the BiDi transition offset. If the offset
+     *                 is on the BiDi transition offset and true is passed, the offset is regarded
+     *                 as the edge of the trailing run's edge. If false, the offset is regarded as
+     *                 the edge of the preceding run's edge. See example above.
+     * @param fmi receives metrics information about the requested character, can be null
+     * @return the signed graphical offset from the leading margin to the requested character edge.
+     *         The positive value means the offset is right from the leading edge. The negative
+     *         value means the offset is left from the leading edge.
      */
-    public float measure(int offset, boolean trailing, FontMetricsInt fmi) {
-        int target = trailing ? offset - 1 : offset;
+    public float measure(@IntRange(from = 0) int offset, boolean trailing,
+            @NonNull FontMetricsInt fmi) {
+        if (offset > mLen) {
+            throw new IndexOutOfBoundsException(
+                    "offset(" + offset + ") should be less than line limit(" + mLen + ")");
+        }
+        final int target = trailing ? offset - 1 : offset;
         if (target < 0) {
             return 0;
         }
 
         float h = 0;
+        for (int runIndex = 0; runIndex < mDirections.getRunCount(); runIndex++) {
+            final int runStart = mDirections.getRunStart(runIndex);
+            final int runLimit = Math.min(runStart + mDirections.getRunLength(runIndex), mLen);
+            final boolean runIsRtl = mDirections.isRunRtl(runIndex);
 
-        if (!mHasTabs) {
-            if (mDirections == Layout.DIRS_ALL_LEFT_TO_RIGHT) {
-                return measureRun(0, offset, mLen, false, fmi);
-            }
-            if (mDirections == Layout.DIRS_ALL_RIGHT_TO_LEFT) {
-                return measureRun(0, offset, mLen, true, fmi);
-            }
-        }
-
-        char[] chars = mChars;
-        int[] runs = mDirections.mDirections;
-        for (int i = 0; i < runs.length; i += 2) {
-            int runStart = runs[i];
-            int runLimit = runStart + (runs[i+1] & Layout.RUN_LENGTH_MASK);
-            if (runLimit > mLen) {
-                runLimit = mLen;
-            }
-            boolean runIsRtl = (runs[i+1] & Layout.RUN_RTL_FLAG) != 0;
-
-            int segstart = runStart;
+            int segStart = runStart;
             for (int j = mHasTabs ? runStart : runLimit; j <= runLimit; j++) {
-                int codept = 0;
-                if (mHasTabs && j < runLimit) {
-                    codept = chars[j];
-                    if (codept >= 0xD800 && codept < 0xDC00 && j + 1 < runLimit) {
-                        codept = Character.codePointAt(chars, j);
-                        if (codept > 0xFFFF) {
-                            ++j;
-                            continue;
-                        }
-                    }
-                }
+                if (j == runLimit || charAt(j) == TAB_CHAR) {
+                    final boolean targetIsInThisSegment = target >= segStart && target < j;
+                    final boolean sameDirection = (mDir == Layout.DIR_RIGHT_TO_LEFT) == runIsRtl;
 
-                if (j == runLimit || codept == '\t') {
-                    boolean inSegment = target >= segstart && target < j;
-
-                    boolean advance = (mDir == Layout.DIR_RIGHT_TO_LEFT) == runIsRtl;
-                    if (inSegment && advance) {
-                        return h + measureRun(segstart, offset, j, runIsRtl, fmi);
+                    if (targetIsInThisSegment && sameDirection) {
+                        return h + measureRun(segStart, offset, j, runIsRtl, fmi);
                     }
 
-                    float w = measureRun(segstart, j, j, runIsRtl, fmi);
-                    h += advance ? w : -w;
+                    final float segmentWidth = measureRun(segStart, j, j, runIsRtl, fmi);
+                    h += sameDirection ? segmentWidth : -segmentWidth;
 
-                    if (inSegment) {
-                        return h + measureRun(segstart, offset, j, runIsRtl, null);
+                    if (targetIsInThisSegment) {
+                        return h + measureRun(segStart, offset, j, runIsRtl, null);
                     }
 
-                    if (codept == '\t') {
+                    if (j != runLimit) {  // charAt(j) == TAB_CHAR
                         if (offset == j) {
                             return h;
                         }
@@ -401,7 +386,7 @@
                         }
                     }
 
-                    segstart = j + 1;
+                    segStart = j + 1;
                 }
             }
         }
@@ -426,62 +411,29 @@
         }
 
         float h = 0;
+        for (int runIndex = 0; runIndex < mDirections.getRunCount(); runIndex++) {
+            final int runStart = mDirections.getRunStart(runIndex);
+            final int runLimit = Math.min(runStart + mDirections.getRunLength(runIndex), mLen);
+            final boolean runIsRtl = mDirections.isRunRtl(runIndex);
 
-        if (!mHasTabs) {
-            if (mDirections == Layout.DIRS_ALL_LEFT_TO_RIGHT) {
-                for (int offset = 0; offset <= mLen; ++offset) {
-                    measurement[offset] = measureRun(0, offset, mLen, false, fmi);
-                }
-                return measurement;
-            }
-            if (mDirections == Layout.DIRS_ALL_RIGHT_TO_LEFT) {
-                for (int offset = 0; offset <= mLen; ++offset) {
-                    measurement[offset] = measureRun(0, offset, mLen, true, fmi);
-                }
-                return measurement;
-            }
-        }
-
-        char[] chars = mChars;
-        int[] runs = mDirections.mDirections;
-        for (int i = 0; i < runs.length; i += 2) {
-            int runStart = runs[i];
-            int runLimit = runStart + (runs[i + 1] & Layout.RUN_LENGTH_MASK);
-            if (runLimit > mLen) {
-                runLimit = mLen;
-            }
-            boolean runIsRtl = (runs[i + 1] & Layout.RUN_RTL_FLAG) != 0;
-
-            int segstart = runStart;
+            int segStart = runStart;
             for (int j = mHasTabs ? runStart : runLimit; j <= runLimit; ++j) {
-                int codept = 0;
-                if (mHasTabs && j < runLimit) {
-                    codept = chars[j];
-                    if (codept >= 0xD800 && codept < 0xDC00 && j + 1 < runLimit) {
-                        codept = Character.codePointAt(chars, j);
-                        if (codept > 0xFFFF) {
-                            ++j;
-                            continue;
-                        }
-                    }
-                }
-
-                if (j == runLimit || codept == '\t') {
-                    float oldh = h;
-                    boolean advance = (mDir == Layout.DIR_RIGHT_TO_LEFT) == runIsRtl;
-                    float w = measureRun(segstart, j, j, runIsRtl, fmi);
+                if (j == runLimit || charAt(j) == TAB_CHAR) {
+                    final  float oldh = h;
+                    final boolean advance = (mDir == Layout.DIR_RIGHT_TO_LEFT) == runIsRtl;
+                    final float w = measureRun(segStart, j, j, runIsRtl, fmi);
                     h += advance ? w : -w;
 
-                    float baseh = advance ? oldh : h;
+                    final float baseh = advance ? oldh : h;
                     FontMetricsInt crtfmi = advance ? fmi : null;
-                    for (int offset = segstart; offset <= j && offset <= mLen; ++offset) {
-                        if (target[offset] >= segstart && target[offset] < j) {
+                    for (int offset = segStart; offset <= j && offset <= mLen; ++offset) {
+                        if (target[offset] >= segStart && target[offset] < j) {
                             measurement[offset] =
-                                    baseh + measureRun(segstart, offset, j, runIsRtl, crtfmi);
+                                    baseh + measureRun(segStart, offset, j, runIsRtl, crtfmi);
                         }
                     }
 
-                    if (codept == '\t') {
+                    if (j != runLimit) {  // charAt(j) == TAB_CHAR
                         if (target[j] == j) {
                             measurement[j] = h;
                         }
@@ -491,7 +443,7 @@
                         }
                     }
 
-                    segstart = j + 1;
+                    segStart = j + 1;
                 }
             }
         }
diff --git a/core/java/android/view/DisplayListCanvas.java b/core/java/android/view/DisplayListCanvas.java
new file mode 100644
index 0000000..043b31d
--- /dev/null
+++ b/core/java/android/view/DisplayListCanvas.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2018 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.view;
+
+import android.annotation.UnsupportedAppUsage;
+import android.graphics.BaseRecordingCanvas;
+import android.graphics.CanvasProperty;
+import android.graphics.Paint;
+
+/**
+ * This class exists temporarily to workaround broken apps
+ *
+ * b/119066174
+ *
+ * @hide
+ */
+public abstract class DisplayListCanvas extends BaseRecordingCanvas {
+
+    /** @hide */
+    protected DisplayListCanvas(long nativeCanvas) {
+        super(nativeCanvas);
+    }
+
+    /** @hide */
+    @UnsupportedAppUsage
+    public abstract void drawRoundRect(CanvasProperty<Float> left, CanvasProperty<Float> top,
+            CanvasProperty<Float> right, CanvasProperty<Float> bottom, CanvasProperty<Float> rx,
+            CanvasProperty<Float> ry, CanvasProperty<Paint> paint);
+
+    /** @hide */
+    @UnsupportedAppUsage
+    public abstract void drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
+            CanvasProperty<Float> radius, CanvasProperty<Paint> paint);
+}
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 07a57fb..4b8b7f3 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -58,10 +58,33 @@
     void dispatchGetNewSurface();
 
     /**
-     * Tell the window that it is either gaining or losing focus.  Keep it up
-     * to date on the current state showing navigational focus (touch mode) too.
+     * Tell the window that it is either gaining or losing focus.
+     *
+     * @param hasFocus       {@code true} if window has focus, {@code false} otherwise.
+     * @param inTouchMode    {@code true} if screen is in touch mode, {@code false} otherwise.
+     * @param reportToClient {@code true} when need to report to child view with
+     *                       {@link View#onWindowFocusChanged(boolean)}, {@code false} otherwise.
+     * <p>
+     * Note: In the previous design, there is only one window focus state tracked by
+     * WindowManagerService.
+     * For multi-display, the window focus state is tracked by each display independently.
+     * <p>
+     * It will introduce a problem if the window was already focused on one display and then
+     * switched to another display, since the window focus state on each display is independent,
+     * there is no global window focus state in WindowManagerService, so the window focus state of
+     * the former display remains unchanged.
+     * <p>
+     * When switched back to former display, some flows that rely on the global window focus state
+     * in view root will be missed due to the window focus state remaining unchanged.
+     * (i.e: Showing single IME window when switching between displays.)
+     * <p>
+     * To solve the problem, WindowManagerService tracks the top focused display change and then
+     * callbacks to the client via this method to make sure that the client side will request the
+     * IME on the top focused display, and then set {@param reportToClient} as {@code false} to
+     * ignore reporting to the application, since its focus remains unchanged on its display.
+     *
      */
-    void windowFocusChanged(boolean hasFocus, boolean inTouchMode);
+    void windowFocusChanged(boolean hasFocus, boolean inTouchMode, boolean reportToClient);
     
     void closeSystemDialogs(String reason);
     
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 907f385..0739516 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -1978,6 +1978,7 @@
     }
 
     /** @hide */
+    @TestApi
     @Override
     public final void setDisplayId(int displayId) {
         mDisplayId = displayId;
@@ -2042,6 +2043,16 @@
     }
 
     /**
+     * Modifies the flags of the event.
+     *
+     * @param newFlags New flags for the event, replacing the entire value.
+     * @hide
+     */
+    public final void setFlags(int newFlags) {
+        mFlags = newFlags;
+    }
+
+    /**
      * Returns the flags for this key event.
      *
      * @see #FLAG_WOKE_HERE
@@ -2542,6 +2553,20 @@
     }
 
     /**
+     * Modifies the down time and the event time of the event.
+     *
+     * @param downTime The new down time (in {@link android.os.SystemClock#uptimeMillis}) of the
+     *                 event.
+     * @param eventTime The new event time (in {@link android.os.SystemClock#uptimeMillis}) of the
+     *                  event.
+     * @hide
+     */
+    public final void setTime(long downTime, long eventTime) {
+        mDownTime = downTime;
+        mEventTime = eventTime;
+    }
+
+    /**
      * Retrieve the time of the most recent key down event,
      * in the {@link android.os.SystemClock#uptimeMillis} time base.  If this
      * is a down event, this will be the same as {@link #getEventTime()}.
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index 9d31bd1..78ad0da 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -293,6 +293,12 @@
         setTarget(canvas.mNode);
     }
 
+    /** @hide */
+    @UnsupportedAppUsage
+    public void setTarget(DisplayListCanvas canvas) {
+        setTarget((RecordingCanvas) canvas);
+    }
+
     private void setTarget(RenderNode node) {
         checkMutable();
         if (mTarget != null) {
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 0d33bbd..3d16eb8 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -572,6 +572,10 @@
      * Good practice is to first create the surface with the {@link #HIDDEN} flag
      * specified, open a transaction, set the surface layer, layer stack, alpha,
      * and position, call {@link #show} if appropriate, and close the transaction.
+     * <p>
+     * Bounds of the surface is determined by its crop and its buffer size. If the
+     * surface has no buffer or crop, the surface is boundless and only constrained
+     * by the size of its parent bounds.
      *
      * @param session The surface session, must not be null.
      * @param name The surface name, must not be null.
@@ -959,6 +963,14 @@
         }
     }
 
+    /**
+     * Bounds the surface and its children to the bounds specified. Size of the surface will be
+     * ignored and only the crop and buffer size will be used to determine the bounds of the
+     * surface. If no crop is specified and the surface has no buffer, the surface bounds is only
+     * constrained by the size of its parent bounds.
+     *
+     * @param crop Bounds of the crop to apply.
+     */
     public void setWindowCrop(Rect crop) {
         checkNotReleased();
         synchronized (SurfaceControl.class) {
@@ -966,6 +978,19 @@
         }
     }
 
+    /**
+     * Same as {@link SurfaceControl#setWindowCrop(Rect)} but sets the crop rect top left at 0, 0.
+     *
+     * @param width width of crop rect
+     * @param height height of crop rect
+     */
+    public void setWindowCrop(int width, int height) {
+        checkNotReleased();
+        synchronized (SurfaceControl.class) {
+            sGlobalTransaction.setWindowCrop(this, width, height);
+        }
+    }
+
     public void setLayerStack(int layerStack) {
         checkNotReleased();
         synchronized(SurfaceControl.class) {
@@ -1477,6 +1502,12 @@
             return this;
         }
 
+        public Transaction setWindowCrop(SurfaceControl sc, int width, int height) {
+            sc.checkNotReleased();
+            nativeSetWindowCrop(mNativeObject, sc.mNativeObject, 0, 0, width, height);
+            return this;
+        }
+
         @UnsupportedAppUsage
         public Transaction setLayerStack(SurfaceControl sc, int layerStack) {
             sc.checkNotReleased();
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 67f9399..2b68ec0 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -598,6 +598,7 @@
                         }
                         if (sizeChanged && !creating) {
                             mSurfaceControl.setSize(mSurfaceWidth, mSurfaceHeight);
+                            mSurfaceControl.setWindowCrop(mSurfaceWidth, mSurfaceHeight);
                         }
                     } finally {
                         SurfaceControl.closeTransaction();
@@ -1169,6 +1170,12 @@
         }
 
         @Override
+        public void setWindowCrop(int width, int height) {
+            super.setWindowCrop(width, height);
+            mBackgroundControl.setWindowCrop(width, height);
+        }
+
+        @Override
         public void setLayerStack(int layerStack) {
             super.setLayerStack(layerStack);
             mBackgroundControl.setLayerStack(layerStack);
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index bac0154..bf1a005 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -172,6 +172,12 @@
      */
     public static final String DEBUG_FPS_DIVISOR = "debug.hwui.fps_divisor";
 
+    /**
+     * Forces smart-dark to be always on.
+     * @hide
+     */
+    public static final String DEBUG_FORCE_DARK = "debug.hwui.force_dark";
+
     public static int EGL_CONTEXT_PRIORITY_HIGH_IMG = 0x3101;
     public static int EGL_CONTEXT_PRIORITY_MEDIUM_IMG = 0x3102;
     public static int EGL_CONTEXT_PRIORITY_LOW_IMG = 0x3103;
@@ -675,10 +681,8 @@
             mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
             mLightZ = a.getDimension(R.styleable.Lighting_lightZ, 0);
             mLightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
-            final int ambientShadowAlpha =
-                    (int) (255 * a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0) + 0.5f);
-            final int spotShadowAlpha =
-                    (int) (255 * a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0) + 0.5f);
+            final float ambientShadowAlpha = a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0);
+            final float spotShadowAlpha = a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0);
             a.recycle();
             setLightSourceAlpha(ambientShadowAlpha, spotShadowAlpha);
         }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 7ba027f..c7f25d7 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -112,6 +112,7 @@
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
+import android.view.intelligence.IntelligenceManager;
 import android.widget.Checkable;
 import android.widget.FrameLayout;
 import android.widget.ScrollBarDrawable;
@@ -799,6 +800,11 @@
     private static final String AUTOFILL_LOG_TAG = "View.Autofill";
 
     /**
+     * The logging tag used by this class when logging content capture-related messages.
+     */
+    private static final String CONTENT_CAPTURE_LOG_TAG = "View.ContentCapture";
+
+    /**
      * When set to true, apps will draw debugging information about their layouts.
      *
      * @hide
@@ -1337,6 +1343,59 @@
      */
     public static final int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x1;
 
+    /** @hide */
+    @IntDef(prefix = { "IMPORTANT_FOR_CONTENT_CAPTURE_" }, value = {
+            IMPORTANT_FOR_CONTENT_CAPTURE_AUTO,
+            IMPORTANT_FOR_CONTENT_CAPTURE_YES,
+            IMPORTANT_FOR_CONTENT_CAPTURE_NO,
+            IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
+            IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ContentCaptureImportance {}
+
+    /**
+     * Automatically determine whether a view is important for content capture.
+     *
+     * @see #isImportantForContentCapture()
+     * @see #setImportantForContentCapture(int)
+     */
+    public static final int IMPORTANT_FOR_CONTENT_CAPTURE_AUTO = 0x0;
+
+    /**
+     * The view is important for content capture, and its children (if any) will be traversed.
+     *
+     * @see #isImportantForContentCapture()
+     * @see #setImportantForContentCapture(int)
+     */
+    public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES = 0x1;
+
+    /**
+     * The view is not important for content capture, but its children (if any) will be traversed.
+     *
+     * @see #isImportantForContentCapture()
+     * @see #setImportantForContentCapture(int)
+     */
+    public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO = 0x2;
+
+    /**
+     * The view is important for content capture, but its children (if any) will not be traversed.
+     *
+     * @see #isImportantForContentCapture()
+     * @see #setImportantForContentCapture(int)
+     */
+    public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS = 0x4;
+
+    /**
+     * The view is not important for content capture, and its children (if any) will not be
+     * traversed.
+     *
+     * @see #isImportantForContentCapture()
+     * @see #setImportantForContentCapture(int)
+     */
+    public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS = 0x8;
+
+
     /**
      * This view is enabled. Interpretation varies by subclass.
      * Use with ENABLED_MASK when calling setFlags.
@@ -2243,7 +2302,44 @@
     @UnsupportedAppUsage
     protected Object mTag = null;
 
-    // for mPrivateFlags:
+    /*
+     * Masks for mPrivateFlags, as generated by dumpFlags():
+     *
+     * |-------|-------|-------|-------|
+     *                                 1 PFLAG_WANTS_FOCUS
+     *                                1  PFLAG_FOCUSED
+     *                               1   PFLAG_SELECTED
+     *                              1    PFLAG_IS_ROOT_NAMESPACE
+     *                             1     PFLAG_HAS_BOUNDS
+     *                            1      PFLAG_DRAWN
+     *                           1       PFLAG_DRAW_ANIMATION
+     *                          1        PFLAG_SKIP_DRAW
+     *                        1          PFLAG_REQUEST_TRANSPARENT_REGIONS
+     *                       1           PFLAG_DRAWABLE_STATE_DIRTY
+     *                      1            PFLAG_MEASURED_DIMENSION_SET
+     *                     1             PFLAG_FORCE_LAYOUT
+     *                    1              PFLAG_LAYOUT_REQUIRED
+     *                   1               PFLAG_PRESSED
+     *                  1                PFLAG_DRAWING_CACHE_VALID
+     *                 1                 PFLAG_ANIMATION_STARTED
+     *                1                  PFLAG_SAVE_STATE_CALLED
+     *               1                   PFLAG_ALPHA_SET
+     *              1                    PFLAG_SCROLL_CONTAINER
+     *             1                     PFLAG_SCROLL_CONTAINER_ADDED
+     *            1                      PFLAG_DIRTY
+     *            1                      PFLAG_DIRTY_MASK
+     *          1                        PFLAG_OPAQUE_BACKGROUND
+     *         1                         PFLAG_OPAQUE_SCROLLBARS
+     *         11                        PFLAG_OPAQUE_MASK
+     *        1                          PFLAG_PREPRESSED
+     *       1                           PFLAG_CANCEL_NEXT_UP_EVENT
+     *      1                            PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH
+     *     1                             PFLAG_HOVERED
+     *    1                              PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK
+     *   1                               PFLAG_ACTIVATED
+     *  1                                PFLAG_INVALIDATED
+     * |-------|-------|-------|-------|
+     */
     /** {@hide} */
     static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
     /** {@hide} */
@@ -2393,7 +2489,9 @@
      */
     static final int PFLAG_INVALIDATED                 = 0x80000000;
 
-    /**
+    /* End of masks for mPrivateFlags */
+
+    /*
      * Masks for mPrivateFlags2, as generated by dumpFlags():
      *
      * |-------|-------|-------|-------|
@@ -2934,7 +3032,7 @@
 
     /* End of masks for mPrivateFlags2 */
 
-    /**
+    /*
      * Masks for mPrivateFlags3, as generated by dumpFlags():
      *
      * |-------|-------|-------|-------|
@@ -3270,6 +3368,72 @@
 
     /* End of masks for mPrivateFlags3 */
 
+    /*
+     * Masks for mPrivateFlags4, as generated by dumpFlags():
+     *
+     * |-------|-------|-------|-------|
+     *                              1111 PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK
+     *                             1     PFLAG4_NOTIFIED_CONTENT_CAPTURE_ON_LAYOUT
+     *                            1      PFLAG4_NOTIFIED_CONTENT_CAPTURE_ADDED
+     *                           1       PFLAG4_LAST_CONTENT_CAPTURE_NOTIFICATION_TYPE
+     * |-------|-------|-------|-------|
+     */
+
+    /**
+     * Mask for obtaining the bits which specify how to determine
+     * whether a view is important for autofill.
+     *
+     * <p>NOTE: the important for content capture values were the first flags added and are set in
+     * the rightmost position, so we don't need to shift them
+     */
+    private static final int PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK =
+            IMPORTANT_FOR_CONTENT_CAPTURE_AUTO | IMPORTANT_FOR_CONTENT_CAPTURE_YES
+            | IMPORTANT_FOR_CONTENT_CAPTURE_NO
+            | IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
+            | IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS;
+
+    /*
+     * Variables used to control when the IntelligenceManager.notifyNodeAdded()/removed() methods
+     * should be called.
+     *
+     * The idea is to call notifyNodeAdded() after the view is layout and visible, then call
+     * notifyNodeRemoved() when it's gone (without known when it was removed from the parent).
+     *
+     * TODO(b/111276913): the current algortighm could probably be optimized and some of them
+     * removed
+     */
+    private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_ON_LAYOUT = 0x10;
+    private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_ADDED = 0x20;
+    private static final int PFLAG4_LAST_CONTENT_CAPTURE_NOTIFICATION_TYPE = 0x40;
+
+    /* End of masks for mPrivateFlags4 */
+
+    private static final int CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED = 1;
+    private static final int CONTENT_CAPTURE_NOTIFICATION_TYPE_DISAPPEARED = 0;
+
+    @IntDef(flag = true, prefix = { "CONTENT_CAPTURE_NOTIFICATION_TYPE_" }, value = {
+            CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED,
+            CONTENT_CAPTURE_NOTIFICATION_TYPE_DISAPPEARED
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface ContentCaptureNotificationType {}
+
+    /** @hide */
+    protected static final int VIEW_STRUCTURE_FOR_ASSIST = 0;
+    /** @hide */
+    protected  static final int VIEW_STRUCTURE_FOR_AUTOFILL = 1;
+    /** @hide */
+    protected  static final int VIEW_STRUCTURE_FOR_CONTENT_CAPTURE = 2;
+
+    /** @hide */
+    @IntDef(flag = true, prefix = { "VIEW_STRUCTURE_FOR" }, value = {
+            VIEW_STRUCTURE_FOR_ASSIST,
+            VIEW_STRUCTURE_FOR_AUTOFILL,
+            VIEW_STRUCTURE_FOR_CONTENT_CAPTURE
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ViewStructureType {}
+
     /**
      * Always allow a user to over-scroll this view, provided it is a
      * view that can scroll.
@@ -3861,6 +4025,8 @@
     @UnsupportedAppUsage
     int mPrivateFlags3;
 
+    private int mPrivateFlags4;
+
     /**
      * This view's request for the visibility of the status bar.
      * @hide
@@ -5803,6 +5969,7 @@
         mAttributes = trimmed;
     }
 
+    @Override
     public String toString() {
         StringBuilder out = new StringBuilder(128);
         out.append(getClass().getName());
@@ -5875,6 +6042,9 @@
                 }
             }
         }
+        if (mAutofillId != null) {
+            out.append(" aid="); out.append(mAutofillId);
+        }
         out.append("}");
         return out.toString();
     }
@@ -7888,7 +8058,7 @@
      * fills in all data that can be inferred from the view itself.
      */
     public void onProvideStructure(ViewStructure structure) {
-        onProvideStructureForAssistOrAutofill(structure, false, 0);
+        onProvideStructure(structure, VIEW_STRUCTURE_FOR_ASSIST, /* flags= */ 0);
     }
 
     /**
@@ -7961,11 +8131,45 @@
      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
      */
     public void onProvideAutofillStructure(ViewStructure structure, @AutofillFlags int flags) {
-        onProvideStructureForAssistOrAutofill(structure, true, flags);
+        onProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
     }
 
-    private void onProvideStructureForAssistOrAutofill(ViewStructure structure,
-            boolean forAutofill, @AutofillFlags int flags) {
+    /**
+     * Populates a {@link ViewStructure} for Content Capture.
+     *
+     * <p>This method is called after a view is that is eligible for Content Capture
+     * (for example, if it {@link #isImportantForAutofill()}, an intelligence service is enabled for
+     * the user, and the activity rendering the view is enabled for Content Capture) is laid out and
+     * is visible.
+     *
+     * <p><b>Note: </b>the following methods of the {@code structure} will be ignored:
+     * <ul>
+     *   <li>{@link ViewStructure#setChildCount(int)}
+     *   <li>{@link ViewStructure#addChildCount(int)}
+     *   <li>{@link ViewStructure#getChildCount()}
+     *   <li>{@link ViewStructure#newChild(int)}
+     *   <li>{@link ViewStructure#asyncNewChild(int)}
+     *   <li>{@link ViewStructure#asyncCommit()}
+     *   <li>{@link ViewStructure#setWebDomain(String)}
+     *   <li>{@link ViewStructure#newHtmlInfoBuilder(String)}
+     *   <li>{@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}
+     *   <li>{@link ViewStructure#setDataIsSensitive(boolean)}
+     * </ul>
+     *
+     * @return whether the IntelligenceService should be notified that the view was added (through
+     * the {@link IntelligenceManager#notifyViewAppeared(ViewStructure)} method) to the view
+     * hierarchy. Most views should return {@code true} here, but views that contains virtual
+     * hierarchy might opt to return {@code false} and notify the manager independently, as the
+     * virtual views are rendered.
+     */
+    public boolean onProvideContentCaptureStructure(@NonNull ViewStructure structure, int flags) {
+        onProvideStructure(structure, VIEW_STRUCTURE_FOR_CONTENT_CAPTURE, flags);
+        return true;
+    }
+
+    /** @hide */
+    protected void onProvideStructure(@NonNull ViewStructure structure,
+            @ViewStructureType int viewFor, int flags) {
         final int id = mID;
         if (id != NO_ID && !isViewIdGenerated(id)) {
             String pkg, type, entry;
@@ -7981,8 +8185,13 @@
         } else {
             structure.setId(id, null, null, null);
         }
+        if (viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
+            //TODO(b/111276913): STOPSHIP - don't set it if not needed
+            structure.setDataIsSensitive(false);
+        }
 
-        if (forAutofill) {
+        if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
+                || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
             final @AutofillType int autofillType = getAutofillType();
             // Don't need to fill autofill info if view does not support it.
             // For example, only TextViews that are editable support autofill
@@ -7996,7 +8205,8 @@
 
         int ignoredParentLeft = 0;
         int ignoredParentTop = 0;
-        if (forAutofill && (flags & AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) {
+        if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
+                && (flags & AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) {
             View parentGroup = null;
 
             ViewParent viewParent = getParent();
@@ -8019,7 +8229,8 @@
 
         structure.setDimens(ignoredParentLeft + mLeft, ignoredParentTop + mTop, mScrollX, mScrollY,
                 mRight - mLeft, mBottom - mTop);
-        if (!forAutofill) {
+        if (viewFor == VIEW_STRUCTURE_FOR_ASSIST
+                || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
             if (!hasIdentityMatrix()) {
                 structure.setTransformation(getMatrix());
             }
@@ -8530,9 +8741,8 @@
             if (parentImportance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
                     || parentImportance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS) {
                 if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
-                    Log.v(AUTOFILL_LOG_TAG, "View (autofillId=" +  getAutofillViewId() + ", "
-                            + getClass() + ") is not important for autofill because parent "
-                            + parent + "'s importance is " + parentImportance);
+                    Log.v(AUTOFILL_LOG_TAG, "View (" +  this + ") is not important for autofill "
+                            + "because parent " + parent + "'s importance is " + parentImportance);
                 }
                 return false;
             }
@@ -8549,14 +8759,18 @@
         if (importance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
                 || importance == IMPORTANT_FOR_AUTOFILL_NO) {
             if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
-                Log.v(AUTOFILL_LOG_TAG, "View (autofillId=" +  getAutofillViewId() + ", "
-                        + getClass() + ") is not important for autofill because its "
-                        + "importance is " + importance);
+                Log.v(AUTOFILL_LOG_TAG, "View (" +  this + ") is not important for autofill "
+                        + "because its importance is " + importance);
             }
             return false;
         }
 
         // Then use some heuristics to handle AUTO.
+        if (importance != IMPORTANT_FOR_AUTOFILL_AUTO) {
+            Log.w(AUTOFILL_LOG_TAG, "invalid autofill importance (" + importance + " on view "
+                    + this);
+            return false;
+        }
 
         // Always include views that have an explicit resource id.
         final int id = mID;
@@ -8584,6 +8798,197 @@
         return false;
     }
 
+    /**
+     * Gets the mode for determining whether this view is important for content capture.
+     *
+     * <p>See {@link #setImportantForContentCapture(int)} and
+     * {@link #isImportantForContentCapture()} for more info about this mode.
+     *
+     * @return {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO} by default, or value passed to
+     * {@link #setImportantForContentCapture(int)}.
+     *
+     * @attr ref android.R.styleable#View_importantForContentCapture
+     */
+    @ViewDebug.ExportedProperty(mapping = {
+            @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, to = "auto"),
+            @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES, to = "yes"),
+            @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO, to = "no"),
+            @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
+                to = "yesExcludeDescendants"),
+            @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
+                to = "noExcludeDescendants")})
+    public @ContentCaptureImportance int getImportantForContentCapture() {
+        // NOTE: the important for content capture values were the first flags added and are set in
+        // the rightmost position, so we don't need to shift them
+        return mPrivateFlags4 & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
+    }
+
+    /**
+     * Sets the mode for determining whether this view is considered important for content capture.
+     *
+     * <p>The platform determines the importance for autofill automatically but you
+     * can use this method to customize the behavior. Typically, a view that provides text should
+     * be marked as {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}.
+     *
+     * @param mode {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO},
+     * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}, {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO},
+     * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS},
+     * or {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS}.
+     *
+     * @attr ref android.R.styleable#View_importantForContentCapture
+     */
+    public void setImportantForContentCapture(@ContentCaptureImportance int mode) {
+        // Reset first
+        mPrivateFlags4 &= ~PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
+        // Then set again
+        // NOTE: the important for content capture values were the first flags added and are set in
+        // the rightmost position, so we don't need to shift them
+        mPrivateFlags4 |= (mode & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK);
+    }
+
+    /**
+     * Hints the Android System whether this view is considered important for Content Capture, based
+     * on the value explicitly set by {@link #setImportantForContentCapture(int)} and heuristics
+     * when it's {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO}.
+     *
+     * @return whether the view is considered important for autofill.
+     *
+     * @see #setImportantForContentCapture(int)
+     * @see #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO
+     * @see #IMPORTANT_FOR_CONTENT_CAPTURE_YES
+     * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO
+     * @see #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
+     * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
+     */
+    public final boolean isImportantForContentCapture() {
+        // Check parent mode to ensure we're important
+        ViewParent parent = mParent;
+        while (parent instanceof View) {
+            final int parentImportance = ((View) parent).getImportantForContentCapture();
+            if (parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
+                    || parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS) {
+                if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
+                    Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" +  this + ") is not important for "
+                            + "content capture because parent " + parent + "'s importance is "
+                            + parentImportance);
+                }
+                return false;
+            }
+            parent = parent.getParent();
+        }
+
+        final int importance = getImportantForContentCapture();
+
+        // First, check the explicit states.
+        if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
+                || importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES) {
+            return true;
+        }
+        if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
+                || importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO) {
+            if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
+                Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" +  this + ") is not important for content "
+                        + "capture because its importance is " + importance);
+            }
+            return false;
+        }
+
+        // Then use some heuristics to handle AUTO.
+        if (importance != IMPORTANT_FOR_CONTENT_CAPTURE_AUTO) {
+            Log.w(CONTENT_CAPTURE_LOG_TAG, "invalid content capture importance (" + importance
+                    + " on view " + this);
+            return false;
+        }
+
+        // View group is important if at least one children also is
+        //TODO(b/111276913): decide if we really need to send the relevant parents or just the
+        // leaves (with absolute coordinates). If it's the latter, then we need to update this
+        // javadoc and ViewGroup's implementation.
+        if (this instanceof ViewGroup) {
+            final ViewGroup group = (ViewGroup) this;
+            for (int i = 0; i < group.getChildCount(); i++) {
+                final View child = group.getChildAt(i);
+                if (child.isImportantForContentCapture()) {
+                    return true;
+                }
+            }
+        }
+
+        // If the app developer explicitly set hints or autofill hintsfor it, it's important.
+        if (getAutofillHints() != null) {
+            return true;
+        }
+
+        // Otherwise, assume it's not important...
+        return false;
+    }
+
+    /**
+     * Helper used to notify the {@link IntelligenceManager} when the view is removed or
+     * added, based on whether it's laid out and visible, and without knowing if the parent removed
+     * it from the view hierarchy.
+     */
+    // TODO(b/111276913): make sure the current algorithm covers all cases. For example, it should
+    // probably be called every time notifyEnterOrExitForAutoFillIfNeeded() is called as well.
+    private void notifyNodeAddedOrRemovedForContentCaptureIfNeeded(
+            @ContentCaptureNotificationType int type) {
+        if (type != CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED
+                && type != CONTENT_CAPTURE_NOTIFICATION_TYPE_DISAPPEARED) {
+            // Sanity check so it does not screw up the flags
+            Log.wtf(CONTENT_CAPTURE_LOG_TAG, "notifyNodeAddedOrRemovedForContentCaptureIfNeeded(): "
+                    + "invalid type " + type + " for " + this);
+            return;
+        }
+
+        if (!isImportantForContentCapture()) return;
+
+        final IntelligenceManager im = mContext.getSystemService(IntelligenceManager.class);
+        if (im == null || !im.isContentCaptureEnabled()) return;
+
+        // Make sure event is notified just once, and reset the
+        // PFLAG4_LAST_CONTENT_CAPTURE_NOTIFICATION_TYPE flag
+        boolean ignoreNotification = false;
+        if (type == CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED) {
+            if ((mPrivateFlags4 & PFLAG4_LAST_CONTENT_CAPTURE_NOTIFICATION_TYPE)
+                    == CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED) {
+                ignoreNotification = true;
+            } else {
+                mPrivateFlags4 |= PFLAG4_LAST_CONTENT_CAPTURE_NOTIFICATION_TYPE;
+            }
+        } else {
+            if ((mPrivateFlags4 & PFLAG4_LAST_CONTENT_CAPTURE_NOTIFICATION_TYPE)
+                    == CONTENT_CAPTURE_NOTIFICATION_TYPE_DISAPPEARED) {
+                ignoreNotification = true;
+            } else {
+                mPrivateFlags4 &= ~PFLAG4_LAST_CONTENT_CAPTURE_NOTIFICATION_TYPE;
+            }
+        }
+        if (ignoreNotification) {
+            if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
+                // TODO(b/111276913): remove this log statement if the algorithm is not improved
+                // (right now it's called too many times when the activity is stopped and/or views
+                // disappear
+                Log.v(CONTENT_CAPTURE_LOG_TAG, "notifyNodeAddedOrRemovedForContentCaptureIfNeeded("
+                        + type + "): ignoring repeated notification on " + this);
+            }
+            return;
+        }
+
+        if (type == CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED) {
+            final ViewStructure structure = im.newViewStructure(this);
+            boolean notifyMgr = onProvideContentCaptureStructure(structure, /* flags= */ 0);
+            if (notifyMgr) {
+                im.notifyViewAppeared(structure);
+            }
+            mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_ADDED;
+        } else {
+            if ((mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_ADDED) == 0) {
+                return; // skip initial notification
+            }
+            im.notifyViewDisappeared(getAutofillId());
+        }
+    }
+
     @Nullable
     private AutofillManager getAutofillManager() {
         return mContext.getSystemService(AutofillManager.class);
@@ -8695,7 +9100,7 @@
      * {@link #onProvideVirtualStructure}.
      */
     public void dispatchProvideStructure(ViewStructure structure) {
-        dispatchProvideStructureForAssistOrAutofill(structure, false, 0);
+        dispatchProvideStructure(structure, VIEW_STRUCTURE_FOR_ASSIST, /* flags= */ 0);
     }
 
     /**
@@ -8737,12 +9142,12 @@
      */
     public void dispatchProvideAutofillStructure(@NonNull ViewStructure structure,
             @AutofillFlags int flags) {
-        dispatchProvideStructureForAssistOrAutofill(structure, true, flags);
+        dispatchProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
     }
 
-    private void dispatchProvideStructureForAssistOrAutofill(ViewStructure structure,
-            boolean forAutofill, @AutofillFlags int flags) {
-        if (forAutofill) {
+    private void dispatchProvideStructure(@NonNull ViewStructure structure,
+            @ViewStructureType int viewFor, @AutofillFlags int flags) {
+        if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
             structure.setAutofillId(getAutofillId());
             onProvideAutofillStructure(structure, flags);
             onProvideAutofillVirtualStructure(structure, flags);
@@ -13094,6 +13499,9 @@
                         : AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED);
             }
         }
+        notifyNodeAddedOrRemovedForContentCaptureIfNeeded(isVisible
+                ? CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED
+                : CONTENT_CAPTURE_NOTIFICATION_TYPE_DISAPPEARED);
     }
 
     /**
@@ -18630,6 +19038,8 @@
         }
 
         notifyEnterOrExitForAutoFillIfNeeded(false);
+        notifyNodeAddedOrRemovedForContentCaptureIfNeeded(
+                CONTENT_CAPTURE_NOTIFICATION_TYPE_DISAPPEARED);
     }
 
     /**
@@ -20934,6 +21344,13 @@
             mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
             notifyEnterOrExitForAutoFillIfNeeded(true);
         }
+
+        if ((mViewFlags & VISIBILITY_MASK) == VISIBLE
+                && (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_ON_LAYOUT) == 0) {
+            notifyNodeAddedOrRemovedForContentCaptureIfNeeded(
+                    CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED);
+            mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_ON_LAYOUT;
+        }
     }
 
     private boolean hasParentWantsFocus() {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index a23d68b..7a621a3 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2695,7 +2695,7 @@
         }
     }
 
-    private void handleWindowFocusChanged() {
+    private void handleWindowFocusChanged(boolean reportToClient) {
         final boolean hasWindowFocus;
         final boolean inTouchMode;
         synchronized (this) {
@@ -2730,8 +2730,9 @@
                         } catch (RemoteException ex) {
                         }
                         // Retry in a bit.
-                        mHandler.sendMessageDelayed(mHandler.obtainMessage(
-                                MSG_WINDOW_FOCUS_CHANGED), 500);
+                        final Message msg = mHandler.obtainMessage(MSG_WINDOW_FOCUS_CHANGED);
+                        msg.arg1 = reportToClient ? 1 : 0;
+                        mHandler.sendMessageDelayed(msg, 500);
                         return;
                     }
                 }
@@ -2748,9 +2749,15 @@
             }
             if (mView != null) {
                 mAttachInfo.mKeyDispatchState.reset();
-                mView.dispatchWindowFocusChanged(hasWindowFocus);
-                mAttachInfo.mTreeObserver.dispatchOnWindowFocusChange(hasWindowFocus);
-
+                // We dispatch onWindowFocusChanged to child view only when window is gaining /
+                // losing focus.
+                // If the focus is updated from top display change but window focus on the display
+                // remains unchanged, will not callback onWindowFocusChanged again since it may
+                // be redundant & can affect the state when it callbacks.
+                if (reportToClient) {
+                    mView.dispatchWindowFocusChanged(hasWindowFocus);
+                    mAttachInfo.mTreeObserver.dispatchOnWindowFocusChange(hasWindowFocus);
+                }
                 if (mAttachInfo.mTooltipHost != null) {
                     mAttachInfo.mTooltipHost.hideTooltip();
                 }
@@ -4340,7 +4347,7 @@
                     }
                     break;
                 case MSG_WINDOW_FOCUS_CHANGED: {
-                    handleWindowFocusChanged();
+                    handleWindowFocusChanged(msg.arg1 != 0 /* reportToClient */);
                 } break;
                 case MSG_DIE:
                     doDie();
@@ -7263,7 +7270,7 @@
         }
 
         if (stage != null) {
-            handleWindowFocusChanged();
+            handleWindowFocusChanged(true /* reportToClient */);
             stage.deliver(q);
         } else {
             finishInputEvent(q);
@@ -7580,6 +7587,11 @@
     }
 
     public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) {
+        windowFocusChanged(hasFocus, inTouchMode, true /* reportToClient */);
+    }
+
+    public void windowFocusChanged(boolean hasFocus, boolean inTouchMode,
+            boolean reportToClient) {
         synchronized (this) {
             mWindowFocusChanged = true;
             mUpcomingWindowFocus = hasFocus;
@@ -7587,6 +7599,7 @@
         }
         Message msg = Message.obtain();
         msg.what = MSG_WINDOW_FOCUS_CHANGED;
+        msg.arg1 = reportToClient ? 1 : 0;
         mHandler.sendMessage(msg);
     }
 
@@ -8131,10 +8144,11 @@
         }
 
         @Override
-        public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) {
+        public void windowFocusChanged(boolean hasFocus, boolean inTouchMode,
+                boolean reportToClient) {
             final ViewRootImpl viewAncestor = mViewAncestor.get();
             if (viewAncestor != null) {
-                viewAncestor.windowFocusChanged(hasFocus, inTouchMode);
+                viewAncestor.windowFocusChanged(hasFocus, inTouchMode, reportToClient);
             }
         }
 
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index 38dcdd3..6efb6f3 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -24,7 +24,6 @@
 import android.os.LocaleList;
 import android.util.Pair;
 import android.view.View.AutofillImportance;
-import android.view.ViewStructure.HtmlInfo;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillValue;
 
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index 4a7e783..a8debbd 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -77,11 +77,17 @@
         CONSUMED = new WindowInsets((Insets) null, null, null, false, false, null);
     }
 
-    /** @hide */
+    /**
+     * Construct a new WindowInsets from individual insets.
+     *
+     * A {@code null} inset indicates that the respective inset is consumed.
+     *
+     * @hide
+     */
     public WindowInsets(Rect systemWindowInsets, Rect windowDecorInsets, Rect stableInsets,
             boolean isRound, boolean alwaysConsumeNavBar, DisplayCutout displayCutout) {
-        this(Insets.of(systemWindowInsets), Insets.of(windowDecorInsets), Insets.of(stableInsets),
-                isRound, alwaysConsumeNavBar, displayCutout);
+        this(insetsOrNull(systemWindowInsets), insetsOrNull(windowDecorInsets),
+                insetsOrNull(stableInsets), isRound, alwaysConsumeNavBar, displayCutout);
     }
 
     private WindowInsets(Insets systemWindowInsets, Insets windowDecorInsets,
@@ -673,6 +679,10 @@
         return Insets.of(newLeft, newTop, newRight, newBottom);
     }
 
+    private static Insets insetsOrNull(Rect insets) {
+        return insets != null ? Insets.of(insets) : null;
+    }
+
     /**
      * @return whether system window insets have been consumed.
      */
diff --git a/core/java/android/view/intelligence/ContentCaptureEvent.java b/core/java/android/view/intelligence/ContentCaptureEvent.java
index 2530ae3..befcb55 100644
--- a/core/java/android/view/intelligence/ContentCaptureEvent.java
+++ b/core/java/android/view/intelligence/ContentCaptureEvent.java
@@ -16,12 +16,17 @@
 package android.view.intelligence;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.SystemClock;
 import android.view.autofill.AutofillId;
 
+import com.android.internal.util.Preconditions;
+
+import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
@@ -60,14 +65,14 @@
      *
      * <p>The metadata of the node is available through {@link #getViewNode()}.
      */
-    public static final int TYPE_VIEW_ADDED = 5;
+    public static final int TYPE_VIEW_APPEARED = 5;
 
     /**
      * Called when a node has been removed from the screen and is not visible to the user anymore.
      *
      * <p>The id of the node is available through {@link #getId()}.
      */
-    public static final int TYPE_VIEW_REMOVED = 6;
+    public static final int TYPE_VIEW_DISAPPEARED = 6;
 
     /**
      * Called when the text of a node has been changed.
@@ -85,8 +90,8 @@
             TYPE_ACTIVITY_PAUSED,
             TYPE_ACTIVITY_RESUMED,
             TYPE_ACTIVITY_STOPPED,
-            TYPE_VIEW_ADDED,
-            TYPE_VIEW_REMOVED,
+            TYPE_VIEW_APPEARED,
+            TYPE_VIEW_DISAPPEARED,
             TYPE_VIEW_TEXT_CHANGED
     })
     @Retention(RetentionPolicy.SOURCE)
@@ -95,7 +100,9 @@
     private final int mType;
     private final long mEventTime;
     private final int mFlags;
-
+    private @Nullable AutofillId mId;
+    private @Nullable ViewNode mNode;
+    private @Nullable CharSequence mText;
 
     /** @hide */
     public ContentCaptureEvent(int type, long eventTime, int flags) {
@@ -104,12 +111,42 @@
         mFlags = flags;
     }
 
+
+    /** @hide */
+    public ContentCaptureEvent(int type, int flags) {
+        this(type, SystemClock.uptimeMillis(), flags);
+    }
+
+    /** @hide */
+    public ContentCaptureEvent(int type) {
+        this(type, /* flags= */ 0);
+    }
+
+    /** @hide */
+    public ContentCaptureEvent setAutofillId(@NonNull AutofillId id) {
+        mId = Preconditions.checkNotNull(id);
+        return this;
+    }
+
+    /** @hide */
+    public ContentCaptureEvent setViewNode(@NonNull ViewNode node) {
+        mNode = Preconditions.checkNotNull(node);
+        return this;
+    }
+
+    /** @hide */
+    public ContentCaptureEvent setText(@Nullable CharSequence text) {
+        mText = text;
+        return this;
+    }
+
     /**
      * Gets the type of the event.
      *
      * @return one of {@link #TYPE_ACTIVITY_STARTED}, {@link #TYPE_ACTIVITY_RESUMED},
      * {@link #TYPE_ACTIVITY_PAUSED}, {@link #TYPE_ACTIVITY_STOPPED},
-     * {@link #TYPE_VIEW_ADDED}, {@link #TYPE_VIEW_REMOVED}, or {@link #TYPE_VIEW_TEXT_CHANGED}.
+     * {@link #TYPE_VIEW_APPEARED}, {@link #TYPE_VIEW_DISAPPEARED},
+     * or {@link #TYPE_VIEW_TEXT_CHANGED}.
      */
     public @EventType int getType() {
         return mType;
@@ -135,21 +172,21 @@
     /**
      * Gets the whole metadata of the node associated with the event.
      *
-     * <p>Only set on {@link #TYPE_VIEW_ADDED} events.
+     * <p>Only set on {@link #TYPE_VIEW_APPEARED} events.
      */
     @Nullable
     public ViewNode getViewNode() {
-        return null;
+        return mNode;
     }
 
     /**
      * Gets the {@link AutofillId} of the node associated with the event.
      *
-     * <p>Only set on {@link #TYPE_VIEW_REMOVED} and {@link #TYPE_VIEW_TEXT_CHANGED} events.
+     * <p>Only set on {@link #TYPE_VIEW_DISAPPEARED} and {@link #TYPE_VIEW_TEXT_CHANGED} events.
      */
     @Nullable
     public AutofillId getId() {
-        return null;
+        return mId;
     }
 
     /**
@@ -159,16 +196,41 @@
      */
     @Nullable
     public CharSequence getText() {
-        return null;
+        return mText;
+    }
+
+    /** @hide */
+    public void dump(@NonNull PrintWriter pw) {
+        pw.print("type="); pw.print(getTypeAsString(mType));
+        pw.print(", time="); pw.print(mEventTime);
+        if (mFlags > 0) {
+            pw.print(", flags="); pw.print(mFlags);
+        }
+        if (mId != null) {
+            pw.print(", id="); pw.print(mId);
+        }
+        if (mNode != null) {
+            pw.print(", id="); pw.print(mNode.getAutofillId());
+        }
     }
 
     @Override
     public String toString() {
         final StringBuilder string = new StringBuilder("ContentCaptureEvent[type=")
-                .append(getTypeAsString(mType)).append(", time=").append(mEventTime);
+                .append(getTypeAsString(mType));
         if (mFlags > 0) {
             string.append(", flags=").append(mFlags);
         }
+        if (mId != null) {
+            string.append(", id=").append(mId);
+        }
+        if (mNode != null) {
+            final String className = mNode.getClassName();
+            if (mNode != null) {
+                string.append(", class=").append(className);
+            }
+            string.append(", id=").append(mNode.getAutofillId());
+        }
         return string.append(']').toString();
     }
 
@@ -182,6 +244,9 @@
         parcel.writeInt(mType);
         parcel.writeLong(mEventTime);
         parcel.writeInt(mFlags);
+        parcel.writeParcelable(mId, flags);
+        ViewNode.writeToParcel(parcel, mNode, flags);
+        parcel.writeCharSequence(mText);
     }
 
     public static final Parcelable.Creator<ContentCaptureEvent> CREATOR =
@@ -192,7 +257,17 @@
             final int type = parcel.readInt();
             final long eventTime  = parcel.readLong();
             final int flags = parcel.readInt();
-            return new ContentCaptureEvent(type, eventTime, flags);
+            final ContentCaptureEvent event = new ContentCaptureEvent(type, eventTime, flags);
+            final AutofillId id = parcel.readParcelable(null);
+            if (id != null) {
+                event.setAutofillId(id);
+            }
+            final ViewNode node = ViewNode.readFromParcel(parcel);
+            if (node != null) {
+                event.setViewNode(node);
+            }
+            event.setText(parcel.readCharSequence());
+            return event;
         }
 
         @Override
@@ -201,7 +276,6 @@
         }
     };
 
-
     /** @hide */
     public static String getTypeAsString(@EventType int type) {
         switch (type) {
@@ -213,10 +287,10 @@
                 return "ACTIVITY_PAUSED";
             case TYPE_ACTIVITY_STOPPED:
                 return "ACTIVITY_STOPPED";
-            case TYPE_VIEW_ADDED:
-                return "VIEW_ADDED";
-            case TYPE_VIEW_REMOVED:
-                return "VIEW_REMOVED";
+            case TYPE_VIEW_APPEARED:
+                return "VIEW_APPEARED";
+            case TYPE_VIEW_DISAPPEARED:
+                return "VIEW_DISAPPEARED";
             case TYPE_VIEW_TEXT_CHANGED:
                 return "VIEW_TEXT_CHANGED";
             default:
diff --git a/core/java/android/view/intelligence/IntelligenceManager.java b/core/java/android/view/intelligence/IntelligenceManager.java
index 9bf6c2c..b74600b 100644
--- a/core/java/android/view/intelligence/IntelligenceManager.java
+++ b/core/java/android/view/intelligence/IntelligenceManager.java
@@ -15,6 +15,12 @@
  */
 package android.view.intelligence;
 
+import static android.view.intelligence.ContentCaptureEvent.TYPE_VIEW_APPEARED;
+import static android.view.intelligence.ContentCaptureEvent.TYPE_VIEW_DISAPPEARED;
+import static android.view.intelligence.ContentCaptureEvent.TYPE_VIEW_TEXT_CHANGED;
+
+import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
@@ -22,11 +28,15 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.RemoteException;
-import android.os.SystemClock;
 import android.service.intelligence.InteractionSessionId;
 import android.util.Log;
+import android.view.View;
+import android.view.ViewStructure;
+import android.view.autofill.AutofillId;
 import android.view.intelligence.ContentCaptureEvent.EventType;
 
 import com.android.internal.annotations.GuardedBy;
@@ -34,8 +44,7 @@
 import com.android.internal.util.Preconditions;
 
 import java.io.PrintWriter;
-import java.util.Arrays;
-import java.util.List;
+import java.util.ArrayList;
 import java.util.Set;
 
 /**
@@ -46,8 +55,9 @@
 
     private static final String TAG = "IntelligenceManager";
 
-    // TODO(b/111276913): define a way to dynamically set it (for example, using settings?)
+    // TODO(b/111276913): define a way to dynamically set them(for example, using settings?)
     private static final boolean VERBOSE = false;
+    private static final boolean DEBUG = true; // STOPSHIP if not set to false
 
     /**
      * Used to indicate that a text change was caused by user input (for example, through IME).
@@ -55,7 +65,6 @@
     //TODO(b/111276913): link to notifyTextChanged() method once available
     public static final int FLAG_USER_INPUT = 0x1;
 
-
     /**
      * Initial state, when there is no session.
      *
@@ -77,6 +86,22 @@
      */
     public static final int STATE_ACTIVE = 2;
 
+    /**
+     * Session is disabled.
+     *
+     * @hide
+     */
+    public static final int STATE_DISABLED = 3;
+
+    private static final String BG_THREAD_NAME = "intel_svc_streamer_thread";
+
+    /**
+     * Maximum number of events that are delayed for an app.
+     *
+     * <p>If the session is not started after the limit is reached, it's discarded.
+     */
+    private static final int MAX_DELAYED_SIZE = 20;
+
     private final Context mContext;
 
     @Nullable
@@ -99,10 +124,24 @@
     @GuardedBy("mLock")
     private ComponentName mComponentName;
 
+    // TODO(b/111276913): create using maximum batch size as capacity
+    /**
+     * List of events held to be sent as a batch.
+     */
+    @GuardedBy("mLock")
+    private final ArrayList<ContentCaptureEvent> mEvents = new ArrayList<>();
+
+    private final Handler mHandler;
+
     /** @hide */
     public IntelligenceManager(@NonNull Context context, @Nullable IIntelligenceManager service) {
         mContext = Preconditions.checkNotNull(context, "context cannot be null");
         mService = service;
+
+        // TODO(b/111276913): use an existing bg thread instead...
+        final HandlerThread bgThread = new HandlerThread(BG_THREAD_NAME);
+        bgThread.start();
+        mHandler = Handler.createAsync(bgThread.getLooper());
     }
 
     /** @hide */
@@ -111,8 +150,9 @@
 
         synchronized (mLock) {
             if (mState != STATE_UNKNOWN) {
+                // TODO(b/111276913): revisit this scenario
                 Log.w(TAG, "ignoring onActivityStarted(" + token + ") while on state "
-                        + getStateAsStringLocked());
+                        + getStateAsString(mState));
                 return;
             }
             mState = STATE_WAITING_FOR_SERVER;
@@ -121,8 +161,8 @@
             mComponentName = componentName;
 
             if (VERBOSE) {
-                Log.v(TAG, "onActivityStarted(): token=" + token + ", act=" + componentName
-                        + ", id=" + mId);
+                Log.v(TAG, "onActivityCreated(): token=" + token + ", act="
+                        + getActivityDebugNameLocked() + ", id=" + mId);
             }
             final int flags = 0; // TODO(b/111276913): get proper flags
 
@@ -133,17 +173,11 @@
                             public void send(int resultCode, Bundle resultData)
                                     throws RemoteException {
                                 synchronized (mLock) {
-                                    if (resultCode > 0) {
-                                        mState = STATE_ACTIVE;
-                                    } else {
-                                        // TODO(b/111276913): handle other cases like disabled by
-                                        // service
-                                        mState = STATE_UNKNOWN;
-                                    }
+                                    mState = resultCode;
                                     if (VERBOSE) {
                                         Log.v(TAG, "onActivityStarted() result: code=" + resultCode
                                                 + ", id=" + mId
-                                                + ", state=" + getStateAsStringLocked());
+                                                + ", state=" + getStateAsString(mState));
                                     }
                                 }
                             }
@@ -154,6 +188,64 @@
         }
     }
 
+    //TODO(b/111276913): should buffer event (and call service on handler thread), instead of
+    // calling right away
+    private void sendEvent(@NonNull ContentCaptureEvent event) {
+        mHandler.sendMessage(obtainMessage(IntelligenceManager::handleSendEvent, this, event));
+    }
+
+    private void handleSendEvent(@NonNull ContentCaptureEvent event) {
+
+        synchronized (mLock) {
+            mEvents.add(event);
+            final int numberEvents = mEvents.size();
+            if (mState != STATE_ACTIVE) {
+                if (numberEvents >= MAX_DELAYED_SIZE) {
+                    // Typically happens on system apps that are started before the system service
+                    // is ready (like com.android.settings/.FallbackHome)
+                    //TODO(b/111276913): try to ignore session while system is not ready / boot
+                    // not complete instead. Similarly, the manager service should return right away
+                    // when the user does not have a service set
+                    if (VERBOSE) {
+                        Log.v(TAG, "Closing session for " + getActivityDebugNameLocked()
+                                + " after " + numberEvents + " delayed events and state "
+                                + getStateAsString(mState));
+                    }
+                    // TODO(b/111276913): blacklist activity / use special flag to indicate that
+                    // when it's launched again
+                    resetStateLocked();
+                    return;
+                }
+
+                if (VERBOSE) {
+                    Log.v(TAG, "Delaying " + numberEvents + " events for "
+                            + getActivityDebugNameLocked() + " while on state "
+                            + getStateAsString(mState));
+                }
+                return;
+            }
+
+            if (mId == null) {
+                // Sanity check - should not happen
+                Log.wtf(TAG, "null session id for " + mComponentName);
+                return;
+            }
+
+            //TODO(b/111276913): right now we're sending sending right away (unless not ready), but
+            // we should hold the events and flush later.
+            try {
+                if (DEBUG) {
+                    Log.d(TAG, "Sending " + numberEvents + " event(s) for "
+                            + getActivityDebugNameLocked());
+                }
+                mService.sendEvents(mContext.getUserId(), mId, mEvents);
+                mEvents.clear();
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
     /**
      * Used for intermediate events (i.e, other than created and destroyed).
      *
@@ -161,28 +253,11 @@
      */
     public void onActivityLifecycleEvent(@EventType int type) {
         if (!isContentCaptureEnabled()) return;
-
-        //TODO(b/111276913): should buffer event (and call service on handler thread), instead of
-        // calling right away
-        final ContentCaptureEvent event = new ContentCaptureEvent(type, SystemClock.uptimeMillis(),
-                0);
-        final List<ContentCaptureEvent> events = Arrays.asList(event);
-
-        synchronized (mLock) {
-            //TODO(b/111276913): check session state; for example, how to handle if it's waiting for
-            // remote id
-
-            if (VERBOSE) {
-                Log.v(TAG, "onActivityLifecycleEvent() for " + mComponentName.flattenToShortString()
-                        + ": " + ContentCaptureEvent.getTypeAsString(type));
-            }
-
-            try {
-                mService.sendEvents(mContext.getUserId(), mId, events);
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
+        if (VERBOSE) {
+            Log.v(TAG, "onActivityLifecycleEvent() for " + getActivityDebugNameLocked()
+                    + ": " + ContentCaptureEvent.getTypeAsString(type));
         }
+        sendEvent(new ContentCaptureEvent(type));
     }
 
     /** @hide */
@@ -194,22 +269,105 @@
             // id) and send it to the cache of batched commands
 
             if (VERBOSE) {
-                Log.v(TAG, "onActivityDestroyed(): state=" + getStateAsStringLocked()
+                Log.v(TAG, "onActivityDestroyed(): state=" + getStateAsString(mState)
                         + ", mId=" + mId);
             }
 
             try {
                 mService.finishSession(mContext.getUserId(), mId);
-                mState = STATE_UNKNOWN;
-                mId = null;
-                mApplicationToken = null;
-                mComponentName = null;
+                resetStateLocked();
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
         }
     }
 
+    @GuardedBy("mLock")
+    private void resetStateLocked() {
+        mState = STATE_UNKNOWN;
+        mId = null;
+        mApplicationToken = null;
+        mComponentName = null;
+        mEvents.clear();
+    }
+
+    /**
+     * Notifies the Intelligence Service that a node has been added to the view structure.
+     *
+     * <p>Typically called "manually" by views that handle their own virtual view hierarchy, or
+     * automatically by the Android System for views that return {@code true} on
+     * {@link View#onProvideContentCaptureStructure(ViewStructure, int)}.
+     *
+     * @param node node that has been added.
+     */
+    public void notifyViewAppeared(@NonNull ViewStructure node) {
+        Preconditions.checkNotNull(node);
+        if (!isContentCaptureEnabled()) return;
+
+        if (!(node instanceof ViewNode.ViewStructureImpl)) {
+            throw new IllegalArgumentException("Invalid node class: " + node.getClass());
+        }
+        sendEvent(new ContentCaptureEvent(TYPE_VIEW_APPEARED)
+                .setViewNode(((ViewNode.ViewStructureImpl) node).mNode));
+    }
+
+    /**
+     * Notifies the Intelligence Service that a node has been removed from the view structure.
+     *
+     * <p>Typically called "manually" by views that handle their own virtual view hierarchy, or
+     * automatically by the Android System for standard views.
+     *
+     * @param id id of the node that has been removed.
+     */
+    public void notifyViewDisappeared(@NonNull AutofillId id) {
+        Preconditions.checkNotNull(id);
+        if (!isContentCaptureEnabled()) return;
+
+        sendEvent(new ContentCaptureEvent(TYPE_VIEW_DISAPPEARED).setAutofillId(id));
+    }
+
+    /**
+     * Notifies the Intelligence Service that the value of a text node has been changed.
+     *
+     * @param id of the node.
+     * @param text new text.
+     * @param flags either {@code 0} or {@link #FLAG_USER_INPUT} when the value was explicitly
+     * changed by the user (for example, through the keyboard).
+     */
+    public void notifyViewTextChanged(@NonNull AutofillId id, @Nullable CharSequence text,
+            int flags) {
+        Preconditions.checkNotNull(id);
+        if (!isContentCaptureEnabled()) return;
+
+        sendEvent(new ContentCaptureEvent(TYPE_VIEW_TEXT_CHANGED, flags).setAutofillId(id)
+                .setText(text));
+    }
+
+    /**
+     * Creates a {@link ViewStructure} for a "standard" view.
+     *
+     * @hide
+     */
+    @NonNull
+    public ViewStructure newViewStructure(@NonNull View view) {
+        return new ViewNode.ViewStructureImpl(view);
+    }
+
+    /**
+     * Creates a {@link ViewStructure} for a "virtual" view, so it can be passed to
+     * {@link #notifyViewAppeared(ViewStructure)} by the view managing the virtual view hierarchy.
+     *
+     * @param parentId id of the virtual view parent (it can be obtained by calling
+     * {@link ViewStructure#getAutofillId()} on the parent).
+     * @param virtualId id of the virtual child, relative to the parent.
+     *
+     * @return a new {@link ViewStructure} that can be used for Content Capture purposes.
+     */
+    @NonNull
+    public ViewStructure newVirtualViewStructure(@NonNull AutofillId parentId, int virtualId) {
+        return new ViewNode.ViewStructureImpl(parentId, virtualId);
+    }
+
     /**
      * Returns the component name of the {@code android.service.intelligence.IntelligenceService}
      * that is enabled for the current user.
@@ -227,7 +385,7 @@
         //TODO(b/111276913): properly implement by checking if it was explicitly disabled by
         // service, or if service is not set
         // (and probably renamign to isEnabledLocked()
-        return mService != null;
+        return mService != null && mState != STATE_DISABLED;
     }
 
     /**
@@ -322,15 +480,29 @@
             pw.print(prefix2); pw.print("enabled: "); pw.println(isContentCaptureEnabled());
             pw.print(prefix2); pw.print("id: "); pw.println(mId);
             pw.print(prefix2); pw.print("state: "); pw.print(mState); pw.print(" (");
-            pw.print(getStateAsStringLocked()); pw.println(")");
-            pw.print(prefix2); pw.print("appToken: "); pw.println(mApplicationToken);
-            pw.print(prefix2); pw.print("componentName: "); pw.println(mComponentName);
+            pw.print(getStateAsString(mState)); pw.println(")");
+            pw.print(prefix2); pw.print("app token: "); pw.println(mApplicationToken);
+            pw.print(prefix2); pw.print("component name: ");
+            pw.println(mComponentName == null ? "null" : mComponentName.flattenToShortString());
+            final int numberEvents = mEvents.size();
+            pw.print(prefix2); pw.print("batched events: "); pw.println(numberEvents);
+            if (numberEvents > 0) {
+                for (int i = 0; i < numberEvents; i++) {
+                    final ContentCaptureEvent event = mEvents.get(i);
+                    pw.println(i); pw.print(": "); event.dump(pw); pw.println();
+                }
+
+            }
         }
     }
 
+    /**
+     * Gets a string that can be used to identify the activity on logging statements.
+     */
     @GuardedBy("mLock")
-    private String getStateAsStringLocked() {
-        return getStateAsString(mState);
+    private String getActivityDebugNameLocked() {
+        return mComponentName == null ? mContext.getPackageName()
+                : mComponentName.flattenToShortString();
     }
 
     @NonNull
@@ -342,6 +514,8 @@
                 return "WAITING_FOR_SERVER";
             case STATE_ACTIVE:
                 return "ACTIVE";
+            case STATE_DISABLED:
+                return "DISABLED";
             default:
                 return "INVALID:" + state;
         }
diff --git a/core/java/android/view/intelligence/ViewNode.java b/core/java/android/view/intelligence/ViewNode.java
index 357ecf5..cc78e6b 100644
--- a/core/java/android/view/intelligence/ViewNode.java
+++ b/core/java/android/view/intelligence/ViewNode.java
@@ -15,10 +15,24 @@
  */
 package android.view.intelligence;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.app.assist.AssistStructure;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.LocaleList;
+import android.os.Parcel;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewParent;
+import android.view.ViewStructure;
+import android.view.ViewStructure.HtmlInfo.Builder;
 import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillValue;
+
+import com.android.internal.util.Preconditions;
 
 //TODO(b/111276913): add javadocs / implement Parcelable / implement
 //TODO(b/111276913): for now it's extending ViewNode directly as it needs most of its properties,
@@ -28,6 +42,16 @@
 @SystemApi
 public final class ViewNode extends AssistStructure.ViewNode {
 
+    private static final String TAG = "ViewNode";
+
+    private AutofillId mParentAutofillId;
+
+    // TODO(b/111276913): temporarily setting some fields here while they're not accessible from the
+    // superclass
+    private AutofillId mAutofillId;
+    private CharSequence mText;
+    private String mClassName;
+
     /** @hide */
     public ViewNode() {
     }
@@ -38,7 +62,343 @@
      */
     @Nullable
     public AutofillId getParentAutofillId() {
-        //TODO(b/111276913): implement
-        return null;
+        return mParentAutofillId;
+    }
+
+    // TODO(b/111276913): temporarily overwriting some methods
+    @Override
+    public AutofillId getAutofillId() {
+        return mAutofillId;
+    }
+    @Override
+    public CharSequence getText() {
+        return mText;
+    }
+    @Override
+    public String getClassName() {
+        return mClassName;
+    }
+
+    /** @hide */
+    public static void writeToParcel(@NonNull Parcel parcel, @Nullable ViewNode node, int flags) {
+        if (node == null) {
+            parcel.writeParcelable(null, flags);
+            return;
+        }
+        parcel.writeParcelable(node.mAutofillId, flags);
+        parcel.writeParcelable(node.mParentAutofillId, flags);
+        parcel.writeCharSequence(node.mText);
+        parcel.writeString(node.mClassName);
+    }
+
+    /** @hide */
+    public static @Nullable ViewNode readFromParcel(@NonNull Parcel parcel) {
+        final AutofillId id = parcel.readParcelable(null);
+        if (id == null) return null;
+
+        final ViewNode node = new ViewNode();
+
+        node.mAutofillId = id;
+        node.mParentAutofillId = parcel.readParcelable(null);
+        node.mText = parcel.readCharSequence();
+        node.mClassName = parcel.readString();
+
+        return node;
+    }
+
+    /** @hide */
+    static final class ViewStructureImpl extends ViewStructure {
+
+        final ViewNode mNode = new ViewNode();
+
+        ViewStructureImpl(@NonNull View view) {
+            mNode.mAutofillId = Preconditions.checkNotNull(view).getAutofillId();
+            final ViewParent parent = view.getParent();
+            if (parent instanceof View) {
+                mNode.mParentAutofillId = ((View) parent).getAutofillId();
+            }
+        }
+
+        ViewStructureImpl(@NonNull AutofillId parentId, int virtualId) {
+            mNode.mParentAutofillId = Preconditions.checkNotNull(parentId);
+            mNode.mAutofillId = new AutofillId(parentId, virtualId);
+        }
+
+        @Override
+        public void setId(int id, String packageName, String typeName, String entryName) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setDimens(int left, int top, int scrollX, int scrollY, int width, int height) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setTransformation(Matrix matrix) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setElevation(float elevation) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setAlpha(float alpha) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setVisibility(int visibility) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setAssistBlocked(boolean state) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setEnabled(boolean state) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setClickable(boolean state) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setLongClickable(boolean state) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setContextClickable(boolean state) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setFocusable(boolean state) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setFocused(boolean state) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setAccessibilityFocused(boolean state) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setCheckable(boolean state) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setChecked(boolean state) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setSelected(boolean state) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setActivated(boolean state) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setOpaque(boolean opaque) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setClassName(String className) {
+            // TODO(b/111276913): temporarily setting directly; should be done on superclass instead
+            mNode.mClassName = className;
+        }
+
+        @Override
+        public void setContentDescription(CharSequence contentDescription) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setText(CharSequence text) {
+            // TODO(b/111276913): temporarily setting directly; should be done on superclass instead
+            mNode.mText = text;
+        }
+
+        @Override
+        public void setText(CharSequence text, int selectionStart, int selectionEnd) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setTextStyle(float size, int fgColor, int bgColor, int style) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setTextLines(int[] charOffsets, int[] baselines) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setHint(CharSequence hint) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public CharSequence getText() {
+            // TODO(b/111276913): temporarily getting directly; should be done on superclass instead
+            return mNode.mText;
+        }
+
+        @Override
+        public int getTextSelectionStart() {
+            // TODO(b/111276913): implement or move to superclass
+            return 0;
+        }
+
+        @Override
+        public int getTextSelectionEnd() {
+            // TODO(b/111276913): implement or move to superclass
+            return 0;
+        }
+
+        @Override
+        public CharSequence getHint() {
+            // TODO(b/111276913): implement or move to superclass
+            return null;
+        }
+
+        @Override
+        public Bundle getExtras() {
+            // TODO(b/111276913): implement or move to superclass
+            return null;
+        }
+
+        @Override
+        public boolean hasExtras() {
+            // TODO(b/111276913): implement or move to superclass
+            return false;
+        }
+
+        @Override
+        public void setChildCount(int num) {
+            Log.w(TAG, "setChildCount() is not supported");
+        }
+
+        @Override
+        public int addChildCount(int num) {
+            Log.w(TAG, "addChildCount() is not supported");
+            return 0;
+        }
+
+        @Override
+        public int getChildCount() {
+            Log.w(TAG, "getChildCount() is not supported");
+            return 0;
+        }
+
+        @Override
+        public ViewStructure newChild(int index) {
+            Log.w(TAG, "newChild() is not supported");
+            return null;
+        }
+
+        @Override
+        public ViewStructure asyncNewChild(int index) {
+            Log.w(TAG, "asyncNewChild() is not supported");
+            return null;
+        }
+
+        @Override
+        public AutofillId getAutofillId() {
+            // TODO(b/111276913): temporarily getting directly; should be done on superclass instead
+            return mNode.mAutofillId;
+        }
+
+        @Override
+        public void setAutofillId(AutofillId id) {
+            // TODO(b/111276913): temporarily setting directly; should be done on superclass instead
+            mNode.mAutofillId = id;
+        }
+
+        @Override
+        public void setAutofillId(AutofillId parentId, int virtualId) {
+            // TODO(b/111276913): temporarily setting directly; should be done on superclass instead
+            mNode.mAutofillId = new AutofillId(parentId, virtualId);
+        }
+
+        @Override
+        public void setAutofillType(int type) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setAutofillHints(String[] hint) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setAutofillValue(AutofillValue value) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setAutofillOptions(CharSequence[] options) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setInputType(int inputType) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setDataIsSensitive(boolean sensitive) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void asyncCommit() {
+            Log.w(TAG, "asyncCommit() is not supported");
+        }
+
+        @Override
+        public Rect getTempRect() {
+            // TODO(b/111276913): implement or move to superclass
+            return null;
+        }
+
+        @Override
+        public void setWebDomain(String domain) {
+            Log.w(TAG, "setWebDomain() is not supported");
+        }
+
+        @Override
+        public void setLocaleList(LocaleList localeList) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public Builder newHtmlInfoBuilder(String tagName) {
+            Log.w(TAG, "newHtmlInfoBuilder() is not supported");
+            return null;
+        }
+
+        @Override
+        public void setHtmlInfo(HtmlInfo htmlInfo) {
+            Log.w(TAG, "setHtmlInfo() is not supported");
+        }
     }
 }
diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java
index e675744..524f709 100644
--- a/core/java/android/view/textclassifier/TextClassifier.java
+++ b/core/java/android/view/textclassifier/TextClassifier.java
@@ -48,6 +48,9 @@
 
 /**
  * Interface for providing text classification related features.
+ * <p>
+ * The TextClassifier may be used to understand the meaning of text, as well as generating predicted
+ * next actions based on the text.
  *
  * <p><strong>NOTE: </strong>Unless otherwise stated, methods of this interface are blocking
  * operations. Call on a worker thread.
diff --git a/core/java/android/view/textclassifier/TextLinks.java b/core/java/android/view/textclassifier/TextLinks.java
index b31438f..02aee50 100644
--- a/core/java/android/view/textclassifier/TextLinks.java
+++ b/core/java/android/view/textclassifier/TextLinks.java
@@ -21,6 +21,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
+import android.os.Bundle;
 import android.os.LocaleList;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -92,10 +93,12 @@
 
     private final String mFullText;
     private final List<TextLink> mLinks;
+    private final Bundle mExtras;
 
-    private TextLinks(String fullText, ArrayList<TextLink> links) {
+    private TextLinks(String fullText, ArrayList<TextLink> links, Bundle extras) {
         mFullText = fullText;
         mLinks = Collections.unmodifiableList(links);
+        mExtras = extras;
     }
 
     /**
@@ -116,6 +119,18 @@
     }
 
     /**
+     * Returns the extended data.
+     *
+     * <p><b>NOTE: </b>Each call to this method returns a new bundle copy so clients should
+     * prefer to hold a reference to the returned bundle rather than frequently calling this
+     * method.
+     */
+    @NonNull
+    public Bundle getExtras() {
+        return mExtras.deepCopy();
+    }
+
+    /**
      * Annotates the given text with the generated links. It will fail if the provided text doesn't
      * match the original text used to create the TextLinks.
      *
@@ -158,6 +173,7 @@
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeString(mFullText);
         dest.writeTypedList(mLinks);
+        dest.writeBundle(mExtras);
     }
 
     public static final Parcelable.Creator<TextLinks> CREATOR =
@@ -176,6 +192,7 @@
     private TextLinks(Parcel in) {
         mFullText = in.readString();
         mLinks = in.createTypedArrayList(TextLink.CREATOR);
+        mExtras = in.readBundle();
     }
 
     /**
@@ -304,18 +321,21 @@
         @Nullable private final TextClassifier.EntityConfig mEntityConfig;
         private final boolean mLegacyFallback;
         private String mCallingPackageName;
+        private final Bundle mExtras;
 
         private Request(
                 CharSequence text,
                 LocaleList defaultLocales,
                 TextClassifier.EntityConfig entityConfig,
                 boolean legacyFallback,
-                String callingPackageName) {
+                String callingPackageName,
+                Bundle extras) {
             mText = text;
             mDefaultLocales = defaultLocales;
             mEntityConfig = entityConfig;
             mLegacyFallback = legacyFallback;
             mCallingPackageName = callingPackageName;
+            mExtras = extras;
         }
 
         /**
@@ -362,6 +382,18 @@
         }
 
         /**
+         * Returns the extended data.
+         *
+         * <p><b>NOTE: </b>Each call to this method returns a new bundle copy so clients should
+         * prefer to hold a reference to the returned bundle rather than frequently calling this
+         * method.
+         */
+        @NonNull
+        public Bundle getExtras() {
+            return mExtras.deepCopy();
+        }
+
+        /**
          * A builder for building TextLinks requests.
          */
         public static final class Builder {
@@ -372,6 +404,7 @@
             @Nullable private TextClassifier.EntityConfig mEntityConfig;
             private boolean mLegacyFallback = true; // Use legacy fall back by default.
             private String mCallingPackageName;
+            @Nullable private Bundle mExtras;
 
             public Builder(@NonNull CharSequence text) {
                 mText = Preconditions.checkNotNull(text);
@@ -431,15 +464,25 @@
             }
 
             /**
+             * Sets the extended data.
+             *
+             * @return this builder
+             */
+            public Builder setExtras(@Nullable Bundle extras) {
+                mExtras = extras;
+                return this;
+            }
+
+            /**
              * Builds and returns the request object.
              */
             @NonNull
             public Request build() {
                 return new Request(
                         mText, mDefaultLocales, mEntityConfig,
-                        mLegacyFallback, mCallingPackageName);
+                        mLegacyFallback, mCallingPackageName,
+                        mExtras == null ? Bundle.EMPTY : mExtras.deepCopy());
             }
-
         }
 
         /**
@@ -469,6 +512,7 @@
                 mEntityConfig.writeToParcel(dest, flags);
             }
             dest.writeString(mCallingPackageName);
+            dest.writeBundle(mExtras);
         }
 
         public static final Parcelable.Creator<Request> CREATOR =
@@ -491,6 +535,7 @@
                     ? null : TextClassifier.EntityConfig.CREATOR.createFromParcel(in);
             mLegacyFallback = true;
             mCallingPackageName = in.readString();
+            mExtras = in.readBundle();
         }
     }
 
@@ -575,6 +620,7 @@
     public static final class Builder {
         private final String mFullText;
         private final ArrayList<TextLink> mLinks;
+        private Bundle mExtras;
 
         /**
          * Create a new TextLinks.Builder.
@@ -622,13 +668,24 @@
         }
 
         /**
+         * Sets the extended data.
+         *
+         * @return this builder
+         */
+        public Builder setExtras(@Nullable Bundle extras) {
+            mExtras = extras;
+            return this;
+        }
+
+        /**
          * Constructs a TextLinks instance.
          *
          * @return the constructed TextLinks
          */
         @NonNull
         public TextLinks build() {
-            return new TextLinks(mFullText, mLinks);
+            return new TextLinks(mFullText, mLinks,
+                    mExtras == null ? Bundle.EMPTY : mExtras.deepCopy());
         }
     }
 }
diff --git a/core/java/android/view/textclassifier/TextSelection.java b/core/java/android/view/textclassifier/TextSelection.java
index 52d01ea..f236915 100644
--- a/core/java/android/view/textclassifier/TextSelection.java
+++ b/core/java/android/view/textclassifier/TextSelection.java
@@ -20,6 +20,7 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.os.Bundle;
 import android.os.LocaleList;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -41,13 +42,16 @@
     private final int mEndIndex;
     private final EntityConfidence mEntityConfidence;
     @Nullable private final String mId;
+    private final Bundle mExtras;
 
     private TextSelection(
-            int startIndex, int endIndex, Map<String, Float> entityConfidence, String id) {
+            int startIndex, int endIndex, Map<String, Float> entityConfidence, String id,
+            Bundle extras) {
         mStartIndex = startIndex;
         mEndIndex = endIndex;
         mEntityConfidence = new EntityConfidence(entityConfidence);
         mId = id;
+        mExtras = extras;
     }
 
     /**
@@ -103,6 +107,18 @@
         return mId;
     }
 
+    /**
+     * Returns the extended data.
+     *
+     * <p><b>NOTE: </b>Each call to this method returns a new bundle copy so clients should
+     * prefer to hold a reference to the returned bundle rather than frequently calling this
+     * method.
+     */
+    @NonNull
+    public Bundle getExtras() {
+        return mExtras.deepCopy();
+    }
+
     @Override
     public String toString() {
         return String.format(
@@ -120,6 +136,8 @@
         private final int mEndIndex;
         private final Map<String, Float> mEntityConfidence = new ArrayMap<>();
         @Nullable private String mId;
+        @Nullable
+        private Bundle mExtras;
 
         /**
          * Creates a builder used to build {@link TextSelection} objects.
@@ -160,12 +178,23 @@
         }
 
         /**
+         * Sets the extended data.
+         *
+         * @return this builder
+         */
+        public Builder setExtras(@Nullable Bundle extras) {
+            mExtras = extras;
+            return this;
+        }
+
+        /**
          * Builds and returns {@link TextSelection} object.
          */
         @NonNull
         public TextSelection build() {
             return new TextSelection(
-                    mStartIndex, mEndIndex, mEntityConfidence, mId);
+                    mStartIndex, mEndIndex, mEntityConfidence, mId,
+                    mExtras == null ? Bundle.EMPTY : mExtras.deepCopy());
         }
     }
 
@@ -179,18 +208,21 @@
         private final int mEndIndex;
         @Nullable private final LocaleList mDefaultLocales;
         private final boolean mDarkLaunchAllowed;
+        private final Bundle mExtras;
 
         private Request(
                 CharSequence text,
                 int startIndex,
                 int endIndex,
                 LocaleList defaultLocales,
-                boolean darkLaunchAllowed) {
+                boolean darkLaunchAllowed,
+                Bundle extras) {
             mText = text;
             mStartIndex = startIndex;
             mEndIndex = endIndex;
             mDefaultLocales = defaultLocales;
             mDarkLaunchAllowed = darkLaunchAllowed;
+            mExtras = extras;
         }
 
         /**
@@ -238,6 +270,18 @@
         }
 
         /**
+         * Returns the extended data.
+         *
+         * <p><b>NOTE: </b>Each call to this method returns a new bundle copy so clients should
+         * prefer to hold a reference to the returned bundle rather than frequently calling this
+         * method.
+         */
+        @NonNull
+        public Bundle getExtras() {
+            return mExtras.deepCopy();
+        }
+
+        /**
          * A builder for building TextSelection requests.
          */
         public static final class Builder {
@@ -248,6 +292,7 @@
 
             @Nullable private LocaleList mDefaultLocales;
             private boolean mDarkLaunchAllowed;
+            private Bundle mExtras;
 
             /**
              * @param text text providing context for the selected text (which is specified by the
@@ -296,12 +341,23 @@
             }
 
             /**
+             * Sets the extended data.
+             *
+             * @return this builder
+             */
+            public Builder setExtras(@Nullable Bundle extras) {
+                mExtras = extras;
+                return this;
+            }
+
+            /**
              * Builds and returns the request object.
              */
             @NonNull
             public Request build() {
                 return new Request(mText, mStartIndex, mEndIndex,
-                        mDefaultLocales, mDarkLaunchAllowed);
+                        mDefaultLocales, mDarkLaunchAllowed,
+                        mExtras == null ? Bundle.EMPTY : mExtras.deepCopy());
             }
         }
 
@@ -319,6 +375,7 @@
             if (mDefaultLocales != null) {
                 mDefaultLocales.writeToParcel(dest, flags);
             }
+            dest.writeBundle(mExtras);
         }
 
         public static final Parcelable.Creator<Request> CREATOR =
@@ -340,6 +397,7 @@
             mEndIndex = in.readInt();
             mDefaultLocales = in.readInt() == 0 ? null : LocaleList.CREATOR.createFromParcel(in);
             mDarkLaunchAllowed = false;
+            mExtras = in.readBundle();
         }
     }
 
@@ -354,6 +412,7 @@
         dest.writeInt(mEndIndex);
         mEntityConfidence.writeToParcel(dest, flags);
         dest.writeString(mId);
+        dest.writeBundle(mExtras);
     }
 
     public static final Parcelable.Creator<TextSelection> CREATOR =
@@ -374,5 +433,6 @@
         mEndIndex = in.readInt();
         mEntityConfidence = EntityConfidence.CREATOR.createFromParcel(in);
         mId = in.readString();
+        mExtras = in.readBundle();
     }
 }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index f343a52..1093719 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2695,6 +2695,11 @@
     }
 
     @Override
+    public boolean onProvideContentCaptureStructure(ViewStructure structure, int flags) {
+        return mProvider.getViewDelegate().onProvideContentCaptureStructure(structure, flags);
+    }
+
+    @Override
     public void autofill(SparseArray<AutofillValue>values) {
         mProvider.getViewDelegate().autofill(values);
     }
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 00e782b..ceada07 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -341,6 +341,12 @@
             return true; // true is the default value returned by View.isVisibleToUserForAutofill()
         }
 
+        default boolean onProvideContentCaptureStructure(
+                @SuppressWarnings("unused") android.view.ViewStructure structure,
+                @SuppressWarnings("unused") int flags) {
+            return false; // WebView provides virtual views and is responsible to notify manager
+        }
+
         public AccessibilityNodeProvider getAccessibilityNodeProvider();
 
         public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info);
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index f3fe16e..ddff858 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -1309,13 +1309,23 @@
     @Override
     public void onProvideAutofillStructure(ViewStructure structure, int flags) {
         super.onProvideAutofillStructure(structure, flags);
+    }
 
-        final Adapter adapter = getAdapter();
-        if (adapter == null) return;
+    /** @hide */
+    @Override
+    protected void onProvideStructure(@NonNull ViewStructure structure,
+            @ViewStructureType int viewFor, int flags) {
+        super.onProvideStructure(structure, viewFor, flags);
 
-        final CharSequence[] options = adapter.getAutofillOptions();
-        if (options != null) {
-            structure.setAutofillOptions(options);
+        if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
+                || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
+            final Adapter adapter = getAdapter();
+            if (adapter == null) return;
+
+            final CharSequence[] options = adapter.getAutofillOptions();
+            if (options != null) {
+                structure.setAutofillOptions(options);
+            }
         }
     }
 }
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index 8d09489..d35bec8 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -578,11 +578,16 @@
         stream.addProperty("checked", isChecked());
     }
 
-    @Override
-    public void onProvideAutofillStructure(ViewStructure structure, int flags) {
-        super.onProvideAutofillStructure(structure, flags);
 
-        structure.setDataIsSensitive(!mCheckedFromResource);
+    /** @hide */
+    @Override
+    protected void onProvideStructure(@NonNull ViewStructure structure,
+            @ViewStructureType int viewFor, int flags) {
+        super.onProvideStructure(structure, viewFor, flags);
+
+        if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
+            structure.setDataIsSensitive(!mCheckedFromResource);
+        }
     }
 
     @Override
diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java
index 9da2a43..9f509b1 100644
--- a/core/java/android/widget/Magnifier.java
+++ b/core/java/android/widget/Magnifier.java
@@ -93,6 +93,8 @@
     private final int mDefaultHorizontalSourceToMagnifierOffset;
     // The vertical offset between the source and window coords when #show(float, float) is used.
     private final int mDefaultVerticalSourceToMagnifierOffset;
+    // Whether the magnifier will be clamped inside the main surface and not overlap system insets.
+    private final boolean mForcePositionWithinWindowSystemInsetsBounds;
     // The parent surface for the magnifier surface.
     private SurfaceInfo mParentSurface;
     // The surface where the content will be copied from.
@@ -141,6 +143,8 @@
                 params.mHorizontalDefaultSourceToMagnifierOffset;
         mDefaultVerticalSourceToMagnifierOffset =
                 params.mVerticalDefaultSourceToMagnifierOffset;
+        mForcePositionWithinWindowSystemInsetsBounds =
+                params.mForcePositionWithinWindowSystemInsetsBounds;
         // The view's surface coordinates will not be updated until the magnifier is first shown.
         mViewCoordinatesInSurface = new int[2];
     }
@@ -379,6 +383,17 @@
     }
 
     /**
+     * Returns whether the magnifier position will be adjusted such that the magnifier will be
+     * fully within the bounds of the main application window, by also avoiding any overlap with
+     * system insets (such as the one corresponding to the status bar).
+     * @return whether the magnifier position will be adjusted
+     * @see Magnifier.Builder#setForcePositionWithinWindowSystemInsetsBounds(boolean)
+     */
+    public boolean isForcePositionWithinWindowSystemInsetsBounds() {
+        return mForcePositionWithinWindowSystemInsetsBounds;
+    }
+
+    /**
      * Returns the top left coordinates of the magnifier, relative to the surface of the
      * main application window. They will be determined by the coordinates of the last
      * {@link #show(float, float)} or {@link #show(float, float, float, float)} call, adjusted
@@ -567,6 +582,11 @@
      * @return the current window coordinates, after they are clamped inside the parent surface
      */
     private Point getCurrentClampedWindowCoordinates() {
+        if (!mForcePositionWithinWindowSystemInsetsBounds) {
+            // No position adjustment should be done, so return the raw coordinates.
+            return new Point(mWindowCoords);
+        }
+
         final Rect windowBounds;
         if (mParentSurface.mIsMainWindowSurface) {
             final Insets systemInsets = mView.getRootWindowInsets().getSystemWindowInsets();
@@ -891,6 +911,7 @@
         private @FloatRange(from = 0f) float mCornerRadius;
         private int mHorizontalDefaultSourceToMagnifierOffset;
         private int mVerticalDefaultSourceToMagnifierOffset;
+        private boolean mForcePositionWithinWindowSystemInsetsBounds;
 
         /**
          * Construct a new builder for {@link Magnifier} objects.
@@ -915,6 +936,7 @@
             mVerticalDefaultSourceToMagnifierOffset =
                     a.getDimensionPixelSize(R.styleable.Magnifier_magnifierVerticalOffset, 0);
             a.recycle();
+            mForcePositionWithinWindowSystemInsetsBounds = true;
         }
 
         /**
@@ -1000,6 +1022,28 @@
         }
 
         /**
+         * Defines the behavior of the magnifier when it is requested to position outside the
+         * surface of the main application window. The default value is {@code true}, which means
+         * that the position will be adjusted such that the magnifier will be fully within the
+         * bounds of the main application window, by also avoiding any overlap with system insets
+         * (such as the one corresponding to the status bar). If you require a custom behavior, this
+         * flag should be set to {@code false}, meaning that the magnifier will be able to cross the
+         * main application surface boundaries (and also overlap the system insets). This should be
+         * handled with care, when passing coordinates to {@link #show(float, float)}; note that:
+         * <ul>
+         *   <li>in a multiwindow context, if the magnifier crosses the boundary between the two
+         *   windows, it will not be able to show over the window of the other application</li>
+         *   <li>if the magnifier overlaps the status bar, there is no guarantee about which one
+         *   will be displayed on top. This should be handled with care.</li>
+         * </ul>
+         * @param force whether the magnifier position will be adjusted
+         */
+        public Builder setForcePositionWithinWindowSystemInsetsBounds(boolean force) {
+            mForcePositionWithinWindowSystemInsetsBounds = force;
+            return this;
+        }
+
+        /**
          * Builds a {@link Magnifier} instance based on the configuration of this {@link Builder}.
          */
         public @NonNull Magnifier build() {
diff --git a/core/java/android/widget/RadioGroup.java b/core/java/android/widget/RadioGroup.java
index 327a5c1..ab12eac 100644
--- a/core/java/android/widget/RadioGroup.java
+++ b/core/java/android/widget/RadioGroup.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import android.annotation.IdRes;
+import android.annotation.NonNull;
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -424,10 +425,15 @@
         }
     }
 
+    /** @hide */
     @Override
-    public void onProvideAutofillStructure(ViewStructure structure, int flags) {
-        super.onProvideAutofillStructure(structure, flags);
-        structure.setDataIsSensitive(mCheckedId != mInitialCheckedId);
+    protected void onProvideStructure(@NonNull ViewStructure structure,
+            @ViewStructureType int viewFor, int flags) {
+        super.onProvideStructure(structure, viewFor, flags);
+
+        if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
+            structure.setDataIsSensitive(mCheckedId != mInitialCheckedId);
+        }
     }
 
     @Override
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index a93604f..c0979fe 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -196,12 +196,6 @@
     private boolean mIsRoot = true;
 
     /**
-     * Optional theme resource id applied in inflateView(). When 0, Theme.DeviceDefault will be
-     * used.
-     */
-    private int mApplyThemeResId;
-
-    /**
      * Whether reapply is disallowed on this remoteview. This maybe be true if some actions modify
      * the layout in a way that isn't recoverable, since views are being removed.
      */
@@ -3262,14 +3256,6 @@
     }
 
     /**
-     * Set the theme used in apply() and applyASync().
-     * @hide
-     */
-    public void setApplyTheme(@StyleRes int themeResId) {
-        mApplyThemeResId = themeResId;
-    }
-
-    /**
      * Inflates the view hierarchy represented by this object and applies
      * all of the actions.
      *
@@ -3290,11 +3276,25 @@
 
         View result = inflateView(context, rvToApply, parent);
         rvToApply.performApply(result, parent, handler);
+        return result;
+    }
 
+    /** @hide */
+    public View applyWithTheme(Context context, ViewGroup parent, OnClickHandler handler,
+            @StyleRes int applyThemeResId) {
+        RemoteViews rvToApply = getRemoteViewsToApply(context);
+
+        View result = inflateView(context, rvToApply, parent, applyThemeResId);
+        rvToApply.performApply(result, parent, handler);
         return result;
     }
 
     private View inflateView(Context context, RemoteViews rv, ViewGroup parent) {
+        return inflateView(context, rv, parent, 0);
+    }
+
+    private View inflateView(Context context, RemoteViews rv, ViewGroup parent,
+            @StyleRes int applyThemeResId) {
         // RemoteViews may be built by an application installed in another
         // user. So build a context that loads resources from that user but
         // still returns the current users userId so settings like data / time formats
@@ -3303,8 +3303,8 @@
         Context inflationContext = new RemoteViewsContextWrapper(context, contextForResources);
 
         // If mApplyThemeResId is not given, Theme.DeviceDefault will be used.
-        if (mApplyThemeResId != 0) {
-            inflationContext = new ContextThemeWrapper(inflationContext, mApplyThemeResId);
+        if (applyThemeResId != 0) {
+            inflationContext = new ContextThemeWrapper(inflationContext, applyThemeResId);
         }
         LayoutInflater inflater = (LayoutInflater)
                 context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index 8bfc151..d55c09f 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -1422,17 +1422,24 @@
     @Override
     public void onProvideStructure(ViewStructure structure) {
         super.onProvideStructure(structure);
-        onProvideAutoFillStructureForAssistOrAutofill(structure);
+        onProvideStructureForAssistOrAutofillOrViewCapture(structure);
     }
 
     @Override
     public void onProvideAutofillStructure(ViewStructure structure, int flags) {
         super.onProvideAutofillStructure(structure, flags);
-        onProvideAutoFillStructureForAssistOrAutofill(structure);
+        onProvideStructureForAssistOrAutofillOrViewCapture(structure);
     }
 
-    // NOTE: currently there is no difference for Assist or AutoFill, so it doesn't take flags
-    private void onProvideAutoFillStructureForAssistOrAutofill(ViewStructure structure) {
+    @Override
+    public boolean onProvideContentCaptureStructure(ViewStructure structure, int flags) {
+        final boolean notifyManager = super.onProvideContentCaptureStructure(structure, flags);
+        onProvideStructureForAssistOrAutofillOrViewCapture(structure);
+        return notifyManager;
+    }
+
+    // NOTE: currently there is no difference for any type, so it doesn't take flags
+    private void onProvideStructureForAssistOrAutofillOrViewCapture(ViewStructure structure) {
         CharSequence switchText = isChecked() ? mTextOn : mTextOff;
         if (!TextUtils.isEmpty(switchText)) {
             CharSequence oldText = structure.getText();
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 572670f..35be766 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -166,6 +166,7 @@
 import android.view.inputmethod.ExtractedTextRequest;
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
+import android.view.intelligence.IntelligenceManager;
 import android.view.textclassifier.TextClassification;
 import android.view.textclassifier.TextClassificationContext;
 import android.view.textclassifier.TextClassificationManager;
@@ -948,6 +949,9 @@
         if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
             setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
         }
+        if (getImportantForContentCapture() == IMPORTANT_FOR_CONTENT_CAPTURE_AUTO) {
+            setImportantForContentCapture(IMPORTANT_FOR_CONTENT_CAPTURE_YES);
+        }
 
         setTextInternal("");
 
@@ -6072,7 +6076,7 @@
         if (needEditableForNotification) {
             sendAfterTextChanged((Editable) text);
         } else {
-            notifyAutoFillManagerAfterTextChanged();
+            notifyListeningManagersAfterTextChanged();
         }
 
         // SelectionModifierCursorController depends on textCanBeSelected, which depends on text
@@ -10120,24 +10124,37 @@
             }
         }
 
-        // Always notify AutoFillManager - it will return right away if autofill is disabled.
-        notifyAutoFillManagerAfterTextChanged();
+        notifyListeningManagersAfterTextChanged();
 
         hideErrorIfUnchanged();
     }
 
-    private void notifyAutoFillManagerAfterTextChanged() {
-        // It is important to not check whether the view is important for autofill
-        // since the user can trigger autofill manually on not important views.
-        if (!isAutofillable()) {
-            return;
-        }
-        final AutofillManager afm = mContext.getSystemService(AutofillManager.class);
-        if (afm != null) {
-            if (android.view.autofill.Helper.sVerbose) {
-                Log.v(LOG_TAG, "notifyAutoFillManagerAfterTextChanged");
+    /**
+     * Notify managers (such as {@link AutofillManager} and {@link IntelligenceManager}) that are
+     * interested on text changes.
+     */
+    private void notifyListeningManagersAfterTextChanged() {
+
+        // Autofill
+        if (isAutofillable()) {
+            // It is important to not check whether the view is important for autofill
+            // since the user can trigger autofill manually on not important views.
+            final AutofillManager afm = mContext.getSystemService(AutofillManager.class);
+            if (afm != null) {
+                if (android.view.autofill.Helper.sVerbose) {
+                    Log.v(LOG_TAG, "notifyAutoFillManagerAfterTextChanged");
+                }
+                afm.notifyValueChanged(TextView.this);
             }
-            afm.notifyValueChanged(TextView.this);
+        }
+
+        // ContentCapture
+        if (isImportantForContentCapture() && isTextEditable()) {
+            final IntelligenceManager im = mContext.getSystemService(IntelligenceManager.class);
+            if (im != null && im.isContentCaptureEnabled()) {
+                // TODO(b/111276913): pass flags when edited by user / add CTS test
+                im.notifyViewTextChanged(getAutofillId(), getText(), /* flags= */ 0);
+            }
         }
     }
 
@@ -10897,24 +10914,19 @@
         return TextView.class.getName();
     }
 
+    /** @hide */
     @Override
-    public void onProvideStructure(ViewStructure structure) {
-        super.onProvideStructure(structure);
-        onProvideAutoStructureForAssistOrAutofill(structure, false);
-    }
+    protected void onProvideStructure(@NonNull ViewStructure structure,
+            @ViewStructureType int viewFor, int flags) {
+        super.onProvideStructure(structure, viewFor, flags);
 
-    @Override
-    public void onProvideAutofillStructure(ViewStructure structure, int flags) {
-        super.onProvideAutofillStructure(structure, flags);
-        onProvideAutoStructureForAssistOrAutofill(structure, true);
-    }
-
-    private void onProvideAutoStructureForAssistOrAutofill(ViewStructure structure,
-            boolean forAutofill) {
         final boolean isPassword = hasPasswordTransformationMethod()
                 || isPasswordInputType(getInputType());
-        if (forAutofill) {
-            structure.setDataIsSensitive(!mTextSetFromXmlOrResourceId);
+        if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
+                || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
+            if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
+                structure.setDataIsSensitive(!mTextSetFromXmlOrResourceId);
+            }
             if (mTextId != ResourceId.ID_NULL) {
                 try {
                     structure.setTextIdEntry(getResources().getResourceEntryName(mTextId));
@@ -10927,7 +10939,8 @@
             }
         }
 
-        if (!isPassword || forAutofill) {
+        if (!isPassword || viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
+                || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
             if (mLayout == null) {
                 assumeLayout();
             }
@@ -10936,7 +10949,7 @@
             if (lineCount <= 1) {
                 // Simple case: this is a single line.
                 final CharSequence text = getText();
-                if (forAutofill) {
+                if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
                     structure.setText(text);
                 } else {
                     structure.setText(text, getSelectionStart(), getSelectionEnd());
@@ -11000,7 +11013,7 @@
                     text = text.subSequence(expandedTopChar, expandedBottomChar);
                 }
 
-                if (forAutofill) {
+                if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
                     structure.setText(text);
                 } else {
                     structure.setText(text, selStart - expandedTopChar, selEnd - expandedTopChar);
@@ -11016,7 +11029,8 @@
                 }
             }
 
-            if (!forAutofill) {
+            if (viewFor == VIEW_STRUCTURE_FOR_ASSIST
+                    || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
                 // Extract style information that applies to the TextView as a whole.
                 int style = 0;
                 int typefaceStyle = getTypefaceStyle();
@@ -11043,7 +11057,9 @@
                 // of the View (and can be any drawable) or a BackgroundColorSpan inside the text.
                 structure.setTextStyle(getTextSize(), getCurrentTextColor(),
                         AssistStructure.ViewNode.TEXT_COLOR_UNDEFINED /* bgColor */, style);
-            } else {
+            }
+            if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
+                    || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
                 structure.setMinTextEms(getMinEms());
                 structure.setMaxTextEms(getMaxEms());
                 int maxLength = -1;
diff --git a/core/java/com/android/internal/app/ColorDisplayController.java b/core/java/com/android/internal/app/ColorDisplayController.java
index 7515180..213bb75 100644
--- a/core/java/com/android/internal/app/ColorDisplayController.java
+++ b/core/java/com/android/internal/app/ColorDisplayController.java
@@ -560,13 +560,6 @@
     }
 
     /**
-     * Returns {@code true} if Night display is supported by the device.
-     */
-    public static boolean isAvailable(Context context) {
-        return context.getResources().getBoolean(R.bool.config_nightDisplayAvailable);
-    }
-
-    /**
      * Callback invoked whenever the Night display settings are changed.
      */
     public interface Callback {
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 0f88722..46c6fa4 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -93,6 +93,9 @@
 @UiThread
 public class ResolverActivity extends Activity {
 
+    // Temporary flag for new chooser delegate behavior.
+    boolean mEnableChooserDelegate = false;
+
     protected ResolveListAdapter mAdapter;
     private boolean mSafeForwardingMode;
     private AbsListView mAdapterView;
@@ -1216,7 +1219,13 @@
 
         @Override
         public boolean startAsCaller(ResolverActivity activity, Bundle options, int userId) {
-            return activity.startAsCallerImpl(mResolvedIntent, options, false, userId);
+
+            if (mEnableChooserDelegate) {
+                return activity.startAsCallerImpl(mResolvedIntent, options, false, userId);
+            } else {
+                activity.startActivityAsCaller(mResolvedIntent, options, null, false, userId);
+                return true;
+            }
         }
 
         @Override
diff --git a/core/java/com/android/internal/content/FileSystemProvider.java b/core/java/com/android/internal/content/FileSystemProvider.java
index 81dab2f..8bc90a8 100644
--- a/core/java/com/android/internal/content/FileSystemProvider.java
+++ b/core/java/com/android/internal/content/FileSystemProvider.java
@@ -389,14 +389,18 @@
      * @param query the search condition used to match file names
      * @param projection projection of the returned cursor
      * @param exclusion absolute file paths to exclude from result
-     * @return cursor containing search result
+     * @param queryArgs the query arguments for search
+     * @return cursor containing search result. Include
+     *         {@link ContentResolver#EXTRA_HONORED_ARGS} in {@link Cursor}
+     *         extras {@link Bundle} when any QUERY_ARG_* value was honored
+     *         during the preparation of the results.
      * @throws FileNotFoundException when root folder doesn't exist or search fails
+     *
+     * @see ContentResolver#EXTRA_HONORED_ARGS
      */
     protected final Cursor querySearchDocuments(
-            File folder, String query, String[] projection, Set<String> exclusion)
+            File folder, String[] projection, Set<String> exclusion, Bundle queryArgs)
             throws FileNotFoundException {
-
-        query = query.toLowerCase();
         final MatrixCursor result = new MatrixCursor(resolveProjection(projection));
         final LinkedList<File> pending = new LinkedList<>();
         pending.add(folder);
@@ -407,11 +411,18 @@
                     pending.add(child);
                 }
             }
-            if (file.getName().toLowerCase().contains(query)
-                    && !exclusion.contains(file.getAbsolutePath())) {
+            if (!exclusion.contains(file.getAbsolutePath()) && matchSearchQueryArguments(file,
+                    queryArgs)) {
                 includeFile(result, null, file);
             }
         }
+
+        final String[] handledQueryArgs = DocumentsContract.getHandledQueryArguments(queryArgs);
+        if (handledQueryArgs.length > 0) {
+            final Bundle extras = new Bundle();
+            extras.putStringArray(ContentResolver.EXTRA_HONORED_ARGS, handledQueryArgs);
+            result.setExtras(extras);
+        }
         return result;
     }
 
@@ -457,6 +468,34 @@
         }
     }
 
+    /**
+     * Test if the file matches the query arguments.
+     *
+     * @param file the file to test
+     * @param queryArgs the query arguments
+     */
+    private boolean matchSearchQueryArguments(File file, Bundle queryArgs) {
+        if (file == null) {
+            return false;
+        }
+
+        final String fileMimeType;
+        final String fileName = file.getName();
+
+        if (file.isDirectory()) {
+            fileMimeType = DocumentsContract.Document.MIME_TYPE_DIR;
+        } else {
+            int dotPos = fileName.lastIndexOf('.');
+            if (dotPos < 0) {
+                return false;
+            }
+            final String extension = fileName.substring(dotPos + 1);
+            fileMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
+        }
+        return DocumentsContract.matchSearchQueryArguments(queryArgs, fileName, fileMimeType,
+                file.lastModified(), file.length());
+    }
+
     private void scanFile(File visibleFile) {
         final Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
         intent.setData(Uri.fromFile(visibleFile));
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 9b8f120..604537f 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -142,7 +142,7 @@
 
     // Used to show the dialog when BiometricService starts authentication
     void showBiometricDialog(in Bundle bundle, IBiometricPromptReceiver receiver, int type,
-            boolean requireConfirmation);
+            boolean requireConfirmation, int userId);
     // Used to hide the dialog when a biometric is authenticated
     void onBiometricAuthenticated();
     // Used to set a temporary message, e.g. fingerprint not recognized, finger moved too fast, etc
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 90f2002..9a7094a 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -92,7 +92,7 @@
 
     // Used to show the dialog when BiometricService starts authentication
     void showBiometricDialog(in Bundle bundle, IBiometricPromptReceiver receiver, int type,
-            boolean requireConfirmation);
+            boolean requireConfirmation, int userId);
     // Used to hide the dialog when a biometric is authenticated
     void onBiometricAuthenticated();
     // Used to set a temporary message, e.g. fingerprint not recognized, finger moved too fast, etc
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index e3490f1..137ca7f 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -16,7 +16,6 @@
 
 package com.android.internal.view;
 
-import android.annotation.UnsupportedAppUsage;
 import android.graphics.Rect;
 import android.hardware.input.InputManager;
 import android.os.Bundle;
@@ -66,7 +65,7 @@
     }
 
     @Override
-    public void windowFocusChanged(boolean hasFocus, boolean touchEnabled) {
+    public void windowFocusChanged(boolean hasFocus, boolean touchEnabled, boolean reportToClient) {
     }
 
     @Override
diff --git a/core/java/com/android/internal/widget/SubtitleView.java b/core/java/com/android/internal/widget/SubtitleView.java
index 1107828..21e63c5 100644
--- a/core/java/com/android/internal/widget/SubtitleView.java
+++ b/core/java/com/android/internal/widget/SubtitleView.java
@@ -58,7 +58,7 @@
     /** Reusable spannable string builder used for holding text. */
     private final SpannableStringBuilder mText = new SpannableStringBuilder();
 
-    private Alignment mAlignment;
+    private Alignment mAlignment = Alignment.ALIGN_CENTER;
     private TextPaint mTextPaint;
     private Paint mPaint;
 
diff --git a/core/jni/android_hardware_camera2_DngCreator.cpp b/core/jni/android_hardware_camera2_DngCreator.cpp
index c977437..29051f1 100644
--- a/core/jni/android_hardware_camera2_DngCreator.cpp
+++ b/core/jni/android_hardware_camera2_DngCreator.cpp
@@ -892,6 +892,13 @@
             cfaOut[3] = 0;
             break;
         }
+        // MONO and NIR are degenerate case of RGGB pattern: only Red channel
+        // will be used.
+        case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_MONO:
+        case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_NIR: {
+            cfaOut[0] = 0;
+            break;
+        }
         default: {
             return BAD_VALUE;
         }
@@ -1063,6 +1070,8 @@
 
     uint32_t preWidth = 0;
     uint32_t preHeight = 0;
+    uint8_t colorFilter = 0;
+    bool isBayer = true;
     {
         // Check dimensions
         camera_metadata_entry entry =
@@ -1083,10 +1092,25 @@
                     "either the preCorrectionActiveArraySize or the pixelArraySize.");
             return nullptr;
         }
+
+        camera_metadata_entry colorFilterEntry =
+                characteristics.find(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT);
+        colorFilter = colorFilterEntry.data.u8[0];
+        camera_metadata_entry capabilitiesEntry =
+                characteristics.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
+        size_t capsCount = capabilitiesEntry.count;
+        uint8_t* caps = capabilitiesEntry.data.u8;
+        if (std::find(caps, caps+capsCount, ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME)
+                != caps+capsCount) {
+            isBayer = false;
+        } else if (colorFilter == ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_MONO ||
+                colorFilter == ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_NIR) {
+            jniThrowException(env, "java/lang/AssertionError",
+                    "A camera device with MONO/NIR color filter must have MONOCHROME capability.");
+            return nullptr;
+        }
     }
 
-
-
     writer->addIfd(TIFF_IFD_0);
 
     status_t err = OK;
@@ -1094,9 +1118,12 @@
     const uint32_t samplesPerPixel = 1;
     const uint32_t bitsPerSample = BITS_PER_SAMPLE;
 
-    OpcodeListBuilder::CfaLayout opcodeCfaLayout = OpcodeListBuilder::CFA_RGGB;
+    OpcodeListBuilder::CfaLayout opcodeCfaLayout = OpcodeListBuilder::CFA_NONE;
     uint8_t cfaPlaneColor[3] = {0, 1, 2};
-    uint8_t cfaEnum = -1;
+    camera_metadata_entry cfaEntry =
+            characteristics.find(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT);
+    BAIL_IF_EMPTY_RET_NULL_SP(cfaEntry, env, TAG_CFAPATTERN, writer);
+    uint8_t cfaEnum = cfaEntry.data.u8[0];
 
     // TODO: Greensplit.
     // TODO: Add remaining non-essential tags
@@ -1141,12 +1168,20 @@
 
     {
         // Set photometric interpretation
-        uint16_t interpretation = 32803; // CFA
+        uint16_t interpretation = isBayer ? 32803 /* CFA */ :
+                34892; /* Linear Raw */;
         BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_PHOTOMETRICINTERPRETATION, 1,
                 &interpretation, TIFF_IFD_0), env, TAG_PHOTOMETRICINTERPRETATION, writer);
     }
 
     {
+        uint16_t repeatDim[2] = {2, 2};
+        if (!isBayer) {
+            repeatDim[0] = repeatDim[1] = 1;
+        }
+        BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_BLACKLEVELREPEATDIM, 2, repeatDim,
+                TIFF_IFD_0), env, TAG_BLACKLEVELREPEATDIM, writer);
+
         // Set blacklevel tags, using dynamic black level if available
         camera_metadata_entry entry =
                 results.find(ANDROID_SENSOR_DYNAMIC_BLACK_LEVEL);
@@ -1165,14 +1200,9 @@
                 blackLevelRational[i * 2] = static_cast<uint32_t>(entry.data.i32[i]);
                 blackLevelRational[i * 2 + 1] = 1;
             }
-
         }
-        BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_BLACKLEVEL, 4, blackLevelRational,
-                TIFF_IFD_0), env, TAG_BLACKLEVEL, writer);
-
-        uint16_t repeatDim[2] = {2, 2};
-        BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_BLACKLEVELREPEATDIM, 2, repeatDim,
-                TIFF_IFD_0), env, TAG_BLACKLEVELREPEATDIM, writer);
+        BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_BLACKLEVEL, repeatDim[0]*repeatDim[1],
+                blackLevelRational, TIFF_IFD_0), env, TAG_BLACKLEVEL, writer);
     }
 
     {
@@ -1189,21 +1219,15 @@
                 TIFF_IFD_0), env, TAG_PLANARCONFIGURATION, writer);
     }
 
-    {
+    // All CFA pattern tags are not necessary for monochrome cameras.
+    if (isBayer) {
         // Set CFA pattern dimensions
         uint16_t repeatDim[2] = {2, 2};
         BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_CFAREPEATPATTERNDIM, 2, repeatDim,
                 TIFF_IFD_0), env, TAG_CFAREPEATPATTERNDIM, writer);
-    }
 
-    {
         // Set CFA pattern
-        camera_metadata_entry entry =
-                        characteristics.find(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT);
-        BAIL_IF_EMPTY_RET_NULL_SP(entry, env, TAG_CFAPATTERN, writer);
-
         const int cfaLength = 4;
-        cfaEnum = entry.data.u8[0];
         uint8_t cfa[cfaLength];
         if ((err = convertCFA(cfaEnum, /*out*/cfa)) != OK) {
             jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
@@ -1214,15 +1238,11 @@
                 env, TAG_CFAPATTERN, writer);
 
         opcodeCfaLayout = convertCFAEnumToOpcodeLayout(cfaEnum);
-    }
 
-    {
         // Set CFA plane color
         BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_CFAPLANECOLOR, 3, cfaPlaneColor,
                 TIFF_IFD_0), env, TAG_CFAPLANECOLOR, writer);
-    }
 
-    {
         // Set CFA layout
         uint16_t cfaLayout = 1;
         BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_CFALAYOUT, 1, &cfaLayout, TIFF_IFD_0),
@@ -1442,7 +1462,7 @@
     }
 
     bool singleIlluminant = false;
-    {
+    if (isBayer) {
         // Set calibration illuminants
         camera_metadata_entry entry1 =
             characteristics.find(ANDROID_SENSOR_REFERENCE_ILLUMINANT1);
@@ -1464,7 +1484,7 @@
         }
     }
 
-    {
+    if (isBayer) {
         // Set color transforms
         camera_metadata_entry entry1 =
             characteristics.find(ANDROID_SENSOR_COLOR_TRANSFORM1);
@@ -1497,7 +1517,7 @@
         }
     }
 
-    {
+    if (isBayer) {
         // Set calibration transforms
         camera_metadata_entry entry1 =
             characteristics.find(ANDROID_SENSOR_CALIBRATION_TRANSFORM1);
@@ -1531,7 +1551,7 @@
         }
     }
 
-    {
+    if (isBayer) {
         // Set forward transforms
         camera_metadata_entry entry1 =
             characteristics.find(ANDROID_SENSOR_FORWARD_MATRIX1);
@@ -1565,7 +1585,7 @@
         }
     }
 
-    {
+    if (isBayer) {
         // Set camera neutral
         camera_metadata_entry entry =
             results.find(ANDROID_SENSOR_NEUTRAL_COLOR_POINT);
@@ -1632,8 +1652,8 @@
         camera_metadata_entry entry =
             results.find(ANDROID_SENSOR_NOISE_PROFILE);
 
-        const status_t numPlaneColors = 3;
-        const status_t numCfaChannels = 4;
+        const status_t numPlaneColors = isBayer ? 3 : 1;
+        const status_t numCfaChannels = isBayer ? 4 : 1;
 
         uint8_t cfaOut[numCfaChannels];
         if ((err = convertCFA(cfaEnum, /*out*/cfaOut)) != OK) {
@@ -1710,42 +1730,44 @@
             }
         }
 
+        // Hot pixel map is specific to bayer camera per DNG spec.
+        if (isBayer) {
+            // Set up bad pixel correction list
+            camera_metadata_entry entry3 = characteristics.find(ANDROID_STATISTICS_HOT_PIXEL_MAP);
 
-        // Set up bad pixel correction list
-        camera_metadata_entry entry3 = characteristics.find(ANDROID_STATISTICS_HOT_PIXEL_MAP);
-
-        if ((entry3.count % 2) != 0) {
-            ALOGE("%s: Hot pixel map contains odd number of values, cannot map to pairs!",
-                    __FUNCTION__);
-            jniThrowRuntimeException(env, "failed to add hotpixel map.");
-            return nullptr;
-        }
-
-        // Adjust the bad pixel coordinates to be relative to the origin of the active area DNG tag
-        std::vector<uint32_t> v;
-        for (size_t i = 0; i < entry3.count; i += 2) {
-            int32_t x = entry3.data.i32[i];
-            int32_t y = entry3.data.i32[i + 1];
-            x -= static_cast<int32_t>(xmin);
-            y -= static_cast<int32_t>(ymin);
-            if (x < 0 || y < 0 || static_cast<uint32_t>(x) >= width ||
-                    static_cast<uint32_t>(y) >= height) {
-                continue;
-            }
-            v.push_back(x);
-            v.push_back(y);
-        }
-        const uint32_t* badPixels = &v[0];
-        uint32_t badPixelCount = v.size();
-
-        if (badPixelCount > 0) {
-            err = builder.addBadPixelListForMetadata(badPixels, badPixelCount, opcodeCfaLayout);
-
-            if (err != OK) {
-                ALOGE("%s: Could not add hotpixel map.", __FUNCTION__);
+            if ((entry3.count % 2) != 0) {
+                ALOGE("%s: Hot pixel map contains odd number of values, cannot map to pairs!",
+                        __FUNCTION__);
                 jniThrowRuntimeException(env, "failed to add hotpixel map.");
                 return nullptr;
             }
+
+            // Adjust the bad pixel coordinates to be relative to the origin of the active area DNG tag
+            std::vector<uint32_t> v;
+            for (size_t i = 0; i < entry3.count; i += 2) {
+                int32_t x = entry3.data.i32[i];
+                int32_t y = entry3.data.i32[i + 1];
+                x -= static_cast<int32_t>(xmin);
+                y -= static_cast<int32_t>(ymin);
+                if (x < 0 || y < 0 || static_cast<uint32_t>(x) >= width ||
+                        static_cast<uint32_t>(y) >= height) {
+                    continue;
+                }
+                v.push_back(x);
+                v.push_back(y);
+            }
+            const uint32_t* badPixels = &v[0];
+            uint32_t badPixelCount = v.size();
+
+            if (badPixelCount > 0) {
+                err = builder.addBadPixelListForMetadata(badPixels, badPixelCount, opcodeCfaLayout);
+
+                if (err != OK) {
+                    ALOGE("%s: Could not add hotpixel map.", __FUNCTION__);
+                    jniThrowRuntimeException(env, "failed to add hotpixel map.");
+                    return nullptr;
+                }
+            }
         }
 
         if (builder.getCount() > 0) {
@@ -1960,10 +1982,12 @@
         tagsToMove.add(TAG_BLACKLEVELREPEATDIM);
         tagsToMove.add(TAG_SAMPLESPERPIXEL);
         tagsToMove.add(TAG_PLANARCONFIGURATION);
-        tagsToMove.add(TAG_CFAREPEATPATTERNDIM);
-        tagsToMove.add(TAG_CFAPATTERN);
-        tagsToMove.add(TAG_CFAPLANECOLOR);
-        tagsToMove.add(TAG_CFALAYOUT);
+        if (isBayer) {
+            tagsToMove.add(TAG_CFAREPEATPATTERNDIM);
+            tagsToMove.add(TAG_CFAPATTERN);
+            tagsToMove.add(TAG_CFAPLANECOLOR);
+            tagsToMove.add(TAG_CFALAYOUT);
+        }
         tagsToMove.add(TAG_XRESOLUTION);
         tagsToMove.add(TAG_YRESOLUTION);
         tagsToMove.add(TAG_RESOLUTIONUNIT);
diff --git a/core/jni/android_hardware_input_InputWindowHandle.cpp b/core/jni/android_hardware_input_InputWindowHandle.cpp
index f4829ad..5b72241 100644
--- a/core/jni/android_hardware_input_InputWindowHandle.cpp
+++ b/core/jni/android_hardware_input_InputWindowHandle.cpp
@@ -80,51 +80,47 @@
     JNIEnv* env = AndroidRuntime::getJNIEnv();
     jobject obj = env->NewLocalRef(mObjWeak);
     if (!obj) {
-        releaseInfo();
+        releaseChannel();
         return false;
     }
 
-    if (!mInfo) {
-        mInfo = new InputWindowInfo();
-    } else {
-        mInfo->touchableRegion.clear();
-    }
+    mInfo.touchableRegion.clear();
 
     jobject inputChannelObj = env->GetObjectField(obj,
             gInputWindowHandleClassInfo.inputChannel);
     if (inputChannelObj) {
-        mInfo->inputChannel = android_view_InputChannel_getInputChannel(env, inputChannelObj);
+        mInfo.inputChannel = android_view_InputChannel_getInputChannel(env, inputChannelObj);
         env->DeleteLocalRef(inputChannelObj);
     } else {
-        mInfo->inputChannel.clear();
+        mInfo.inputChannel.clear();
     }
 
     jstring nameObj = jstring(env->GetObjectField(obj,
             gInputWindowHandleClassInfo.name));
     if (nameObj) {
         const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
-        mInfo->name = nameStr;
+        mInfo.name = nameStr;
         env->ReleaseStringUTFChars(nameObj, nameStr);
         env->DeleteLocalRef(nameObj);
     } else {
-        mInfo->name = "<null>";
+        mInfo.name = "<null>";
     }
 
-    mInfo->layoutParamsFlags = env->GetIntField(obj,
+    mInfo.layoutParamsFlags = env->GetIntField(obj,
             gInputWindowHandleClassInfo.layoutParamsFlags);
-    mInfo->layoutParamsType = env->GetIntField(obj,
+    mInfo.layoutParamsType = env->GetIntField(obj,
             gInputWindowHandleClassInfo.layoutParamsType);
-    mInfo->dispatchingTimeout = env->GetLongField(obj,
+    mInfo.dispatchingTimeout = env->GetLongField(obj,
             gInputWindowHandleClassInfo.dispatchingTimeoutNanos);
-    mInfo->frameLeft = env->GetIntField(obj,
+    mInfo.frameLeft = env->GetIntField(obj,
             gInputWindowHandleClassInfo.frameLeft);
-    mInfo->frameTop = env->GetIntField(obj,
+    mInfo.frameTop = env->GetIntField(obj,
             gInputWindowHandleClassInfo.frameTop);
-    mInfo->frameRight = env->GetIntField(obj,
+    mInfo.frameRight = env->GetIntField(obj,
             gInputWindowHandleClassInfo.frameRight);
-    mInfo->frameBottom = env->GetIntField(obj,
+    mInfo.frameBottom = env->GetIntField(obj,
             gInputWindowHandleClassInfo.frameBottom);
-    mInfo->scaleFactor = env->GetFloatField(obj,
+    mInfo.scaleFactor = env->GetFloatField(obj,
             gInputWindowHandleClassInfo.scaleFactor);
 
     jobject regionObj = env->GetObjectField(obj,
@@ -133,30 +129,30 @@
         SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj);
         for (SkRegion::Iterator it(*region); !it.done(); it.next()) {
             const SkIRect& rect = it.rect();
-            mInfo->addTouchableRegion(Rect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom));
+            mInfo.addTouchableRegion(Rect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom));
         }
         env->DeleteLocalRef(regionObj);
     }
 
-    mInfo->visible = env->GetBooleanField(obj,
+    mInfo.visible = env->GetBooleanField(obj,
             gInputWindowHandleClassInfo.visible);
-    mInfo->canReceiveKeys = env->GetBooleanField(obj,
+    mInfo.canReceiveKeys = env->GetBooleanField(obj,
             gInputWindowHandleClassInfo.canReceiveKeys);
-    mInfo->hasFocus = env->GetBooleanField(obj,
+    mInfo.hasFocus = env->GetBooleanField(obj,
             gInputWindowHandleClassInfo.hasFocus);
-    mInfo->hasWallpaper = env->GetBooleanField(obj,
+    mInfo.hasWallpaper = env->GetBooleanField(obj,
             gInputWindowHandleClassInfo.hasWallpaper);
-    mInfo->paused = env->GetBooleanField(obj,
+    mInfo.paused = env->GetBooleanField(obj,
             gInputWindowHandleClassInfo.paused);
-    mInfo->layer = env->GetIntField(obj,
+    mInfo.layer = env->GetIntField(obj,
             gInputWindowHandleClassInfo.layer);
-    mInfo->ownerPid = env->GetIntField(obj,
+    mInfo.ownerPid = env->GetIntField(obj,
             gInputWindowHandleClassInfo.ownerPid);
-    mInfo->ownerUid = env->GetIntField(obj,
+    mInfo.ownerUid = env->GetIntField(obj,
             gInputWindowHandleClassInfo.ownerUid);
-    mInfo->inputFeatures = env->GetIntField(obj,
+    mInfo.inputFeatures = env->GetIntField(obj,
             gInputWindowHandleClassInfo.inputFeatures);
-    mInfo->displayId = env->GetIntField(obj,
+    mInfo.displayId = env->GetIntField(obj,
             gInputWindowHandleClassInfo.displayId);
 
     env->DeleteLocalRef(obj);
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index 72892fa..7de8020 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -332,6 +332,18 @@
     }
     optional Dropbox dropbox = 46;
 
+    message DynamicPowerSavings {
+        option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+        // When to auto disable interventions that were triggered due to
+        // {@link #DYNAMIC_POWER_SAVINGS_ENABLED}. Value is a percentage indicating
+        // a battery level.
+        optional SettingProto disable_threshold = 1 [ (android.privacy).dest = DEST_AUTOMATIC];
+        // Whether dynamic power savings based behaviors should be running or not.
+        optional SettingProto enabled = 2 [ (android.privacy).dest = DEST_AUTOMATIC];
+    }
+    optional DynamicPowerSavings dynamic_power_savings = 143;
+
     message Emergency {
         option (android.msg_privacy).dest = DEST_EXPLICIT;
 
@@ -491,6 +503,9 @@
         // The max value for {@link #LOW_POWER_MODE_TRIGGER_LEVEL}. If this setting
         // is not set or the value is 0, the default max will be used.
         optional SettingProto trigger_level_max = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+        // Whether automatic battery saver mode is controlled via percentage,
+        // {@link #DYNAMIC_POWER_SAVINGS_ENABLED} or disabled.
+        optional SettingProto automatic_power_saver_mode = 4 [ (android.privacy).dest = DEST_AUTOMATIC];
     }
     optional LowPowerMode low_power_mode = 70;
 
@@ -972,5 +987,5 @@
 
     // Please insert fields in alphabetical order and group them into messages
     // if possible (to avoid reaching the method limit).
-    // Next tag = 143;
+    // Next tag = 144;
 }
diff --git a/core/proto/android/server/usagestatsservice.proto b/core/proto/android/server/usagestatsservice.proto
index 941c81f..3d60a86 100644
--- a/core/proto/android/server/usagestatsservice.proto
+++ b/core/proto/android/server/usagestatsservice.proto
@@ -45,11 +45,15 @@
     optional string package = 1;
     // package_index contains the index + 1 of the package name in the string pool
     optional int32 package_index = 2;
+    // Time attributes stored as an offset of the IntervalStats's beginTime.
     optional int64 last_time_active_ms = 3;
     optional int64 total_time_active_ms = 4;
     optional int32 last_event = 5;
     optional int32 app_launch_count = 6;
     repeated ChooserAction chooser_actions = 7;
+    // Time attributes stored as an offset of the IntervalStats's beginTime.
+    optional int64 last_time_service_used_ms = 8;
+    optional int64 total_time_service_used_ms = 9;
   }
 
   // Stores the relevant information an IntervalStats will have about a Configuration
@@ -86,6 +90,8 @@
   // stringpool contains all the package and class names used by UsageStats and Event
   // They will hold a number that is equal to the index + 1 of their string in the pool
   optional StringPool stringpool = 2;
+  optional int32 major_version = 3;
+  optional int32 minor_version = 4;
 
   // The following fields contain aggregated usage stats data
   optional CountAndTime interactive = 10;
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 68ec342..a99b942 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2448,6 +2448,25 @@
             <flag name="noExcludeDescendants" value="0x8" />
         </attr>
 
+        <!-- Hints the Android System whether the view node associated with this View should be
+             use for content capture purposes. -->
+        <attr name="importantForContentCapture">
+            <!-- Let the Android System use its heuristics to determine if the view is important for content capture. -->
+            <flag name="auto" value="0" />
+            <!-- Hint the Android System that this view is important for content capture,
+                  and its children (if any) will be traversed.. -->
+            <flag name="yes" value="0x1" />
+            <!-- Hint the Android System that this view is *not* important for content capture,
+                  but its children (if any) will be traversed.. -->
+            <flag name="no" value="0x2" />
+            <!-- Hint the Android System that this view is important for content capture,
+                 but its children (if any) will not be traversed. -->
+            <flag name="yesExcludeDescendants" value="0x4" />
+            <!-- Hint the Android System that this view is *not* important for content capture,
+                 and its children (if any) will not be traversed. -->
+            <flag name="noExcludeDescendants" value="0x8" />
+        </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/config.xml b/core/res/res/values/config.xml
index 6ae183b..26f3370 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3531,6 +3531,9 @@
     <!-- Whether or not battery saver should be "sticky" when manually enabled. -->
     <bool name="config_batterySaverStickyBehaviourDisabled">false</bool>
 
+    <!-- Config flag to track default disable threshold for Dynamic power savings enabled battery saver. -->
+    <integer name="config_dynamicPowerSavingsDefaultDisableThreshold">80</integer>
+
     <!-- Model of potentially misprovisioned devices. If none is specified in an overlay, an
          empty string is passed in. -->
     <string name="config_misprovisionedDeviceModel" translatable="false"></string>
diff --git a/core/res/res/values/locale_config.xml b/core/res/res/values/locale_config.xml
index 35eee6a..d6c0a10 100644
--- a/core/res/res/values/locale_config.xml
+++ b/core/res/res/values/locale_config.xml
@@ -23,80 +23,81 @@
         <item>ak-GH</item> <!-- Akan (Ghana) -->
         <item>am-ET</item> <!-- Amharic (Ethiopia) -->
         <item>ar-AE</item> <!-- Arabic (United Arab Emirates) -->
-        <item>ar-AE-u-nu-latn</item> <!-- Arabic (United Arab Emirates,Western Digits) -->
+        <item>ar-AE-u-nu-latn</item> <!-- Arabic (United Arab Emirates, Western Digits) -->
         <item>ar-BH</item> <!-- Arabic (Bahrain) -->
-        <item>ar-BH-u-nu-latn</item> <!-- Arabic (Bahrain,Western Digits) -->
+        <item>ar-BH-u-nu-latn</item> <!-- Arabic (Bahrain, Western Digits) -->
         <item>ar-DJ</item> <!-- Arabic (Djibouti) -->
-        <item>ar-DJ-u-nu-latn</item> <!-- Arabic (Djibouti,Western Digits) -->
+        <item>ar-DJ-u-nu-latn</item> <!-- Arabic (Djibouti, Western Digits) -->
         <item>ar-DZ</item> <!-- Arabic (Algeria) -->
-        <item>ar-DZ-u-nu-arab</item> <!-- Arabic (Algeria,Arabic-Indic Digits) -->
+        <item>ar-DZ-u-nu-arab</item> <!-- Arabic (Algeria, Arabic-Indic Digits) -->
         <item>ar-EG</item> <!-- Arabic (Egypt) -->
-        <item>ar-EG-u-nu-latn</item> <!-- Arabic (Egypt,Western Digits) -->
+        <item>ar-EG-u-nu-latn</item> <!-- Arabic (Egypt, Western Digits) -->
         <item>ar-EH</item> <!-- Arabic (Western Sahara) -->
-        <item>ar-EH-u-nu-arab</item> <!-- Arabic (Western Sahara,Arabic-Indic Digits) -->
+        <item>ar-EH-u-nu-arab</item> <!-- Arabic (Western Sahara, Arabic-Indic Digits) -->
         <item>ar-ER</item> <!-- Arabic (Eritrea) -->
-        <item>ar-ER-u-nu-latn</item> <!-- Arabic (Eritrea,Western Digits) -->
+        <item>ar-ER-u-nu-latn</item> <!-- Arabic (Eritrea, Western Digits) -->
         <item>ar-IL</item> <!-- Arabic (Israel) -->
-        <item>ar-IL-u-nu-latn</item> <!-- Arabic (Israel,Western Digits) -->
+        <item>ar-IL-u-nu-latn</item> <!-- Arabic (Israel, Western Digits) -->
         <item>ar-IQ</item> <!-- Arabic (Iraq) -->
-        <item>ar-IQ-u-nu-latn</item> <!-- Arabic (Iraq,Western Digits) -->
+        <item>ar-IQ-u-nu-latn</item> <!-- Arabic (Iraq, Western Digits) -->
         <item>ar-JO</item> <!-- Arabic (Jordan) -->
-        <item>ar-JO-u-nu-latn</item> <!-- Arabic (Jordan,Western Digits) -->
+        <item>ar-JO-u-nu-latn</item> <!-- Arabic (Jordan, Western Digits) -->
         <item>ar-KM</item> <!-- Arabic (Comoros) -->
-        <item>ar-KM-u-nu-latn</item> <!-- Arabic (Comoros,Western Digits) -->
+        <item>ar-KM-u-nu-latn</item> <!-- Arabic (Comoros, Western Digits) -->
         <item>ar-KW</item> <!-- Arabic (Kuwait) -->
-        <item>ar-KW-u-nu-latn</item> <!-- Arabic (Kuwait,Western Digits) -->
+        <item>ar-KW-u-nu-latn</item> <!-- Arabic (Kuwait, Western Digits) -->
         <item>ar-LB</item> <!-- Arabic (Lebanon) -->
-        <item>ar-LB-u-nu-latn</item> <!-- Arabic (Lebanon,Western Digits) -->
+        <item>ar-LB-u-nu-latn</item> <!-- Arabic (Lebanon, Western Digits) -->
         <item>ar-LY</item> <!-- Arabic (Libya) -->
-        <item>ar-LY-u-nu-arab</item> <!-- Arabic (Libya,Arabic-Indic Digits) -->
+        <item>ar-LY-u-nu-arab</item> <!-- Arabic (Libya, Arabic-Indic Digits) -->
         <item>ar-MA</item> <!-- Arabic (Morocco) -->
-        <item>ar-MA-u-nu-arab</item> <!-- Arabic (Morocco,Arabic-Indic Digits) -->
+        <item>ar-MA-u-nu-arab</item> <!-- Arabic (Morocco, Arabic-Indic Digits) -->
         <item>ar-MR</item> <!-- Arabic (Mauritania) -->
-        <item>ar-MR-u-nu-latn</item> <!-- Arabic (Mauritania,Western Digits) -->
+        <item>ar-MR-u-nu-latn</item> <!-- Arabic (Mauritania, Western Digits) -->
         <item>ar-OM</item> <!-- Arabic (Oman) -->
-        <item>ar-OM-u-nu-latn</item> <!-- Arabic (Oman,Western Digits) -->
+        <item>ar-OM-u-nu-latn</item> <!-- Arabic (Oman, Western Digits) -->
         <item>ar-PS</item> <!-- Arabic (Palestine) -->
-        <item>ar-PS-u-nu-latn</item> <!-- Arabic (Palestine,Western Digits) -->
+        <item>ar-PS-u-nu-latn</item> <!-- Arabic (Palestine, Western Digits) -->
         <item>ar-QA</item> <!-- Arabic (Qatar) -->
-        <item>ar-QA-u-nu-latn</item> <!-- Arabic (Qatar,Western Digits) -->
+        <item>ar-QA-u-nu-latn</item> <!-- Arabic (Qatar, Western Digits) -->
         <item>ar-SA</item> <!-- Arabic (Saudi Arabia) -->
-        <item>ar-SA-u-nu-latn</item> <!-- Arabic (Saudi Arabia,Western Digits) -->
+        <item>ar-SA-u-nu-latn</item> <!-- Arabic (Saudi Arabia, Western Digits) -->
         <item>ar-SD</item> <!-- Arabic (Sudan) -->
-        <item>ar-SD-u-nu-latn</item> <!-- Arabic (Sudan,Western Digits) -->
+        <item>ar-SD-u-nu-latn</item> <!-- Arabic (Sudan, Western Digits) -->
         <item>ar-SO</item> <!-- Arabic (Somalia) -->
-        <item>ar-SO-u-nu-latn</item> <!-- Arabic (Somalia,Western Digits) -->
+        <item>ar-SO-u-nu-latn</item> <!-- Arabic (Somalia, Western Digits) -->
         <item>ar-SS</item> <!-- Arabic (South Sudan) -->
-        <item>ar-SS-u-nu-latn</item> <!-- Arabic (South Sudan,Western Digits) -->
+        <item>ar-SS-u-nu-latn</item> <!-- Arabic (South Sudan, Western Digits) -->
         <item>ar-SY</item> <!-- Arabic (Syria) -->
-        <item>ar-SY-u-nu-latn</item> <!-- Arabic (Syria,Western Digits) -->
+        <item>ar-SY-u-nu-latn</item> <!-- Arabic (Syria, Western Digits) -->
         <item>ar-TD</item> <!-- Arabic (Chad) -->
-        <item>ar-TD-u-nu-latn</item> <!-- Arabic (Chad,Western Digits) -->
+        <item>ar-TD-u-nu-latn</item> <!-- Arabic (Chad, Western Digits) -->
         <item>ar-TN</item> <!-- Arabic (Tunisia) -->
-        <item>ar-TN-u-nu-arab</item> <!-- Arabic (Tunisia,Arabic-Indic Digits) -->
+        <item>ar-TN-u-nu-arab</item> <!-- Arabic (Tunisia, Arabic-Indic Digits) -->
         <item>ar-XB</item> <!-- Right-to-left pseudolocale -->
         <item>ar-YE</item> <!-- Arabic (Yemen) -->
-        <item>ar-YE-u-nu-latn</item> <!-- Arabic (Yemen,Western Digits) -->
+        <item>ar-YE-u-nu-latn</item> <!-- Arabic (Yemen, Western Digits) -->
         <item>as-IN</item> <!-- Assamese (India) -->
         <item>asa-TZ</item> <!-- Asu (Tanzania) -->
-        <item>az-Cyrl-AZ</item> <!-- Azerbaijani (Cyrillic,Azerbaijan) -->
-        <item>az-Latn-AZ</item> <!-- Azerbaijani (Latin,Azerbaijan) -->
+        <item>ast-ES</item> <!-- Asturian (Spain) -->
+        <item>az-Cyrl-AZ</item> <!-- Azerbaijani (Cyrillic, Azerbaijan) -->
+        <item>az-Latn-AZ</item> <!-- Azerbaijani (Latin, Azerbaijan) -->
         <item>bas-CM</item> <!-- Basaa (Cameroon) -->
         <item>be-BY</item> <!-- Belarusian (Belarus) -->
         <item>bem-ZM</item> <!-- Bemba (Zambia) -->
         <item>bez-TZ</item> <!-- Bena (Tanzania) -->
         <item>bg-BG</item> <!-- Bulgarian (Bulgaria) -->
         <item>bm-ML</item> <!-- Bambara (Mali) -->
-        <item>bn-BD</item> <!-- Bengali (Bangladesh) -->
-        <item>bn-BD-u-nu-latn</item> <!-- Bengali (Bangladesh,Western Digits) -->
-        <item>bn-IN</item> <!-- Bengali (India) -->
-        <item>bn-IN-u-nu-latn</item> <!-- Bengali (India,Western Digits) -->
+        <item>bn-BD</item> <!-- Bangla (Bangladesh) -->
+        <item>bn-BD-u-nu-latn</item> <!-- Bangla (Bangladesh, Western Digits) -->
+        <item>bn-IN</item> <!-- Bangla (India) -->
+        <item>bn-IN-u-nu-latn</item> <!-- Bangla (India, Western Digits) -->
         <item>bo-CN</item> <!-- Tibetan (China) -->
         <item>bo-IN</item> <!-- Tibetan (India) -->
         <item>br-FR</item> <!-- Breton (France) -->
         <item>brx-IN</item> <!-- Bodo (India) -->
-        <item>bs-Cyrl-BA</item> <!-- Bosnian (Cyrillic,Bosnia & Herzegovina) -->
-        <item>bs-Latn-BA</item> <!-- Bosnian (Latin,Bosnia & Herzegovina) -->
+        <item>bs-Cyrl-BA</item> <!-- Bosnian (Cyrillic, Bosnia & Herzegovina) -->
+        <item>bs-Latn-BA</item> <!-- Bosnian (Latin, Bosnia & Herzegovina) -->
         <item>ca-AD</item> <!-- Catalan (Andorra) -->
         <item>ca-ES</item> <!-- Catalan (Spain) -->
         <item>ca-FR</item> <!-- Catalan (France) -->
@@ -113,6 +114,7 @@
         <item>de-BE</item> <!-- German (Belgium) -->
         <item>de-CH</item> <!-- German (Switzerland) -->
         <item>de-DE</item> <!-- German (Germany) -->
+        <item>de-IT</item> <!-- German (Italy) -->
         <item>de-LI</item> <!-- German (Liechtenstein) -->
         <item>de-LU</item> <!-- German (Luxembourg) -->
         <item>dje-NE</item> <!-- Zarma (Niger) -->
@@ -230,6 +232,8 @@
         <item>en-ZW</item> <!-- English (Zimbabwe) -->
         <item>es-AR</item> <!-- Spanish (Argentina) -->
         <item>es-BO</item> <!-- Spanish (Bolivia) -->
+        <item>es-BR</item> <!-- Spanish (Brazil) -->
+        <item>es-BZ</item> <!-- Spanish (Belize) -->
         <item>es-CL</item> <!-- Spanish (Chile) -->
         <item>es-CO</item> <!-- Spanish (Colombia) -->
         <item>es-CR</item> <!-- Spanish (Costa Rica) -->
@@ -257,9 +261,9 @@
         <item>eu-ES</item> <!-- Basque (Spain) -->
         <item>ewo-CM</item> <!-- Ewondo (Cameroon) -->
         <item>fa-AF</item> <!-- Persian (Afghanistan) -->
-        <item>fa-AF-u-nu-latn</item> <!-- Persian (Afghanistan,Western Digits) -->
+        <item>fa-AF-u-nu-latn</item> <!-- Persian (Afghanistan, Western Digits) -->
         <item>fa-IR</item> <!-- Persian (Iran) -->
-        <item>fa-IR-u-nu-latn</item> <!-- Persian (Iran,Western Digits) -->
+        <item>fa-IR-u-nu-latn</item> <!-- Persian (Iran, Western Digits) -->
         <item>ff-CM</item> <!-- Fulah (Cameroon) -->
         <item>ff-GN</item> <!-- Fulah (Guinea) -->
         <item>ff-MR</item> <!-- Fulah (Mauritania) -->
@@ -274,9 +278,9 @@
         <item>fr-BJ</item> <!-- French (Benin) -->
         <item>fr-BL</item> <!-- French (St. Barthélemy) -->
         <item>fr-CA</item> <!-- French (Canada) -->
-        <item>fr-CD</item> <!-- French (Congo (DRC)) -->
+        <item>fr-CD</item> <!-- French (Congo - Kinshasa) -->
         <item>fr-CF</item> <!-- French (Central African Republic) -->
-        <item>fr-CG</item> <!-- French (Congo (Republic)) -->
+        <item>fr-CG</item> <!-- French (Congo - Brazzaville) -->
         <item>fr-CH</item> <!-- French (Switzerland) -->
         <item>fr-CI</item> <!-- French (Côte d’Ivoire) -->
         <item>fr-CM</item> <!-- French (Cameroon) -->
@@ -329,20 +333,20 @@
         <item>ha-NE</item> <!-- Hausa (Niger) -->
         <item>ha-NG</item> <!-- Hausa (Nigeria) -->
         <item>haw-US</item> <!-- Hawaiian (United States) -->
-        <item>iw-IL</item> <!-- Hebrew (Israel) -->
         <item>hi-IN</item> <!-- Hindi (India) -->
         <item>hr-BA</item> <!-- Croatian (Bosnia & Herzegovina) -->
         <item>hr-HR</item> <!-- Croatian (Croatia) -->
         <item>hsb-DE</item> <!-- Upper Sorbian (Germany) -->
         <item>hu-HU</item> <!-- Hungarian (Hungary) -->
         <item>hy-AM</item> <!-- Armenian (Armenia) -->
-        <item>in-ID</item> <!-- Indonesian (Indonesia) -->
         <item>ig-NG</item> <!-- Igbo (Nigeria) -->
         <item>ii-CN</item> <!-- Sichuan Yi (China) -->
+        <item>in-ID</item> <!-- Indonesian (Indonesia) -->
         <item>is-IS</item> <!-- Icelandic (Iceland) -->
         <item>it-CH</item> <!-- Italian (Switzerland) -->
         <item>it-IT</item> <!-- Italian (Italy) -->
         <item>it-SM</item> <!-- Italian (San Marino) -->
+        <item>iw-IL</item> <!-- Hebrew (Israel) -->
         <item>ja-JP</item> <!-- Japanese (Japan) -->
         <item>jgo-CM</item> <!-- Ngomba (Cameroon) -->
         <item>jmc-TZ</item> <!-- Machame (Tanzania) -->
@@ -372,12 +376,12 @@
         <item>lg-UG</item> <!-- Ganda (Uganda) -->
         <item>lkt-US</item> <!-- Lakota (United States) -->
         <item>ln-AO</item> <!-- Lingala (Angola) -->
-        <item>ln-CD</item> <!-- Lingala (Congo (DRC)) -->
+        <item>ln-CD</item> <!-- Lingala (Congo - Kinshasa) -->
         <item>ln-CF</item> <!-- Lingala (Central African Republic) -->
-        <item>ln-CG</item> <!-- Lingala (Congo (Republic)) -->
+        <item>ln-CG</item> <!-- Lingala (Congo - Brazzaville) -->
         <item>lo-LA</item> <!-- Lao (Laos) -->
         <item>lt-LT</item> <!-- Lithuanian (Lithuania) -->
-        <item>lu-CD</item> <!-- Luba-Katanga (Congo (DRC)) -->
+        <item>lu-CD</item> <!-- Luba-Katanga (Congo - Kinshasa) -->
         <item>luo-KE</item> <!-- Luo (Kenya) -->
         <item>luy-KE</item> <!-- Luyia (Kenya) -->
         <item>lv-LV</item> <!-- Latvian (Latvia) -->
@@ -418,11 +422,11 @@
         <item>nyn-UG</item> <!-- Nyankole (Uganda) -->
         <item>om-ET</item> <!-- Oromo (Ethiopia) -->
         <item>om-KE</item> <!-- Oromo (Kenya) -->
-        <item>or-IN</item> <!-- Oriya (India) -->
+        <item>or-IN</item> <!-- Odia (India) -->
         <item>os-GE</item> <!-- Ossetic (Georgia) -->
         <item>os-RU</item> <!-- Ossetic (Russia) -->
-        <item>pa-Arab-PK</item> <!-- Punjabi (Arabic,Pakistan) -->
-        <item>pa-Guru-IN</item> <!-- Punjabi (Gurmukhi,India) -->
+        <item>pa-Arab-PK</item> <!-- Punjabi (Arabic, Pakistan) -->
+        <item>pa-Guru-IN</item> <!-- Punjabi (Gurmukhi, India) -->
         <item>pl-PL</item> <!-- Polish (Poland) -->
         <item>ps-AF</item> <!-- Pashto (Afghanistan) -->
         <item>pt-AO</item> <!-- Portuguese (Angola) -->
@@ -471,18 +475,18 @@
         <item>sq-AL</item> <!-- Albanian (Albania) -->
         <item>sq-MK</item> <!-- Albanian (Macedonia (FYROM)) -->
         <item>sq-XK</item> <!-- Albanian (Kosovo) -->
-        <item>sr-Cyrl-BA</item> <!-- Serbian (Cyrillic,Bosnia & Herzegovina) -->
-        <item>sr-Cyrl-ME</item> <!-- Serbian (Cyrillic,Montenegro) -->
-        <item>sr-Cyrl-RS</item> <!-- Serbian (Cyrillic,Serbia) -->
-        <item>sr-Cyrl-XK</item> <!-- Serbian (Cyrillic,Kosovo) -->
-        <item>sr-Latn-BA</item> <!-- Serbian (Latin,Bosnia & Herzegovina) -->
-        <item>sr-Latn-ME</item> <!-- Serbian (Latin,Montenegro) -->
-        <item>sr-Latn-RS</item> <!-- Serbian (Latin,Serbia) -->
-        <item>sr-Latn-XK</item> <!-- Serbian (Latin,Kosovo) -->
+        <item>sr-Cyrl-BA</item> <!-- Serbian (Cyrillic, Bosnia & Herzegovina) -->
+        <item>sr-Cyrl-ME</item> <!-- Serbian (Cyrillic, Montenegro) -->
+        <item>sr-Cyrl-RS</item> <!-- Serbian (Cyrillic, Serbia) -->
+        <item>sr-Cyrl-XK</item> <!-- Serbian (Cyrillic, Kosovo) -->
+        <item>sr-Latn-BA</item> <!-- Serbian (Latin, Bosnia & Herzegovina) -->
+        <item>sr-Latn-ME</item> <!-- Serbian (Latin, Montenegro) -->
+        <item>sr-Latn-RS</item> <!-- Serbian (Latin, Serbia) -->
+        <item>sr-Latn-XK</item> <!-- Serbian (Latin, Kosovo) -->
         <item>sv-AX</item> <!-- Swedish (Åland Islands) -->
         <item>sv-FI</item> <!-- Swedish (Finland) -->
         <item>sv-SE</item> <!-- Swedish (Sweden) -->
-        <item>sw-CD</item> <!-- Swahili (Congo (DRC)) -->
+        <item>sw-CD</item> <!-- Swahili (Congo - Kinshasa) -->
         <item>sw-KE</item> <!-- Swahili (Kenya) -->
         <item>sw-TZ</item> <!-- Swahili (Tanzania) -->
         <item>sw-UG</item> <!-- Swahili (Uganda) -->
@@ -502,12 +506,12 @@
         <item>ug-CN</item> <!-- Uyghur (China) -->
         <item>uk-UA</item> <!-- Ukrainian (Ukraine) -->
         <item>ur-IN</item> <!-- Urdu (India) -->
-        <item>ur-IN-u-nu-latn</item> <!-- Urdu (India,Western Digits) -->
+        <item>ur-IN-u-nu-latn</item> <!-- Urdu (India, Western Digits) -->
         <item>ur-PK</item> <!-- Urdu (Pakistan) -->
-        <item>ur-PK-u-nu-arabext</item> <!-- Urdu (Pakistan,Extended Arabic-Indic Digits) -->
-        <item>uz-Arab-AF</item> <!-- Uzbek (Arabic,Afghanistan) -->
-        <item>uz-Cyrl-UZ</item> <!-- Uzbek (Cyrillic,Uzbekistan) -->
-        <item>uz-Latn-UZ</item> <!-- Uzbek (Latin,Uzbekistan) -->
+        <item>ur-PK-u-nu-arabext</item> <!-- Urdu (Pakistan, Extended Arabic-Indic Digits) -->
+        <item>uz-Arab-AF</item> <!-- Uzbek (Arabic, Afghanistan) -->
+        <item>uz-Cyrl-UZ</item> <!-- Uzbek (Cyrillic, Uzbekistan) -->
+        <item>uz-Latn-UZ</item> <!-- Uzbek (Latin, Uzbekistan) -->
         <item>vi-VN</item> <!-- Vietnamese (Vietnam) -->
         <item>vun-TZ</item> <!-- Vunjo (Tanzania) -->
         <item>wae-CH</item> <!-- Walser (Switzerland) -->
@@ -515,15 +519,16 @@
         <item>yav-CM</item> <!-- Yangben (Cameroon) -->
         <item>yo-BJ</item> <!-- Yoruba (Benin) -->
         <item>yo-NG</item> <!-- Yoruba (Nigeria) -->
-        <item>yue-HK</item> <!-- Cantonese (Hong Kong) -->
+        <item>yue-Hans-CN</item> <!-- Cantonese (Simplified, China) -->
+        <item>yue-Hant-HK</item> <!-- Cantonese (Traditional, Hong Kong) -->
         <item>zgh-MA</item> <!-- Standard Moroccan Tamazight (Morocco) -->
-        <item>zh-Hans-CN</item> <!-- Chinese (Simplified Han,China) -->
-        <item>zh-Hans-HK</item> <!-- Chinese (Simplified Han,Hong Kong) -->
-        <item>zh-Hans-MO</item> <!-- Chinese (Simplified Han,Macau) -->
-        <item>zh-Hans-SG</item> <!-- Chinese (Simplified Han,Singapore) -->
-        <item>zh-Hant-HK</item> <!-- Chinese (Traditional Han,Hong Kong) -->
-        <item>zh-Hant-MO</item> <!-- Chinese (Traditional Han,Macau) -->
-        <item>zh-Hant-TW</item> <!-- Chinese (Traditional Han,Taiwan) -->
+        <item>zh-Hans-CN</item> <!-- Chinese (Simplified, China) -->
+        <item>zh-Hans-HK</item> <!-- Chinese (Simplified, Hong Kong) -->
+        <item>zh-Hans-MO</item> <!-- Chinese (Simplified, Macau) -->
+        <item>zh-Hans-SG</item> <!-- Chinese (Simplified, Singapore) -->
+        <item>zh-Hant-HK</item> <!-- Chinese (Traditional, Hong Kong) -->
+        <item>zh-Hant-MO</item> <!-- Chinese (Traditional, Macau) -->
+        <item>zh-Hant-TW</item> <!-- Chinese (Traditional, Taiwan) -->
         <item>zu-ZA</item> <!-- Zulu (South Africa) -->
     </string-array>
 
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 86879c3..73dae08 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2919,6 +2919,7 @@
         <public name="settingsSliceUri" />
         <public name="shell" />
         <public name="interactiveUiTimeout" />
+        <public name="importantForContentCapture" />
     </public-group>
 
     <public-group type="drawable" first-id="0x010800b4">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6276884..4eb723e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3436,6 +3436,7 @@
 
   <java-symbol type="integer" name="config_lowBatteryAutoTriggerDefaultLevel" />
   <java-symbol type="bool" name="config_batterySaverStickyBehaviourDisabled" />
+  <java-symbol type="integer" name="config_dynamicPowerSavingsDefaultDisableThreshold" />
 
   <!-- For car devices -->
   <java-symbol type="string" name="car_loading_profile" />
diff --git a/core/tests/coretests/src/android/app/usage/UsageStatsTest.java b/core/tests/coretests/src/android/app/usage/UsageStatsTest.java
index c6d077d..1f047f9e 100644
--- a/core/tests/coretests/src/android/app/usage/UsageStatsTest.java
+++ b/core/tests/coretests/src/android/app/usage/UsageStatsTest.java
@@ -16,8 +16,19 @@
 
 package android.app.usage;
 
-import static com.google.common.truth.Truth.assertThat;
+import static android.app.usage.UsageEvents.Event.CONTINUE_PREVIOUS_DAY;
+import static android.app.usage.UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE;
+import static android.app.usage.UsageEvents.Event.END_OF_DAY;
+import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_START;
+import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_STOP;
+import static android.app.usage.UsageEvents.Event.MOVE_TO_BACKGROUND;
+import static android.app.usage.UsageEvents.Event.MOVE_TO_FOREGROUND;
+import static android.app.usage.UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import android.os.Parcel;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
@@ -46,7 +57,7 @@
 
         left.add(right);
 
-        assertThat(left.getFirstTimeStamp()).isEqualTo(99999);
+        assertEquals(left.getFirstTimeStamp(), 99999);
     }
 
     @Test
@@ -58,7 +69,7 @@
 
         left.add(right);
 
-        assertThat(left.getLastTimeStamp()).isEqualTo(100001);
+        assertEquals(left.getLastTimeStamp(), 100001);
     }
 
     @Test
@@ -72,7 +83,7 @@
 
         left.add(right);
 
-        assertThat(left.getLastTimeUsed()).isEqualTo(200001);
+        assertEquals(left.getLastTimeUsed(), 200001);
     }
 
     @Test
@@ -86,7 +97,7 @@
 
         left.add(right);
 
-        assertThat(left.getLastTimeUsed()).isEqualTo(200000);
+        assertEquals(left.getLastTimeUsed(), 200000);
     }
 
     @Test
@@ -100,6 +111,373 @@
 
         left.add(right);
 
-        assertThat(left.getTotalTimeInForeground()).isEqualTo(11);
+        assertEquals(left.getTotalTimeInForeground(), 11);
+    }
+
+    @Test
+    public void testParcelable() {
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+        left.mTotalTimeInForeground = 10;
+
+        left.mLastForegroundActivityEventMap.put("com.test.activity1", MOVE_TO_FOREGROUND);
+        left.mLastForegroundActivityEventMap.put("com.test.activity2", MOVE_TO_FOREGROUND);
+        left.mLastForegroundServiceEventMap.put("com.test.service1", FOREGROUND_SERVICE_START);
+        left.mLastForegroundServiceEventMap.put("com.test.service2", FOREGROUND_SERVICE_START);
+
+        Parcel p = Parcel.obtain();
+        left.writeToParcel(p, 0);
+        p.setDataPosition(0);
+        right = UsageStats.CREATOR.createFromParcel(p);
+        compareUsageStats(left, right);
+    }
+
+    @Test
+    public void testForegroundActivity() {
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+
+        left.update("com.test.activity1", 200000, MOVE_TO_FOREGROUND);
+        assertEquals(left.mLastTimeUsed, 200000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+                new Integer(MOVE_TO_FOREGROUND));
+        assertEquals(left.mLaunchCount, 1);
+
+        left.update("com.test.activity1", 350000, MOVE_TO_BACKGROUND);
+        assertEquals(left.mLastTimeUsed, 350000);
+        assertFalse(left.mLastForegroundActivityEventMap.containsKey("com.test.activity1"));
+        assertEquals(left.mTotalTimeInForeground, 350000 - 200000);
+    }
+
+    @Test
+    public void testEvent_CONTINUE_PREVIOUS_DAY() {
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+
+        left.update("com.test.activity1", 100000, CONTINUE_PREVIOUS_DAY);
+        assertEquals(left.mLastTimeUsed, 100000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+                new Integer(CONTINUE_PREVIOUS_DAY));
+        assertEquals(left.mLaunchCount, 0);
+
+        left.update("com.test.activity1", 350000, MOVE_TO_BACKGROUND);
+        assertEquals(left.mLastTimeUsed, 350000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"), null);
+        assertEquals(left.mTotalTimeInForeground, 350000 - 100000);
+    }
+
+    @Test
+    public void testEvent_END_OF_DAY() {
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+
+        left.update("com.test.activity1", 100000, CONTINUE_PREVIOUS_DAY);
+        assertEquals(left.mLastTimeUsed, 100000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+                new Integer(CONTINUE_PREVIOUS_DAY));
+        assertEquals(left.mLaunchCount, 0);
+
+        left.update(null, 350000, END_OF_DAY);
+        assertEquals(left.mLastTimeUsed, 350000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+                new Integer(END_OF_DAY));
+        assertEquals(left.mTotalTimeInForeground, 350000 - 100000);
+    }
+
+    @Test
+    public void testForegroundActivityEventSequence() {
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+
+        left.update("com.test.activity1", 100000, CONTINUE_PREVIOUS_DAY);
+        assertEquals(left.mLastTimeUsed, 100000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+                new Integer(CONTINUE_PREVIOUS_DAY));
+        assertEquals(left.mLaunchCount, 0);
+
+        left.update("com.test.activity1", 350000, MOVE_TO_BACKGROUND);
+        assertEquals(left.mLastTimeUsed, 350000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"), null);
+        assertEquals(left.mTotalTimeInForeground, 250000 /*350000 - 100000*/);
+
+        left.update("com.test.activity1", 450000, MOVE_TO_FOREGROUND);
+        assertEquals(left.mLastTimeUsed, 450000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+                new Integer(MOVE_TO_FOREGROUND));
+        assertEquals(left.mTotalTimeInForeground, 250000);
+
+        left.update("com.test.activity1", 500000, MOVE_TO_BACKGROUND);
+        assertEquals(left.mLastTimeUsed, 500000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"), null);
+        assertEquals(left.mTotalTimeInForeground, 250000 + 50000 /*500000 - 450000*/);
+    }
+
+    @Test
+    public void testForegroundActivityEventOutOfSequence() {
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+
+        left.update("com.test.activity1", 100000, CONTINUE_PREVIOUS_DAY);
+        assertEquals(left.mLastTimeUsed, 100000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+                new Integer(CONTINUE_PREVIOUS_DAY));
+        assertEquals(left.mLaunchCount, 0);
+
+        left.update("com.test.activity1", 150000, MOVE_TO_FOREGROUND);
+        assertEquals(left.mLastTimeUsed, 150000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+                new Integer(MOVE_TO_FOREGROUND));
+        assertEquals(left.mLaunchCount, 1);
+        assertEquals(left.mTotalTimeInForeground, 50000 /*150000 - 100000*/);
+
+        left.update("com.test.activity1", 200000, MOVE_TO_FOREGROUND);
+        assertEquals(left.mLastTimeUsed, 200000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+                new Integer(MOVE_TO_FOREGROUND));
+        assertEquals(left.mLaunchCount, 2);
+        assertEquals(left.mTotalTimeInForeground, 100000);
+
+        left.update("com.test.activity1", 250000, MOVE_TO_BACKGROUND);
+        assertEquals(left.mLastTimeUsed, 250000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"), null);
+        assertEquals(left.mTotalTimeInForeground, 150000);
+
+        left.update("com.test.activity1", 300000, MOVE_TO_BACKGROUND);
+        assertEquals(left.mLastTimeUsed, 250000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"), null);
+        assertEquals(left.mTotalTimeInForeground, 150000);
+
+        left.update("com.test.activity1", 350000, MOVE_TO_FOREGROUND);
+        assertEquals(left.mLastTimeUsed, 350000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+                new Integer(MOVE_TO_FOREGROUND));
+        assertEquals(left.mTotalTimeInForeground, 150000);
+
+        left.update("com.test.activity1", 400000, END_OF_DAY);
+        assertEquals(left.mLastTimeUsed, 400000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+                new Integer(END_OF_DAY));
+        assertEquals(left.mTotalTimeInForeground, 200000);
+    }
+
+    @Test
+    public void testTwoActivityEventSequence() {
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+
+        left.update("com.test.activity1", 100000, CONTINUE_PREVIOUS_DAY);
+        left.update("com.test.activity2", 100000, CONTINUE_PREVIOUS_DAY);
+        assertEquals(left.mLastTimeUsed, 100000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+                new Integer(CONTINUE_PREVIOUS_DAY));
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity2"),
+                new Integer(CONTINUE_PREVIOUS_DAY));
+        assertEquals(left.mLaunchCount, 0);
+
+        left.update("com.test.activity1", 350000, MOVE_TO_BACKGROUND);
+        assertEquals(left.mLastTimeUsed, 350000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"), null);
+        assertEquals(left.mTotalTimeInForeground, 250000 /*350000 - 100000*/);
+
+        left.update("com.test.activity2", 450000, MOVE_TO_BACKGROUND);
+        assertEquals(left.mLastTimeUsed, 450000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity2"), null);
+        assertEquals(left.mTotalTimeInForeground, 250000 + 100000 /*450000 - 350000*/);
+
+        left.update(null, 500000, END_OF_DAY);
+        assertEquals(left.mLastTimeUsed, 450000);
+        assertEquals(left.mTotalTimeInForeground, 350000);
+    }
+
+    @Test
+    public void testForegroundService() {
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+
+        left.update("com.test.service1", 200000, FOREGROUND_SERVICE_START);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 200000);
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+                new Integer(FOREGROUND_SERVICE_START));
+        assertEquals(left.mLaunchCount, 0);
+
+        left.update("com.test.service1", 350000, FOREGROUND_SERVICE_STOP);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 350000);
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"), null);
+        assertEquals(left.mTotalTimeForegroundServiceUsed, 350000 - 200000);
+    }
+
+    @Test
+    public void testEvent_CONTINUING_FOREGROUND_SERVICE() {
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+
+        left.update("com.test.service1", 100000, CONTINUING_FOREGROUND_SERVICE);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 100000);
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+                new Integer(CONTINUING_FOREGROUND_SERVICE));
+        assertEquals(left.mLaunchCount, 0);
+
+        left.update("com.test.service1", 350000, FOREGROUND_SERVICE_STOP);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 350000);
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"), null);
+        assertEquals(left.mTotalTimeForegroundServiceUsed, 350000 - 100000);
+    }
+
+    @Test
+    public void testEvent_ROLLOVER_FOREGROUND_SERVICE() {
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+
+        left.update("com.test.service1", 100000,
+                CONTINUING_FOREGROUND_SERVICE);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 100000);
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+                new Integer(CONTINUING_FOREGROUND_SERVICE));
+        assertEquals(left.mLaunchCount, 0);
+
+        left.update(null, 350000, ROLLOVER_FOREGROUND_SERVICE);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 350000);
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+                new Integer(ROLLOVER_FOREGROUND_SERVICE));
+        assertEquals(left.mTotalTimeForegroundServiceUsed, 350000 - 100000);
+    }
+
+    @Test
+    public void testForegroundServiceEventSequence() {
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+
+        left.update("com.test.service1", 100000,
+                CONTINUING_FOREGROUND_SERVICE);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 100000);
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+                new Integer(CONTINUING_FOREGROUND_SERVICE));
+        assertEquals(left.mLaunchCount, 0);
+
+        left.update("com.test.service1", 350000, FOREGROUND_SERVICE_STOP);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 350000);
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"), null);
+        assertEquals(left.mTotalTimeForegroundServiceUsed, 250000 /*350000 - 100000*/);
+
+        left.update("com.test.service1", 450000, FOREGROUND_SERVICE_START);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 450000);
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+                new Integer(FOREGROUND_SERVICE_START));
+        assertEquals(left.mTotalTimeForegroundServiceUsed, 250000);
+
+        left.update("com.test.service1", 500000, FOREGROUND_SERVICE_STOP);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 500000);
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"), null);
+        assertEquals(left.mTotalTimeForegroundServiceUsed, 250000 + 50000 /*500000 - 450000*/);
+    }
+
+    @Test
+    public void testTwoServiceEventSequence() {
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+
+        left.update("com.test.service1", 100000,
+                CONTINUING_FOREGROUND_SERVICE);
+        left.update("com.test.service2", 100000,
+                CONTINUING_FOREGROUND_SERVICE);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 100000);
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+                new Integer(CONTINUING_FOREGROUND_SERVICE));
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service2"),
+                new Integer(CONTINUING_FOREGROUND_SERVICE));
+        assertEquals(left.mLaunchCount, 0);
+
+        left.update("com.test.service1", 350000, FOREGROUND_SERVICE_STOP);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 350000);
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"), null);
+        assertEquals(left.mTotalTimeForegroundServiceUsed, 250000 /*350000 - 100000*/);
+
+        left.update("com.test.service2", 450000, FOREGROUND_SERVICE_STOP);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 450000);
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service2"), null);
+        assertEquals(left.mTotalTimeForegroundServiceUsed, 250000 + 100000 /*450000 - 350000*/);
+
+        left.update(null, 500000, ROLLOVER_FOREGROUND_SERVICE);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 450000);
+        assertEquals(left.mTotalTimeForegroundServiceUsed, 350000);
+    }
+
+    @Test
+    public void testTwoActivityAndTwoServiceEventSequence() {
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+
+        left.update("com.test.activity1", 100000, CONTINUE_PREVIOUS_DAY);
+        left.update("com.test.activity2", 100000, CONTINUE_PREVIOUS_DAY);
+        left.update("com.test.service1", 100000,
+                CONTINUING_FOREGROUND_SERVICE);
+        left.update("com.test.service2", 100000,
+                CONTINUING_FOREGROUND_SERVICE);
+        assertEquals(left.mLastTimeUsed, 100000);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 100000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+                new Integer(CONTINUE_PREVIOUS_DAY));
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity2"),
+                new Integer(CONTINUE_PREVIOUS_DAY));
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+                new Integer(CONTINUING_FOREGROUND_SERVICE));
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service2"),
+                new Integer(CONTINUING_FOREGROUND_SERVICE));
+        assertEquals(left.mLaunchCount, 0);
+
+        left.update("com.test.activity1", 350000, MOVE_TO_BACKGROUND);
+        assertEquals(left.mLastTimeUsed, 350000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"), null);
+        assertEquals(left.mTotalTimeInForeground, 250000 /*350000 - 100000*/);
+
+        left.update("com.test.service1", 400000, FOREGROUND_SERVICE_STOP);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 400000);
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"), null);
+        assertEquals(left.mTotalTimeForegroundServiceUsed, 300000 /*400000 - 100000*/);
+
+        left.update("com.test.activity2", 450000, MOVE_TO_BACKGROUND);
+        assertEquals(left.mLastTimeUsed, 450000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity2"), null);
+        assertEquals(left.mTotalTimeInForeground, 250000 + 100000 /*450000 - 350000*/);
+
+        left.update("com.test.service2", 500000, FOREGROUND_SERVICE_STOP);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 500000);
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service2"), null);
+        assertEquals(left.mTotalTimeForegroundServiceUsed, 300000 + 100000 /*500000 - 400000*/);
+
+
+        left.update(null, 550000, END_OF_DAY);
+        assertEquals(left.mLastTimeUsed, 450000);
+        assertEquals(left.mTotalTimeInForeground, 350000);
+        left.update(null, 550000, ROLLOVER_FOREGROUND_SERVICE);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 500000);
+        assertEquals(left.mTotalTimeForegroundServiceUsed, 400000);
+    }
+
+    void compareUsageStats(UsageStats us1, UsageStats us2) {
+        assertEquals(us1.mPackageName, us2.mPackageName);
+        assertEquals(us1.mBeginTimeStamp, us2.mBeginTimeStamp);
+        assertEquals(us1.mLastTimeUsed, us2.mLastTimeUsed);
+        assertEquals(us1.mLastTimeForegroundServiceUsed, us2.mLastTimeForegroundServiceUsed);
+        assertEquals(us1.mTotalTimeInForeground, us2.mTotalTimeInForeground);
+        assertEquals(us1.mTotalTimeForegroundServiceUsed, us2.mTotalTimeForegroundServiceUsed);
+        assertEquals(us1.mAppLaunchCount, us2.mAppLaunchCount);
+        assertEquals(us1.mLastForegroundActivityEventMap.size(),
+                us2.mLastForegroundActivityEventMap.size());
+        for (int i = 0; i < us1.mLastForegroundActivityEventMap.size(); i++) {
+            assertEquals(us1.mLastForegroundActivityEventMap.keyAt(i),
+                    us2.mLastForegroundActivityEventMap.keyAt(i));
+            assertEquals(us1.mLastForegroundActivityEventMap.valueAt(i),
+                    us2.mLastForegroundActivityEventMap.valueAt(i));
+        }
+        assertEquals(us1.mLastForegroundServiceEventMap.size(),
+                us2.mLastForegroundServiceEventMap.size());
+        for (int i = 0; i < us1.mLastForegroundServiceEventMap.size(); i++) {
+            assertEquals(us1.mLastForegroundServiceEventMap.keyAt(i),
+                    us2.mLastForegroundServiceEventMap.keyAt(i));
+            assertEquals(us1.mLastForegroundServiceEventMap.valueAt(i),
+                    us2.mLastForegroundServiceEventMap.valueAt(i));
+        }
+        assertEquals(us1.mChooserCounts, us2.mChooserCounts);
     }
 }
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 78d45d0..8c91c37 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -124,6 +124,7 @@
                     Settings.Global.AUTOFILL_LOGGING_LEVEL,
                     Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE,
                     Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS,
+                    Settings.Global.AUTOMATIC_POWER_SAVER_MODE,
                     Settings.Global.BATTERY_DISCHARGE_DURATION_THRESHOLD,
                     Settings.Global.BATTERY_DISCHARGE_THRESHOLD,
                     Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS,
@@ -235,6 +236,8 @@
                     Settings.Global.ENABLE_DELETION_HELPER_NO_THRESHOLD_TOGGLE,
                     Settings.Global.ENABLE_DISKSTATS_LOGGING,
                     Settings.Global.ENABLE_EPHEMERAL_FEATURE,
+                    Settings.Global.DYNAMIC_POWER_SAVINGS_ENABLED,
+                    Settings.Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD,
                     Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS,
                     Settings.Global.ENHANCED_4G_MODE_ENABLED,
                     Settings.Global.EPHEMERAL_COOKIE_MAX_SIZE_BYTES,
@@ -261,8 +264,7 @@
                     Settings.Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED,
                     Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED,
                     Settings.Global.HIDDEN_API_ACCESS_LOG_SAMPLING_RATE,
-                    Settings.Global.HIDDEN_API_POLICY_P_APPS,
-                    Settings.Global.HIDDEN_API_POLICY_PRE_P_APPS,
+                    Settings.Global.HIDDEN_API_POLICY,
                     Settings.Global.HIDE_ERROR_DIALOGS,
                     Settings.Global.HTTP_PROXY,
                     HYBRID_SYSUI_BATTERY_WARNING_FLAGS,
diff --git a/core/tests/coretests/src/android/view/WindowInsetsTest.java b/core/tests/coretests/src/android/view/WindowInsetsTest.java
new file mode 100644
index 0000000..1c2df2c
--- /dev/null
+++ b/core/tests/coretests/src/android/view/WindowInsetsTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 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.view;
+
+import static org.junit.Assert.assertTrue;
+
+import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Presubmit
+public class WindowInsetsTest {
+
+    @Test
+    public void systemWindowInsets_afterConsuming_isConsumed() {
+        assertTrue(new WindowInsets(new Rect(1, 2, 3, 4), null, null, false, false, null)
+                .consumeSystemWindowInsets().isConsumed());
+    }
+
+    @Test
+    public void multiNullConstructor_isConsumed() {
+        assertTrue(new WindowInsets(null, null, null, false, false, null).isConsumed());
+    }
+
+    @Test
+    public void singleNullConstructor_isConsumed() {
+        assertTrue(new WindowInsets((Rect) null).isConsumed());
+    }
+
+}
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java b/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java
index fff723f..f6ec0e6 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java
@@ -18,6 +18,7 @@
 
 import static org.junit.Assert.assertEquals;
 
+import android.os.Bundle;
 import android.os.LocaleList;
 import android.os.Parcel;
 import android.support.test.filters.SmallTest;
@@ -38,6 +39,12 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class TextLinksTest {
+    private static final String BUNDLE_KEY = "key";
+    private static final String BUNDLE_VALUE = "value";
+    private static final Bundle BUNDLE = new Bundle();
+    static {
+        BUNDLE.putString(BUNDLE_KEY, BUNDLE_VALUE);
+    }
 
     private Map<String, Float> getEntityScores(float address, float phone, float other) {
         final Map<String, Float> result = new ArrayMap<>();
@@ -59,6 +66,7 @@
         final TextLinks reference = new TextLinks.Builder(fullText)
                 .addLink(0, 4, getEntityScores(0.f, 0.f, 1.f))
                 .addLink(5, 12, getEntityScores(.8f, .1f, .5f))
+                .setExtras(BUNDLE)
                 .build();
 
         // Parcel and unparcel.
@@ -83,6 +91,7 @@
         assertEquals(.8f, resultList.get(1).getConfidenceScore(TextClassifier.TYPE_ADDRESS), 1e-7f);
         assertEquals(.5f, resultList.get(1).getConfidenceScore(TextClassifier.TYPE_OTHER), 1e-7f);
         assertEquals(.1f, resultList.get(1).getConfidenceScore(TextClassifier.TYPE_PHONE), 1e-7f);
+        assertEquals(BUNDLE_VALUE, result.getExtras().getString(BUNDLE_KEY));
     }
 
     @Test
@@ -94,6 +103,7 @@
         final TextLinks.Request reference = new TextLinks.Request.Builder("text")
                 .setDefaultLocales(new LocaleList(Locale.US, Locale.GERMANY))
                 .setEntityConfig(entityConfig)
+                .setExtras(BUNDLE)
                 .build();
 
         // Parcel and unparcel.
@@ -108,5 +118,6 @@
                 result.getEntityConfig().getHints().toArray());
         assertEquals(new HashSet<String>(Arrays.asList("a", "c")),
                 result.getEntityConfig().resolveEntityListModifications(Collections.emptyList()));
+        assertEquals(BUNDLE_VALUE, result.getExtras().getString(BUNDLE_KEY));
     }
 }
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextSelectionTest.java b/core/tests/coretests/src/android/view/textclassifier/TextSelectionTest.java
index 4855dad..7ea5108b 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextSelectionTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextSelectionTest.java
@@ -18,6 +18,7 @@
 
 import static org.junit.Assert.assertEquals;
 
+import android.os.Bundle;
 import android.os.LocaleList;
 import android.os.Parcel;
 import android.support.test.filters.SmallTest;
@@ -31,6 +32,12 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class TextSelectionTest {
+    private static final String BUNDLE_KEY = "key";
+    private static final String BUNDLE_VALUE = "value";
+    private static final Bundle BUNDLE = new Bundle();
+    static {
+        BUNDLE.putString(BUNDLE_KEY, BUNDLE_VALUE);
+    }
 
     @Test
     public void testParcel() {
@@ -42,6 +49,7 @@
                 .setEntityType(TextClassifier.TYPE_PHONE, 0.7f)
                 .setEntityType(TextClassifier.TYPE_URL, 0.1f)
                 .setId(id)
+                .setExtras(BUNDLE)
                 .build();
 
         // Parcel and unparcel
@@ -61,6 +69,7 @@
         assertEquals(0.7f, result.getConfidenceScore(TextClassifier.TYPE_PHONE), 1e-7f);
         assertEquals(0.3f, result.getConfidenceScore(TextClassifier.TYPE_ADDRESS), 1e-7f);
         assertEquals(0.1f, result.getConfidenceScore(TextClassifier.TYPE_URL), 1e-7f);
+        assertEquals(BUNDLE_VALUE, result.getExtras().getString(BUNDLE_KEY));
     }
 
     @Test
@@ -69,6 +78,7 @@
         final TextSelection.Request reference =
                 new TextSelection.Request.Builder(text, 0, text.length())
                         .setDefaultLocales(new LocaleList(Locale.US, Locale.GERMANY))
+                        .setExtras(BUNDLE)
                         .build();
 
         // Parcel and unparcel.
@@ -81,5 +91,6 @@
         assertEquals(0, result.getStartIndex());
         assertEquals(text.length(), result.getEndIndex());
         assertEquals("en-US,de-DE", result.getDefaultLocales().toLanguageTags());
+        assertEquals(BUNDLE_VALUE, result.getExtras().getString(BUNDLE_KEY));
     }
 }
diff --git a/core/tests/packagemanagertests/src/android/content/pm/KernelPackageMappingTests.java b/core/tests/packagemanagertests/src/android/content/pm/KernelPackageMappingTests.java
index 01382aa..4e0f2a8 100644
--- a/core/tests/packagemanagertests/src/android/content/pm/KernelPackageMappingTests.java
+++ b/core/tests/packagemanagertests/src/android/content/pm/KernelPackageMappingTests.java
@@ -81,7 +81,7 @@
 
     @Test
     public void testSharedInstalledPrimary() throws Exception {
-        assertEquals("1001", getContent(getKernelPackageFile("shared:android.uid.phone", "appid")));
+        assertEquals("1001", getContent(getKernelPackageFile("shared-android.uid.phone", "appid")));
     }
 
     @Test
@@ -92,7 +92,7 @@
 
     @Test
     public void testSharedInstalledAll() throws Exception {
-        assertEquals("", getContent(getKernelPackageFile("shared:android.uid.phone",
+        assertEquals("", getContent(getKernelPackageFile("shared-android.uid.phone",
                 "excluded_userids")));
     }
 
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index a1fbe0a..84cb5f8 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -194,6 +194,8 @@
 
     <privapp-permissions package="com.android.providers.calendar">
         <permission name="android.permission.GET_ACCOUNTS_PRIVILEGED"/>
+        <permission name="android.permission.INTERACT_ACROSS_USERS" />
+        <permission name="android.permission.MANAGE_USERS" />
         <permission name="android.permission.UPDATE_APP_OPS_STATS"/>
         <permission name="android.permission.USE_RESERVED_DISK"/>
     </privapp-permissions>
@@ -324,6 +326,7 @@
         <permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
         <permission name="android.permission.MOVE_PACKAGE"/>
         <permission name="android.permission.PACKAGE_USAGE_STATS" />
+        <permission name="android.permission.POWER_SAVER" />
         <permission name="android.permission.READ_FRAME_BUFFER"/>
         <permission name="android.permission.READ_LOWPAN_CREDENTIAL"/>
         <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
diff --git a/graphics/java/android/graphics/RecordingCanvas.java b/graphics/java/android/graphics/RecordingCanvas.java
index fd5d624..67ad404 100644
--- a/graphics/java/android/graphics/RecordingCanvas.java
+++ b/graphics/java/android/graphics/RecordingCanvas.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.util.Pools.SynchronizedPool;
+import android.view.DisplayListCanvas;
 import android.view.TextureLayer;
 
 import dalvik.annotation.optimization.CriticalNative;
@@ -34,7 +35,7 @@
  * {@link RenderNode#endRecording()} is called. It must not be retained beyond that as it is
  * internally reused.
  */
-public final class RecordingCanvas extends BaseRecordingCanvas {
+public final class RecordingCanvas extends DisplayListCanvas {
     // The recording canvas pool should be large enough to handle a deeply nested
     // view hierarchy because display lists are generated recursively.
     private static final int POOL_LIMIT = 25;
@@ -89,7 +90,8 @@
     // Constructors
     ///////////////////////////////////////////////////////////////////////////
 
-    private RecordingCanvas(@NonNull RenderNode node, int width, int height) {
+    /** @hide */
+    protected RecordingCanvas(@NonNull RenderNode node, int width, int height) {
         super(nCreateDisplayListCanvas(node.mNativeRenderNode, width, height));
         mDensity = 0; // disable bitmap density scaling
     }
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index c10e482..d3c8782 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -38,11 +38,13 @@
 import android.security.keymaster.KeymasterCertificateChain;
 import android.security.keymaster.KeymasterDefs;
 import android.security.keymaster.OperationResult;
+import android.security.keystore.IKeystoreService;
 import android.security.keystore.KeyExpiredException;
 import android.security.keystore.KeyNotYetValidException;
 import android.security.keystore.KeyPermanentlyInvalidatedException;
 import android.security.keystore.KeyProperties;
 import android.security.keystore.KeyProtection;
+import android.security.keystore.KeystoreResponse;
 import android.security.keystore.StrongBoxUnavailableException;
 import android.security.keystore.UserNotAuthenticatedException;
 import android.util.Log;
@@ -54,6 +56,8 @@
 import java.security.InvalidKeyException;
 import java.util.List;
 import java.util.Locale;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
 import sun.security.util.ObjectIdentifier;
 import sun.security.x509.AlgorithmId;
 
@@ -451,27 +455,107 @@
 
     public boolean addRngEntropy(byte[] data, int flags) {
         try {
-            return mBinder.addRngEntropy(data, flags) == NO_ERROR;
+            KeystoreResultPromise promise = new KeystoreResultPromise();
+            int errorCode = mBinder.addRngEntropy(promise, data, flags);
+            if (errorCode == NO_ERROR) {
+                return promise.getFuture().get().getErrorCode() == NO_ERROR;
+            } else {
+                return false;
+            }
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return false;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "AddRngEntropy completed with exception", e);
+            return false;
         }
     }
 
+    private class KeyCharacteristicsCallbackResult {
+        private KeystoreResponse keystoreResponse;
+        private KeyCharacteristics keyCharacteristics;
+
+        public KeyCharacteristicsCallbackResult(KeystoreResponse keystoreResponse,
+                                                KeyCharacteristics keyCharacteristics) {
+            this.keystoreResponse = keystoreResponse;
+            this.keyCharacteristics = keyCharacteristics;
+        }
+
+        public KeystoreResponse getKeystoreResponse() {
+            return keystoreResponse;
+        }
+
+        public void setKeystoreResponse(KeystoreResponse keystoreResponse) {
+            this.keystoreResponse = keystoreResponse;
+        }
+
+        public KeyCharacteristics getKeyCharacteristics() {
+            return keyCharacteristics;
+        }
+
+        public void setKeyCharacteristics(KeyCharacteristics keyCharacteristics) {
+            this.keyCharacteristics = keyCharacteristics;
+        }
+    }
+
+    private class KeyCharacteristicsPromise
+    extends android.security.keystore.IKeystoreKeyCharacteristicsCallback.Stub {
+        final private CompletableFuture<KeyCharacteristicsCallbackResult> future =
+                new CompletableFuture<KeyCharacteristicsCallbackResult>();
+        @Override
+        public void onFinished(KeystoreResponse keystoreResponse,
+                               KeyCharacteristics keyCharacteristics)
+                                       throws android.os.RemoteException {
+            future.complete(
+                    new KeyCharacteristicsCallbackResult(keystoreResponse, keyCharacteristics));
+        }
+        public final CompletableFuture<KeyCharacteristicsCallbackResult> getFuture() {
+            return future;
+        }
+    };
+
+    private int generateKeyInternal(String alias, KeymasterArguments args, byte[] entropy, int uid,
+            int flags, KeyCharacteristics outCharacteristics)
+                    throws RemoteException, ExecutionException, InterruptedException {
+        KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
+        int error = mBinder.generateKey(promise, alias, args, entropy, uid, flags);
+        if (error != NO_ERROR) {
+            Log.e(TAG, "generateKeyInternal failed on request " + error);
+            return error;
+        }
+
+        KeyCharacteristicsCallbackResult result = promise.getFuture().get();
+        error = result.getKeystoreResponse().getErrorCode();
+        if (error != NO_ERROR) {
+            Log.e(TAG, "generateKeyInternal failed on response " + error);
+            return error;
+        }
+        KeyCharacteristics characteristics = result.getKeyCharacteristics();
+        if (characteristics == null) {
+            Log.e(TAG, "generateKeyInternal got empty key cheractariestics " + error);
+            return SYSTEM_ERROR;
+        }
+        outCharacteristics.shallowCopyFrom(characteristics);
+        return NO_ERROR;
+    }
+
     public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int uid,
             int flags, KeyCharacteristics outCharacteristics) {
         try {
             entropy = entropy != null ? entropy : new byte[0];
             args = args != null ? args : new KeymasterArguments();
-            int error = mBinder.generateKey(alias, args, entropy, uid, flags, outCharacteristics);
+            int error = generateKeyInternal(alias, args, entropy, uid, flags, outCharacteristics);
             if (error == KEY_ALREADY_EXISTS) {
                 mBinder.del(alias, uid);
-                error = mBinder.generateKey(alias, args, entropy, uid, flags, outCharacteristics);
+                error = generateKeyInternal(alias, args, entropy, uid, flags, outCharacteristics);
             }
             return error;
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return SYSTEM_ERROR;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "generateKey completed with exception", e);
+            return SYSTEM_ERROR;
         }
     }
 
@@ -485,10 +569,24 @@
         try {
             clientId = clientId != null ? clientId : new KeymasterBlob(new byte[0]);
             appId = appId != null ? appId : new KeymasterBlob(new byte[0]);
-            return mBinder.getKeyCharacteristics(alias, clientId, appId, uid, outCharacteristics);
+            KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
+            int error = mBinder.getKeyCharacteristics(promise, alias, clientId, appId, uid);
+            if (error != NO_ERROR) return error;
+
+            KeyCharacteristicsCallbackResult result = promise.getFuture().get();
+            error = result.getKeystoreResponse().getErrorCode();
+            if (error != NO_ERROR) return error;
+
+            KeyCharacteristics characteristics = result.getKeyCharacteristics();
+            if (characteristics == null) return SYSTEM_ERROR;
+            outCharacteristics.shallowCopyFrom(characteristics);
+            return NO_ERROR;
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return SYSTEM_ERROR;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "GetKeyCharacteristics completed with exception", e);
+            return SYSTEM_ERROR;
         }
     }
 
@@ -497,20 +595,40 @@
         return getKeyCharacteristics(alias, clientId, appId, UID_SELF, outCharacteristics);
     }
 
+    private int importKeyInternal(String alias, KeymasterArguments args, int format, byte[] keyData,
+            int uid, int flags, KeyCharacteristics outCharacteristics)
+                    throws RemoteException, ExecutionException, InterruptedException {
+        KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
+        int error = mBinder.importKey(promise, alias, args, format, keyData, uid, flags);
+        if (error != NO_ERROR) return error;
+
+        KeyCharacteristicsCallbackResult result = promise.getFuture().get();
+        error = result.getKeystoreResponse().getErrorCode();
+        if (error != NO_ERROR) return error;
+
+        KeyCharacteristics characteristics = result.getKeyCharacteristics();
+        if (characteristics == null) return SYSTEM_ERROR;
+        outCharacteristics.shallowCopyFrom(characteristics);
+        return NO_ERROR;
+    }
+
     public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
             int uid, int flags, KeyCharacteristics outCharacteristics) {
         try {
-            int error = mBinder.importKey(alias, args, format, keyData, uid, flags,
+            int error = importKeyInternal(alias, args, format, keyData, uid, flags,
                     outCharacteristics);
             if (error == KEY_ALREADY_EXISTS) {
                 mBinder.del(alias, uid);
-                error = mBinder.importKey(alias, args, format, keyData, uid, flags,
+                error = importKeyInternal(alias, args, format, keyData, uid, flags,
                         outCharacteristics);
             }
             return error;
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return SYSTEM_ERROR;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "ImportKey completed with exception", e);
+            return SYSTEM_ERROR;
         }
     }
 
@@ -578,34 +696,79 @@
         return true;
     }
 
+    private int importWrappedKeyInternal(String wrappedKeyAlias, byte[] wrappedKey,
+            String wrappingKeyAlias,
+            byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid,
+            KeyCharacteristics outCharacteristics)
+                    throws RemoteException, ExecutionException, InterruptedException {
+        KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
+        int error = mBinder.importWrappedKey(promise, wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
+                maskingKey, args, rootSid, fingerprintSid);
+        if (error != NO_ERROR) return error;
+
+        KeyCharacteristicsCallbackResult result = promise.getFuture().get();
+        error = result.getKeystoreResponse().getErrorCode();
+        if (error != NO_ERROR) return error;
+
+        KeyCharacteristics characteristics = result.getKeyCharacteristics();
+        if (characteristics == null) return SYSTEM_ERROR;
+        outCharacteristics.shallowCopyFrom(characteristics);
+        return NO_ERROR;
+    }
+
     public int importWrappedKey(String wrappedKeyAlias, byte[] wrappedKey,
             String wrappingKeyAlias,
             byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid, int uid,
             KeyCharacteristics outCharacteristics) {
+        // TODO b/119217337 uid parameter gets silently ignored.
         try {
-            int error = mBinder.importWrappedKey(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
+            int error = importWrappedKeyInternal(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
                     maskingKey, args, rootSid, fingerprintSid, outCharacteristics);
             if (error == KEY_ALREADY_EXISTS) {
-                mBinder.del(wrappedKeyAlias, -1);
-                error = mBinder.importWrappedKey(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
+                mBinder.del(wrappedKeyAlias, UID_SELF);
+                error = importWrappedKeyInternal(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
                         maskingKey, args, rootSid, fingerprintSid, outCharacteristics);
             }
             return error;
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return SYSTEM_ERROR;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "ImportWrappedKey completed with exception", e);
+            return SYSTEM_ERROR;
         }
     }
 
+    private class ExportKeyPromise
+    extends android.security.keystore.IKeystoreExportKeyCallback.Stub {
+        final private CompletableFuture<ExportResult> future = new CompletableFuture<ExportResult>();
+        @Override
+        public void onFinished(ExportResult exportKeyResult) throws android.os.RemoteException {
+            future.complete(exportKeyResult);
+        }
+        public final CompletableFuture<ExportResult> getFuture() {
+            return future;
+        }
+    };
+
     public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
             KeymasterBlob appId, int uid) {
         try {
             clientId = clientId != null ? clientId : new KeymasterBlob(new byte[0]);
             appId = appId != null ? appId : new KeymasterBlob(new byte[0]);
-            return mBinder.exportKey(alias, format, clientId, appId, uid);
+            ExportKeyPromise promise = new ExportKeyPromise();
+            int error = mBinder.exportKey(promise, alias, format, clientId, appId, uid);
+            if (error == NO_ERROR) {
+                return promise.getFuture().get();
+            } else {
+                return new ExportResult(error);
+            }
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return null;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "ExportKey completed with exception", e);
+            return null;
         }
     }
     public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
@@ -613,15 +776,37 @@
         return exportKey(alias, format, clientId, appId, UID_SELF);
     }
 
+    private class OperationPromise
+    extends android.security.keystore.IKeystoreOperationResultCallback.Stub {
+        final private CompletableFuture<OperationResult> future = new CompletableFuture<OperationResult>();
+        @Override
+        public void onFinished(OperationResult operationResult) throws android.os.RemoteException {
+            future.complete(operationResult);
+        }
+        public final CompletableFuture<OperationResult> getFuture() {
+            return future;
+        }
+    };
+
     public OperationResult begin(String alias, int purpose, boolean pruneable,
             KeymasterArguments args, byte[] entropy, int uid) {
         try {
             args = args != null ? args : new KeymasterArguments();
             entropy = entropy != null ? entropy : new byte[0];
-            return mBinder.begin(getToken(), alias, purpose, pruneable, args, entropy, uid);
+            OperationPromise promise = new OperationPromise();
+            int errorCode =  mBinder.begin(promise, getToken(), alias, purpose, pruneable, args,
+                                           entropy, uid);
+            if (errorCode == NO_ERROR) {
+                return promise.getFuture().get();
+            } else {
+                return new OperationResult(errorCode);
+            }
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return null;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "Begin completed with exception", e);
+            return null;
         }
     }
 
@@ -636,10 +821,19 @@
         try {
             arguments = arguments != null ? arguments : new KeymasterArguments();
             input = input != null ? input : new byte[0];
-            return mBinder.update(token, arguments, input);
+            OperationPromise promise = new OperationPromise();
+            int errorCode =  mBinder.update(promise, token, arguments, input);
+            if (errorCode == NO_ERROR) {
+                return promise.getFuture().get();
+            } else {
+                return new OperationResult(errorCode);
+            }
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return null;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "Update completed with exception", e);
+            return null;
         }
     }
 
@@ -649,10 +843,19 @@
             arguments = arguments != null ? arguments : new KeymasterArguments();
             entropy = entropy != null ? entropy : new byte[0];
             signature = signature != null ? signature : new byte[0];
-            return mBinder.finish(token, arguments, signature, entropy);
+            OperationPromise promise = new OperationPromise();
+            int errorCode = mBinder.finish(promise, token, arguments, signature, entropy);
+            if (errorCode == NO_ERROR) {
+                return promise.getFuture().get();
+            } else {
+                return new OperationResult(errorCode);
+            }
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return null;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "Finish completed with exception", e);
+            return null;
         }
     }
 
@@ -660,12 +863,33 @@
         return finish(token, arguments, signature, null);
     }
 
+    private class KeystoreResultPromise
+    extends android.security.keystore.IKeystoreResponseCallback.Stub {
+        final private CompletableFuture<KeystoreResponse> future = new CompletableFuture<KeystoreResponse>();
+        @Override
+        public void onFinished(KeystoreResponse keystoreResponse) throws android.os.RemoteException {
+            future.complete(keystoreResponse);
+        }
+        public final CompletableFuture<KeystoreResponse> getFuture() {
+            return future;
+        }
+    };
+
     public int abort(IBinder token) {
         try {
-            return mBinder.abort(token);
+            KeystoreResultPromise promise = new KeystoreResultPromise();
+            int errorCode = mBinder.abort(promise, token);
+            if (errorCode == NO_ERROR) {
+                return promise.getFuture().get().getErrorCode();
+            } else {
+                return errorCode;
+            }
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return SYSTEM_ERROR;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "Abort completed with exception", e);
+            return SYSTEM_ERROR;
         }
     }
 
@@ -747,6 +971,47 @@
         return onUserPasswordChanged(UserHandle.getUserId(Process.myUid()), newPassword);
     }
 
+    private class KeyAttestationCallbackResult {
+        private KeystoreResponse keystoreResponse;
+        private KeymasterCertificateChain certificateChain;
+
+        public KeyAttestationCallbackResult(KeystoreResponse keystoreResponse,
+                KeymasterCertificateChain certificateChain) {
+            this.keystoreResponse = keystoreResponse;
+            this.certificateChain = certificateChain;
+        }
+
+        public KeystoreResponse getKeystoreResponse() {
+            return keystoreResponse;
+        }
+
+        public void setKeystoreResponse(KeystoreResponse keystoreResponse) {
+            this.keystoreResponse = keystoreResponse;
+        }
+
+        public KeymasterCertificateChain getCertificateChain() {
+            return certificateChain;
+        }
+
+        public void setCertificateChain(KeymasterCertificateChain certificateChain) {
+            this.certificateChain = certificateChain;
+        }
+    }
+
+    private class CertificateChainPromise
+    extends android.security.keystore.IKeystoreCertificateChainCallback.Stub {
+        final private CompletableFuture<KeyAttestationCallbackResult> future = new CompletableFuture<KeyAttestationCallbackResult>();
+        @Override
+        public void onFinished(KeystoreResponse keystoreResponse,
+                KeymasterCertificateChain certificateChain) throws android.os.RemoteException {
+            future.complete(new KeyAttestationCallbackResult(keystoreResponse, certificateChain));
+        }
+        public final CompletableFuture<KeyAttestationCallbackResult> getFuture() {
+            return future;
+        }
+    };
+
+
     public int attestKey(
             String alias, KeymasterArguments params, KeymasterCertificateChain outChain) {
         try {
@@ -756,10 +1021,21 @@
             if (outChain == null) {
                 outChain = new KeymasterCertificateChain();
             }
-            return mBinder.attestKey(alias, params, outChain);
+            CertificateChainPromise promise = new CertificateChainPromise();
+            int error = mBinder.attestKey(promise, alias, params);
+            if (error != NO_ERROR) return error;
+            KeyAttestationCallbackResult result = promise.getFuture().get();
+            error = result.getKeystoreResponse().getErrorCode();
+            if (error == NO_ERROR) {
+                outChain.shallowCopyFrom(result.getCertificateChain());
+            }
+            return error;
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return SYSTEM_ERROR;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "AttestKey completed with exception", e);
+            return SYSTEM_ERROR;
         }
     }
 
@@ -771,10 +1047,21 @@
             if (outChain == null) {
                 outChain = new KeymasterCertificateChain();
             }
-            return mBinder.attestDeviceIds(params, outChain);
+            CertificateChainPromise promise = new CertificateChainPromise();
+            int error = mBinder.attestDeviceIds(promise, params);
+            if (error != NO_ERROR) return error;
+            KeyAttestationCallbackResult result = promise.getFuture().get();
+            error = result.getKeystoreResponse().getErrorCode();
+            if (error == NO_ERROR) {
+                outChain.shallowCopyFrom(result.getCertificateChain());
+            }
+            return error;
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return SYSTEM_ERROR;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "AttestDevicdeIds completed with exception", e);
+            return SYSTEM_ERROR;
         }
     }
 
diff --git a/keystore/java/android/security/keystore/KeystoreResponse.java b/keystore/java/android/security/keystore/KeystoreResponse.java
new file mode 100644
index 0000000..3a229cb
--- /dev/null
+++ b/keystore/java/android/security/keystore/KeystoreResponse.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2018 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.security.keystore;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.ParcelFormatException;
+
+/**
+ * The Java side of the KeystoreResponse.
+ * <p>
+ * Serialization code for this and subclasses must be kept in sync with system/security/keystore.
+ * @hide
+ */
+public class KeystoreResponse implements Parcelable {
+    public final int error_code_;
+    public final String error_msg_;
+
+    public static final Parcelable.Creator<KeystoreResponse> CREATOR = new
+            Parcelable.Creator<KeystoreResponse>() {
+                @Override
+                public KeystoreResponse createFromParcel(Parcel in) {
+                    final int error_code = in.readInt();
+                    final String error_msg = in.readString();
+                    return new KeystoreResponse(error_code, error_msg);
+                }
+
+                @Override
+                public KeystoreResponse[] newArray(int size) {
+                    return new KeystoreResponse[size];
+                }
+            };
+
+    protected KeystoreResponse(int error_code, String error_msg) {
+        this.error_code_ = error_code;
+        this.error_msg_ = error_msg;
+    }
+
+    /**
+     * @return the error_code_
+     */
+    public final int getErrorCode() {
+        return error_code_;
+    }
+
+    /**
+     * @return the error_msg_
+     */
+    public final String getErrorMessage() {
+        return error_msg_;
+    }
+
+    
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(error_code_);
+        out.writeString(error_msg_);
+    }
+}
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index 7fc41ac..a494e49 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -51,7 +51,7 @@
     LOG_ALWAYS_FATAL_IF(mVkSurface == nullptr,
                         "drawRenderNode called on a context with no surface!");
 
-    SkSurface* backBuffer = mVkManager.getBackbufferSurface(mVkSurface);
+    SkSurface* backBuffer = mVkManager.getBackbufferSurface(&mVkSurface);
     if (backBuffer == nullptr) {
         SkDebugf("failed to get backbuffer");
         return Frame(-1, -1, 0);
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index f96b1f8..d84ec85 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -16,6 +16,8 @@
 
 #include "VulkanManager.h"
 
+#include <gui/Surface.h>
+
 #include "Properties.h"
 #include "RenderThread.h"
 #include "renderstate/RenderState.h"
@@ -452,7 +454,20 @@
     return backbuffer;
 }
 
-SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface* surface) {
+SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface** surfaceOut) {
+    // Recreate VulkanSurface, if ANativeWindow has been resized.
+    VulkanSurface* surface = *surfaceOut;
+    int windowWidth = 0, windowHeight = 0;
+    ANativeWindow* window = surface->mNativeWindow;
+    window->query(window, NATIVE_WINDOW_WIDTH, &windowWidth);
+    window->query(window, NATIVE_WINDOW_HEIGHT, &windowHeight);
+    if (windowWidth != surface->mWindowWidth || windowHeight != surface->mWindowHeight) {
+        ColorMode colorMode = surface->mColorMode;
+        destroySurface(surface);
+        *surfaceOut = createSurface(window, colorMode);
+        surface = *surfaceOut;
+    }
+
     VulkanSurface::BackbufferInfo* backbuffer = getAvailableBackbuffer(surface);
     SkASSERT(backbuffer);
 
@@ -717,6 +732,8 @@
         extent.height = caps.minImageExtent.height;
     }
     SkASSERT(extent.height <= caps.maxImageExtent.height);
+    surface->mWindowWidth = extent.width;
+    surface->mWindowHeight = extent.height;
 
     uint32_t imageCount = caps.minImageCount + 2;
     if (caps.maxImageCount > 0 && imageCount > caps.maxImageCount) {
@@ -814,7 +831,7 @@
         return nullptr;
     }
 
-    VulkanSurface* surface = new VulkanSurface(colorMode);
+    VulkanSurface* surface = new VulkanSurface(colorMode, window);
 
     VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo;
     memset(&surfaceCreateInfo, 0, sizeof(VkAndroidSurfaceCreateInfoKHR));
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index 6702649..8594a1b 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -38,7 +38,8 @@
 
 class VulkanSurface {
 public:
-    VulkanSurface(ColorMode colorMode) : mColorMode(colorMode) {}
+    VulkanSurface(ColorMode colorMode, ANativeWindow* window)
+            : mColorMode(colorMode), mNativeWindow(window) {}
 
     sk_sp<SkSurface> getBackBufferSurface() { return mBackbuffer; }
 
@@ -75,6 +76,9 @@
     ImageInfo* mImageInfos;
     uint16_t mCurrentTime = 0;
     ColorMode mColorMode;
+    ANativeWindow* mNativeWindow;
+    int mWindowWidth = 0;
+    int mWindowHeight = 0;
 };
 
 // This class contains the shared global Vulkan objects, such as VkInstance, VkDevice and VkQueue,
@@ -109,7 +113,7 @@
     // Returns an SkSurface which wraps the next image returned from vkAcquireNextImageKHR. It also
     // will transition the VkImage from a present layout to color attachment so that it can be used
     // by the client for drawing.
-    SkSurface* getBackbufferSurface(VulkanSurface* surface);
+    SkSurface* getBackbufferSurface(VulkanSurface** surface);
 
     // Presents the current VkImage.
     void swapBuffers(VulkanSurface* surface);
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java
index 0431820..9b97b10 100644
--- a/media/java/android/media/MediaPlayer2Impl.java
+++ b/media/java/android/media/MediaPlayer2Impl.java
@@ -56,15 +56,20 @@
 import java.nio.ByteOrder;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Queue;
 import java.util.UUID;
+import java.util.WeakHashMap;
+import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.Executor;
 import java.util.concurrent.RejectedExecutionException;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
 
 /**
  * @hide
@@ -94,17 +99,11 @@
 
     private final Object mSrcLock = new Object();
     //--- guarded by |mSrcLock| start
-    private long mSrcIdGenerator = 0;
-    private DataSourceDesc mCurrentDSD;
-    private long mCurrentSrcId = mSrcIdGenerator++;
-    private List<DataSourceDesc> mNextDSDs;
-    private long mNextSrcId = mSrcIdGenerator++;
-    private int mNextSourceState = NEXT_SOURCE_STATE_INIT;
-    private boolean mNextSourcePlayPending = false;
+    private SourceInfo mCurrentSourceInfo;
+    private final Queue<SourceInfo> mNextSourceInfos = new ConcurrentLinkedQueue<>();
     //--- guarded by |mSrcLock| end
+    private final AtomicLong mSrcIdGenerator = new AtomicLong(0);
 
-    private AtomicInteger mBufferedPercentageCurrent = new AtomicInteger(0);
-    private AtomicInteger mBufferedPercentageNext = new AtomicInteger(0);
     private volatile float mVolume = 1.0f;
     private VideoSize mVideoSize = new VideoSize(0, 0);
 
@@ -227,7 +226,15 @@
     @Override
     public long getBufferedPosition() {
         // Use cached buffered percent for now.
-        return getDuration() * mBufferedPercentageCurrent.get() / 100;
+        int bufferedPercentage;
+        synchronized (mSrcLock) {
+            if (mCurrentSourceInfo == null) {
+                bufferedPercentage = 0;
+            } else {
+                bufferedPercentage = mCurrentSourceInfo.mBufferedPercentage.get();
+            }
+        }
+        return getDuration() * bufferedPercentage / 100;
     }
 
     @Override
@@ -246,15 +253,14 @@
                     final String msg = "Cannot set AudioAttributes to null";
                     throw new IllegalArgumentException(msg);
                 }
-                setParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES, attributes);
+                native_setAudioAttributes(attributes);
             }
         });
     }
 
     @Override
     public @NonNull AudioAttributes getAudioAttributes() {
-        AudioAttributes attributes = (AudioAttributes) getParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES);
-        return attributes;
+        return native_getAudioAttributes();
     }
 
     @Override
@@ -269,9 +275,8 @@
                 }
 
                 synchronized (mSrcLock) {
-                    mCurrentDSD = dsd;
-                    mCurrentSrcId = mSrcIdGenerator++;
-                    handleDataSource(true /* isCurrent */, dsd, mCurrentSrcId);
+                    mCurrentSourceInfo = new SourceInfo(dsd);
+                    handleDataSource(true /* isCurrent */, dsd, mCurrentSourceInfo.mId);
                 }
             }
         });
@@ -284,10 +289,8 @@
             void process() {
                 checkArgument(dsd != null, "the DataSourceDesc cannot be null");
                 synchronized (mSrcLock) {
-                    mNextDSDs = new ArrayList<DataSourceDesc>(1);
-                    mNextDSDs.add(dsd);
-                    mNextSrcId = mSrcIdGenerator++;
-                    mNextSourceState = NEXT_SOURCE_STATE_INIT;
+                    mNextSourceInfos.clear();
+                    mNextSourceInfos.add(new SourceInfo(dsd));
                 }
                 prepareNextDataSource();
             }
@@ -310,9 +313,10 @@
                 }
 
                 synchronized (mSrcLock) {
-                    mNextDSDs = new ArrayList(dsds);
-                    mNextSrcId = mSrcIdGenerator++;
-                    mNextSourceState = NEXT_SOURCE_STATE_INIT;
+                    mNextSourceInfos.clear();
+                    for (DataSourceDesc dsd : dsds) {
+                        mNextSourceInfos.add(new SourceInfo(dsd));
+                    }
                 }
                 prepareNextDataSource();
             }
@@ -324,22 +328,15 @@
         return addTask(new Task(CALL_COMPLETED_CLEAR_NEXT_DATA_SOURCES, false) {
             @Override
             void process() {
-                synchronized (mSrcLock) {
-                    if (mNextDSDs != null) {
-                        mNextDSDs.clear();
-                        mNextDSDs = null;
-                    }
-                    mNextSrcId = mSrcIdGenerator++;
-                    mNextSourceState = NEXT_SOURCE_STATE_INIT;
-                }
+                mNextSourceInfos.clear();
             }
         });
     }
 
     @Override
-    public @NonNull DataSourceDesc getCurrentDataSource() {
+    public DataSourceDesc getCurrentDataSource() {
         synchronized (mSrcLock) {
-            return mCurrentDSD;
+            return mCurrentSourceInfo == null ? null : mCurrentSourceInfo.mDSD;
         }
     }
 
@@ -703,39 +700,35 @@
     // return true if there is a next data source, false otherwise.
     // This function should be always called on |mHandlerThread|.
     private boolean prepareNextDataSource() {
-        if (Looper.myLooper() != mHandlerThread.getLooper()) {
+        HandlerThread handlerThread = mHandlerThread;
+        if (handlerThread != null && Looper.myLooper() != handlerThread.getLooper()) {
             Log.e(TAG, "prepareNextDataSource: called on wrong looper");
         }
 
         boolean hasNextDSD;
-        synchronized (mSrcLock) {
-            hasNextDSD = (mNextDSDs != null && !mNextDSDs.isEmpty());
-        }
-
         int state = getState();
-        if (state == PLAYER_STATE_ERROR || state == PLAYER_STATE_IDLE) {
-            // Current source has not been prepared yet.
-            return hasNextDSD;
-        }
-
         synchronized (mSrcLock) {
-            if (!hasNextDSD || mNextSourceState != NEXT_SOURCE_STATE_INIT) {
+            hasNextDSD = !mNextSourceInfos.isEmpty();
+            if (state == PLAYER_STATE_ERROR || state == PLAYER_STATE_IDLE) {
+                // Current source has not been prepared yet.
+                return hasNextDSD;
+            }
+
+            SourceInfo nextSource = mNextSourceInfos.peek();
+            if (!hasNextDSD || nextSource.mStateAsNextSource != NEXT_SOURCE_STATE_INIT) {
                 // There is no next source or it's in preparing or prepared state.
                 return hasNextDSD;
             }
 
             try {
-                mNextSourceState = NEXT_SOURCE_STATE_PREPARING;
-                handleDataSource(false /* isCurrent */, mNextDSDs.get(0), mNextSrcId);
+                nextSource.mStateAsNextSource = NEXT_SOURCE_STATE_PREPARING;
+                handleDataSource(false /* isCurrent */, nextSource.mDSD, nextSource.mId);
             } catch (Exception e) {
                 Message msg = mTaskHandler.obtainMessage(
                         MEDIA_ERROR, MEDIA_ERROR_IO, MEDIA_ERROR_UNKNOWN, null);
-                mTaskHandler.handleMessage(msg, mNextSrcId);
+                mTaskHandler.handleMessage(msg, nextSource.mId);
 
-                mNextDSDs.remove(0);
-                // make a new SrcId to obsolete notification for previous one.
-                mNextSrcId = mSrcIdGenerator++;
-                mNextSourceState = NEXT_SOURCE_STATE_INIT;
+                mNextSourceInfos.poll();
                 return prepareNextDataSource();
             }
         }
@@ -744,25 +737,21 @@
 
     // This function should be always called on |mHandlerThread|.
     private void playNextDataSource() {
-        if (Looper.myLooper() != mHandlerThread.getLooper()) {
+        HandlerThread handlerThread = mHandlerThread;
+        if (handlerThread != null && Looper.myLooper() != handlerThread.getLooper()) {
             Log.e(TAG, "playNextDataSource: called on wrong looper");
         }
 
         boolean hasNextDSD = false;
         synchronized (mSrcLock) {
-            if (mNextDSDs != null && !mNextDSDs.isEmpty()) {
+            if (!mNextSourceInfos.isEmpty()) {
                 hasNextDSD = true;
-                if (mNextSourceState == NEXT_SOURCE_STATE_PREPARED) {
+                SourceInfo nextSourceInfo = mNextSourceInfos.peek();
+                if (nextSourceInfo.mStateAsNextSource == NEXT_SOURCE_STATE_PREPARED) {
                     // Switch to next source only when it has been prepared.
-                    mCurrentDSD = mNextDSDs.get(0);
-                    mCurrentSrcId = mNextSrcId;
-                    mBufferedPercentageCurrent.set(mBufferedPercentageNext.get());
-                    mNextDSDs.remove(0);
-                    mNextSrcId = mSrcIdGenerator++;  // make it different from |mCurrentSrcId|
-                    mBufferedPercentageNext.set(0);
-                    mNextSourceState = NEXT_SOURCE_STATE_INIT;
+                    mCurrentSourceInfo = mNextSourceInfos.poll();
 
-                    long srcId = mCurrentSrcId;
+                    long srcId = mCurrentSourceInfo.mId;
                     try {
                         nativePlayNextDataSource(srcId);
                     } catch (Exception e) {
@@ -777,9 +766,8 @@
 
                         // Now a new current src is playing.
                         // Wait for MEDIA_INFO_DATA_SOURCE_START to prepare next source.
-                        mNextSourcePlayPending = false;
                     }
-                } else if (mNextSourceState == NEXT_SOURCE_STATE_INIT) {
+                } else if (nextSourceInfo.mStateAsNextSource == NEXT_SOURCE_STATE_INIT) {
                     hasNextDSD = prepareNextDataSource();
                 }
             }
@@ -1074,12 +1062,8 @@
             mDrmEventCallbackRecords.clear();
         }
         synchronized (mSrcLock) {
-            if (mNextDSDs != null) {
-                mNextDSDs.clear();
-                mNextDSDs = null;
-            }
-            mNextSrcId = mSrcIdGenerator++;
-            mNextSourceState = NEXT_SOURCE_STATE_INIT;
+            mCurrentSourceInfo = null;
+            mNextSourceInfos.clear();
         }
 
         synchronized (mTaskLock) {
@@ -1102,14 +1086,12 @@
     // Keep KEY_PARAMETER_* in sync with include/media/mediaplayer2.h
     private final static int KEY_PARAMETER_AUDIO_ATTRIBUTES = 1400;
     /**
-     * Sets the parameter indicated by key.
-     * @param key key indicates the parameter to be set.
+     * Sets the audio attributes.
      * @param value value of the parameter to be set.
      * @return true if the parameter is set successfully, false otherwise
      */
-    private native boolean setParameter(int key, Object value);
-
-    private native Object getParameter(int key);
+    private native boolean native_setAudioAttributes(AudioAttributes audioAttributes);
+    private native AudioAttributes native_getAudioAttributes();
 
 
     /**
@@ -1535,20 +1517,11 @@
             final int what = msg.arg1;
             final int extra = msg.arg2;
 
-            final DataSourceDesc dsd;
-            boolean isCurrentSrcId = false;
-            boolean isNextSrcId = false;
-            synchronized (mSrcLock) {
-                if (srcId == mCurrentSrcId) {
-                    dsd = mCurrentDSD;
-                    isCurrentSrcId = true;
-                } else if (mNextDSDs != null && !mNextDSDs.isEmpty() && srcId == mNextSrcId) {
-                    dsd = mNextDSDs.get(0);
-                    isNextSrcId = true;
-                } else {
-                    return;
-                }
+            final SourceInfo sourceInfo = getSourceInfoById(srcId);
+            if (sourceInfo == null) {
+                return;
             }
+            final DataSourceDesc dsd = sourceInfo.mDSD;
 
             switch(msg.what) {
                 case MEDIA_PREPARED:
@@ -1564,14 +1537,16 @@
                     }
 
                     synchronized (mSrcLock) {
+                        SourceInfo nextSourceInfo = mNextSourceInfos.peek();
                         Log.i(TAG, "MEDIA_PREPARED: srcId=" + srcId
-                                + ", currentSrcId=" + mCurrentSrcId + ", nextSrcId=" + mNextSrcId);
+                                + ", curSrc=" + mCurrentSourceInfo
+                                + ", nextSrc=" + nextSourceInfo);
 
-                        if (isCurrentSrcId) {
+                        if (isCurrentSource(srcId)) {
                             prepareNextDataSource();
-                        } else if (isNextSrcId) {
-                            mNextSourceState = NEXT_SOURCE_STATE_PREPARED;
-                            if (mNextSourcePlayPending) {
+                        } else if (isNextSource(srcId)) {
+                            nextSourceInfo.mStateAsNextSource = NEXT_SOURCE_STATE_PREPARED;
+                            if (nextSourceInfo.mPlayPendingAsNextSource) {
                                 playNextDataSource();
                             }
                         }
@@ -1624,7 +1599,7 @@
 
                 case MEDIA_PLAYBACK_COMPLETE:
                 {
-                    if (isCurrentSrcId) {
+                    if (isCurrentSource(srcId)) {
                         sendEvent(new EventNotifier() {
                             @Override
                             public void notify(EventCallback callback) {
@@ -1635,11 +1610,13 @@
                         stayAwake(false);
 
                         synchronized (mSrcLock) {
-                            mNextSourcePlayPending = true;
-
+                            SourceInfo nextSourceInfo = mNextSourceInfos.peek();
+                            if (nextSourceInfo != null) {
+                                nextSourceInfo.mPlayPendingAsNextSource = true;
+                            }
                             Log.i(TAG, "MEDIA_PLAYBACK_COMPLETE: srcId=" + srcId
-                                    + ", currentSrcId=" + mCurrentSrcId
-                                    + ", nextSrcId=" + mNextSrcId);
+                                    + ", curSrc=" + mCurrentSourceInfo
+                                    + ", nextSrc=" + nextSourceInfo);
                         }
 
                         playNextDataSource();
@@ -1670,13 +1647,11 @@
                         }
                     });
 
-                    synchronized (mSrcLock) {
-                        if (isCurrentSrcId) {
-                            mBufferedPercentageCurrent.set(percent);
-                        } else if (isNextSrcId) {
-                            mBufferedPercentageNext.set(percent);
-                        }
+                    SourceInfo src = getSourceInfoById(srcId);
+                    if (src != null) {
+                        src.mBufferedPercentage.set(percent);
                     }
+
                     return;
                 }
 
@@ -1754,7 +1729,7 @@
                     });
 
                     if (msg.arg1 == MEDIA_INFO_DATA_SOURCE_START) {
-                        if (isCurrentSrcId) {
+                        if (isCurrentSource(srcId)) {
                             prepareNextDataSource();
                         }
                     }
@@ -1857,6 +1832,7 @@
                 }
             }
         }
+
     }
 
     /*
@@ -2133,7 +2109,7 @@
                         @Override
                         public void notify(DrmEventCallback callback) {
                             callback.onDrmPrepared(
-                                    MediaPlayer2Impl.this, mCurrentDSD, prepareDrmStatus);
+                                    MediaPlayer2Impl.this, getCurrentDataSource(), prepareDrmStatus);
                         }
                     });
 
@@ -2199,7 +2175,7 @@
 
         // call the callback outside the lock
         if (mOnDrmConfigHelper != null)  {
-            mOnDrmConfigHelper.onDrmConfig(this, mCurrentDSD);
+            mOnDrmConfigHelper.onDrmConfig(this, getCurrentDataSource());
         }
 
         synchronized (mDrmLock) {
@@ -2820,7 +2796,7 @@
                 @Override
                 public void notify(DrmEventCallback callback) {
                     callback.onDrmPrepared(
-                            mediaPlayer, mCurrentDSD, status);
+                            mediaPlayer, getCurrentDataSource(), status);
                 }
             });
 
@@ -3087,9 +3063,7 @@
             } catch (Exception e) {
                 status = CALL_STATUS_ERROR_UNKNOWN;
             }
-            synchronized (mSrcLock) {
-                mDSD = mCurrentDSD;
-            }
+            mDSD = getCurrentDataSource();
 
             if (mMediaCallType != CALL_COMPLETED_SEEK_TO) {
                 synchronized (mTaskLock) {
@@ -3132,4 +3106,50 @@
             super(detailMessage);
         }
     };
+
+    private final class SourceInfo {
+        final DataSourceDesc mDSD;
+        final long mId = mSrcIdGenerator.getAndIncrement();
+        AtomicInteger mBufferedPercentage = new AtomicInteger(0);
+
+        // m*AsNextSource (below) only applies to pending data sources in the playlist;
+        // the meanings of mCurrentSourceInfo.{mStateAsNextSource,mPlayPendingAsNextSource}
+        // are undefined.
+        int mStateAsNextSource = NEXT_SOURCE_STATE_INIT;
+        boolean mPlayPendingAsNextSource = false;
+
+        SourceInfo(DataSourceDesc dsd) {
+            this.mDSD = dsd;
+        }
+
+        @Override
+        public String toString() {
+            return String.format("%s(%d)", SourceInfo.class.getName(), mId);
+        }
+
+    }
+
+    private SourceInfo getSourceInfoById(long srcId) {
+        synchronized (mSrcLock) {
+            if (isCurrentSource(srcId)) {
+                return mCurrentSourceInfo;
+            }
+            if (isNextSource(srcId)) {
+                return mNextSourceInfos.peek();
+            }
+        }
+        return null;
+    }
+
+    private boolean isCurrentSource(long srcId) {
+        synchronized (mSrcLock) {
+            return mCurrentSourceInfo != null && mCurrentSourceInfo.mId == srcId;
+        }
+    }
+
+    private boolean isNextSource(long srcId) {
+        SourceInfo nextSourceInfo = mNextSourceInfos.peek();
+        return nextSourceInfo != null && nextSourceInfo.mId == srcId;
+    }
+
 }
diff --git a/media/java/android/media/MediaPlayer2Utils.java b/media/java/android/media/MediaPlayer2Utils.java
new file mode 100644
index 0000000..c6dee22
--- /dev/null
+++ b/media/java/android/media/MediaPlayer2Utils.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2018 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.media;
+
+/**
+ * Helper class used by native code to reduce JNI calls from native side.
+ * @hide
+ */
+public class MediaPlayer2Utils {
+    /**
+     * Returns whether audio offloading is supported for the given audio format.
+     *
+     * @param encoding the type of encoding defined in {@link AudioFormat}
+     * @param sampleRate the sampling rate of the stream
+     * @param channelMask the channel mask defined in {@link AudioFormat}
+     */
+    // @CalledByNative
+    public static boolean isOffloadedAudioPlaybackSupported(
+            int encoding, int sampleRate, int channelMask) {
+        final AudioFormat format = new AudioFormat.Builder()
+                .setEncoding(encoding)
+                .setSampleRate(sampleRate)
+                .setChannelMask(channelMask)
+                .build();
+        return AudioManager.isOffloadedPlaybackSupported(format);
+    }
+}
diff --git a/media/jni/android_media_MediaPlayer2.cpp b/media/jni/android_media_MediaPlayer2.cpp
index 8e30455..0769e5c 100644
--- a/media/jni/android_media_MediaPlayer2.cpp
+++ b/media/jni/android_media_MediaPlayer2.cpp
@@ -846,56 +846,29 @@
 }
 
 static jboolean
-android_media_MediaPlayer2_setParameter(JNIEnv *env, jobject thiz, jint key, jobject)
+android_media_MediaPlayer2_setAudioAttributes(JNIEnv *env, jobject thiz, jobject attributes)
 {
-    ALOGV("setParameter: key %d", key);
+    ALOGV("setAudioAttributes");
     sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
     if (mp == NULL ) {
         jniThrowException(env, "java/lang/IllegalStateException", NULL);
         return false;
     }
-
-    return false;
-    // TODO: set/getParameter is temporarily disabled to remove android_runtime.so dependency.
-    //       Once JAudioTrack migration is done, the AudioAttribute jobject
-    //       should be directly passed to AudioTrack without native parcel conversion.
-    /*
-    Parcel *request = parcelForJavaObject(env, java_request);
-    status_t err = mp->setParameter(key, *request);
-    if (err == OK) {
-        return true;
-    } else {
-        return false;
-    }
-    */
+    status_t err = mp->setAudioAttributes(attributes);
+    return err == OK;
 }
 
 static jobject
-android_media_MediaPlayer2_getParameter(JNIEnv *env, jobject thiz, jint key)
+android_media_MediaPlayer2_getAudioAttributes(JNIEnv *env, jobject thiz)
 {
-    ALOGV("getParameter: key %d", key);
+    ALOGV("getAudioAttributes");
     sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
     if (mp == NULL) {
         jniThrowException(env, "java/lang/IllegalStateException", NULL);
         return NULL;
     }
 
-    return NULL;
-    // TODO: set/getParameter is temporarily disabled to remove android_runtime.so dependency.
-    //       Once JAudioTrack migration is done, the AudioAttribute jobject
-    //       should be directly passed to AudioTrack without native parcel conversion.
-    /*
-    jobject jParcel = createJavaParcelObject(env);
-    if (jParcel != NULL) {
-        Parcel* nativeParcel = parcelForJavaObject(env, jParcel);
-        status_t err = mp->getParameter(key, nativeParcel);
-        if (err != OK) {
-            env->DeleteLocalRef(jParcel);
-            return NULL;
-        }
-    }
-    return jParcel;
-    */
+    return mp->getAudioAttributes();
 }
 
 static void
@@ -1428,17 +1401,17 @@
     {"native_getState",     "()I",                              (void *)android_media_MediaPlayer2_getState},
     {"native_getMetrics",   "()Landroid/os/PersistableBundle;", (void *)android_media_MediaPlayer2_native_getMetrics},
     {"_setPlaybackParams", "(Landroid/media/PlaybackParams;)V", (void *)android_media_MediaPlayer2_setPlaybackParams},
-    {"getPlaybackParams", "()Landroid/media/PlaybackParams;", (void *)android_media_MediaPlayer2_getPlaybackParams},
-    {"_setSyncParams",     "(Landroid/media/SyncParams;)V",  (void *)android_media_MediaPlayer2_setSyncParams},
-    {"getSyncParams",     "()Landroid/media/SyncParams;",   (void *)android_media_MediaPlayer2_getSyncParams},
+    {"getPlaybackParams", "()Landroid/media/PlaybackParams;",   (void *)android_media_MediaPlayer2_getPlaybackParams},
+    {"_setSyncParams",     "(Landroid/media/SyncParams;)V",     (void *)android_media_MediaPlayer2_setSyncParams},
+    {"getSyncParams",     "()Landroid/media/SyncParams;",       (void *)android_media_MediaPlayer2_getSyncParams},
     {"_seekTo",             "(JI)V",                            (void *)android_media_MediaPlayer2_seekTo},
     {"_pause",              "()V",                              (void *)android_media_MediaPlayer2_pause},
     {"getCurrentPosition",  "()J",                              (void *)android_media_MediaPlayer2_getCurrentPosition},
     {"getDuration",         "()J",                              (void *)android_media_MediaPlayer2_getDuration},
     {"_release",            "()V",                              (void *)android_media_MediaPlayer2_release},
     {"_reset",              "()V",                              (void *)android_media_MediaPlayer2_reset},
-    {"setParameter",        "(ILjava/lang/Object;)Z",          (void *)android_media_MediaPlayer2_setParameter},
-    {"getParameter",        "(I)Ljava/lang/Object;",           (void *)android_media_MediaPlayer2_getParameter},
+    {"native_setAudioAttributes", "(Landroid/media/AudioAttributes;)Z", (void *)android_media_MediaPlayer2_setAudioAttributes},
+    {"native_getAudioAttributes", "()Landroid/media/AudioAttributes;", (void *)android_media_MediaPlayer2_getAudioAttributes},
     {"setLooping",          "(Z)V",                             (void *)android_media_MediaPlayer2_setLooping},
     {"isLooping",           "()Z",                              (void *)android_media_MediaPlayer2_isLooping},
     {"native_setVolume",    "(F)V",                             (void *)android_media_MediaPlayer2_setVolume},
diff --git a/packages/ExtServices/src/android/ext/services/notification/Assistant.java b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
index 1136684..60153fc 100644
--- a/packages/ExtServices/src/android/ext/services/notification/Assistant.java
+++ b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
@@ -78,8 +78,6 @@
 public class Assistant extends NotificationAssistantService {
     private static final String TAG = "ExtAssistant";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-    public static final boolean AUTO_DEMOTE_NOTIFICATIONS = SystemProperties.getBoolean(
-            "debug.demote_notifs", false);
     public static final boolean AGE_NOTIFICATIONS = SystemProperties.getBoolean(
             "debug.age_notifs", false);
 
@@ -242,7 +240,8 @@
         if (!smartReplies.isEmpty()) {
             signals.putCharSequenceArrayList(Adjustment.KEY_SMART_REPLIES, smartReplies);
         }
-        if (AUTO_DEMOTE_NOTIFICATIONS) {
+        if (Settings.Secure.getInt(getContentResolver(),
+                Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL, 0) == 1) {
             if (mNotificationCategorizer.shouldSilence(entry)) {
                 final int importance = entry.getImportance() < IMPORTANCE_LOW
                         ? entry.getImportance() : IMPORTANCE_LOW;
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 4e52ff6d..c9ee5c8 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -186,7 +186,8 @@
                     title = mStorageManager.getBestVolumeDescription(privateVol);
                     storageUuid = StorageManager.convert(privateVol.fsUuid);
                 }
-            } else if (volume.getType() == VolumeInfo.TYPE_PUBLIC
+            } else if ((volume.getType() == VolumeInfo.TYPE_PUBLIC
+                            || volume.getType() == VolumeInfo.TYPE_STUB)
                     && volume.getMountUserId() == userId) {
                 rootId = volume.getFsUuid();
                 title = mStorageManager.getBestVolumeDescription(volume);
@@ -540,14 +541,14 @@
     }
 
     @Override
-    public Cursor querySearchDocuments(String rootId, String query, String[] projection)
+    public Cursor querySearchDocuments(String rootId, String[] projection, Bundle queryArgs)
             throws FileNotFoundException {
         final File parent;
         synchronized (mRootsLock) {
             parent = mRoots.get(rootId).path;
         }
 
-        return querySearchDocuments(parent, query, projection, Collections.emptySet());
+        return querySearchDocuments(parent, projection, Collections.emptySet(), queryArgs);
     }
 
     @Override
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index b77d4e5..d34820c 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Kan nie skandeer vir netwerke nie"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Geen"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Gestoor"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Gedeaktiveer"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-opstelling het misluk"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 836ec80..b595e2b 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"ለአውታረመረቦች መቃኘት አይቻልም"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"የለም"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"ተቀምጧል"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"ተሰናክሏል"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"የአይ.ፒ. ውቅረት መሰናከል"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 83c4b8e..f8c2ba2 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"لا يمكن فحص الشبكات"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"بدون"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"تم الحفظ"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"غير مفعّلة"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"‏تعذّرت تهيئة عنوان IP"</string>
@@ -227,11 +226,11 @@
     <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="6893955536658137179">"‏اختيار برنامج ترميز LDAC\nلصوت مشغّل البلوتوث: جودة التشغيل"</string>
     <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"البث: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"نظام أسماء النطاقات الخاص"</string>
-    <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"اختر وضع نظام أسماء النطاقات الخاص"</string>
+    <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"تحديد وضع \"نظام أسماء النطاقات الخاص\""</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"غير مفعّل"</string>
     <string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"تلقائي"</string>
-    <string name="private_dns_mode_provider" msgid="8354935160639360804">"اسم مضيف مزوّد نظام أسماء النطاقات الخاص"</string>
-    <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"أدخل اسم مضيف مزوّد نظام أسماء النطاقات"</string>
+    <string name="private_dns_mode_provider" msgid="8354935160639360804">"اسم مضيف مزوّد \"نظام أسماء النطاقات الخاص\""</string>
+    <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"يُرجى إدخال اسم مضيف \"مزوّد نظام أسماء النطاقات\""</string>
     <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"تعذّر الاتصال"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"عرض خيارات شهادة عرض شاشة لاسلكي"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"‏زيادة مستوى تسجيل Wi-Fi، وعرض لكل SSID RSSI في منتقي Wi-Fi"</string>
@@ -371,10 +370,10 @@
     <string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"يتبقى <xliff:g id="TIME_REMAINING">%1$s</xliff:g> تقريبًا، بناءً على استخدامك"</string>
     <string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"يتبقى <xliff:g id="TIME_REMAINING">%1$s</xliff:g> تقريبًا، بناءً على استخدامك (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"الوقت المتبقي: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_discharge_by_enhanced" msgid="2095821536747992464">"من المفترض أن يستمر شحن البطارية حتى حوالي الساعة <xliff:g id="TIME">%1$s</xliff:g> حسب استخدامك (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
-    <string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"من المفترض أن يستمر شحن البطارية حتى حوالي الساعة <xliff:g id="TIME">%1$s</xliff:g> حسب استخدامك."</string>
-    <string name="power_discharge_by" msgid="6453537733650125582">"من المفترض أن يستمر شحن البطارية حتى حوالي الساعة <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
-    <string name="power_discharge_by_only" msgid="107616694963545745">"من المفترض أن يستمر شحن البطارية حتى حوالي الساعة <xliff:g id="TIME">%1$s</xliff:g>."</string>
+    <string name="power_discharge_by_enhanced" msgid="2095821536747992464">"قد تكفي طاقة البطارية حتى حوالي الساعة <xliff:g id="TIME">%1$s</xliff:g> حسب استخدامك (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
+    <string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"قد تكفي طاقة البطارية حتى حوالي الساعة <xliff:g id="TIME">%1$s</xliff:g> حسب استخدامك."</string>
+    <string name="power_discharge_by" msgid="6453537733650125582">"قد تكفي طاقة البطارية حتى حوالي الساعة <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
+    <string name="power_discharge_by_only" msgid="107616694963545745">"قد تكفي طاقة البطارية حتى حوالي الساعة <xliff:g id="TIME">%1$s</xliff:g>."</string>
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"يتبقى أقل من <xliff:g id="THRESHOLD">%1$s</xliff:g>."</string>
     <string name="power_remaining_less_than_duration" msgid="5751885147712659423">"يتبقى أقل من <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
     <string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"يتبقى أكثر من <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index ddd17daf..72122c2 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"নেটৱৰ্ক বিচাৰি স্কেন কৰিব পৰা নাই"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"নাই"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"ছেভ কৰি থোৱা নেটৱৰ্কসমূহ"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"নিষ্ক্ৰিয় হৈ আছে"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP কনফিগাৰেশ্বন বিফল হৈছে"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index a6e484f..23008e2 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Şəbəkə axtarmaq olmur"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Heç biri"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Yadda saxlanılan"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Deaktiv"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Konfiqurasiya Uğursuzluğu"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index a446845..3ee8589 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -21,13 +21,12 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nije moguće skenirati mreže"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Nema"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Sačuvano"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Onemogućeno"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP konfiguracija je otkazala"</string>
     <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Nije povezano zbog lošeg kvaliteta mreže"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi veza je otkazala"</string>
-    <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problem sa potvrdom autentičnosti"</string>
+    <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problem sa potvrdom identiteta"</string>
     <string name="wifi_cant_connect" msgid="5410016875644565884">"Povezivanje nije uspelo"</string>
     <string name="wifi_cant_connect_to_ap" msgid="1222553274052685331">"Povezivanje sa „<xliff:g id="AP_NAME">%1$s</xliff:g>“ nije uspelo"</string>
     <string name="wifi_check_password_try_again" msgid="516958988102584767">"Proverite lozinku i probajte ponovo"</string>
@@ -448,5 +447,5 @@
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Trajanje"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Uvek pitaj"</string>
     <string name="zen_mode_forever" msgid="2704305038191592967">"Dok ne isključite"</string>
-    <string name="time_unit_just_now" msgid="6363336622778342422">"Upravo sada"</string>
+    <string name="time_unit_just_now" msgid="6363336622778342422">"Upravo"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index d56db13..64253bf 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Не атрымлiваецца выканаць сканаванне для сетак"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Няма"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Захавана"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Адключана"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Збой канфігурацыі IP"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index c1bc31c..668aa2d 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Не може да се сканира за мрежи"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Няма"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Запазено"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Деактивирани"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Неуспешно конфигуриране на IP адреса"</string>
@@ -374,7 +373,7 @@
     <string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Следва да издържи приблизително до <xliff:g id="TIME">%1$s</xliff:g> въз основа на използването (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Следва да издържи приблизително до <xliff:g id="TIME">%1$s</xliff:g> въз основа на използването"</string>
     <string name="power_discharge_by" msgid="6453537733650125582">"Следва да издържи приблизително до <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
-    <string name="power_discharge_by_only" msgid="107616694963545745">"Следва да издържи приблизително до <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_discharge_by_only" msgid="107616694963545745">"Следва да издържи до около <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Остава/т по-малко от <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
     <string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Остава/т по-малко от <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Остава/т повече от <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 1550c00..c6eed2c 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"নেটওয়ার্কগুলির জন্য স্ক্যান করা যাবে না"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"কোনো কিছুই নয়"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"সংরক্ষিত"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"অক্ষম হয়েছে"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP কনফিগারেশনের ব্যর্থতা"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 460e7cf..16179fb 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Ne može skenirati mreže"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Nema"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Sačuvano"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Onemogućeno"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Greška u konfiguraciji IP-a"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 5638947..f906ea4 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"No es poden cercar xarxes"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Cap"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Desat"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Desactivat"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Error de configuració d\'IP"</string>
@@ -70,7 +69,7 @@
     <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Actiu"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Àudio multimèdia"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Trucades telefòniques"</string>
-    <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transferència del fitxer"</string>
+    <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transferència de fitxers"</string>
     <string name="bluetooth_profile_hid" msgid="3680729023366986480">"Dispositiu d\'entrada"</string>
     <string name="bluetooth_profile_pan" msgid="3391606497945147673">"Accés a Internet"</string>
     <string name="bluetooth_profile_pbap" msgid="5372051906968576809">"Compartir contactes"</string>
@@ -393,7 +392,7 @@
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"s\'està carregant"</string>
     <string name="battery_info_status_discharging" msgid="310932812698268588">"No s\'està carregant"</string>
     <string name="battery_info_status_not_charging" msgid="8523453668342598579">"El dispositiu està endollat però en aquests moments no es pot carregar"</string>
-    <string name="battery_info_status_full" msgid="2824614753861462808">"Plena"</string>
+    <string name="battery_info_status_full" msgid="2824614753861462808">"Completa"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlat per l\'administrador"</string>
     <string name="disabled" msgid="9206776641295849915">"Desactivat"</string>
     <string name="external_source_trusted" msgid="2707996266575928037">"Amb permís"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index de02245..f9c8669 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nelze hledat sítě"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Žádné"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Uloženo"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Vypnuto"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Selhání konfigurace protokolu IP"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 34608d3..6b2bd98 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Der kan ikke søges efter netværk"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Ingen"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Gemt"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Deaktiveret"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-konfigurationsfejl"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 79965d2..ad6f5f2 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Netzwerkscan nicht möglich"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Keine"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Gespeichert"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Deaktiviert"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-Konfigurationsfehler"</string>
@@ -231,7 +230,7 @@
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Aus"</string>
     <string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automatisch"</string>
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Hostname des privaten DNS-Anbieters"</string>
-    <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Hostnamen des DNS-Anbieters eingeben"</string>
+    <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Hostname des DNS-Anbieters eingeben"</string>
     <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Verbindung nicht möglich"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Optionen zur Zertifizierung für kabellose Übertragung anzeigen"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Level für WLAN-Protokollierung erhöhen, in WiFi Picker pro SSID-RSSI anzeigen"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index b9ea843..5bfbf2c 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Δεν είναι δυνατή η σάρωση για δίκτυα"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Καμία"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Αποθηκευμένο"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Απενεργοποιημένο"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Αποτυχία διαμόρφωσης διεύθυνσης IP"</string>
@@ -231,7 +230,7 @@
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Ανενεργή"</string>
     <string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Αυτόματα"</string>
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Όνομα κεντρικού υπολογιστή παρόχου DNS"</string>
-    <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Εισαγάγετε το όνομα κεντρικού υπολογιστή του παρόχου DNS"</string>
+    <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Όνομα κεντρικού υπολογιστή του παρόχου DNS"</string>
     <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Δεν ήταν δυνατή η σύνδεση"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Εμφάνιση επιλογών για πιστοποίηση ασύρματης οθόνης"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Αύξηση επιπέδου καταγ. Wi-Fi, εμφάνιση ανά SSID RSSI στο εργαλείο επιλογής Wi-Fi"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 1a7d7c5..f0eaeed 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Can\'t scan for networks"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"None"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Saved"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Disabled"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Configuration Failure"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index 1a7d7c5..f0eaeed 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Can\'t scan for networks"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"None"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Saved"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Disabled"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Configuration Failure"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 1a7d7c5..f0eaeed 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Can\'t scan for networks"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"None"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Saved"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Disabled"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Configuration Failure"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 1a7d7c5..f0eaeed 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Can\'t scan for networks"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"None"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Saved"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Disabled"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Configuration Failure"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 2bfd5b1..6927fda 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‏‏‎‎‏‎‎‎‎‎‎‎‏‏‎‏‎‎‎‏‏‏‏‎‎‏‎‎‎‏‎‎‎‎‏‎‎‏‎‏‎‏‏‏‎‏‏‏‎‏‎‏‏‎‏‎‏‎Can\'t scan for networks‎‏‎‎‏‎"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‎‏‎‎‏‎‎‎‎‎‏‏‏‎‏‎‎‎‏‎‎‏‎‏‏‎‎‏‏‏‏‏‎‏‎‏‎‎‎‏‏‎‏‏‏‎‏‏‏‎‎‎‎‎‎None‎‏‎‎‏‎"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‎‎‎‏‏‎‎‏‎‏‏‎‎‏‏‎‎‎‏‏‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‎‎‏‎‎‎‏‎‏‎‎‎‎Saved‎‏‎‎‏‎"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‏‎‎‎‏‏‏‎‏‏‏‎‏‎‏‎‎‏‏‏‎‎‏‏‎‏‏‎‏‏‏‎‏‎‏‏‎‏‏‏‎‏‎‏‏‎‎‏‏‎‎‎‏‏‎‏‎‎Disabled‎‏‎‎‏‎"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‎‎‏‏‎‏‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‏‎‎‏‎‏‎‏‏‎‏‎‎‏‎‎‎‎‎‎‎‏‎‏‎‎‏‏‎‏‎‏‎‎‎IP Configuration Failure‎‏‎‎‏‎"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 790c0d3..675084f 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"No se pueden buscar las redes."</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Ninguna"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Guardada"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Inhabilitada"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Error de configuración IP"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 1dec85d..b51b847 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"No se puede buscar redes."</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Ninguna"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Guardado"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Inhabilitado"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Error de configuración de IP"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 406e15d..fb077be 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Võrke ei saa kontrollida"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Puudub"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Salvestatud"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Keelatud"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP seadistamise ebaõnnestumine"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index bd4724e..3d3b8c3 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Ezin dira sareak bilatu"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Bat ere ez"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Gordeta"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Desgaituta"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Ezin izan da konfiguratu IP helbidea"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 45b8ac7..0af118e 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"اسکن شبکه‌ها امکان‌پذیر نیست"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"هیچ‌کدام"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"ذخیره‌شده"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"غیرفعال شد"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"‏پیکربندی IP انجام نشد"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 23c63b1..dde10d0d 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Verkkoja ei voi etsiä."</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Ei mitään"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Tallennettu"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Pois käytöstä"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-kokoonpanovirhe"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index ad99000..1257ea5 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Impossible de rechercher des réseaux."</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Aucune"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Enregistré"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Désactivés"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Échec de configuration de l\'adresse IP"</string>
@@ -227,7 +226,7 @@
     <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="6893955536658137179">"Déclencher le codec audio Bluetooth LDAC\nSélection : qualité de lecture"</string>
     <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Diffusion : <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS privé"</string>
-    <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Sélectionnez le mode DNS privé"</string>
+    <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Sélectionner le mode DNS privé"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Désactivé"</string>
     <string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automatique"</string>
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Nom d\'hôte du fournisseur DNS privé"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index c23db25..444a52e 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Impossible de rechercher des réseaux."</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Aucune"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Enregistré"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Désactivé"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Échec de configuration de l\'adresse IP"</string>
@@ -70,7 +69,7 @@
     <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Actif"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Multimédia"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Appels téléphoniques"</string>
-    <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transfert de fichier"</string>
+    <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transfert de fichiers"</string>
     <string name="bluetooth_profile_hid" msgid="3680729023366986480">"Périphérique d\'entrée"</string>
     <string name="bluetooth_profile_pan" msgid="3391606497945147673">"Accès Internet"</string>
     <string name="bluetooth_profile_pbap" msgid="5372051906968576809">"Partage de contacts"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 46532e9..8df2697 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Non se poden explorar redes"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Ningunha"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Gardada"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Desactivadas"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Erro na configuración de IP"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 6a74490..4a92f2a 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"નેટવર્ક્સ માટે સ્કૅન કરી શકતા નથી"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"કોઈ નહીં"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"સાચવેલા"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"અક્ષમ કર્યો"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP કન્ફિગરેશન નિષ્ફળ"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index bd9a6ec..6d88c35 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"नेटवर्क के लिए स्‍कैन नहीं कर सकता"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"कोई नहीं"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"सेव किया गया"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"अक्षम"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP कॉन्‍फ़िगरेशन की विफलता"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 5270531..32c9a62 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Skeniranje mreža nije moguće"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Nema"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Spremljeno"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Onemogućeno"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Konfiguracija IP-a nije uspjela"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index ad897f8..ed19267 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nem lehet beolvasni a hálózatokat"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Nincs"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Mentve"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Letiltva"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-konfigurációs hiba"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 82755f9..6d516ea 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Հնարավոր չէ սկանավորել ցանցերը"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Ոչ մեկը"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Պահված է"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Անջատված"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP կարգավորման ձախողում"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 961f892..a5f2317 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Tidak dapat memindai jaringan"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Tidak ada"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Disimpan"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Nonaktif"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Kegagalan Konfigurasi IP"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 759b7ba..6cf09a6 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Ekki er hægt að leita að netum"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Ekkert"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Vistað"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Óvirkt"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-stillingarvilla"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index bd41e28..a1b9b82 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Impossibile cercare reti"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Nessuna"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Salvata"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Disattivata"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Errore configurazione IP"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 5da253c..1a50622 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"לא ניתן לסרוק לאיתור רשתות"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"ללא"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"נשמר"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"מושבת"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"‏כשל בתצורת IP"</string>
@@ -316,7 +315,7 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"מגבלה של תהליכים ברקע"</string>
     <string name="show_all_anrs" msgid="4924885492787069007">"‏הצגת מקרי ANR ברקע"</string>
     <string name="show_all_anrs_summary" msgid="6636514318275139826">"הצגת תיבת דו-שיח של \'אפליקציה לא מגיבה\' עבור אפליקציות שפועלות ברקע"</string>
-    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"אזהרות לגבי ערוץ הודעות"</string>
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"אזהרות לגבי ערוץ התראות"</string>
     <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"הצגת אזהרה כשאפליקציה שולחת התראה ללא ערוץ חוקי"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"אילוץ הרשאת אפליקציות באחסון חיצוני"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"מאפשר כתיבה של כל אפליקציה באחסון חיצוני, ללא התחשבות בערכי המניפסט"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index f6b81ed..4c544af 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"ネットワークをスキャンできません"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"なし"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"保存済み"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"無効"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP設定エラー"</string>
@@ -436,7 +435,7 @@
     <string name="cancel" msgid="6859253417269739139">"キャンセル"</string>
     <string name="okay" msgid="1997666393121016642">"OK"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"ON にする"</string>
-    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"マナーモードを ON にする"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"サイレント モードを ON にする"</string>
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"なし"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"優先的な通知のみ"</string>
     <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>。<xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index d5f5408..92f3049 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"ქსელების სკანირება არა არის შესაძლებელი"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"არცერთი"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"დამახსოვრებულია"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"გამორთულია"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP კონფიგურაციის შეფერხება"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index c3fbfcd..b56c6fd 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Желілерді шолу мүмкін емес"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Ешқандай"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Сақталды"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Өшірілген"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP конфигурациясының қатесі"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 8e73f81..5860473 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"មិន​អាច​វិភាគ​រក​បណ្ដាញ"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"គ្មាន"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"បាន​រក្សាទុក"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"បាន​បិទ"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"ការ​កំណត់​រចនាសម្ព័ន្ធ IP បរាជ័យ"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index ce225ea..87e18e6 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"ನೆಟ್‌ವರ್ಕ್‌ಗಳಿಗಾಗಿ ಸ್ಕ್ಯಾನ್‌ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"ಯಾವುದೂ ಇಲ್ಲ"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"ಉಳಿಸಲಾಗಿದೆ"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP ಕಾನ್ಫಿಗರೇಶನ್ ವಿಫಲತೆ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index b47471b..3333c0d 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"네트워크를 검색할 수 없습니다."</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"없음"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"저장됨"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"사용 중지됨"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP 설정 실패"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 9853dac..cbbc47c 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Түйүндөрдү издөө мүмкүн эмес"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Жок"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Сакталды"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Өчүрүлгөн"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP конфигурациясы бузулду"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 1816515..21e4679 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"ບໍ່ສາມາດກວດຫາເຄືອຂ່າຍໄດ້"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"ບໍ່ໃຊ້"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"ບັນ​ທຶກແລ້ວ"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"ປິດການນຳໃຊ້"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"ການ​ຕັ້ງ​ຄ່າ IP ລົ້ມ​ເຫຼວ"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index e6a8e1c..cbff9e7 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nepavyksta nuskaityti tinklų"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Nėra"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Išsaugotas"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Neleidžiama"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP konfigūracijos triktis"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index b55afc0..d200828 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nevar skenēt tīklus"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Nav"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Saglabāts"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Atspējots"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP konfigurācijas kļūme"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index e28c8ee..db16847 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Не може да скенира за мрежи"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Ниедна"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Зачувано"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Оневозможено"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Конфигурирањето ИП не успеа"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 6860398..c3af968 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"നെ‌റ്റ്‌വർക്കുകൾക്കായി സ്കാൻ ചെയ്യാനായില്ല"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"ഒന്നുമില്ല"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"സംരക്ഷിച്ചു"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"പ്രവർത്തനരഹിതമാക്കി"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP കോൺഫിഗറേഷൻ പരാജയം"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index ba6d601..8627e1b 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Сүлжээнүүдийг скан хийх боломжгүй"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Байхгүй"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Хадгалагдсан"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Идэвхгүйжүүлсэн"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP тохируулга амжилтгүй"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index a5d230a..cd7f175 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"नेटवर्कसाठी स्कॅन करू शकत नाही"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"काहीही नाही"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"सेव्ह केले"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"अक्षम"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP कॉन्फिगरेशन अयशस्वी"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index a7ac3ef..d0b2e12 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Tidak boleh mengimbas untuk rangkaian"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Tiada"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Disimpan"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Dinyahdayakan"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Kegagalan Konfigurasi IP"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 6cdab67..5f5957c 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"ကွန်ယက်များကို စကင်မလုပ်နိုင်ပါ"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"တစ်ခုမျှ မဟုတ်ပါ"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"သိမ်းဆည်းပြီး"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"ပိတ်ထားသည်"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP ပြုပြင်ခြင်း မအောင်မြင်ပါ"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index cf18477..3c240f8 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Kan ikke søke etter nettverk"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Ingen"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Lagret"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Slått av"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-konfigurasjonsfeil"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 8aba0f8..1699870 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"सञ्जालका लागि स्क्यान गर्न सक्दैन"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"कुनै पनि होइन"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"सुरक्षित गरियो"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"असक्षम पारियो"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP विन्यास असफल"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index e3f1aea..738df94 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Kan niet zoeken naar netwerken"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Geen"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Opgeslagen"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Uitgeschakeld"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-configuratie mislukt"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 8ecac4d..2d39cc6 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"ନେଟ୍‌ୱର୍କଗୁଡ଼ିକୁ ଖୋଜିପାରୁନାହିଁ"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"କିଛି ନାହିଁ"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"ସେଭ୍‌ ହୋଇଗଲା"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"ଅକ୍ଷମ ହୋଇଛି"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP କନଫିଗରେଶନ ବିଫଳ ହୋଇଛି"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 6f17e13..61f0447 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"ਨੈਟਵਰਕਾਂ ਲਈ ਸਕੈਨ ਨਹੀਂ ਕਰ ਸਕਦਾ"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"ਕੋਈ ਨਹੀਂ"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"ਰੱਖਿਅਤ ਕੀਤਾ"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"ਅਯੋਗ ਬਣਾਇਆ"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP ਕੌਂਫਿਗਰੇਸ਼ਨ ਅਸਫਲਤਾ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 3c208e3..519f82c 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nie można wyszukać sieci."</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Brak"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Zapisana"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Wyłączona"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Błąd konfiguracji IP"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 5c363a4..16844a2 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Não é possível verificar a existência de redes"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Nenhuma"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Salva"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Desativado"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Falha de configuração de IP"</string>
@@ -227,7 +226,7 @@
     <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="6893955536658137179">"Acionar seleção de codec de áudio\nBluetooth LDAC: qualidade de reprodução"</string>
     <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Streaming: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS particular"</string>
-    <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Selecione o modo DNS particular"</string>
+    <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Selecione o modo de DNS particular"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Desativado"</string>
     <string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automático"</string>
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Nome do host do provedor de DNS particular"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 66c59ac..f01ddfa 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Não é possível verificar redes"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Nenhuma"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Guardada"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Desativado"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Falha de configuração de IP"</string>
@@ -278,7 +277,7 @@
     <string name="media_category" msgid="4388305075496848353">"Multimédia"</string>
     <string name="debug_monitoring_category" msgid="7640508148375798343">"Monitorização"</string>
     <string name="strict_mode" msgid="1938795874357830695">"Modo rigoroso ativado"</string>
-    <string name="strict_mode_summary" msgid="142834318897332338">"Piscar ecrã se aplic. fazem oper. prolong. no tópico princ."</string>
+    <string name="strict_mode_summary" msgid="142834318897332338">"Piscar ecrã se app fazem oper. prolong. no tópico princ."</string>
     <string name="pointer_location" msgid="6084434787496938001">"Localização do ponteiro"</string>
     <string name="pointer_location_summary" msgid="840819275172753713">"Apresentar dados atuais de toque"</string>
     <string name="show_touches" msgid="2642976305235070316">"Mostrar toques"</string>
@@ -305,7 +304,7 @@
     <string name="show_non_rect_clip" msgid="505954950474595172">"Depurar operações de clipe não retangulares"</string>
     <string name="track_frame_time" msgid="6094365083096851167">"Renderiz. HWUI do perfil"</string>
     <string name="enable_gpu_debug_layers" msgid="3848838293793255097">"Ativar cam. depuração GPU"</string>
-    <string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"Permitir carreg. cam. depuração GPU p/ dep. aplic."</string>
+    <string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"Permitir carreg. cam. depuração GPU p/ dep. app"</string>
     <string name="window_animation_scale_title" msgid="6162587588166114700">"Escala de anim. da janela"</string>
     <string name="transition_animation_scale_title" msgid="387527540523595875">"Escala de anim. de trans."</string>
     <string name="animator_duration_scale_title" msgid="3406722410819934083">"Esc. de duração do anim."</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 5c363a4..16844a2 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Não é possível verificar a existência de redes"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Nenhuma"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Salva"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Desativado"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Falha de configuração de IP"</string>
@@ -227,7 +226,7 @@
     <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="6893955536658137179">"Acionar seleção de codec de áudio\nBluetooth LDAC: qualidade de reprodução"</string>
     <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Streaming: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS particular"</string>
-    <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Selecione o modo DNS particular"</string>
+    <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Selecione o modo de DNS particular"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Desativado"</string>
     <string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automático"</string>
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Nome do host do provedor de DNS particular"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 703add6..8a7b440 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nu se poate scana pentru rețele"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Niciuna"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Salvată"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Dezactivată"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Eroare de configurație IP"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 4eb3ca4..31274d1 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Не удалось начать поиск сетей."</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Нет"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Сохранено"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Отключено"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Ошибка IP-конфигурации"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 1ab5b79..b22e068 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"ජාල සඳහා පරිලෝකනය කළ නොහැක"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"කිසිවක් නැත"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"සුරකින ලදි"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"අබලයි"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP වින්‍යාස කිරීම අසාර්ථකයි"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 5c3920f..43923b8 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Siete sa nedajú vyhľadávať"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Žiadne"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Uložené"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Vypnuté"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Zlyhanie konfigurácie adresy IP"</string>
@@ -438,7 +437,7 @@
     <string name="cancel" msgid="6859253417269739139">"Zrušiť"</string>
     <string name="okay" msgid="1997666393121016642">"OK"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Zapnúť"</string>
-    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Zapnite režim Nerušiť"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Zapnite režim bez vyrušení"</string>
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Nikdy"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Iba prioritné"</string>
     <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index f479405..6d392fe 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Ni mogoče iskati omrežij"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Brez"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Shranjeno"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Onemogočeno"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Konfiguracija IP-ja ni uspela"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 2741985..e05a019 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nuk mund të skanojë për rrjete"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Asnjë"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"U ruajt"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Të çaktivizuara"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Dështim në konfigurimin e IP-së"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 241d9cb..371b909 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -21,13 +21,12 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Није могуће скенирати мреже"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Нема"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Сачувано"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Онемогућено"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP конфигурација је отказала"</string>
     <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Није повезано због лошег квалитета мреже"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi веза је отказала"</string>
-    <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Проблем са потврдом аутентичности"</string>
+    <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Проблем са потврдом идентитета"</string>
     <string name="wifi_cant_connect" msgid="5410016875644565884">"Повезивање није успело"</string>
     <string name="wifi_cant_connect_to_ap" msgid="1222553274052685331">"Повезивање са „<xliff:g id="AP_NAME">%1$s</xliff:g>“ није успело"</string>
     <string name="wifi_check_password_try_again" msgid="516958988102584767">"Проверите лозинку и пробајте поново"</string>
@@ -448,5 +447,5 @@
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Трајање"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Увек питај"</string>
     <string name="zen_mode_forever" msgid="2704305038191592967">"Док не искључите"</string>
-    <string name="time_unit_just_now" msgid="6363336622778342422">"Управо сада"</string>
+    <string name="time_unit_just_now" msgid="6363336622778342422">"Управо"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index d338e96..e6872bb 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Det går inte att söka efter nätverk"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Ingen"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Sparat"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Inaktiverad"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-konfigurationsfel"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index d693077..23efb91 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Haiwezi kutambaza mitandao"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Hamna"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Imehifadhiwa"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Imezimwa"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Haikuweza Kusanidi IP"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 8f5c7d8..53ba738 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"நெட்வொர்க்குகளுக்கு ஸ்கேன் செய்யப்படவில்லை"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"ஏதுமில்லை"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"சேமிக்கப்பட்டது"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"முடக்கப்பட்டது"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP உள்ளமைவில் தோல்வி"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 5f7ab996..c8c6b4c 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"నెట్‌వర్క్‌ల కోసం స్కాన్ చేయడం సాధ్యపడదు"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"ఏదీ లేదు"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"సేవ్ చేయబడింది"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"నిలిపివేయబడింది"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP కాన్ఫిగరేషన్ వైఫల్యం"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 020baf0..d293d59 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"ไม่สามารถสแกนหาเครือข่าย"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"ไม่มี"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"บันทึกแล้ว"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"ปิดอยู่"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"การกำหนดค่า IP ล้มเหลว"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 2164ade..9da4561 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Hindi makapag-scan ng mga network"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Wala"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Na-save"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Naka-disable"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Pagkabigo ng Configuration ng IP"</string>
@@ -374,7 +373,7 @@
     <string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Tatagal dapat nang hanggang humigit-kumulang <xliff:g id="TIME">%1$s</xliff:g> batay sa iyong paggamit (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Tatagal dapat nang hanggang humigit-kumulang <xliff:g id="TIME">%1$s</xliff:g> batay sa iyong paggamit"</string>
     <string name="power_discharge_by" msgid="6453537733650125582">"Tatagal dapat nang hanggang humigit-kumulang <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
-    <string name="power_discharge_by_only" msgid="107616694963545745">"Tatagal dapat nang hanggang humigit-kumulang <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_discharge_by_only" msgid="107616694963545745">"Tatagal hanggang mga <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Wala nang <xliff:g id="THRESHOLD">%1$s</xliff:g> ang natitira"</string>
     <string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Wala nang <xliff:g id="THRESHOLD">%1$s</xliff:g> ang natitira (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Mahigit <xliff:g id="TIME_REMAINING">%1$s</xliff:g> pa ang natitira (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 532927c..2d5cd7f 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Ağlar taranamıyor"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Yok"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Kaydedildi"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Devre dışı"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Yapılandırması Hatası"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index cf26d20..512ea86 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Неможливо здійснити сканування мереж"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Немає"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Збережено"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Вимкнено"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Помилка конфігурації IP-адреси"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index c158179..84ad3ed 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"نیٹ ورکس کیلئے اسکین نہيں کر سکتے ہیں"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"کوئی نہیں"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"محفوظ کردیا گیا"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"غیر فعال"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"‏IP کنفیگریشن کی ناکامی"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index ac8bffe..af2ada5 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Tarmoqlarni tekshirib chiqishni iloji bo‘lmadi"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Hech qanday"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Saqlandi"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"O‘chiq"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP manzilini sozlab bo‘lmadi"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 78306da..f454127 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Không thể dò tìm mạng"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Không"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Đã lưu"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Đã tắt"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Lỗi cấu hình IP"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 4fb26100..10a20be 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"无法扫描网络"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"无"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"已保存"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"已停用"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP 配置失败"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index c5a8f92..1510545 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"無法掃瞄網絡"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"無"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"已儲存"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"已停用"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP 設定失敗"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 0947ccec..90c0d80 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"無法掃描網路"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"無"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"已儲存"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"已停用"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP 設定失敗"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index cd90d74..e4f9f4d 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Ayikwazi ukuhlola amanethiwekhi"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Lutho"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Kulondoloziwe"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Akusebenzi"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Ukwehluleka kokulungiswa kwe-IP"</string>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index c9bcd65..2823149 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -39,8 +39,8 @@
     <!-- Do not translate.  Concise terminology for wifi with 802.1x EAP Suite-B security -->
     <string name="wifi_security_short_eap_suiteb" translatable="false">Suite-B</string>
 
-    <!-- Used in Wi-Fi settings dialogs when Wi-Fi does not have any security. -->
-    <string name="wifi_security_none" translatable="false">None</string>
+    <!-- Used in Wi-Fi settings dialogs when Wi-Fi does not have any security. [CHAR LIMIT=40] -->
+    <string name="wifi_security_none">None</string>
 
     <!-- Do not translate.  Terminology for wifi with WEP security -->
     <string name="wifi_security_wep" translatable="false">WEP</string>
@@ -930,6 +930,8 @@
     <string name="power_discharge_by">Should last until about <xliff:g id="time">%1$s</xliff:g> (<xliff:g id="level">%2$s</xliff:g>)</string>
     <!-- [CHAR_LIMIT=100] Label for estimated time that phone will run out of battery -->
     <string name="power_discharge_by_only">Should last until about <xliff:g id="time">%1$s</xliff:g></string>
+    <!-- [CHAR_LIMIT=100] Label for estimated time that phone will run out of battery -->
+    <string name="power_discharge_by_only_short">Until <xliff:g id="time" example="12 PM">%1$s</xliff:g></string>
 
     <!-- [CHAR_LIMIT=60] label for estimated remaining duration of battery when under a certain amount -->
     <string name="power_remaining_less_than_duration_only">Less than <xliff:g id="threshold">%1$s</xliff:g> remaining</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/EventLogWriter.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/EventLogWriter.java
index 1aeb075..e824508 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/EventLogWriter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/EventLogWriter.java
@@ -44,7 +44,14 @@
 
     @Override
     public void action(Context context, int category, Pair<Integer, Object>... taggedData) {
-        action(context, category, "", taggedData);
+        final LogMaker logMaker = new LogMaker(category)
+                .setType(MetricsProto.MetricsEvent.TYPE_ACTION);
+        if (taggedData != null) {
+            for (Pair<Integer, Object> pair : taggedData) {
+                logMaker.addTaggedData(pair.first, pair.second);
+            }
+        }
+        MetricsLogger.action(logMaker);
     }
 
     @Override
@@ -58,19 +65,12 @@
     }
 
     @Override
-    public void action(Context context, int category, String pkg,
-            Pair<Integer, Object>... taggedData) {
-        if (taggedData == null || taggedData.length == 0) {
-            MetricsLogger.action(context, category, pkg);
-        } else {
-            final LogMaker logMaker = new LogMaker(category)
-                    .setType(MetricsProto.MetricsEvent.TYPE_ACTION)
-                    .setPackageName(pkg);
-            for (Pair<Integer, Object> pair : taggedData) {
-                logMaker.addTaggedData(pair.first, pair.second);
-            }
-            MetricsLogger.action(logMaker);
-        }
+    public void action(Context context, int category, String pkg) {
+        final LogMaker logMaker = new LogMaker(category)
+                .setType(MetricsProto.MetricsEvent.TYPE_ACTION)
+                .setPackageName(pkg);
+
+        MetricsLogger.action(logMaker);
     }
 
     @Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/LogWriter.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/LogWriter.java
index b60364e..f187688 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/LogWriter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/LogWriter.java
@@ -51,7 +51,7 @@
     /**
      * Logs an user action.
      */
-    void action(Context context, int category, String pkg, Pair<Integer, Object>... taggedData);
+    void action(Context context, int category, String pkg);
 
     /**
      * Generically log action.
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java
index 188204e..8cc3b5a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java
@@ -79,7 +79,10 @@
         }
     }
 
-    public void action(Context context, int category, Pair<Integer, Object>... taggedData) {
+    /**
+     * Logs a simple action without page id or attribution
+     */
+    public void action(Context context, int category,  Pair<Integer, Object>... taggedData) {
         for (LogWriter writer : mLoggerWriters) {
             writer.action(context, category, taggedData);
         }
@@ -88,10 +91,9 @@
     /**
      * Logs a generic Settings event.
      */
-    public void action(Context context, int category, String pkg,
-            Pair<Integer, Object>... taggedData) {
+    public void action(Context context, int category, String pkg) {
         for (LogWriter writer : mLoggerWriters) {
-            writer.action(context, category, pkg, taggedData);
+            writer.action(context, category, pkg);
         }
     }
 
@@ -135,16 +137,22 @@
                 // Not loggable
                 return;
             }
-            action(context, MetricsEvent.ACTION_SETTINGS_TILE_CLICK, action,
-                    Pair.create(MetricsEvent.FIELD_CONTEXT, sourceMetricsCategory));
+            action(sourceMetricsCategory,
+                    MetricsEvent.ACTION_SETTINGS_TILE_CLICK,
+                    SettingsEnums.PAGE_UNKNOWN,
+                    action,
+                    0);
             return;
         } else if (TextUtils.equals(cn.getPackageName(), context.getPackageName())) {
             // Going to a Setting internal page, skip click logging in favor of page's own
             // visibility logging.
             return;
         }
-        action(context, MetricsEvent.ACTION_SETTINGS_TILE_CLICK, cn.flattenToString(),
-                Pair.create(MetricsEvent.FIELD_CONTEXT, sourceMetricsCategory));
+        action(sourceMetricsCategory,
+                MetricsEvent.ACTION_SETTINGS_TILE_CLICK,
+                SettingsEnums.PAGE_UNKNOWN,
+                cn.flattenToString(),
+                0);
     }
 
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SharedPreferencesLogger.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SharedPreferencesLogger.java
index 71f3789..320380f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SharedPreferencesLogger.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SharedPreferencesLogger.java
@@ -15,6 +15,7 @@
 package com.android.settingslib.core.instrumentation;
 
 import android.annotation.Nullable;
+import android.app.settings.SettingsEnums;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.SharedPreferences;
@@ -22,12 +23,9 @@
 import android.os.AsyncTask;
 import android.text.TextUtils;
 import android.util.Log;
-import android.util.Pair;
 
 import androidx.annotation.VisibleForTesting;
 
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentSkipListSet;
@@ -117,10 +115,9 @@
             return;
         }
 
-        final Pair<Integer, Object> valueData;
+        final int intVal;
         if (value instanceof Long) {
             final Long longVal = (Long) value;
-            final int intVal;
             if (longVal > Integer.MAX_VALUE) {
                 intVal = Integer.MAX_VALUE;
             } else if (longVal < Integer.MIN_VALUE) {
@@ -128,47 +125,45 @@
             } else {
                 intVal = longVal.intValue();
             }
-            valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE,
-                    intVal);
         } else if (value instanceof Integer) {
-            valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE,
-                    value);
+            intVal = (int) value;
         } else if (value instanceof Boolean) {
-            valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE,
-                    (Boolean) value ? 1 : 0);
+            intVal = (Boolean) value ? 1 : 0;
         } else if (value instanceof Float) {
-            valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_FLOAT_VALUE,
-                    value);
-        } else if (value instanceof String) {
-            Log.d(LOG_TAG, "Tried to log string preference " + prefKey + " = " + value);
-            valueData = null;
+            final float floatValue = (float) value;
+            if (floatValue > Integer.MAX_VALUE) {
+                intVal = Integer.MAX_VALUE;
+            } else if (floatValue < Integer.MIN_VALUE) {
+                intVal = Integer.MIN_VALUE;
+            } else {
+                intVal = (int) floatValue;
+            }
         } else {
             Log.w(LOG_TAG, "Tried to log unloggable object" + value);
-            valueData = null;
+            return;
         }
-        if (valueData != null) {
-            // Pref key exists in set, log it's change in metrics.
-            mMetricsFeature.action(mContext, MetricsEvent.ACTION_SETTINGS_PREFERENCE_CHANGE,
-                    Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME, prefKey),
-                    valueData);
-        }
+        // Pref key exists in set, log it's change in metrics.
+        mMetricsFeature.action(SettingsEnums.PAGE_UNKNOWN,
+                SettingsEnums.ACTION_SETTINGS_PREFERENCE_CHANGE,
+                SettingsEnums.PAGE_UNKNOWN,
+                prefKey,
+                intVal);
     }
 
     @VisibleForTesting
     void logPackageName(String key, String value) {
         final String prefKey = mTag + "/" + key;
-        mMetricsFeature.action(mContext, MetricsEvent.ACTION_SETTINGS_PREFERENCE_CHANGE, value,
-                Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME, prefKey));
+        mMetricsFeature.action(SettingsEnums.PAGE_UNKNOWN,
+                SettingsEnums.ACTION_SETTINGS_PREFERENCE_CHANGE,
+                SettingsEnums.PAGE_UNKNOWN,
+                prefKey + ":" + value,
+                0);
     }
 
     private void safeLogValue(String key, String value) {
         new AsyncPackageCheck().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, key, value);
     }
 
-    public static String buildCountName(String prefKey, Object value) {
-        return prefKey + "|" + value;
-    }
-
     public static String buildPrefKey(String tag, String key) {
         return tag + "/" + key;
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
index 5a57e69..8f9394f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
@@ -152,7 +152,8 @@
         final MeasurementDetails details = new MeasurementDetails();
         if (mVolume == null) return details;
 
-        if (mVolume.getType() == VolumeInfo.TYPE_PUBLIC) {
+        if (mVolume.getType() == VolumeInfo.TYPE_PUBLIC
+                || mVolume.getType() == VolumeInfo.TYPE_STUB) {
             details.totalSize = mVolume.getPath().getTotalSpace();
             details.availSize = mVolume.getPath().getUsableSpace();
             return details;
diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java b/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
index fa59688..43c97df 100644
--- a/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
+++ b/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
@@ -81,6 +81,30 @@
         return null;
     }
 
+    /**
+     * Method to produce a shortened string describing the remaining battery. Suitable for Quick
+     * Settings and other areas where space is constrained.
+     *
+     * @param context context to fetch descriptions from
+     * @param drainTimeMs The estimated time remaining before the phone dies in milliseconds.
+     *
+     * @return a properly formatted and localized short string describing how much time remains
+     * before the battery runs out.
+     */
+    @Nullable
+    public static String getBatteryRemainingShortStringFormatted(
+            Context context, long drainTimeMs) {
+        if (drainTimeMs <= 0) {
+            return null;
+        }
+
+        if (drainTimeMs <= ONE_DAY_MILLIS) {
+            return getRegularTimeRemainingShortString(context, drainTimeMs);
+        } else {
+            return getMoreThanOneDayShortString(context, drainTimeMs);
+        }
+    }
+
     private static String getShutdownImminentString(Context context, String percentageString) {
         return TextUtils.isEmpty(percentageString)
                 ? context.getString(R.string.power_remaining_duration_only_shutdown_imminent)
@@ -120,6 +144,14 @@
         }
     }
 
+    private static String getMoreThanOneDayShortString(Context context, long drainTimeMs) {
+        final long roundedTimeMs = roundTimeToNearestThreshold(drainTimeMs, ONE_HOUR_MILLIS);
+        CharSequence timeString = StringUtil.formatElapsedTime(context, roundedTimeMs,
+                false /* withSeconds */);
+
+        return context.getString(R.string.power_remaining_duration_only_short, timeString);
+    }
+
     private static String getMoreThanTwoDaysString(Context context, String percentageString) {
         final Locale currentLocale = context.getResources().getConfiguration().getLocales().get(0);
         final MeasureFormat frmt = MeasureFormat.getInstance(currentLocale, FormatWidth.SHORT);
@@ -162,6 +194,22 @@
         }
     }
 
+    private static String getRegularTimeRemainingShortString(Context context, long drainTimeMs) {
+        // Get the time of day we think device will die rounded to the nearest 15 min.
+        final long roundedTimeOfDayMs =
+                roundTimeToNearestThreshold(
+                        System.currentTimeMillis() + drainTimeMs,
+                        FIFTEEN_MINUTES_MILLIS);
+
+        // convert the time to a properly formatted string.
+        String skeleton = android.text.format.DateFormat.getTimeFormatString(context);
+        DateFormat fmt = DateFormat.getInstanceForSkeleton(skeleton);
+        Date date = Date.from(Instant.ofEpochMilli(roundedTimeOfDayMs));
+        CharSequence timeString = fmt.format(date);
+
+        return context.getString(R.string.power_discharge_by_only_short, timeString);
+    }
+
     public static long convertUsToMs(long timeUs) {
         return timeUs / 1000;
     }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java
index 603f838..4ec6fb2 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java
@@ -17,8 +17,6 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 
@@ -27,7 +25,6 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.util.Pair;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
@@ -77,10 +74,11 @@
         mProvider.logDashboardStartIntent(mContext, intent, MetricsEvent.SETTINGS_GESTURES);
 
         verify(mLogWriter).action(
-                eq(mContext),
-                eq(MetricsEvent.ACTION_SETTINGS_TILE_CLICK),
-                anyString(),
-                eq(Pair.create(MetricsEvent.FIELD_CONTEXT, MetricsEvent.SETTINGS_GESTURES)));
+                MetricsEvent.SETTINGS_GESTURES,
+                MetricsEvent.ACTION_SETTINGS_TILE_CLICK,
+                SettingsEnums.PAGE_UNKNOWN,
+                Intent.ACTION_ASSIST,
+                0);
     }
 
     @Test
@@ -90,10 +88,11 @@
         mProvider.logDashboardStartIntent(mContext, intent, MetricsEvent.SETTINGS_GESTURES);
 
         verify(mLogWriter).action(
-                eq(mContext),
-                eq(MetricsEvent.ACTION_SETTINGS_TILE_CLICK),
-                anyString(),
-                eq(Pair.create(MetricsEvent.FIELD_CONTEXT, MetricsEvent.SETTINGS_GESTURES)));
+                MetricsEvent.SETTINGS_GESTURES,
+                MetricsEvent.ACTION_SETTINGS_TILE_CLICK,
+                SettingsEnums.PAGE_UNKNOWN,
+                "pkg/cls",
+                0);
     }
 
     @Test
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SharedPreferenceLoggerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SharedPreferenceLoggerTest.java
index be671e6..6285fcd 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SharedPreferenceLoggerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SharedPreferenceLoggerTest.java
@@ -15,25 +15,16 @@
  */
 package com.android.settingslib.core.instrumentation;
 
-import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
-        .ACTION_SETTINGS_PREFERENCE_CHANGE;
-import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
-        .FIELD_SETTINGS_PREFERENCE_CHANGE_FLOAT_VALUE;
-import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
-        .FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE;
-import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
-        .FIELD_SETTINGS_PREFERENCE_CHANGE_NAME;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_SETTINGS_PREFERENCE_CHANGE;
 
-import static org.mockito.Matchers.any;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
+import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.content.SharedPreferences;
-import android.util.Pair;
 
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
 
@@ -41,7 +32,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Answers;
-import org.mockito.ArgumentMatcher;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -50,11 +40,11 @@
 
     private static final String TEST_TAG = "tag";
     private static final String TEST_KEY = "key";
+    private static final String TEST_TAGGED_KEY = TEST_TAG + "/" + TEST_KEY;
 
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private Context mContext;
 
-    private ArgumentMatcher<Pair<Integer, Object>> mNamePairMatcher;
     @Mock
     private MetricsFeatureProvider mMetricsFeature;
     private SharedPreferencesLogger mSharedPrefLogger;
@@ -63,7 +53,6 @@
     public void init() {
         MockitoAnnotations.initMocks(this);
         mSharedPrefLogger = new SharedPreferencesLogger(mContext, TEST_TAG, mMetricsFeature);
-        mNamePairMatcher = pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_NAME, String.class);
     }
 
     @Test
@@ -77,9 +66,11 @@
         editor.putInt(TEST_KEY, 2);
         editor.putInt(TEST_KEY, 2);
 
-        verify(mMetricsFeature, times(6)).action(any(Context.class), anyInt(),
-                argThat(mNamePairMatcher),
-                argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, Integer.class)));
+        verify(mMetricsFeature, times(6)).action(eq(SettingsEnums.PAGE_UNKNOWN),
+                eq(SettingsEnums.ACTION_SETTINGS_PREFERENCE_CHANGE),
+                eq(SettingsEnums.PAGE_UNKNOWN),
+                eq(TEST_TAGGED_KEY),
+                anyInt());
     }
 
     @Test
@@ -92,12 +83,16 @@
         editor.putBoolean(TEST_KEY, false);
 
 
-        verify(mMetricsFeature).action(any(Context.class), anyInt(),
-                argThat(mNamePairMatcher),
-                argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, true)));
-        verify(mMetricsFeature, times(3)).action(any(Context.class), anyInt(),
-                argThat(mNamePairMatcher),
-                argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, false)));
+        verify(mMetricsFeature).action(SettingsEnums.PAGE_UNKNOWN,
+                SettingsEnums.ACTION_SETTINGS_PREFERENCE_CHANGE,
+                SettingsEnums.PAGE_UNKNOWN,
+                TEST_TAGGED_KEY,
+                1);
+        verify(mMetricsFeature, times(3)).action(SettingsEnums.PAGE_UNKNOWN,
+                SettingsEnums.ACTION_SETTINGS_PREFERENCE_CHANGE,
+                SettingsEnums.PAGE_UNKNOWN,
+                TEST_TAGGED_KEY,
+                0);
     }
 
     @Test
@@ -109,9 +104,11 @@
         editor.putLong(TEST_KEY, 1);
         editor.putLong(TEST_KEY, 2);
 
-        verify(mMetricsFeature, times(4)).action(any(Context.class), anyInt(),
-                argThat(mNamePairMatcher),
-                argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, Integer.class)));
+        verify(mMetricsFeature, times(4)).action(eq(SettingsEnums.PAGE_UNKNOWN),
+                eq(SettingsEnums.ACTION_SETTINGS_PREFERENCE_CHANGE),
+                eq(SettingsEnums.PAGE_UNKNOWN),
+                eq(TEST_TAGGED_KEY),
+                anyInt());
     }
 
     @Test
@@ -121,10 +118,11 @@
         editor.putLong(TEST_KEY, 1);
         editor.putLong(TEST_KEY, veryBigNumber);
 
-        verify(mMetricsFeature).action(any(Context.class), anyInt(),
-                argThat(mNamePairMatcher),
-                argThat(pairMatches(
-                        FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, Integer.MAX_VALUE)));
+        verify(mMetricsFeature).action(SettingsEnums.PAGE_UNKNOWN,
+                SettingsEnums.ACTION_SETTINGS_PREFERENCE_CHANGE,
+                SettingsEnums.PAGE_UNKNOWN,
+                TEST_TAGGED_KEY,
+                Integer.MAX_VALUE);
     }
 
     @Test
@@ -134,10 +132,10 @@
         editor.putLong(TEST_KEY, 1);
         editor.putLong(TEST_KEY, veryNegativeNumber);
 
-        verify(mMetricsFeature).action(any(Context.class), anyInt(),
-                argThat(mNamePairMatcher),
-                argThat(pairMatches(
-                        FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, Integer.MIN_VALUE)));
+        verify(mMetricsFeature).action(SettingsEnums.PAGE_UNKNOWN,
+                SettingsEnums.ACTION_SETTINGS_PREFERENCE_CHANGE,
+                SettingsEnums.PAGE_UNKNOWN,
+                TEST_TAGGED_KEY, Integer.MIN_VALUE);
     }
 
     @Test
@@ -149,38 +147,20 @@
         editor.putFloat(TEST_KEY, 1);
         editor.putFloat(TEST_KEY, 2);
 
-        verify(mMetricsFeature, times(4)).action(any(Context.class), anyInt(),
-                argThat(mNamePairMatcher),
-                argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_FLOAT_VALUE, Float.class)));
+        verify(mMetricsFeature, times(4)).action(eq(SettingsEnums.PAGE_UNKNOWN),
+                eq(SettingsEnums.ACTION_SETTINGS_PREFERENCE_CHANGE),
+                eq(SettingsEnums.PAGE_UNKNOWN),
+                eq(TEST_TAGGED_KEY),
+                anyInt());
     }
 
     @Test
     public void logPackage_shouldUseLogPackageApi() {
         mSharedPrefLogger.logPackageName("key", "com.android.settings");
-        verify(mMetricsFeature).action(any(Context.class),
-                eq(ACTION_SETTINGS_PREFERENCE_CHANGE),
-                eq("com.android.settings"),
-                any(Pair.class));
-    }
-
-    private ArgumentMatcher<Pair<Integer, Object>> pairMatches(int tag, Class clazz) {
-        return pair -> pair.first == tag && isInstanceOfType(pair.second, clazz);
-    }
-
-    private ArgumentMatcher<Pair<Integer, Object>> pairMatches(int tag, boolean bool) {
-        return pair -> pair.first == tag
-                && isInstanceOfType(pair.second, Integer.class)
-                && pair.second.equals((bool ? 1 : 0));
-    }
-
-    private ArgumentMatcher<Pair<Integer, Object>> pairMatches(int tag, int val) {
-        return pair -> pair.first == tag
-                && isInstanceOfType(pair.second, Integer.class)
-                && pair.second.equals(val);
-    }
-
-    /** Returns true if the instance is assignable to the type Clazz. */
-    private static boolean isInstanceOfType(Object instance, Class<?> clazz) {
-        return clazz.isInstance(instance);
+        verify(mMetricsFeature).action(SettingsEnums.PAGE_UNKNOWN,
+                ACTION_SETTINGS_PREFERENCE_CHANGE,
+                SettingsEnums.PAGE_UNKNOWN,
+                "tag/key:com.android.settings",
+                0);
     }
 }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 448a963..cbb6e82 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -572,6 +572,15 @@
                 GlobalSettingsProto.Dropbox.SETTINGS);
         p.end(dropboxToken);
 
+        final long dynamicPowerSavingsToken = p.start(GlobalSettingsProto.DYNAMIC_POWER_SAVINGS);
+        dumpSetting(s, p,
+                Settings.Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD,
+                GlobalSettingsProto.DynamicPowerSavings.DISABLE_THRESHOLD);
+        dumpSetting(s, p,
+                Settings.Global.DYNAMIC_POWER_SAVINGS_ENABLED,
+                GlobalSettingsProto.DynamicPowerSavings.ENABLED);
+        p.end(dynamicPowerSavingsToken);
+
         final long emergencyToken = p.start(GlobalSettingsProto.EMERGENCY);
         dumpSetting(s, p,
                 Settings.Global.EMERGENCY_TONE,
@@ -794,6 +803,9 @@
         dumpSetting(s, p,
                 Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL_MAX,
                 GlobalSettingsProto.LowPowerMode.TRIGGER_LEVEL_MAX);
+        dumpSetting(s, p,
+                Settings.Global.AUTOMATIC_POWER_SAVER_MODE,
+                GlobalSettingsProto.LowPowerMode.AUTOMATIC_POWER_SAVER_MODE);
         p.end(lpmToken);
 
         dumpSetting(s, p,
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 822c39b..89690fb 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -83,6 +83,7 @@
     <uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" />
     <uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
     <uses-permission android:name="android.permission.DEVICE_POWER" />
+    <uses-permission android:name="android.permission.POWER_SAVER" />
     <uses-permission android:name="android.permission.INSTALL_LOCATION_PROVIDER" />
     <uses-permission android:name="android.permission.BACKUP" />
     <uses-permission android:name="android.permission.FORCE_STOP_PACKAGES" />
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
index b51ad1c..51f6a4b 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
@@ -20,8 +20,8 @@
 <!-- This is a view that shows general status information in Keyguard. -->
 <com.android.keyguard.KeyguardSliceView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_marginStart="16dp"
-    android:layout_marginEnd="16dp"
+    android:paddingStart="16dp"
+    android:paddingEnd="16dp"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:layout_gravity="center_horizontal"
diff --git a/packages/SystemUI/res/drawable-nodpi/work_challenge_background.png b/packages/SystemUI/res/drawable-nodpi/work_challenge_background.png
new file mode 100644
index 0000000..311f30bc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/work_challenge_background.png
Binary files differ
diff --git a/packages/SystemUI/res/layout/biometric_dialog.xml b/packages/SystemUI/res/layout/biometric_dialog.xml
index 67c0adf..5ca34b0 100644
--- a/packages/SystemUI/res/layout/biometric_dialog.xml
+++ b/packages/SystemUI/res/layout/biometric_dialog.xml
@@ -14,157 +14,169 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License
   -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/layout"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:gravity="bottom"
-    android:background="@color/biometric_dialog_dim_color"
-    android:orientation="vertical">
+    android:layout_height="match_parent">
 
-    <!-- This is not a Space since Spaces cannot be clicked -->
-    <View
-        android:id="@+id/space"
+    <ImageView
+        android:id="@+id/background"
         android:layout_width="match_parent"
-        android:layout_height="0dp"
-        android:layout_weight="1" />
+        android:layout_height="match_parent"
+        android:scaleType="center" />
 
     <LinearLayout
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="horizontal">
+        android:layout_height="match_parent"
+        android:gravity="bottom"
+        android:background="@color/biometric_dialog_dim_color"
+        android:orientation="vertical">
 
-        <!-- This is not a Space since Spaces cannot be clicked. The width of this changes depending
-         on horizontal/portrait orientation -->
+        <!-- This is not a Space since Spaces cannot be clicked -->
         <View
-            android:id="@+id/left_space"
-            android:layout_weight="1"
-            android:layout_width="0dp"
-            android:layout_height="match_parent"/>
+            android:id="@+id/space"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="1" />
 
         <LinearLayout
-            android:id="@+id/dialog"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:orientation="vertical"
-            android:background="@drawable/biometric_dialog_bg"
-            android:layout_marginBottom="@dimen/biometric_dialog_border_padding"
-            android:layout_marginLeft="@dimen/biometric_dialog_border_padding"
-            android:layout_marginRight="@dimen/biometric_dialog_border_padding">
+            android:orientation="horizontal">
 
-            <TextView
-                android:id="@+id/title"
-                android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginEnd="24dp"
-                android:layout_marginStart="24dp"
-                android:layout_marginTop="24dp"
-                android:gravity="@integer/biometric_dialog_text_gravity"
-                android:textSize="20sp"
-                android:maxLines="1"
-                android:singleLine="true"
-                android:ellipsize="marquee"
-                android:marqueeRepeatLimit="marquee_forever"
-                android:textColor="?android:attr/textColorPrimary"/>
-
-            <TextView
-                android:id="@+id/subtitle"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="8dp"
-                android:layout_marginStart="24dp"
-                android:layout_marginEnd="24dp"
-                android:gravity="@integer/biometric_dialog_text_gravity"
-                android:textSize="16sp"
-                android:maxLines="1"
-                android:singleLine="true"
-                android:ellipsize="marquee"
-                android:marqueeRepeatLimit="marquee_forever"
-                android:textColor="?android:attr/textColorPrimary"/>
-
-            <TextView
-                android:id="@+id/description"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginEnd="24dp"
-                android:layout_marginStart="24dp"
-                android:gravity="@integer/biometric_dialog_text_gravity"
-                android:paddingTop="8dp"
-                android:textSize="16sp"
-                android:maxLines="4"
-                android:textColor="?android:attr/textColorPrimary"/>
-
-            <ImageView
-                android:id="@+id/biometric_icon"
-                android:layout_width="@dimen/biometric_dialog_biometric_icon_size"
-                android:layout_height="@dimen/biometric_dialog_biometric_icon_size"
-                android:layout_gravity="center_horizontal"
-                android:layout_marginTop="48dp"
-                android:scaleType="fitXY" />
-
-            <TextView
-                android:id="@+id/error"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginEnd="24dp"
-                android:layout_marginStart="24dp"
-                android:paddingTop="16dp"
-                android:paddingBottom="24dp"
-                android:textSize="12sp"
-                android:gravity="center_horizontal"
-                android:accessibilityLiveRegion="polite"
-                android:contentDescription="@string/accessibility_biometric_dialog_help_area"
-                android:textColor="?android:attr/textColorSecondary"/>
+            <!-- This is not a Space since Spaces cannot be clicked. The width of this changes depending
+             on horizontal/portrait orientation -->
+            <View
+                android:id="@+id/left_space"
+                android:layout_weight="1"
+                android:layout_width="0dp"
+                android:layout_height="match_parent"/>
 
             <LinearLayout
+                android:id="@+id/dialog"
                 android:layout_width="match_parent"
-                android:layout_height="72dip"
-                android:paddingTop="24dp"
-                android:layout_gravity="center_vertical"
-                style="?android:attr/buttonBarStyle"
-                android:orientation="horizontal"
-                android:measureWithLargestChild="true">
-                <Space android:id="@+id/leftSpacer"
-                    android:layout_width="12dp"
-                    android:layout_height="match_parent"
-                    android:visibility="visible" />
-                <!-- Negative Button -->
-                <Button android:id="@+id/button2"
-                    android:layout_width="wrap_content"
-                    android:layout_height="match_parent"
-                    style="@*android:style/Widget.DeviceDefault.Button.Borderless.Colored"
-                    android:gravity="center"
-                    android:maxLines="2" />
-                <Space android:id="@+id/middleSpacer"
-                    android:layout_width="0dp"
-                    android:layout_height="match_parent"
-                    android:layout_weight="1"
-                    android:visibility="visible" />
-                <!-- Positive Button -->
-                <Button android:id="@+id/button1"
-                    android:layout_width="wrap_content"
-                    android:layout_height="match_parent"
-                    style="@*android:style/Widget.DeviceDefault.Button.Colored"
-                    android:gravity="center"
-                    android:maxLines="2"
-                    android:text="@string/biometric_dialog_confirm"
-                    android:visibility="gone"/>
-                <Space android:id="@+id/rightSpacer"
-                    android:layout_width="12dip"
-                    android:layout_height="match_parent"
-                    android:visibility="visible" />
-            </LinearLayout>
-        </LinearLayout>
+                android:layout_height="wrap_content"
+                android:orientation="vertical"
+                android:background="@drawable/biometric_dialog_bg"
+                android:layout_marginBottom="@dimen/biometric_dialog_border_padding"
+                android:layout_marginLeft="@dimen/biometric_dialog_border_padding"
+                android:layout_marginRight="@dimen/biometric_dialog_border_padding">
 
-        <!-- This is not a Space since Spaces cannot be clicked. The width of this changes depending
-         on horizontal/portrait orientation -->
-        <View
-            android:id="@+id/right_space"
-            android:layout_weight="1"
-            android:layout_width="0dp"
-            android:layout_height="match_parent" />
+                <TextView
+                    android:id="@+id/title"
+                    android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginEnd="24dp"
+                    android:layout_marginStart="24dp"
+                    android:layout_marginTop="24dp"
+                    android:gravity="@integer/biometric_dialog_text_gravity"
+                    android:textSize="20sp"
+                    android:maxLines="1"
+                    android:singleLine="true"
+                    android:ellipsize="marquee"
+                    android:marqueeRepeatLimit="marquee_forever"
+                    android:textColor="?android:attr/textColorPrimary"/>
+
+                <TextView
+                    android:id="@+id/subtitle"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="8dp"
+                    android:layout_marginStart="24dp"
+                    android:layout_marginEnd="24dp"
+                    android:gravity="@integer/biometric_dialog_text_gravity"
+                    android:textSize="16sp"
+                    android:maxLines="1"
+                    android:singleLine="true"
+                    android:ellipsize="marquee"
+                    android:marqueeRepeatLimit="marquee_forever"
+                    android:textColor="?android:attr/textColorPrimary"/>
+
+                <TextView
+                    android:id="@+id/description"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginEnd="24dp"
+                    android:layout_marginStart="24dp"
+                    android:gravity="@integer/biometric_dialog_text_gravity"
+                    android:paddingTop="8dp"
+                    android:textSize="16sp"
+                    android:maxLines="4"
+                    android:textColor="?android:attr/textColorPrimary"/>
+
+                <ImageView
+                    android:id="@+id/biometric_icon"
+                    android:layout_width="@dimen/biometric_dialog_biometric_icon_size"
+                    android:layout_height="@dimen/biometric_dialog_biometric_icon_size"
+                    android:layout_gravity="center_horizontal"
+                    android:layout_marginTop="48dp"
+                    android:scaleType="fitXY" />
+
+                <TextView
+                    android:id="@+id/error"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginEnd="24dp"
+                    android:layout_marginStart="24dp"
+                    android:paddingTop="16dp"
+                    android:paddingBottom="24dp"
+                    android:textSize="12sp"
+                    android:gravity="center_horizontal"
+                    android:accessibilityLiveRegion="polite"
+                    android:contentDescription="@string/accessibility_biometric_dialog_help_area"
+                    android:textColor="?android:attr/textColorSecondary"/>
+
+                <LinearLayout
+                    android:layout_width="match_parent"
+                    android:layout_height="72dip"
+                    android:paddingTop="24dp"
+                    android:layout_gravity="center_vertical"
+                    style="?android:attr/buttonBarStyle"
+                    android:orientation="horizontal"
+                    android:measureWithLargestChild="true">
+                    <Space android:id="@+id/leftSpacer"
+                        android:layout_width="12dp"
+                        android:layout_height="match_parent"
+                        android:visibility="visible" />
+                    <!-- Negative Button -->
+                    <Button android:id="@+id/button2"
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        style="@*android:style/Widget.DeviceDefault.Button.Borderless.Colored"
+                        android:gravity="center"
+                        android:maxLines="2" />
+                    <Space android:id="@+id/middleSpacer"
+                        android:layout_width="0dp"
+                        android:layout_height="match_parent"
+                        android:layout_weight="1"
+                        android:visibility="visible" />
+                    <!-- Positive Button -->
+                    <Button android:id="@+id/button1"
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        style="@*android:style/Widget.DeviceDefault.Button.Colored"
+                        android:gravity="center"
+                        android:maxLines="2"
+                        android:text="@string/biometric_dialog_confirm"
+                        android:visibility="gone"/>
+                    <Space android:id="@+id/rightSpacer"
+                        android:layout_width="12dip"
+                        android:layout_height="match_parent"
+                        android:visibility="visible" />
+                </LinearLayout>
+            </LinearLayout>
+
+            <!-- This is not a Space since Spaces cannot be clicked. The width of this changes depending
+             on horizontal/portrait orientation -->
+            <View
+                android:id="@+id/right_space"
+                android:layout_weight="1"
+                android:layout_width="0dp"
+                android:layout_height="match_parent" />
+
+        </LinearLayout>
 
     </LinearLayout>
 
-</LinearLayout>
+</FrameLayout>
diff --git a/packages/SystemUI/res/layout/navigation_bar_window.xml b/packages/SystemUI/res/layout/navigation_bar_window.xml
index 6fa46d4..f98cbd8 100644
--- a/packages/SystemUI/res/layout/navigation_bar_window.xml
+++ b/packages/SystemUI/res/layout/navigation_bar_window.xml
@@ -20,6 +20,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:id="@+id/navigation_bar_frame"
+    android:theme="@style/Theme.SystemUI"
     android:layout_height="match_parent"
     android:layout_width="match_parent">
 
diff --git a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
index 5e952e3..ddefb6a 100644
--- a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
+++ b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
@@ -21,7 +21,8 @@
     android:layout_width="wrap_content"
     android:layout_height="match_parent"
     android:layout_margin="@dimen/ongoing_appops_chip_margin"
-    android:gravity="center_vertical|end"
+    android:gravity="center_vertical|center_horizontal"
+    android:layout_gravity="center_vertical|end"
     android:orientation="horizontal"
     android:paddingStart="@dimen/ongoing_appops_chip_side_padding"
     android:paddingEnd="@dimen/ongoing_appops_chip_side_padding"
@@ -32,13 +33,17 @@
             android:id="@+id/icons_container"
             android:layout_height="match_parent"
             android:layout_width="wrap_content"
-            android:gravity="center_vertical|start"
+            android:layout_gravity="center_vertical|start"
+            android:gravity="center_vertical"
             />
 
         <TextView
             android:id="@+id/app_name"
             android:layout_height="match_parent"
             android:layout_width="wrap_content"
-            android:gravity="center_vertical|end"
+            android:singleLine="true"
+            android:ellipsize="end"
+            android:layout_gravity="center_vertical|end"
+            android:gravity="center_vertical"
         />
 </com.android.systemui.privacy.OngoingPrivacyChip>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/quick_qs_status_icons.xml b/packages/SystemUI/res/layout/quick_qs_status_icons.xml
index 94189bb..2000104 100644
--- a/packages/SystemUI/res/layout/quick_qs_status_icons.xml
+++ b/packages/SystemUI/res/layout/quick_qs_status_icons.xml
@@ -42,6 +42,20 @@
         android:id="@+id/statusIcons"
         android:layout_width="0dp"
         android:layout_height="match_parent"
-        android:layout_weight="1" />
+        android:layout_weight="1"
+        android:paddingEnd="@dimen/signal_cluster_battery_padding" />
+
+    <com.android.systemui.BatteryMeterView
+        android:id="@+id/batteryRemainingIcon"
+        android:layout_height="match_parent"
+        android:layout_width="wrap_content"
+        android:paddingEnd="2dp" />
+
+    <TextView
+        android:id="@+id/batteryRemainingText"
+        android:textAppearance="@style/TextAppearance.QS.TileLabel"
+        android:layout_height="match_parent"
+        android:layout_width="wrap_content"
+        android:gravity="center_vertical" />
 
 </LinearLayout>
diff --git a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
index 007070e..e7f2c51 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
@@ -27,6 +27,13 @@
     android:paddingStart="@dimen/status_bar_padding_start"
     android:paddingEnd="@dimen/status_bar_padding_end" >
 
+    <LinearLayout
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:orientation="horizontal"
+        android:gravity="center_vertical|start" >
+
     <com.android.systemui.statusbar.policy.Clock
         android:id="@+id/clock"
         android:layout_width="wrap_content"
@@ -38,13 +45,21 @@
         android:singleLine="true"
         android:textAppearance="@style/TextAppearance.StatusBar.Clock"
         systemui:showDark="false" />
+    </LinearLayout>
 
     <android.widget.Space
         android:id="@+id/space"
         android:layout_width="0dp"
         android:layout_height="match_parent"
+        android:layout_gravity="center_vertical|center_horizontal"
+        android:visibility="gone" />
+
+    <LinearLayout
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
         android:layout_weight="1"
-        android:gravity="center_vertical|center_horizontal" />
+        android:orientation="horizontal"
+        android:gravity="center_vertical|end">
 
     <include layout="@layout/ongoing_privacy_chip" />
 
@@ -53,4 +68,5 @@
         android:layout_height="match_parent"
         android:layout_width="wrap_content"
         android:gravity="center_vertical|end" />
+    </LinearLayout>
 </LinearLayout>
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierText.java b/packages/SystemUI/src/com/android/keyguard/CarrierText.java
index a0a3687..b7d5197 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierText.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierText.java
@@ -16,10 +16,6 @@
 
 package com.android.keyguard;
 
-import java.util.List;
-import java.util.Locale;
-import java.util.Objects;
-
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -28,6 +24,7 @@
 import android.net.wifi.WifiManager;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionInfo;
+import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.text.method.SingleLineTransformationMethod;
 import android.util.AttributeSet;
@@ -40,7 +37,9 @@
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.settingslib.WirelessUtils;
 
-import android.telephony.TelephonyManager;
+import java.util.List;
+import java.util.Locale;
+import java.util.Objects;
 
 public class CarrierText extends TextView {
     private static final boolean DEBUG = KeyguardConstants.DEBUG;
diff --git a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
index ac8f024..210b82d 100644
--- a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
+++ b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
@@ -16,7 +16,6 @@
 
 package com.android.keyguard;
 
-import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.app.ActivityTaskManager;
 import android.content.Context;
@@ -37,8 +36,8 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.telephony.IccCardConstants.State;
-import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.util.EmergencyAffordanceManager;
+import com.android.internal.widget.LockPatternUtils;
 import com.android.systemui.util.EmergencyDialerConstants;
 
 /**
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java b/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java
index 63b7ae2..c2bbfbf 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java
@@ -22,19 +22,15 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.os.Handler;
-import android.os.HandlerThread;
 import android.os.UserHandle;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.euicc.EuiccManager;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.View;
 import android.view.WindowManager;
 import android.widget.Button;
-import android.telephony.SubscriptionManager;
-import android.telephony.SubscriptionInfo;
-import android.telephony.euicc.EuiccManager;
-import android.util.Log;
-
-import java.lang.ref.WeakReference;
 
 /***
  * This button is used by the device with embedded SIM card to disable current carrier to unlock
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
index 34df15f..cf22286 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
@@ -19,8 +19,8 @@
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.content.Context;
-import android.content.res.Resources;
 import android.content.res.ColorStateList;
+import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.media.AudioManager;
 import android.os.SystemClock;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
index f400f60..3cc18dd 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -23,8 +23,6 @@
 import android.view.MotionEvent;
 import android.view.View;
 
-import com.android.internal.annotations.VisibleForTesting;
-
 /**
  * A Pin based Keyguard input view
  */
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index b8df3c06..7af27f2 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -21,7 +21,6 @@
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.os.UserHandle;
-import androidx.annotation.VisibleForTesting;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Slog;
@@ -31,6 +30,8 @@
 import android.view.WindowManager;
 import android.widget.FrameLayout;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
index 1a09364..272b3bd 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
@@ -15,9 +15,10 @@
  */
 package com.android.keyguard;
 
-import com.android.internal.widget.LockPatternUtils;
 import android.content.res.ColorStateList;
 
+import com.android.internal.widget.LockPatternUtils;
+
 public interface KeyguardSecurityView {
     static public final int SCREEN_ON = 1;
     static public final int VIEW_REVEALED = 2;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
index 74e2a68..e6a0250 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
@@ -18,8 +18,8 @@
 
 import android.annotation.NonNull;
 import android.content.Context;
-import android.content.res.TypedArray;
 import android.content.res.ColorStateList;
+import android.content.res.TypedArray;
 import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -28,18 +28,15 @@
 import android.view.ViewDebug;
 import android.view.ViewGroup;
 import android.view.ViewHierarchyEncoder;
-import android.view.WindowManager;
 import android.widget.FrameLayout;
 import android.widget.ViewFlipper;
 
 import com.android.internal.widget.LockPatternUtils;
 
-import java.lang.Override;
-
 /**
  * Subclass of the current view flipper that allows us to overload dispatchTouchEvent() so
- * we can emulate {@link WindowManager.LayoutParams#FLAG_SLIPPERY} within a view hierarchy.
- *
+ * we can emulate {@link android.view.WindowManager.LayoutParams#FLAG_SLIPPERY} within a view
+ * hierarchy.
  */
 public class KeyguardSecurityViewFlipper extends ViewFlipper implements KeyguardSecurityView {
     private static final String TAG = "KeyguardSecurityViewFlipper";
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
index 42c7a56..6528d8c 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
@@ -16,32 +16,31 @@
 
 package com.android.keyguard;
 
-import com.android.internal.telephony.ITelephony;
-import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.telephony.IccCardConstants.State;
-import com.android.internal.telephony.PhoneConstants;
-
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.content.res.Configuration;
-import android.content.res.Resources;
 import android.app.AlertDialog;
 import android.app.AlertDialog.Builder;
 import android.app.Dialog;
 import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.graphics.Color;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
-import android.telephony.euicc.EuiccManager;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.View;
 import android.view.WindowManager;
 import android.widget.ImageView;
 
+import com.android.internal.telephony.ITelephony;
+import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.telephony.IccCardConstants.State;
+import com.android.internal.telephony.PhoneConstants;
+
 /**
  * Displays a PIN pad for unlocking.
  */
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
index 1b61568..1157f86 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
@@ -16,20 +16,19 @@
 
 package com.android.keyguard;
 
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.content.res.Resources;
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
 import android.graphics.Color;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
-import android.telephony.euicc.EuiccManager;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.View;
@@ -38,8 +37,8 @@
 
 import com.android.internal.telephony.ITelephony;
 import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.IccCardConstants.State;
+import com.android.internal.telephony.PhoneConstants;
 
 
 /**
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index 79966f7..c41ef0e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -243,46 +243,6 @@
         }
     }
 
-    /**
-     * Breaks a string in 2 lines where both have similar character count
-     * but first line is always longer.
-     *
-     * @param charSequence Original text.
-     * @return Optimal string.
-     */
-    private static CharSequence findBestLineBreak(CharSequence charSequence) {
-        if (TextUtils.isEmpty(charSequence)) {
-            return charSequence;
-        }
-
-        String source = charSequence.toString();
-        // Ignore if there is only 1 word,
-        // or if line breaks were manually set.
-        if (source.contains("\n") || !source.contains(" ")) {
-            return source;
-        }
-
-        final String[] words = source.split(" ");
-        final StringBuilder optimalString = new StringBuilder(source.length());
-        int current = 0;
-        while (optimalString.length() < source.length() - optimalString.length()) {
-            optimalString.append(words[current]);
-            if (current < words.length - 1) {
-                optimalString.append(" ");
-            }
-            current++;
-        }
-        optimalString.append("\n");
-        for (int i = current; i < words.length; i++) {
-            optimalString.append(words[i]);
-            if (current < words.length - 1) {
-                optimalString.append(" ");
-            }
-        }
-
-        return optimalString.toString();
-    }
-
     public void setDarkAmount(float darkAmount) {
         mDarkAmount = darkAmount;
         mRow.setDarkAmount(darkAmount);
diff --git a/packages/SystemUI/src/com/android/systemui/AutoReinflateContainer.java b/packages/SystemUI/src/com/android/systemui/AutoReinflateContainer.java
index bbc8ecd..5ed9eaa 100644
--- a/packages/SystemUI/src/com/android/systemui/AutoReinflateContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/AutoReinflateContainer.java
@@ -18,7 +18,6 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
-import android.os.LocaleList;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index f6fec54..053ea67 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -19,7 +19,10 @@
 import static android.app.StatusBarManager.DISABLE_NONE;
 import static android.provider.Settings.System.SHOW_BATTERY_PERCENT;
 
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
 import android.animation.ArgbEvaluator;
+import android.annotation.IntDef;
 import android.app.ActivityManager;
 import android.content.Context;
 import android.content.res.Resources;
@@ -55,15 +58,23 @@
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerService.Tunable;
 import com.android.systemui.util.Utils.DisableStateTracker;
-import com.android.systemui.R;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.lang.annotation.Retention;
 import java.text.NumberFormat;
 
 public class BatteryMeterView extends LinearLayout implements
         BatteryStateChangeCallback, Tunable, DarkReceiver, ConfigurationListener {
 
+
+    @Retention(SOURCE)
+    @IntDef({MODE_DEFAULT, MODE_ON, MODE_OFF})
+    public @interface BatteryPercentMode {}
+    public static final int MODE_DEFAULT = 0;
+    public static final int MODE_ON = 1;
+    public static final int MODE_OFF = 2;
+
     private final BatteryMeterDrawableBase mDrawable;
     private final String mSlotBattery;
     private final ImageView mBatteryIconView;
@@ -74,6 +85,7 @@
     private SettingObserver mSettingObserver;
     private int mTextColor;
     private int mLevel;
+    private int mShowPercentMode = MODE_DEFAULT;
     private boolean mForceShowPercent;
     private boolean mShowPercentAvailable;
 
@@ -154,7 +166,19 @@
     }
 
     public void setForceShowPercent(boolean show) {
-        mForceShowPercent = show;
+        setPercentShowMode(show ? MODE_ON : MODE_DEFAULT);
+    }
+
+    /**
+     * Force a particular mode of showing percent
+     *
+     * 0 - No preference
+     * 1 - Force on
+     * 2 - Force off
+     * @param mode desired mode (none, on, off)
+     */
+    public void setPercentShowMode(@BatteryPercentMode int mode) {
+        mShowPercentMode = mode;
         updateShowPercent();
     }
 
@@ -273,7 +297,8 @@
                 .getIntForUser(getContext().getContentResolver(),
                 SHOW_BATTERY_PERCENT, 0, mUser);
 
-        if ((mShowPercentAvailable && systemSetting) || mForceShowPercent) {
+        if ((mShowPercentAvailable && systemSetting && mShowPercentMode != MODE_OFF)
+                || mShowPercentMode == MODE_ON) {
             if (!showing) {
                 mBatteryPercentView = loadPercentView();
                 if (mTextColor != 0) mBatteryPercentView.setTextColor(mTextColor);
diff --git a/packages/SystemUI/src/com/android/systemui/DejankUtils.java b/packages/SystemUI/src/com/android/systemui/DejankUtils.java
index 4ee3bd3..bec8820 100644
--- a/packages/SystemUI/src/com/android/systemui/DejankUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/DejankUtils.java
@@ -16,12 +16,12 @@
 
 package com.android.systemui;
 
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.util.Assert;
-
 import android.os.Handler;
 import android.view.Choreographer;
 
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.util.Assert;
+
 import java.util.ArrayList;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index fbcf068..5e6d272 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -296,7 +296,7 @@
                 new WakefulnessLifecycle());
 
         mProviders.put(FragmentService.class, () ->
-                new FragmentService(mContext));
+                new FragmentService());
 
         mProviders.put(ExtensionController.class, () ->
                 new ExtensionControllerImpl(mContext));
diff --git a/packages/SystemUI/src/com/android/systemui/DockedStackExistsListener.java b/packages/SystemUI/src/com/android/systemui/DockedStackExistsListener.java
index 81e4db3..5c0df17 100644
--- a/packages/SystemUI/src/com/android/systemui/DockedStackExistsListener.java
+++ b/packages/SystemUI/src/com/android/systemui/DockedStackExistsListener.java
@@ -14,7 +14,6 @@
 
 package com.android.systemui;
 
-import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Log;
 import android.view.IDockedStackListener;
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index f5ad747..ecf4c0a 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -32,9 +32,9 @@
 import android.view.ViewConfiguration;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.statusbar.FlingAnimationUtils;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.ExpandableView;
-import com.android.systemui.statusbar.FlingAnimationUtils;
 import com.android.systemui.statusbar.policy.ScrollAdapter;
 
 public class ExpandHelper implements Gefingerpoken {
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java
index 1fa925e..bab472c 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java
@@ -23,7 +23,6 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Log;
-import android.util.Slog;
 import android.util.SparseArray;
 
 import com.android.internal.messages.nano.SystemMessageProto;
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServicesDialog.java b/packages/SystemUI/src/com/android/systemui/ForegroundServicesDialog.java
index 9d286cf..cb9523f 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServicesDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServicesDialog.java
@@ -42,8 +42,6 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
 
-import com.android.systemui.R;
-
 import java.util.ArrayList;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
index b1463a3..16e869e 100644
--- a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
@@ -14,6 +14,10 @@
 
 package com.android.systemui;
 
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_NONE;
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
+
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
@@ -33,10 +37,6 @@
 import com.android.systemui.tuner.TunerService.Tunable;
 import com.android.systemui.util.leak.RotationUtils;
 
-import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
-import static com.android.systemui.util.leak.RotationUtils.ROTATION_NONE;
-import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
-
 public class HardwareUiLayout extends LinearLayout implements Tunable {
 
     private static final String EDGE_BLEED = "sysui_hwui_edge_bleed";
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index d8eb965..1d2d7fa 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -20,6 +20,7 @@
 import android.content.ComponentCallbacks2;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.RecordingCanvas;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.Region.Op;
@@ -30,7 +31,6 @@
 import android.util.Log;
 import android.view.Display;
 import android.view.DisplayInfo;
-import android.graphics.RecordingCanvas;
 import android.view.Surface;
 import android.view.SurfaceHolder;
 import android.view.WindowManager;
diff --git a/packages/SystemUI/src/com/android/systemui/LatencyTester.java b/packages/SystemUI/src/com/android/systemui/LatencyTester.java
index 1e458fa..50f1b44 100644
--- a/packages/SystemUI/src/com/android/systemui/LatencyTester.java
+++ b/packages/SystemUI/src/com/android/systemui/LatencyTester.java
@@ -16,17 +16,17 @@
 
 package com.android.systemui;
 
-import android.hardware.biometrics.BiometricSourceType;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.hardware.biometrics.BiometricSourceType;
 import android.os.Build;
 import android.os.PowerManager;
 import android.os.SystemClock;
 
-import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.internal.util.LatencyTracker;
+import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.statusbar.phone.BiometricUnlockController;
 import com.android.systemui.statusbar.phone.StatusBar;
 
diff --git a/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java b/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java
index f6ad626..f9617ca 100644
--- a/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java
@@ -21,8 +21,8 @@
 import android.view.View;
 
 import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.plugins.ViewProvider;
+import com.android.systemui.shared.plugins.PluginManager;
 
 /**
  * Define an interface or abstract class as follows that includes the
diff --git a/packages/SystemUI/src/com/android/systemui/RegionInterceptingFrameLayout.java b/packages/SystemUI/src/com/android/systemui/RegionInterceptingFrameLayout.java
index 6dc2d67..8351bbf 100644
--- a/packages/SystemUI/src/com/android/systemui/RegionInterceptingFrameLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/RegionInterceptingFrameLayout.java
@@ -21,7 +21,6 @@
 import android.graphics.Region.Op;
 import android.util.AttributeSet;
 import android.view.View;
-import android.view.ViewTreeObserver;
 import android.view.ViewTreeObserver.InternalInsetsInfo;
 import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
 import android.widget.FrameLayout;
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index c844496..1dd231c 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -63,6 +63,8 @@
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.internal.util.Preconditions;
 import com.android.systemui.RegionInterceptingFrameLayout.RegionInterceptableView;
 import com.android.systemui.fragments.FragmentHostManager;
@@ -79,8 +81,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import androidx.annotation.VisibleForTesting;
-
 /**
  * An overlay that draws screen decorations in software (e.g for rounded corners or display cutout)
  * for antialiasing and emulation purposes.
diff --git a/packages/SystemUI/src/com/android/systemui/SysUIToast.java b/packages/SystemUI/src/com/android/systemui/SysUIToast.java
index 43b918d..8bcf057 100644
--- a/packages/SystemUI/src/com/android/systemui/SysUIToast.java
+++ b/packages/SystemUI/src/com/android/systemui/SysUIToast.java
@@ -15,11 +15,12 @@
  */
 package com.android.systemui;
 
+import static android.widget.Toast.Duration;
+
 import android.annotation.StringRes;
 import android.content.Context;
 import android.view.WindowManager;
 import android.widget.Toast;
-import static android.widget.Toast.Duration;
 
 public class SysUIToast {
 
diff --git a/packages/SystemUI/src/com/android/systemui/SystemBars.java b/packages/SystemUI/src/com/android/systemui/SystemBars.java
index b5093b3..6edc23b 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemBars.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemBars.java
@@ -14,13 +14,8 @@
 
 package com.android.systemui;
 
-import android.content.res.Configuration;
-import android.provider.Settings;
 import android.util.Log;
 
-import com.android.systemui.R;
-import com.android.systemui.SystemUI;
-
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index c4bf27b..2dd362e 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -22,9 +22,9 @@
 import android.util.Log;
 import android.view.ViewGroup;
 
+import com.android.internal.colorextraction.ColorExtractor.GradientColors;
 import com.android.internal.util.function.TriConsumer;
 import com.android.internal.widget.LockPatternUtils;
-import com.android.internal.colorextraction.ColorExtractor.GradientColors;
 import com.android.keyguard.ViewMediatorCallback;
 import com.android.systemui.Dependency.DependencyProvider;
 import com.android.systemui.classifier.FalsingManager;
@@ -32,20 +32,20 @@
 import com.android.systemui.qs.QSTileHost;
 import com.android.systemui.statusbar.AmbientPulseManager;
 import com.android.systemui.statusbar.KeyguardIndicationController;
-import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
-import com.android.systemui.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
 import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.NotificationViewHierarchyManager;
 import com.android.systemui.statusbar.ScrimView;
 import com.android.systemui.statusbar.SmartReplyController;
+import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.statusbar.phone.KeyguardBouncer;
 import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index 8e29841..ac108be 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -24,13 +24,13 @@
 import android.os.SystemProperties;
 import android.util.Slog;
 
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
 import com.android.internal.os.BinderInternal;
 import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.shared.plugins.PluginManagerImpl;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
 public class SystemUIService extends Service {
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java b/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java
index 4bd095d..79d4f8d 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java
@@ -31,7 +31,6 @@
 import android.view.View;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
-import android.view.animation.AnimationUtils;
 
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
index 67bc8b6..c0047c0 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
@@ -140,7 +140,7 @@
 
     @Override
     public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver, int type,
-            boolean requireConfirmation) {
+            boolean requireConfirmation, int userId) {
         if (DEBUG) Log.d(TAG, "showBiometricDialog, type: " + type);
         // Remove these messages as they are part of the previous client
         mHandler.removeMessages(MSG_BIOMETRIC_ERROR);
@@ -151,6 +151,7 @@
         args.arg2 = receiver;
         args.argi1 = type;
         args.arg3 = requireConfirmation;
+        args.argi2 = userId;
         mHandler.obtainMessage(MSG_SHOW_DIALOG, args).sendToTarget();
     }
 
@@ -194,7 +195,8 @@
         }
         mReceiver = (IBiometricPromptReceiver) args.arg2;
         mCurrentDialog.setBundle((Bundle)args.arg1);
-        mCurrentDialog.setRequireConfirmation((boolean)args.arg3);
+        mCurrentDialog.setRequireConfirmation((boolean) args.arg3);
+        mCurrentDialog.setUserId(args.argi2);
         mCurrentDialog.setSkipIntro(skipAnimation);
         mWindowManager.addView(mCurrentDialog, mCurrentDialog.getLayoutParams());
         mDialogShowing = true;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
index 1faae9d..38427ad 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
@@ -16,15 +16,19 @@
 
 package com.android.systemui.biometrics;
 
+import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
 import android.hardware.biometrics.BiometricPrompt;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
+import android.os.UserManager;
 import android.text.TextUtils;
 import android.util.DisplayMetrics;
 import android.util.Log;
@@ -64,6 +68,8 @@
     private final IBinder mWindowToken = new Binder();
     private final Interpolator mLinearOutSlowIn;
     private final WindowManager mWindowManager;
+    private final UserManager mUserManager;
+    private final DevicePolicyManager mDevicePolicyManager;
     private final float mAnimationTranslationOffset;
     private final int mErrorColor;
     private final int mTextColor;
@@ -79,6 +85,7 @@
     private boolean mWasForceRemoved;
     private boolean mSkipIntro;
     protected boolean mRequireConfirmation;
+    private int mUserId; // used to determine if we should show work background
 
     protected abstract void updateIcon(int lastState, int newState);
     protected abstract int getHintStringResourceId();
@@ -121,7 +128,9 @@
         super(context);
         mCallback = callback;
         mLinearOutSlowIn = Interpolators.LINEAR_OUT_SLOW_IN;
-        mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+        mWindowManager = mContext.getSystemService(WindowManager.class);
+        mUserManager = mContext.getSystemService(UserManager.class);
+        mDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class);
         mAnimationTranslationOffset = getResources()
                 .getDimension(R.dimen.biometric_dialog_animation_translation_offset);
 
@@ -199,6 +208,18 @@
         final TextView description = mLayout.findViewById(R.id.description);
         final Button negative = mLayout.findViewById(R.id.button2);
         final Button positive = mLayout.findViewById(R.id.button1);
+        final ImageView backgroundView = mLayout.findViewById(R.id.background);
+
+        if (mUserManager.isManagedProfile(mUserId)) {
+            final Drawable image = getResources().getDrawable(R.drawable.work_challenge_background,
+                    mContext.getTheme());
+            image.setColorFilter(mDevicePolicyManager.getOrganizationColorForUser(mUserId),
+                    PorterDuff.Mode.DARKEN);
+            backgroundView.setImageDrawable(image);
+        } else {
+            backgroundView.setImageDrawable(null);
+            backgroundView.setBackgroundColor(R.color.biometric_dialog_dim_color);
+        }
 
         if (RotationUtils.getRotation(mContext) != RotationUtils.ROTATION_NONE) {
             mDialog.getLayoutParams().width = (int) mDialogWidth;
@@ -329,6 +350,10 @@
         positive.setVisibility(View.VISIBLE);
     }
 
+    public void setUserId(int userId) {
+        mUserId = userId;
+    }
+
     public ViewGroup getLayout() {
         return mLayout;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
index 96af08b..50fefe9 100644
--- a/packages/SystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
@@ -17,9 +17,9 @@
 
 import android.content.Context;
 
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 
 public class CarNotificationEntryManager extends NotificationEntryManager {
     public CarNotificationEntryManager(Context context) {
diff --git a/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java
index e4b2e07..09c000b 100644
--- a/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java
@@ -23,10 +23,10 @@
 import com.android.systemui.Dependency.DependencyProvider;
 import com.android.systemui.SystemUIFactory;
 import com.android.systemui.statusbar.NotificationMediaManager;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.car.CarFacetButtonController;
 import com.android.systemui.statusbar.car.CarStatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.car.hvac.HvacController;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/chooser/ChooserActivity.java b/packages/SystemUI/src/com/android/systemui/chooser/ChooserActivity.java
index 158deb4..28a3808 100644
--- a/packages/SystemUI/src/com/android/systemui/chooser/ChooserActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/chooser/ChooserActivity.java
@@ -17,16 +17,7 @@
 package com.android.systemui.chooser;
 
 import android.app.Activity;
-import android.app.ActivityManager;
-import android.content.Intent;
 import android.os.Bundle;
-import android.os.IBinder;
-import android.util.Log;
-
-import com.android.systemui.R;
-
-import java.lang.Thread;
-import java.util.ArrayList;
 
 /**
  * Activity for selecting which application ought to handle an ACTION_SEND intent.
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java
index cdf4ba7..6d13973 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java
@@ -18,7 +18,6 @@
 
 import android.os.Build;
 import android.os.SystemProperties;
-import android.util.Log;
 import android.view.MotionEvent;
 
 import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java
index 71ddba5..cb7c998 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java
@@ -23,8 +23,6 @@
 import android.util.Log;
 
 import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.text.SimpleDateFormat;
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
index 592a275..577d57a 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
@@ -24,13 +24,11 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.DisplayMetrics;
-import android.util.Log;
 import android.view.MotionEvent;
 
 import com.android.systemui.R;
 
 import java.util.ArrayDeque;
-import java.util.ArrayList;
 
 /**
  * An classifier trying to determine whether it is a human interacting with the phone or not.
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index e2047bf..d93ed178 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -22,7 +22,6 @@
 import android.hardware.Sensor;
 import android.hardware.SensorManager;
 import android.os.Handler;
-import android.os.PowerManager;
 
 import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.keyguard.KeyguardUpdateMonitor;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeReceiver.java b/packages/SystemUI/src/com/android/systemui/doze/DozeReceiver.java
index 30dfd36..4a2e06c 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeReceiver.java
@@ -22,11 +22,6 @@
 public interface DozeReceiver {
 
     /**
-     * If device enters or leaves doze mode
-     */
-    void setDozing(boolean dozing);
-
-    /**
      * Invoked every time a minute is elapsed in doze mode
      */
     void dozeTimeTick();
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
index ce84b84..01a2345 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
@@ -33,8 +33,6 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.Dependency;
 
-import java.util.concurrent.atomic.AtomicBoolean;
-
 /**
  * Controls the screen brightness when dozing.
  */
@@ -66,7 +64,6 @@
      * --ei brightness_bucket 1}
      */
     private int mDebugBrightnessBucket = -1;
-    private AtomicBoolean mIsDestroyed = new AtomicBoolean();
 
     @VisibleForTesting
     public DozeScreenBrightness(Context context, DozeMachine.Service service,
@@ -89,9 +86,7 @@
             Dependency.get(Dependency.BG_HANDLER).post(()-> {
                 IntentFilter filter = new IntentFilter();
                 filter.addAction(ACTION_AOD_BRIGHTNESS);
-                if (!mIsDestroyed.get()) {
-                    mContext.registerReceiverAsUser(this, UserHandle.ALL, filter, null, handler);
-                }
+                mContext.registerReceiverAsUser(this, UserHandle.ALL, filter, null, handler);
             });
         }
     }
@@ -129,10 +124,11 @@
     }
 
     private void onDestroy() {
-        mIsDestroyed.set(true);
         setLightSensorEnabled(false);
         if (mDebuggable) {
-            mContext.unregisterReceiver(this);
+            Dependency.get(Dependency.BG_HANDLER).post(()-> {
+                mContext.unregisterReceiver(this);
+            });
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java
index 4fc2d9b..25c2c39 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java
@@ -16,9 +16,10 @@
 
 package com.android.systemui.doze;
 
-import androidx.annotation.VisibleForTesting;
 import android.view.Display;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.systemui.statusbar.phone.DozeParameters;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapter.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapter.java
index 3013b96..a0c490951 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapter.java
@@ -16,9 +16,10 @@
 
 package com.android.systemui.doze;
 
-import androidx.annotation.VisibleForTesting;
 import android.view.Display;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.systemui.statusbar.phone.DozeParameters;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java
index 47f86fe..9a5a5b8 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java
@@ -23,8 +23,6 @@
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.systemui.statusbar.phone.DozeParameters;
 
 import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java b/packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java
index f06ea45..84b91bc 100644
--- a/packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java
@@ -19,7 +19,6 @@
 import android.app.Activity;
 import android.os.Bundle;
 import android.view.View;
-import android.view.ViewGroup;
 
 import com.android.systemui.R;
 
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
index 0ed1cd1..60e39b2 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
@@ -28,11 +28,12 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Parcelable;
-import androidx.annotation.NonNull;
 import android.util.ArrayMap;
 import android.view.LayoutInflater;
 import android.view.View;
 
+import androidx.annotation.NonNull;
+
 import com.android.settingslib.applications.InterestingConfigChanges;
 import com.android.systemui.Dependency;
 import com.android.systemui.plugins.Plugin;
@@ -59,11 +60,11 @@
     private FragmentController mFragments;
     private FragmentLifecycleCallbacks mLifecycleCallbacks;
 
-    FragmentHostManager(Context context, FragmentService manager, View rootView) {
-        mContext = context;
+    FragmentHostManager(FragmentService manager, View rootView) {
+        mContext = rootView.getContext();
         mManager = manager;
         mRootView = rootView;
-        mConfigChanges.applyNewConfig(context.getResources());
+        mConfigChanges.applyNewConfig(mContext.getResources());
         createFragmentHost(null);
     }
 
@@ -203,6 +204,10 @@
         }
     }
 
+    public static void removeAndDestroy(View view) {
+        Dependency.get(FragmentService.class).removeAndDestroy(view);
+    }
+
     class HostCallbacks extends FragmentHostCallback<FragmentHostManager> {
         public HostCallbacks() {
             super(mContext, FragmentHostManager.this.mHandler, 0);
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
index f9bf4f5..bf7d629 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
@@ -14,18 +14,13 @@
 
 package com.android.systemui.fragments;
 
-import android.content.Context;
 import android.content.res.Configuration;
-import android.os.Bundle;
 import android.os.Handler;
 import android.util.ArrayMap;
-import android.util.Log;
 import android.view.View;
 
 import com.android.systemui.ConfigurationChangedReceiver;
 import com.android.systemui.Dumpable;
-import com.android.systemui.SystemUI;
-import com.android.systemui.SystemUIApplication;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -40,11 +35,6 @@
 
     private final ArrayMap<View, FragmentHostState> mHosts = new ArrayMap<>();
     private final Handler mHandler = new Handler();
-    private final Context mContext;
-
-    public FragmentService(Context context) {
-        mContext = context;
-    }
 
     public FragmentHostManager getFragmentHostManager(View view) {
         View root = view.getRootView();
@@ -56,6 +46,13 @@
         return state.getFragmentHostManager();
     }
 
+    public void removeAndDestroy(View view) {
+        final FragmentHostState state = mHosts.remove(view.getRootView());
+        if (state != null) {
+            state.mFragmentHostManager.destroy();
+        }
+    }
+
     public void destroyAll() {
         for (FragmentHostState state : mHosts.values()) {
             state.mFragmentHostManager.destroy();
@@ -84,7 +81,7 @@
 
         public FragmentHostState(View view) {
             mView = view;
-            mFragmentHostManager = new FragmentHostManager(mContext, FragmentService.this, mView);
+            mFragmentHostManager = new FragmentHostManager(FragmentService.this, mView);
         }
 
         public void sendConfigurationChange(Configuration newConfig) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
index e0657c9..7d52a9a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
@@ -43,12 +43,12 @@
 import android.widget.Toast;
 
 import com.android.settingslib.bluetooth.BluetoothCallback;
+import com.android.settingslib.bluetooth.BluetoothUtils;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
 import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
-import com.android.settingslib.bluetooth.BluetoothUtils;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java b/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java
index d833c16..7bec5c0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java
@@ -19,6 +19,7 @@
 import com.android.internal.policy.IKeyguardDismissCallback;
 import com.android.systemui.Dependency;
 import com.android.systemui.UiOffloadThread;
+
 import java.util.ArrayList;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java
index 4c98c08..b3481c5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java
@@ -19,8 +19,6 @@
 import android.os.Handler;
 import android.os.Message;
 
-import com.android.internal.policy.IKeyguardDrawnCallback;
-
 /**
  * Dispatches the lifecycles keyguard gets from WindowManager on the main thread.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 22b41a4..81247cd 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.keyguard;
 
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
 import android.app.Service;
 import android.content.Intent;
 import android.os.Binder;
@@ -34,8 +36,6 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.SystemUIApplication;
 
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-
 public class KeyguardService extends Service {
     static final String TAG = "KeyguardService";
     static final String PERMISSION = android.Manifest.permission.CONTROL_KEYGUARD;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index fe1b356..3b9110d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1940,11 +1940,6 @@
                     mContext.getSystemService(Context.STATUS_BAR_SERVICE);
         }
 
-        // TODO(b/113914868): investigation log for disappearing home button
-        Log.d(TAG, "adjustStatusBarLocked (b/113914868): mShowing=" + mShowing
-                + " mStatusBarManager=" + mStatusBarManager + " mOccluded="
-                + mOccluded + " isSecure=" + isSecure() + " force=" + forceHideHomeRecentsButtons);
-
         if (mStatusBarManager == null) {
             Log.w(TAG, "Could not get status bar manager");
         } else {
@@ -1961,6 +1956,12 @@
                         +  " --> flags=0x" + Integer.toHexString(flags));
             }
 
+            // TODO(b/113914868): investigation log for disappearing home button
+            Log.d(TAG, "adjustStatusBarLocked (b/113914868): flags=" + flags
+                    + "mShowing=" + mShowing + " mStatusBarManager=" + mStatusBarManager
+                    + " mOccluded=" + mOccluded + " isSecure=" + isSecure()
+                    + " force=" + forceHideHomeRecentsButtons);
+
             mStatusBarManager.disable(flags);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java
index 74f7706..6498b91 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java
@@ -28,6 +28,7 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.Log;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.TaskStackChangeListener;
diff --git a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
index ab612dd..ddd9cbf 100644
--- a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
@@ -33,10 +33,8 @@
 import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.provider.MediaStore;
-import android.provider.MediaStore.Audio.AudioColumns;
 import android.util.Log;
 
-import com.android.internal.util.Preconditions;
 import com.android.systemui.SystemUI;
 
 import java.io.FileDescriptor;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipUI.java b/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
index 70b581a..7792e17 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
@@ -23,8 +23,10 @@
 import android.content.res.Configuration;
 import android.os.UserHandle;
 import android.os.UserManager;
+
 import com.android.systemui.SystemUI;
 import com.android.systemui.statusbar.CommandQueue;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
index 9ce2606..8615e43 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
@@ -27,6 +27,7 @@
 import android.view.WindowManager;
 import android.view.WindowManager.LayoutParams;
 import android.widget.FrameLayout;
+
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.shared.system.WindowManagerWrapper;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index 08208e5..8c3f436 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -35,6 +35,7 @@
 import android.view.IPinnedStackListener;
 import android.view.IWindowManager;
 import android.view.WindowManagerGlobal;
+
 import com.android.systemui.Dependency;
 import com.android.systemui.UiOffloadThread;
 import com.android.systemui.pip.BasePipManager;
@@ -42,6 +43,7 @@
 import com.android.systemui.shared.system.InputConsumerController;
 import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.shared.system.WindowManagerWrapper;
+
 import java.io.PrintWriter;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index b746c19..e447def 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -23,15 +23,14 @@
 import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_ACTIONS;
 import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_ALLOW_TIMEOUT;
 import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_CONTROLLER_MESSENGER;
-import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_WILL_RESIZE_MENU;
 import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_DISMISS_FRACTION;
-import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_MOVEMENT_BOUNDS;
 import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_MENU_STATE;
+import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_MOVEMENT_BOUNDS;
 import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_STACK_BOUNDS;
-
-import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_NONE;
+import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_WILL_RESIZE_MENU;
 import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_CLOSE;
 import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_FULL;
+import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_NONE;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
index 56b8324..46d53e4 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
@@ -37,8 +37,10 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.util.Log;
+
 import com.android.systemui.pip.phone.PipMediaController.ActionListener;
 import com.android.systemui.shared.system.InputConsumerController;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
index ce7da79..3858356 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
@@ -18,6 +18,7 @@
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+
 import static com.android.systemui.Interpolators.FAST_OUT_LINEAR_IN;
 import static com.android.systemui.Interpolators.FAST_OUT_SLOW_IN;
 import static com.android.systemui.Interpolators.LINEAR_OUT_SLOW_IN;
@@ -42,11 +43,13 @@
 import android.os.RemoteException;
 import android.util.Log;
 import android.view.animation.Interpolator;
+
 import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
 import com.android.internal.os.SomeArgs;
 import com.android.internal.policy.PipSnapAlgorithm;
 import com.android.systemui.shared.system.WindowManagerWrapper;
 import com.android.systemui.statusbar.FlingAnimationUtils;
+
 import java.io.PrintWriter;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
index b9369d3..9aa21f8 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
@@ -18,7 +18,6 @@
 
 import android.graphics.PointF;
 import android.os.Handler;
-import android.os.SystemClock;
 import android.util.Log;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java
index 10206d4..a40b72b 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.pip.tv;
 
-import android.app.ActivityManager;
 import android.app.PendingIntent.CanceledException;
 import android.app.RemoteAction;
 import android.content.Context;
@@ -24,20 +23,15 @@
 import android.media.session.MediaController;
 import android.media.session.PlaybackState;
 import android.os.Handler;
-import android.os.RemoteException;
+import android.util.AttributeSet;
 import android.util.Log;
-import android.view.View;
 import android.view.Gravity;
 import android.view.LayoutInflater;
-import android.widget.ImageView;
+import android.view.View;
 import android.widget.LinearLayout;
-import android.util.AttributeSet;
 
 import com.android.systemui.R;
 
-import static android.media.session.PlaybackState.ACTION_PAUSE;
-import static android.media.session.PlaybackState.ACTION_PLAY;
-
 import java.util.ArrayList;
 import java.util.List;
 
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index e17e0bc..ca3cdf4 100755
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -49,6 +49,7 @@
 import android.view.IPinnedStackListener;
 import android.view.IWindowManager;
 import android.view.WindowManagerGlobal;
+
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.UiOffloadThread;
@@ -56,7 +57,7 @@
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.shared.system.WindowManagerWrapper;
-import java.io.PrintWriter;
+
 import java.util.ArrayList;
 import java.util.List;
 
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipMenuActivity.java
index e437eff..3a5fa22 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipMenuActivity.java
@@ -22,7 +22,6 @@
 import android.content.Intent;
 import android.content.pm.ParceledListSlice;
 import android.os.Bundle;
-import android.view.View;
 
 import com.android.systemui.R;
 
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java
index ac41b75..89ecc6a 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java
@@ -26,17 +26,15 @@
 import android.content.pm.ParceledListSlice;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
-import android.graphics.drawable.Icon;
 import android.media.MediaMetadata;
 import android.media.session.MediaController;
 import android.media.session.PlaybackState;
 import android.text.TextUtils;
 import android.util.Log;
-import android.view.View;
 
-import com.android.systemui.util.NotificationChannels;
-import com.android.systemui.R;
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.systemui.R;
+import com.android.systemui.util.NotificationChannels;
 
 /**
  * A notification that informs users that PIP is running and also provides PIP controls.
diff --git a/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java b/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java
index 5686d80..3f24176 100644
--- a/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java
@@ -1,7 +1,5 @@
 package com.android.systemui.power;
 
-import android.util.Log;
-
 public class EnhancedEstimatesImpl implements EnhancedEstimates {
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index 21eab59..b722f9f 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -41,6 +41,7 @@
 import android.util.Log;
 import android.util.Slog;
 import android.view.View;
+
 import androidx.annotation.VisibleForTesting;
 
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
index 3953139d..fc1baef 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
@@ -14,21 +14,14 @@
 
 package com.android.systemui.privacy
 
-import android.app.ActivityManager
-import android.app.AppOpsManager
 import android.content.Context
 import android.graphics.Color
-import android.os.UserHandle
-import android.os.UserManager
 import android.util.AttributeSet
 import android.view.ViewGroup
 import android.widget.ImageView
 import android.widget.LinearLayout
 import android.widget.TextView
-import com.android.systemui.Dependency
 import com.android.systemui.R
-import com.android.systemui.appops.AppOpItem
-import com.android.systemui.appops.AppOpsController
 
 class OngoingPrivacyChip @JvmOverloads constructor(
     context: Context,
@@ -37,37 +30,15 @@
     defStyleRes: Int = 0
 ) : LinearLayout(context, attrs, defStyleAttrs, defStyleRes) {
 
-    companion object {
-        val OPS = intArrayOf(AppOpsManager.OP_CAMERA,
-                AppOpsManager.OP_RECORD_AUDIO,
-                AppOpsManager.OP_COARSE_LOCATION,
-                AppOpsManager.OP_FINE_LOCATION)
-    }
-
     private lateinit var appName: TextView
     private lateinit var iconsContainer: LinearLayout
-    private var privacyList = emptyList<PrivacyItem>()
-    private val appOpsController = Dependency.get(AppOpsController::class.java)
-    private val userManager = context.getSystemService(UserManager::class.java)
-    private val currentUser = ActivityManager.getCurrentUser()
-    private val currentUserIds = userManager.getProfiles(currentUser).map { it.id }
-    private var listening = false
-
-    var builder = PrivacyDialogBuilder(context, privacyList)
-
-    private val callback = object : AppOpsController.Callback {
-        override fun onActiveStateChanged(
-            code: Int,
-            uid: Int,
-            packageName: String,
-            active: Boolean
-        ) {
-            val userId = UserHandle.getUserId(uid)
-            if (userId in currentUserIds) {
-                updatePrivacyList()
-            }
+    var builder = PrivacyDialogBuilder(context, emptyList<PrivacyItem>())
+    var privacyList = emptyList<PrivacyItem>()
+        set(value) {
+            field = value
+            builder = PrivacyDialogBuilder(context, value)
+            updateView()
         }
-    }
 
     override fun onFinishInflate() {
         super.onFinishInflate()
@@ -76,36 +47,6 @@
         iconsContainer = findViewById(R.id.icons_container)
     }
 
-    fun setListening(listen: Boolean) {
-        if (listening == listen) return
-        listening = listen
-        if (listening) {
-            appOpsController.addCallback(OPS, callback)
-            updatePrivacyList()
-        } else {
-            appOpsController.removeCallback(OPS, callback)
-        }
-    }
-
-    private fun updatePrivacyList() {
-        privacyList = currentUserIds.flatMap { appOpsController.getActiveAppOpsForUser(it) }
-                .mapNotNull { toPrivacyItem(it) }
-        builder = PrivacyDialogBuilder(context, privacyList)
-        updateView()
-    }
-
-    private fun toPrivacyItem(appOpItem: AppOpItem): PrivacyItem? {
-        val type: PrivacyType = when (appOpItem.code) {
-            AppOpsManager.OP_CAMERA -> PrivacyType.TYPE_CAMERA
-            AppOpsManager.OP_COARSE_LOCATION -> PrivacyType.TYPE_LOCATION
-            AppOpsManager.OP_FINE_LOCATION -> PrivacyType.TYPE_LOCATION
-            AppOpsManager.OP_RECORD_AUDIO -> PrivacyType.TYPE_MICROPHONE
-            else -> return null
-        }
-        val app = PrivacyApplication(appOpItem.packageName, context)
-        return PrivacyItem(type, app, appOpItem.timeStarted)
-    }
-
     // Should only be called if the builder icons or app changed
     private fun updateView() {
         fun setIcons(dialogBuilder: PrivacyDialogBuilder, iconsContainer: ViewGroup) {
@@ -121,11 +62,9 @@
         }
 
         if (privacyList.isEmpty()) {
-            visibility = GONE
             return
         } else {
             generateContentDescription()
-            visibility = VISIBLE
             setIcons(builder, iconsContainer)
             appName.visibility = GONE
             builder.app?.let {
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt
index 2f86f78..5ce4ee7 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt
@@ -16,7 +16,6 @@
 
 import android.content.Context
 import com.android.systemui.R
-import java.lang.IllegalStateException
 import java.lang.Math.max
 
 class PrivacyDialogBuilder(val context: Context, itemsList: List<PrivacyItem>) {
@@ -71,4 +70,4 @@
     fun generateTypesText() = itemsByType.keys.map { it.getName(context) }.sorted().joinToString()
 
     fun generateIcons() = itemsByType.keys.map { it.getIcon(context) }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
new file mode 100644
index 0000000..5141e50
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2018 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.privacy
+
+import android.app.ActivityManager
+import android.app.AppOpsManager
+import android.content.Context
+import android.os.Handler
+import android.os.UserHandle
+import android.os.UserManager
+import com.android.systemui.Dependency
+import com.android.systemui.appops.AppOpItem
+import com.android.systemui.appops.AppOpsController
+
+class PrivacyItemController(val context: Context, val callback: Callback) {
+
+    companion object {
+        val OPS = intArrayOf(AppOpsManager.OP_CAMERA,
+                AppOpsManager.OP_RECORD_AUDIO,
+                AppOpsManager.OP_COARSE_LOCATION,
+                AppOpsManager.OP_FINE_LOCATION)
+    }
+
+    private var privacyList = emptyList<PrivacyItem>()
+    private val appOpsController = Dependency.get(AppOpsController::class.java)
+    private val userManager = context.getSystemService(UserManager::class.java)
+    private val currentUser = ActivityManager.getCurrentUser()
+    private val currentUserIds = userManager.getProfiles(currentUser).map { it.id }
+    private val bgHandler = Handler(Dependency.get(Dependency.BG_LOOPER))
+    private val uiHandler = Dependency.get(Dependency.MAIN_HANDLER)
+    private val notifyChanges = Runnable {
+        callback.privacyChanged(privacyList)
+    }
+    private val updateListAndNotifyChanges = Runnable {
+        updatePrivacyList()
+        uiHandler.post(notifyChanges)
+    }
+
+    private var listening = false
+
+    private val cb = object : AppOpsController.Callback {
+        override fun onActiveStateChanged(
+            code: Int,
+            uid: Int,
+            packageName: String,
+            active: Boolean
+        ) {
+            val userId = UserHandle.getUserId(uid)
+            if (userId in currentUserIds) {
+                update()
+            }
+        }
+    }
+
+    private fun update() {
+        bgHandler.post(updateListAndNotifyChanges)
+    }
+
+    fun setListening(listen: Boolean) {
+        if (listening == listen) return
+        listening = listen
+        if (listening) {
+            appOpsController.addCallback(OPS, cb)
+            update()
+        } else {
+            appOpsController.removeCallback(OPS, cb)
+        }
+    }
+
+    private fun updatePrivacyList() {
+        privacyList = currentUserIds.flatMap { appOpsController.getActiveAppOpsForUser(it) }
+                .mapNotNull { toPrivacyItem(it) }
+    }
+
+    private fun toPrivacyItem(appOpItem: AppOpItem): PrivacyItem? {
+        val type: PrivacyType = when (appOpItem.code) {
+            AppOpsManager.OP_CAMERA -> PrivacyType.TYPE_CAMERA
+            AppOpsManager.OP_COARSE_LOCATION -> PrivacyType.TYPE_LOCATION
+            AppOpsManager.OP_FINE_LOCATION -> PrivacyType.TYPE_LOCATION
+            AppOpsManager.OP_RECORD_AUDIO -> PrivacyType.TYPE_MICROPHONE
+            else -> return null
+        }
+        val app = PrivacyApplication(appOpItem.packageName, context)
+        return PrivacyItem(type, app, appOpItem.timeStarted)
+    }
+
+    // Used by containing class to get notified of changes
+    interface Callback {
+        fun privacyChanged(privacyItems: List<PrivacyItem>)
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/AlphaControlledSignalTileView.java b/packages/SystemUI/src/com/android/systemui/qs/AlphaControlledSignalTileView.java
index 2c7ec70..6a6f572 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/AlphaControlledSignalTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/AlphaControlledSignalTileView.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.graphics.drawable.Drawable;
+
 import com.android.systemui.qs.tileimpl.SlashImageView;
 
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/AutoSizingList.java b/packages/SystemUI/src/com/android/systemui/qs/AutoSizingList.java
index 767fd9e..1195184 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/AutoSizingList.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/AutoSizingList.java
@@ -23,6 +23,7 @@
 import android.view.View;
 import android.widget.LinearLayout;
 import android.widget.ListAdapter;
+
 import com.android.systemui.R;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java b/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
index 376e6ae..c1aa706 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
@@ -20,7 +20,6 @@
 import android.widget.ImageView;
 
 import com.android.settingslib.graph.SignalDrawable;
-import com.android.settingslib.Utils;
 import com.android.systemui.R;
 import com.android.systemui.plugins.qs.QSTile.Icon;
 import com.android.systemui.plugins.qs.QSTile.State;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java b/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java
index 6aad479..afce69e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java
@@ -18,7 +18,6 @@
 
 import android.content.Context;
 import android.content.res.Resources;
-import android.content.res.ColorStateList;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.RectF;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java b/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
index aa2f8d1..d5c5ba4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
@@ -6,10 +6,10 @@
 import android.graphics.drawable.AnimatedVectorDrawable;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.util.TypedValue;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ImageView;
+
 import com.android.systemui.R;
 
 import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index 1451e71..dbd3042 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -23,14 +23,11 @@
 import android.content.res.Configuration;
 import android.graphics.Point;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.View;
 import android.widget.FrameLayout;
 
 import com.android.systemui.R;
-import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.qs.customize.QSCustomizer;
-import com.android.systemui.statusbar.CommandQueue;
 
 /**
  * Wrapper view with background which contains {@link QSPanel} and {@link BaseStatusBarHeader}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
index ddd9910..dab0efe 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
@@ -32,6 +32,7 @@
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.TextView;
+
 import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
 import com.android.systemui.plugins.qs.QSTile;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
index 84eb3da5..b597a72 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
@@ -15,9 +15,10 @@
  */
 package com.android.systemui.qs;
 
-import androidx.annotation.Nullable;
 import android.view.View;
 
+import androidx.annotation.Nullable;
+
 /**
  * The bottom footer of the quick settings panel.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
index f147fb3..8903a38 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
@@ -28,8 +28,6 @@
 import android.graphics.drawable.RippleDrawable;
 import android.os.Bundle;
 import android.os.UserManager;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.View;
@@ -40,6 +38,9 @@
 import android.widget.LinearLayout;
 import android.widget.Toast;
 
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.keyguard.CarrierText;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index f9971d8..953eb70 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -22,8 +22,6 @@
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Bundle;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
 import android.util.Log;
 import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
@@ -34,6 +32,9 @@
 import android.view.ViewTreeObserver;
 import android.widget.FrameLayout.LayoutParams;
 
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
 import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
@@ -42,9 +43,9 @@
 import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.qs.customize.QSCustomizer;
 import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
 import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
-import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 
 public class QSFragment extends Fragment implements QS, CommandQueue.Callbacks {
     private static final String TAG = "QS";
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index cf63e47..f1f0f69 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -17,6 +17,7 @@
 package com.android.systemui.qs;
 
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+
 import static com.android.systemui.qs.tileimpl.QSTileImpl.getColorForState;
 
 import android.annotation.Nullable;
@@ -30,7 +31,6 @@
 import android.os.Message;
 import android.service.quicksettings.Tile;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.LinearLayout;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSScrollLayout.java b/packages/SystemUI/src/com/android/systemui/qs/QSScrollLayout.java
index 7ebab0b..001cbba 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSScrollLayout.java
@@ -17,7 +17,6 @@
 import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.graphics.Canvas;
-import androidx.core.widget.NestedScrollView;
 import android.util.Property;
 import android.view.MotionEvent;
 import android.view.View;
@@ -25,6 +24,8 @@
 import android.view.ViewParent;
 import android.widget.LinearLayout;
 
+import androidx.core.widget.NestedScrollView;
+
 import com.android.systemui.R;
 import com.android.systemui.qs.touch.OverScroll;
 import com.android.systemui.qs.touch.SwipeDetector;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
index 8f3a7b3..e2e943a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
@@ -33,8 +33,8 @@
 import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.view.ViewGroup;
 import android.view.View.OnClickListener;
+import android.view.ViewGroup;
 import android.view.Window;
 import android.widget.ImageView;
 import android.widget.TextView;
@@ -46,8 +46,6 @@
 import com.android.systemui.statusbar.phone.SystemUIDialog;
 import com.android.systemui.statusbar.policy.SecurityController;
 
-import static android.provider.Settings.ACTION_VPN_SETTINGS;
-
 public class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListener {
     protected static final String TAG = "QSSecurityFooter";
     protected static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index cefeeb5..d1c2df5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -31,14 +31,14 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.plugins.qs.QSFactory;
-import com.android.systemui.plugins.qs.QSTileView;
 import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.plugins.qs.QSTileView;
 import com.android.systemui.qs.external.CustomTile;
 import com.android.systemui.qs.external.TileLifecycleManager;
 import com.android.systemui.qs.external.TileServices;
 import com.android.systemui.qs.tileimpl.QSFactoryImpl;
+import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.statusbar.phone.AutoTileManager;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 3ee6195..e3f85d9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -15,6 +15,7 @@
 package com.android.systemui.qs;
 
 import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS;
+import static android.provider.Settings.System.SHOW_BATTERY_PERCENT;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -28,23 +29,29 @@
 import android.content.IntentFilter;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.database.ContentObserver;
 import android.graphics.Color;
 import android.graphics.Rect;
 import android.media.AudioManager;
+import android.net.Uri;
 import android.os.Handler;
 import android.os.Looper;
 import android.provider.AlarmClock;
+import android.provider.Settings;
 import android.service.notification.ZenModeConfig;
 import android.text.format.DateUtils;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Pair;
+import android.view.DisplayCutout;
 import android.view.View;
 import android.view.WindowInsets;
 import android.view.WindowManager;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
+import android.widget.LinearLayout;
 import android.widget.RelativeLayout;
+import android.widget.Space;
 import android.widget.TextView;
 
 import androidx.annotation.VisibleForTesting;
@@ -57,12 +64,15 @@
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.privacy.OngoingPrivacyChip;
 import com.android.systemui.privacy.OngoingPrivacyDialog;
+import com.android.systemui.privacy.PrivacyItem;
+import com.android.systemui.privacy.PrivacyItemController;
 import com.android.systemui.qs.QSDetail.Callback;
 import com.android.systemui.statusbar.phone.PhoneStatusBarView;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager;
 import com.android.systemui.statusbar.phone.StatusIconContainer;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
+import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.Clock;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
@@ -70,6 +80,7 @@
 import com.android.systemui.statusbar.policy.NextAlarmController;
 import com.android.systemui.statusbar.policy.ZenModeController;
 
+import java.util.List;
 import java.util.Locale;
 import java.util.Objects;
 
@@ -125,9 +136,14 @@
     private Clock mClockView;
     private DateView mDateView;
     private OngoingPrivacyChip mPrivacyChip;
+    private Space mSpace;
+    private BatteryMeterView mBatteryRemainingIcon;
+    private TextView mBatteryRemainingText;
+    private boolean mShowBatteryPercentAndEstimate;
 
     private NextAlarmController mAlarmController;
     private ZenModeController mZenController;
+    private PrivacyItemController mPrivacyItemController;
     /** Counts how many times the long press tooltip has been shown to the user. */
     private int mShownCount;
 
@@ -138,16 +154,29 @@
             updateStatusText();
         }
     };
+    private boolean mHasTopCutout = false;
+
+    private final PercentSettingObserver mPercentSettingObserver =
+            new PercentSettingObserver(new Handler(mContext.getMainLooper()));
 
     /**
      * Runnable for automatically fading out the long press tooltip (as if it were animating away).
      */
     private final Runnable mAutoFadeOutTooltipRunnable = () -> hideLongPressTooltip(false);
 
+    private PrivacyItemController.Callback mPICCallback = new PrivacyItemController.Callback() {
+        @Override
+        public void privacyChanged(List<PrivacyItem> privacyItems) {
+            mPrivacyChip.setPrivacyList(privacyItems);
+            setChipVisibility(!privacyItems.isEmpty());
+        }
+    };
+
     public QuickStatusBarHeader(Context context, AttributeSet attrs) {
         super(context, attrs);
         mAlarmController = Dependency.get(NextAlarmController.class);
         mZenController = Dependency.get(ZenModeController.class);
+        mPrivacyItemController = new PrivacyItemController(context, mPICCallback);
         mShownCount = getStoredShownCount();
     }
 
@@ -186,14 +215,28 @@
         // Set the correct tint for the status icons so they contrast
         mIconManager.setTint(fillColor);
 
+        mShowBatteryPercentAndEstimate = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_battery_percentage_setting_available);
+
         mBatteryMeterView = findViewById(R.id.battery);
-        mBatteryMeterView.setForceShowPercent(true);
+        mBatteryMeterView.setPercentShowMode(mShowBatteryPercentAndEstimate
+                ? BatteryMeterView.MODE_ON : BatteryMeterView.MODE_OFF);
         mBatteryMeterView.setOnClickListener(this);
         mClockView = findViewById(R.id.clock);
         mClockView.setOnClickListener(this);
         mDateView = findViewById(R.id.date);
         mPrivacyChip = findViewById(R.id.privacy_chip);
         mPrivacyChip.setOnClickListener(this);
+        mSpace = findViewById(R.id.space);
+
+        // Tint for the battery icons are handled in setupHost()
+        mBatteryRemainingIcon = findViewById(R.id.batteryRemainingIcon);
+        mBatteryRemainingIcon.setPercentShowMode(BatteryMeterView.MODE_OFF);
+
+        mBatteryRemainingText = findViewById(R.id.batteryRemainingText);
+        mBatteryRemainingText.setTextColor(fillColor);
+
+        updateShowPercent();
     }
 
     private void updateStatusText() {
@@ -208,6 +251,16 @@
         }
     }
 
+    private void setChipVisibility(boolean chipVisible) {
+        mBatteryMeterView.setVisibility(View.VISIBLE);
+        if (chipVisible) {
+            mPrivacyChip.setVisibility(View.VISIBLE);
+            if (mHasTopCutout) mBatteryMeterView.setVisibility(View.GONE);
+        } else {
+            mPrivacyChip.setVisibility(View.GONE);
+        }
+    }
+
     private boolean updateRingerStatus() {
         boolean isOriginalVisible = mRingerModeTextView.getVisibility() == View.VISIBLE;
         CharSequence originalRingerText = mRingerModeTextView.getText();
@@ -342,6 +395,14 @@
                 .build();
     }
 
+    private void updateBatteryRemainingText() {
+        if (!mShowBatteryPercentAndEstimate) {
+            return;
+        }
+        mBatteryRemainingText.setText(
+                Dependency.get(BatteryController.class).getEstimatedTimeRemainingString());
+    }
+
     public void setExpanded(boolean expanded) {
         if (mExpanded == expanded) return;
         mExpanded = expanded;
@@ -407,12 +468,16 @@
         super.onAttachedToWindow();
         Dependency.get(StatusBarIconController.class).addIconGroup(mIconManager);
         requestApplyInsets();
+        mContext.getContentResolver().registerContentObserver(
+                Settings.System.getUriFor(SHOW_BATTERY_PERCENT), false, mPercentSettingObserver,
+                ActivityManager.getCurrentUser());
     }
 
     @Override
     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+        DisplayCutout cutout = insets.getDisplayCutout();
         Pair<Integer, Integer> padding = PhoneStatusBarView.cornerCutoutMargins(
-                insets.getDisplayCutout(), getDisplay());
+                cutout, getDisplay());
         if (padding == null) {
             mSystemIconsView.setPaddingRelative(
                     getResources().getDimensionPixelSize(R.dimen.status_bar_padding_start), 0,
@@ -421,6 +486,22 @@
             mSystemIconsView.setPadding(padding.first, 0, padding.second, 0);
 
         }
+        LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mSpace.getLayoutParams();
+        if (cutout != null) {
+            Rect topCutout = cutout.getBoundingRectTop();
+            if (topCutout.isEmpty()) {
+                mHasTopCutout = false;
+                lp.width = 0;
+                mSpace.setVisibility(View.GONE);
+            } else {
+                mHasTopCutout = true;
+                lp.width = topCutout.width();
+                mSpace.setVisibility(View.VISIBLE);
+            }
+        }
+        mSpace.setLayoutParams(lp);
+        // Decide whether to show BatteryMeterView
+        setChipVisibility(mPrivacyChip.getVisibility() == View.VISIBLE);
         return super.onApplyWindowInsets(insets);
     }
 
@@ -429,6 +510,7 @@
     public void onDetachedFromWindow() {
         setListening(false);
         Dependency.get(StatusBarIconController.class).removeIconGroup(mIconManager);
+        mContext.getContentResolver().unregisterContentObserver(mPercentSettingObserver);
         super.onDetachedFromWindow();
     }
 
@@ -437,7 +519,7 @@
             return;
         }
         mHeaderQsPanel.setListening(listening);
-        mPrivacyChip.setListening(listening);
+        mPrivacyItemController.setListening(listening);
         mListening = listening;
 
         if (listening) {
@@ -445,6 +527,7 @@
             mAlarmController.addCallback(this);
             mContext.registerReceiver(mRingerReceiver,
                     new IntentFilter(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION));
+            updateBatteryRemainingText();
         } else {
             mZenController.removeCallback(this);
             mAlarmController.removeCallback(this);
@@ -614,6 +697,14 @@
         // Use SystemUI context to get battery meter colors, and let it use the default tint (white)
         mBatteryMeterView.setColorsFromContext(mHost.getContext());
         mBatteryMeterView.onDarkChanged(new Rect(), 0, DarkIconDispatcher.DEFAULT_ICON_TINT);
+
+        Rect tintArea = new Rect(0, 0, 0, 0);
+        int colorForeground = Utils.getColorAttrDefaultColor(getContext(),
+                android.R.attr.colorForeground);
+        float intensity = getColorIntensity(colorForeground);
+        int fillColor = fillColorForIntensity(intensity, getContext());
+        mBatteryRemainingIcon.setColorsFromContext(mHost.getContext());
+        mBatteryRemainingIcon.onDarkChanged(tintArea, intensity, fillColor);
     }
 
     public void setCallback(Callback qsPanelCallback) {
@@ -646,4 +737,39 @@
             lp.rightMargin = sideMargins;
         }
     }
+
+    private void updateShowPercent() {
+        final boolean systemSetting = 0 != Settings.System
+                .getIntForUser(getContext().getContentResolver(),
+                        SHOW_BATTERY_PERCENT, 0, ActivityManager.getCurrentUser());
+
+        mShowBatteryPercentAndEstimate = systemSetting;
+
+        updateBatteryViews();
+    }
+
+    private void updateBatteryViews() {
+        if (mShowBatteryPercentAndEstimate) {
+            mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ON);
+            mBatteryRemainingIcon.setVisibility(View.VISIBLE);
+            mBatteryRemainingText.setVisibility(View.VISIBLE);
+            updateBatteryRemainingText();
+        } else {
+            mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_OFF);
+            mBatteryRemainingIcon.setVisibility(View.GONE);
+            mBatteryRemainingText.setVisibility(View.GONE);
+        }
+    }
+
+    private final class PercentSettingObserver extends ContentObserver {
+        PercentSettingObserver(Handler handler) {
+            super(handler);
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            super.onChange(selfChange, uri);
+            updateShowPercent();
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
index f6b08b0..0389030 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
@@ -16,14 +16,14 @@
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.drawable.Drawable;
-import androidx.annotation.Nullable;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.view.View;
 import android.widget.ImageView;
 import android.widget.RelativeLayout;
 import android.widget.TextView;
 
+import androidx.annotation.Nullable;
+
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.plugins.ActivityStarter;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
index 2d9e4d7..3e82c54 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
@@ -22,14 +22,15 @@
 import android.app.Fragment;
 import android.content.Context;
 import android.os.Bundle;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-import androidx.recyclerview.widget.GridLayoutManager;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+import androidx.recyclerview.widget.GridLayoutManager;
+
 import com.android.systemui.R;
 import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.qs.QSFooter;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarStatusBarHeader.java
index 9b225bb..083a747 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarStatusBarHeader.java
@@ -16,11 +16,12 @@
 import android.content.Context;
 import android.graphics.Color;
 import android.graphics.Rect;
-import androidx.annotation.IdRes;
 import android.util.AttributeSet;
 import android.view.View;
 import android.widget.LinearLayout;
 
+import androidx.annotation.IdRes;
+
 import com.android.settingslib.Utils;
 import com.android.systemui.BatteryMeterView;
 import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index dc17dd8..64ad95c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -20,13 +20,8 @@
 import android.animation.AnimatorListenerAdapter;
 import android.content.Context;
 import android.content.res.Configuration;
-import android.graphics.Point;
 import android.os.Bundle;
-import androidx.recyclerview.widget.DefaultItemAnimator;
-import androidx.recyclerview.widget.GridLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.util.TypedValue;
 import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
@@ -37,6 +32,10 @@
 import android.widget.Toolbar;
 import android.widget.Toolbar.OnMenuItemClickListener;
 
+import androidx.recyclerview.widget.DefaultItemAnimator;
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settingslib.Utils;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index 15d2e66..a29e93a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -23,13 +23,6 @@
 import android.graphics.Canvas;
 import android.graphics.drawable.ColorDrawable;
 import android.os.Handler;
-import androidx.core.view.ViewCompat;
-import androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup;
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.recyclerview.widget.RecyclerView.ItemDecoration;
-import androidx.recyclerview.widget.RecyclerView.State;
-import androidx.recyclerview.widget.RecyclerView.ViewHolder;
-import androidx.recyclerview.widget.ItemTouchHelper;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.OnClickListener;
@@ -39,6 +32,14 @@
 import android.widget.FrameLayout;
 import android.widget.TextView;
 
+import androidx.core.view.ViewCompat;
+import androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup;
+import androidx.recyclerview.widget.ItemTouchHelper;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.ItemDecoration;
+import androidx.recyclerview.widget.RecyclerView.State;
+import androidx.recyclerview.widget.RecyclerView.ViewHolder;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index bb65bed..8906665 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -15,6 +15,9 @@
  */
 package com.android.systemui.qs.external;
 
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
+
 import android.app.ActivityManager;
 import android.content.ComponentName;
 import android.content.Intent;
@@ -41,13 +44,11 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.qs.QSTile.State;
-import com.android.systemui.qs.tileimpl.QSTileImpl;
-import com.android.systemui.qs.external.TileLifecycleManager.TileChangeListener;
 import com.android.systemui.qs.QSTileHost;
-import java.util.Objects;
+import com.android.systemui.qs.external.TileLifecycleManager.TileChangeListener;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
 
-import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
+import java.util.Objects;
 
 public class CustomTile extends QSTileImpl<State> implements TileChangeListener {
     public static final String PREFIX = "custom(";
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java b/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java
index 451e1f6..2345667 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java
@@ -16,9 +16,7 @@
 package com.android.systemui.qs.external;
 
 import android.os.IBinder;
-import android.service.quicksettings.IQSService;
 import android.service.quicksettings.IQSTileService;
-import android.service.quicksettings.Tile;
 import android.util.Log;
 
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileColorPicker.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileColorPicker.java
index 75dd0d9..1caab5a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileColorPicker.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileColorPicker.java
@@ -18,7 +18,9 @@
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.service.quicksettings.Tile;
+
 import androidx.annotation.VisibleForTesting;
+
 import com.android.systemui.R;
 
 public class TileColorPicker {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index 4e0f38f..305fbf2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -15,15 +15,14 @@
  */
 package com.android.systemui.qs.external;
 
-import android.app.AppGlobals;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
-import android.content.ServiceConnection;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Handler;
@@ -34,10 +33,10 @@
 import android.service.quicksettings.IQSTileService;
 import android.service.quicksettings.Tile;
 import android.service.quicksettings.TileService;
-import androidx.annotation.VisibleForTesting;
 import android.util.ArraySet;
 import android.util.Log;
-import com.android.systemui.qs.external.PackageManagerAdapter;
+
+import androidx.annotation.VisibleForTesting;
 
 import java.util.Objects;
 import java.util.Set;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
index 9f9fe39..416c2da 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
@@ -30,9 +30,10 @@
 import android.service.quicksettings.IQSTileService;
 import android.service.quicksettings.Tile;
 import android.service.quicksettings.TileService;
-import androidx.annotation.VisibleForTesting;
 import android.util.Log;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.systemui.qs.external.TileLifecycleManager.TileChangeListener;
 
 import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index ac7ef5d..b2f6043 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -20,8 +20,11 @@
 import android.view.ContextThemeWrapper;
 
 import com.android.systemui.R;
-import com.android.systemui.plugins.qs.*;
+import com.android.systemui.plugins.qs.QSFactory;
+import com.android.systemui.plugins.qs.QSIconView;
+import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.plugins.qs.QSTileView;
+import com.android.systemui.qs.QSTileHost;
 import com.android.systemui.qs.external.CustomTile;
 import com.android.systemui.qs.tiles.AirplaneModeTile;
 import com.android.systemui.qs.tiles.BatterySaverTile;
@@ -41,7 +44,6 @@
 import com.android.systemui.qs.tiles.UserTile;
 import com.android.systemui.qs.tiles.WifiTile;
 import com.android.systemui.qs.tiles.WorkModeTile;
-import com.android.systemui.qs.QSTileHost;
 import com.android.systemui.util.leak.GarbageMonitor;
 
 public class QSFactoryImpl implements QSFactory {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
index 9dd5d8f..e245312 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
@@ -34,8 +34,8 @@
 import com.android.systemui.plugins.qs.QSIconView;
 import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.plugins.qs.QSTile.State;
-
 import com.android.systemui.qs.AlphaControlledSignalTileView.AlphaControlledSlashImageView;
+
 import java.util.Objects;
 
 public class QSIconViewImpl extends QSIconView {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SlashImageView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SlashImageView.java
index a3e9afd..72c68ce 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SlashImageView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SlashImageView.java
@@ -17,9 +17,10 @@
 import android.annotation.Nullable;
 import android.content.Context;
 import android.graphics.drawable.Drawable;
-import androidx.annotation.NonNull;
 import android.widget.ImageView;
 
+import androidx.annotation.NonNull;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.plugins.qs.QSTile.SlashState;
 import com.android.systemui.qs.SlashDrawable;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
index 7f3537c..da2828e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
@@ -20,6 +20,7 @@
 import android.graphics.drawable.Drawable;
 import android.service.quicksettings.Tile;
 import android.widget.Switch;
+
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settingslib.graph.BatteryMeterDrawableBase;
 import com.android.systemui.Dependency;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index cd00311..c62a592 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -16,8 +16,6 @@
 
 package com.android.systemui.qs.tiles;
 
-import static com.android.settingslib.graph.BluetoothDeviceLayerDrawable.createLayerDrawable;
-
 import android.annotation.Nullable;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothClass;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index b93f1c2..c13a07f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -22,14 +22,13 @@
 import android.service.quicksettings.Tile;
 import android.widget.Switch;
 
-import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.R.drawable;
-import com.android.systemui.qs.QSHost;
 import com.android.systemui.plugins.qs.QSTile.BooleanState;
-import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.qs.QSHost;
 import com.android.systemui.qs.SecureSetting;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
 
 /** Quick settings tile: Invert colors **/
 public class ColorInversionTile extends QSTileImpl<BooleanState> {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
index ace361b..fd8b9c9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
@@ -18,6 +18,7 @@
 import android.content.Intent;
 import android.service.quicksettings.Tile;
 import android.widget.Switch;
+
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
 import com.android.systemui.Prefs;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
index 7bcc6d7..5578558 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
@@ -16,11 +16,10 @@
 
 package com.android.systemui.qs.tiles;
 
-import android.annotation.ColorInt;
 import android.content.Context;
+import android.content.res.ColorStateList;
 import android.content.res.Configuration;
 import android.content.res.Resources;
-import android.content.res.ColorStateList;
 import android.util.AttributeSet;
 import android.view.View;
 import android.widget.LinearLayout;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
index 3c565ef..a639a95 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
@@ -29,13 +29,11 @@
 import android.text.TextUtils;
 import android.util.Log;
 
-import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
 import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.qs.QSHost;
-import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.plugins.qs.QSTile.State;
+import com.android.systemui.qs.QSHost;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 
 import java.util.Arrays;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index d7f2a26..b5f2d00 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -27,8 +27,8 @@
 import com.android.systemui.R;
 import com.android.systemui.R.drawable;
 import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.qs.QSHost;
 import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.QSHost;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
 import com.android.systemui.statusbar.policy.LocationController;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
index 9edd65e..a365e4c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
@@ -22,17 +22,15 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
-import android.graphics.drawable.Drawable;
 import android.nfc.NfcAdapter;
 import android.provider.Settings;
 import android.service.quicksettings.Tile;
 import android.widget.Switch;
 
-import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
-import com.android.systemui.qs.QSHost;
 import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.QSHost;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 
 /** Quick settings tile: Enable/Disable NFC **/
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
index c41f087..90890c0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
@@ -21,19 +21,21 @@
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.content.Intent;
+import android.hardware.display.ColorDisplayManager;
 import android.metrics.LogMaker;
 import android.provider.Settings;
 import android.service.quicksettings.Tile;
-import androidx.annotation.StringRes;
 import android.text.TextUtils;
 import android.util.Log;
 import android.widget.Switch;
 
+import androidx.annotation.StringRes;
+
 import com.android.internal.app.ColorDisplayController;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
-import com.android.systemui.qs.QSHost;
 import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.QSHost;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 
 import java.text.DateFormat;
@@ -53,7 +55,6 @@
     private static final String PATTERN_HOUR_MINUTE = "h:mm a";
     private static final String PATTERN_HOUR_NINUTE_24 = "HH:mm";
 
-
     private ColorDisplayController mController;
     private boolean mIsListening;
 
@@ -64,7 +65,7 @@
 
     @Override
     public boolean isAvailable() {
-        return ColorDisplayController.isAvailable(mContext);
+        return ColorDisplayManager.isNightDisplayAvailable(mContext);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
index 28b047b..6345816 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
@@ -19,17 +19,15 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Configuration;
-
 import android.provider.Settings;
 import android.service.quicksettings.Tile;
 import android.widget.Switch;
 
-import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.qs.QSHost;
 import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.QSHost;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.statusbar.policy.RotationLockController;
 import com.android.systemui.statusbar.policy.RotationLockController.RotationLockControllerCallback;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
index ad7d1b6..64fe54a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
@@ -30,7 +30,6 @@
 import android.widget.TextView;
 
 import com.android.internal.util.ArrayUtils;
-import com.android.settingslib.drawable.UserIconDrawable;
 import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.phone.UserAvatarView;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
index bde1c98..e5c51a6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
@@ -24,9 +24,9 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
 import com.android.systemui.plugins.qs.DetailAdapter;
-import com.android.systemui.qs.QSHost;
 import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.plugins.qs.QSTile.State;
+import com.android.systemui.qs.QSHost;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.statusbar.policy.UserInfoController;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/touch/SwipeDetector.java b/packages/SystemUI/src/com/android/systemui/qs/touch/SwipeDetector.java
index 911bea6..e7161e1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/touch/SwipeDetector.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/touch/SwipeDetector.java
@@ -19,12 +19,13 @@
 
 import android.content.Context;
 import android.graphics.PointF;
-import androidx.annotation.NonNull;
-import androidx.annotation.VisibleForTesting;
 import android.util.Log;
 import android.view.MotionEvent;
 import android.view.ViewConfiguration;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+
 /**
  * One dimensional scroll/drag/swipe gesture detector.
  *
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
index 661b958..958695d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
@@ -31,6 +31,7 @@
 import android.util.Log;
 import android.view.Display;
 import android.widget.Toast;
+
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.SysUiServiceProvider;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 19f7675..1b89324 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -17,9 +17,9 @@
 package com.android.systemui.recents;
 
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
+import static android.view.MotionEvent.ACTION_CANCEL;
 import static android.view.MotionEvent.ACTION_DOWN;
 import static android.view.MotionEvent.ACTION_UP;
-import static android.view.MotionEvent.ACTION_CANCEL;
 
 import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_SWIPE_UP;
 import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON;
@@ -42,6 +42,7 @@
 import android.provider.Settings;
 import android.util.Log;
 import android.view.MotionEvent;
+
 import com.android.systemui.Dependency;
 import com.android.systemui.Dumpable;
 import com.android.systemui.Prefs;
@@ -55,6 +56,7 @@
 import com.android.systemui.statusbar.policy.CallbackController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index de22d21..0702d74 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -20,9 +20,11 @@
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.provider.Settings;
+
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
 import com.android.systemui.statusbar.CommandQueue;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java
index 8a04c11..3efed3f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java
@@ -18,7 +18,9 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.Rect;
+
 import com.android.systemui.SysUiServiceProvider;
+
 import java.io.PrintWriter;
 
 interface RecentsImplementation {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
index af0ebdc..34f3c60 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
@@ -19,16 +19,17 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 
-import static com.android.systemui.Prefs.Key.HAS_DISMISSED_RECENTS_QUICK_SCRUB_ONBOARDING_ONCE;
 import static com.android.systemui.Prefs.Key.DISMISSED_RECENTS_SWIPE_UP_ONBOARDING_COUNT;
+import static com.android.systemui.Prefs.Key.HAS_DISMISSED_RECENTS_QUICK_SCRUB_ONBOARDING_ONCE;
 import static com.android.systemui.Prefs.Key.HAS_SEEN_RECENTS_QUICK_SCRUB_ONBOARDING;
 import static com.android.systemui.Prefs.Key.HAS_SEEN_RECENTS_SWIPE_UP_ONBOARDING;
 import static com.android.systemui.Prefs.Key.OVERVIEW_OPENED_COUNT;
 import static com.android.systemui.Prefs.Key.OVERVIEW_OPENED_FROM_HOME_COUNT;
-import static com.android.systemui.shared.system.LauncherEventUtil.VISIBLE;
 import static com.android.systemui.shared.system.LauncherEventUtil.DISMISS;
-import static com.android.systemui.shared.system.LauncherEventUtil.RECENTS_QUICK_SCRUB_ONBOARDING_TIP;
+import static com.android.systemui.shared.system.LauncherEventUtil
+        .RECENTS_QUICK_SCRUB_ONBOARDING_TIP;
 import static com.android.systemui.shared.system.LauncherEventUtil.RECENTS_SWIPE_UP_ONBOARDING_TIP;
+import static com.android.systemui.shared.system.LauncherEventUtil.VISIBLE;
 
 import android.annotation.StringRes;
 import android.annotation.TargetApi;
@@ -45,9 +46,9 @@
 import android.graphics.PixelFormat;
 import android.graphics.drawable.ShapeDrawable;
 import android.os.Build;
+import android.os.RemoteException;
 import android.os.SystemProperties;
 import android.os.UserManager;
-import android.os.RemoteException;
 import android.util.TypedValue;
 import android.view.Gravity;
 import android.view.LayoutInflater;
@@ -64,6 +65,7 @@
 import com.android.systemui.shared.recents.IOverviewProxy;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.TaskStackChangeListener;
+
 import java.io.PrintWriter;
 import java.util.Collections;
 import java.util.HashSet;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index f92c50a..216b940 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -16,6 +16,9 @@
 
 package com.android.systemui.recents;
 
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
+
 import android.animation.ArgbEvaluator;
 import android.animation.ValueAnimator;
 import android.app.ActivityManager;
@@ -50,9 +53,6 @@
 
 import java.util.ArrayList;
 
-import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
-import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
-
 public class ScreenPinningRequest implements View.OnClickListener {
 
     private final Context mContext;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/TriangleShape.java b/packages/SystemUI/src/com/android/systemui/recents/TriangleShape.java
index af8c2d0..ef4e195 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/TriangleShape.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/TriangleShape.java
@@ -19,6 +19,7 @@
 import android.graphics.Outline;
 import android.graphics.Path;
 import android.graphics.drawable.shapes.PathShape;
+
 import androidx.annotation.NonNull;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
index 3ed5f70..79228b9 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
@@ -43,7 +43,6 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.systemui.Dependency;
 
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
index 2ae53b5..0374a01 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
@@ -18,7 +18,6 @@
 
 import android.app.Activity;
 import android.os.Bundle;
-import android.view.ContextThemeWrapper;
 import android.view.Gravity;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
diff --git a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
index 64fa8f8..07675e2 100644
--- a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
@@ -26,6 +26,7 @@
 import android.view.KeyEvent;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
+
 import com.android.internal.policy.DividerSnapAlgorithm;
 import com.android.systemui.SystemUI;
 import com.android.systemui.recents.Recents;
diff --git a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyServiceProxy.java b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyServiceProxy.java
index 8ec862e..156964a 100644
--- a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyServiceProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyServiceProxy.java
@@ -19,6 +19,7 @@
 import android.os.Handler;
 import android.os.Message;
 import android.os.RemoteException;
+
 import com.android.internal.policy.IShortcutService;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
index ea194a7..cd2074f 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
@@ -26,9 +26,11 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.WindowManagerGlobal;
+
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
 import com.android.systemui.recents.Recents;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index fa01af6..7a7d1f6 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -55,6 +55,7 @@
 import android.view.animation.Interpolator;
 import android.view.animation.PathInterpolator;
 import android.widget.FrameLayout;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.policy.DividerSnapAlgorithm;
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java
index b7a5d31..2486d653 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java
@@ -16,12 +16,6 @@
 
 package com.android.systemui.stackdivider;
 
-import android.content.Context;
-import android.graphics.PixelFormat;
-import android.os.Binder;
-import android.view.View;
-import android.view.WindowManager;
-
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
@@ -32,6 +26,12 @@
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
 
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.os.Binder;
+import android.view.View;
+import android.view.WindowManager;
+
 /**
  * Manages the window parameters of the docked stack divider.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
index f66db48..c6ac309 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
@@ -16,7 +16,8 @@
 
 package com.android.systemui.stackdivider;
 
-import static com.android.systemui.stackdivider.ForcedResizableInfoActivity.EXTRA_FORCED_RESIZEABLE_REASON;
+import static com.android.systemui.stackdivider.ForcedResizableInfoActivity
+        .EXTRA_FORCED_RESIZEABLE_REASON;
 
 import android.app.ActivityOptions;
 import android.content.Context;
@@ -25,6 +26,7 @@
 import android.os.UserHandle;
 import android.util.ArraySet;
 import android.widget.Toast;
+
 import com.android.systemui.R;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.TaskStackChangeListener;
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
index 600964e..228aab5 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
@@ -18,7 +18,6 @@
 
 import static android.view.WindowManager.DOCKED_INVALID;
 
-import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
 import android.graphics.Rect;
 import android.os.RemoteException;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index daaefb9..0c8f487 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -27,9 +27,9 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.util.Pair;
 
 import androidx.annotation.VisibleForTesting;
-import android.util.Pair;
 
 import com.android.internal.os.SomeArgs;
 import com.android.internal.statusbar.IStatusBar;
@@ -164,7 +164,7 @@
         default void onRotationProposal(int rotation, boolean isValid) { }
 
         default void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver,
-                int type, boolean requireConfirmation) { }
+                int type, boolean requireConfirmation, int userId) { }
         default void onBiometricAuthenticated() { }
         default void onBiometricHelp(String message) { }
         default void onBiometricError(String error) { }
@@ -524,13 +524,14 @@
 
     @Override
     public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver, int type,
-            boolean requireConfirmation) {
+            boolean requireConfirmation, int userId) {
         synchronized (mLock) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = bundle;
             args.arg2 = receiver;
             args.argi1 = type;
             args.arg3 = requireConfirmation;
+            args.argi2 = userId;
             mHandler.obtainMessage(MSG_BIOMETRIC_SHOW, args)
                     .sendToTarget();
         }
@@ -774,8 +775,9 @@
                         mCallbacks.get(i).showBiometricDialog(
                                 (Bundle) someArgs.arg1,
                                 (IBiometricPromptReceiver) someArgs.arg2,
-                                someArgs.argi1,
-                                (boolean) someArgs.arg3);
+                                someArgs.argi1 /* type */,
+                                (boolean) someArgs.arg3 /* requireConfirmation */,
+                                someArgs.argi2 /* userId */);
                     }
                     someArgs.recycle();
                     break;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
index 00e0b95..7f39e47 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
@@ -62,11 +62,13 @@
 import android.widget.LinearLayout;
 import android.widget.RelativeLayout;
 import android.widget.TextView;
+
 import com.android.internal.app.AssistUtils;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settingslib.Utils;
 import com.android.systemui.R;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
index 1f57634..a188c5a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
@@ -40,7 +40,6 @@
 
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.KeyguardAffordanceHelper;
 
 /**
  * An ImageView which does not have overlapping renderings commands and therefore does not need a
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NeutralGoodDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/NeutralGoodDrawable.java
index cdb0514..8642ca4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NeutralGoodDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NeutralGoodDrawable.java
@@ -17,14 +17,11 @@
 package com.android.systemui.statusbar;
 
 import android.content.Context;
-import android.content.res.Resources.Theme;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.LayerDrawable;
 import android.view.ContextThemeWrapper;
 import android.view.Gravity;
+
 import com.android.settingslib.Utils;
 import com.android.systemui.R;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java
index 62c21dc..ecd9814 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java
@@ -1,9 +1,9 @@
 package com.android.systemui.statusbar;
 
-import com.android.systemui.statusbar.notification.NotificationData;
-
 import androidx.annotation.NonNull;
 
+import com.android.systemui.statusbar.notification.NotificationData;
+
 /**
  * Interface for anything that may need to keep notifications managed even after
  * {@link NotificationListener} removes it.  The lifetime extender is in charge of performing the
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java
index 5c8f4cb..0e9f950 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java
@@ -16,11 +16,8 @@
 package com.android.systemui.statusbar;
 
 import android.content.Intent;
-import android.os.Handler;
-import android.view.View;
 
 import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
-import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java
index 47b7fe9..f42c6ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java
@@ -22,10 +22,10 @@
 import android.graphics.drawable.Icon;
 import android.text.TextUtils;
 
-import com.android.systemui.statusbar.notification.NotificationData;
-
 import androidx.annotation.VisibleForTesting;
 
+import com.android.systemui.statusbar.notification.NotificationData;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameView.java b/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameView.java
index 5090f74..f1a891b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameView.java
@@ -15,10 +15,9 @@
 package com.android.systemui.statusbar;
 
 import android.content.Context;
-import android.net.ConnectivityManager;
 import android.graphics.Rect;
+import android.net.ConnectivityManager;
 import android.os.Bundle;
-import android.provider.Settings;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionInfo;
 import android.text.TextUtils;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
index 7f63191..929f43e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
@@ -16,10 +16,6 @@
 
 package com.android.systemui.statusbar;
 
-import com.android.internal.util.Preconditions;
-import com.android.systemui.statusbar.notification.NotificationData;
-import com.android.systemui.statusbar.policy.RemoteInputView;
-
 import android.app.Notification;
 import android.app.RemoteInput;
 import android.content.Context;
@@ -27,6 +23,10 @@
 import android.util.ArrayMap;
 import android.util.Pair;
 
+import com.android.internal.util.Preconditions;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.policy.RemoteInputView;
+
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
index 3bc4342..cb9060b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
@@ -28,16 +28,14 @@
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuff.Mode;
 import android.graphics.PorterDuffColorFilter;
-import android.graphics.PorterDuffXfermode;
-import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
-import androidx.core.graphics.ColorUtils;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.Display;
 import android.view.View;
 import android.view.WindowManager;
-import android.view.animation.Interpolator;
+
+import androidx.core.graphics.ColorUtils;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.colorextraction.ColorExtractor;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
index fb888dd..758c33a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
@@ -16,13 +16,11 @@
 package com.android.systemui.statusbar;
 
 import android.os.RemoteException;
-import android.service.notification.StatusBarNotification;
 import android.util.ArraySet;
 
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.systemui.Dependency;
 import com.android.systemui.statusbar.notification.NotificationData;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
 
 import java.util.Set;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconContainer.java
index 56f78f4..0652227 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconContainer.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar;
 
 import com.android.internal.statusbar.StatusBarIcon;
+
 import java.util.ArrayList;
 import java.util.List;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
index 3c52e8c..bc89889 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
@@ -27,16 +27,14 @@
 import android.graphics.Color;
 import android.graphics.Rect;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
-
 import android.widget.LinearLayout;
+
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.keyguard.AlphaOptimizedLinearLayout;
 import com.android.settingslib.graph.SignalDrawable;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java
index 12c0fcb..eaf52cb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java
@@ -18,11 +18,17 @@
 
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
 import android.annotation.IntDef;
-import android.util.ArraySet;
-import android.util.Log;
+import android.util.FloatProperty;
+import android.view.animation.Interpolator;
+
 import com.android.internal.annotations.GuardedBy;
+import com.android.systemui.Interpolators;
+import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 import com.android.systemui.statusbar.phone.StatusBar;
+
 import java.lang.annotation.Retention;
 import java.util.ArrayList;
 import java.util.Comparator;
@@ -38,14 +44,51 @@
 
     private static final Comparator <RankedListener> mComparator
             = (o1, o2) -> Integer.compare(o1.rank, o2.rank);
+    private static final FloatProperty<StatusBarStateController> SET_DARK_AMOUNT_PROPERTY =
+            new FloatProperty<StatusBarStateController>("mDozeAmount") {
+
+                @Override
+                public void setValue(StatusBarStateController object, float value) {
+                    object.setDozeAmountInternal(value);
+                }
+
+                @Override
+                public Float get(StatusBarStateController object) {
+                    return object.mDozeAmount;
+                }
+            };
 
     private final ArrayList<RankedListener> mListeners = new ArrayList<>();
-    private boolean mIsDozing;
     private int mState;
     private int mLastState;
     private boolean mLeaveOpenOnKeyguardHide;
     private boolean mKeyguardRequested;
 
+    /**
+     * If the device is currently dozing or not.
+     */
+    private boolean mIsDozing;
+
+    /**
+     * Current {@link #mDozeAmount} animator.
+     */
+    private ValueAnimator mDarkAnimator;
+
+    /**
+     * Current doze amount in this frame.
+     */
+    private float mDozeAmount;
+
+    /**
+     * Where the animator will stop.
+     */
+    private float mDozeAmountTarget;
+
+    /**
+     * The type of interpolator that should be used to the doze animation.
+     */
+    private Interpolator mDozeInterpolator = Interpolators.FAST_OUT_SLOW_IN;
+
     // TODO: b/115739177 (remove this explicit ordering if we can)
     @Retention(SOURCE)
     @IntDef({RANK_STATUS_BAR, RANK_STATUS_BAR_WINDOW_CONTROLLER, RANK_STACK_SCROLLER, RANK_SHELF})
@@ -94,6 +137,14 @@
         return mIsDozing;
     }
 
+    public float getDozeAmount() {
+        return mDozeAmount;
+    }
+
+    public float getInterpolatedDozeAmount() {
+        return mDozeInterpolator.getInterpolation(mDozeAmount);
+    }
+
     /**
      * Update the dozing state from {@link StatusBar}'s perspective
      * @param isDozing well, are we dozing?
@@ -116,6 +167,51 @@
         return true;
     }
 
+    /**
+     * Changes the current doze amount.
+     *
+     * @param dozeAmount New doze/dark amount.
+     * @param animated If change should be animated or not. This will cancel current animations.
+     */
+    public void setDozeAmount(float dozeAmount, boolean animated) {
+        if (mDarkAnimator != null && mDarkAnimator.isRunning()) {
+            if (animated && mDozeAmountTarget == dozeAmount) {
+                return;
+            } else {
+                mDarkAnimator.cancel();
+            }
+        }
+
+        mDozeAmountTarget = dozeAmount;
+        if (animated) {
+            startDozeAnimation();
+        } else {
+            setDozeAmountInternal(dozeAmount);
+        }
+    }
+
+    private void startDozeAnimation() {
+        if (mDozeAmount == 0f || mDozeAmount == 1f) {
+            mDozeInterpolator = mIsDozing
+                    ? Interpolators.FAST_OUT_SLOW_IN
+                    : Interpolators.TOUCH_RESPONSE_REVERSE;
+        }
+        mDarkAnimator = ObjectAnimator.ofFloat(this, SET_DARK_AMOUNT_PROPERTY, mDozeAmountTarget);
+        mDarkAnimator.setInterpolator(Interpolators.LINEAR);
+        mDarkAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_WAKEUP);
+        mDarkAnimator.start();
+    }
+
+    private void setDozeAmountInternal(float dozeAmount) {
+        mDozeAmount = dozeAmount;
+        float interpolatedAmount = mDozeInterpolator.getInterpolation(dozeAmount);
+        synchronized (mListeners) {
+            for (RankedListener rl : new ArrayList<>(mListeners)) {
+                rl.listener.onDozeAmountChanged(mDozeAmount, interpolatedAmount);
+            }
+        }
+    }
+
     public boolean goingToFullShade() {
         return mState == StatusBarState.SHADE && mLeaveOpenOnKeyguardHide;
     }
@@ -202,7 +298,8 @@
     public interface StateListener {
 
         /**
-         * Callback before the new state is applied, for those who need to preempt the change
+         * Callback before the new state is applied, for those who need to preempt the change.
+         *
          * @param oldState state before the change
          * @param newState new state to be applied in {@link #onStateChanged}
          */
@@ -218,17 +315,29 @@
         /**
          * Required callback. Get the new state and do what you will with it. Keep in mind that
          * other listeners are typically unordered and don't rely on your work being done before
-         * other peers
+         * other peers.
          *
-         * Only called if the state is actually different
+         * Only called if the state is actually different.
+         *
          * @param newState the new {@link StatusBarState}
          */
         public void onStateChanged(int newState);
 
         /**
          * Callback to be notified when Dozing changes. Dozing is stored separately from state.
+         *
          * @param isDozing {@code true} if dozing according to {@link StatusBar}
          */
         public default void onDozingChanged(boolean isDozing) {}
+
+        /**
+         * Callback to be notified when the doze amount changes. Useful for animations.
+         * Note: this will be called for each animation frame. Please be careful to avoid
+         * performance regressions.
+         *
+         * @param linear A number from 0 to 1, where 1 means that the device is dozing.
+         * @param eased Same as {@code linear} but transformed by an interpolator.
+         */
+        default void onDozeAmountChanged(float linear, float eased) {}
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
index f3fc99e..045221f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
@@ -27,18 +27,14 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.ContextThemeWrapper;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
-
 import android.widget.LinearLayout;
-import com.android.keyguard.AlphaOptimizedLinearLayout;
+
 import com.android.settingslib.Utils;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/UserUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/UserUtil.java
index f9afc7c..c4fadff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/UserUtil.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/UserUtil.java
@@ -16,12 +16,12 @@
 
 package com.android.systemui.statusbar;
 
-import com.android.systemui.statusbar.phone.SystemUIDialog;
-import com.android.systemui.statusbar.policy.UserSwitcherController;
 import android.content.Context;
 import android.content.DialogInterface;
 
 import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.SystemUIDialog;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
 
 public class UserUtil {
     public static void deleteUserWithPrompt(Context context, int userId,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
index 46f8863..bd32856 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
@@ -3,10 +3,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
 import android.os.UserHandle;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
index 9ed0929..81f7846 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
@@ -16,13 +16,10 @@
 
 package com.android.systemui.statusbar.car;
 
-import android.app.UiModeManager;
 import android.content.Context;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.View;
 import android.widget.LinearLayout;
-import android.widget.TextView;
 
 import com.android.keyguard.AlphaOptimizedImageButton;
 import com.android.systemui.Dependency;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java
index 0304086..f2923f7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java
@@ -1,5 +1,7 @@
 package com.android.systemui.statusbar.car;
 
+import static com.android.systemui.statusbar.phone.StatusBar.DEBUG;
+
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHeadsetClient;
@@ -9,21 +11,19 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.telephony.SignalStrength;
 import android.util.Log;
 import android.util.TypedValue;
 import android.view.View;
 import android.widget.ImageView;
+
 import com.android.settingslib.graph.SignalDrawable;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.ScalingDrawableWrapper;
 import com.android.systemui.statusbar.policy.BluetoothController;
 
-import static com.android.systemui.statusbar.phone.StatusBar.DEBUG;
-
 /**
  * Controller that monitors signal strength for a device that is connected via bluetooth.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/SwitchToGuestTimer.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/SwitchToGuestTimer.java
index f9fa44b..0c91cba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/SwitchToGuestTimer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/SwitchToGuestTimer.java
@@ -21,10 +21,10 @@
 import android.os.CountDownTimer;
 import android.util.Log;
 
-import com.android.systemui.R;
-
 import androidx.annotation.GuardedBy;
 
+import com.android.systemui.R;
+
 /**
  * Wrapper for a countdown timer that switches to Guest if the user has been driving with
  * the keyguard up for configurable number of seconds.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
index 53a7afe..d802ed8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
@@ -29,7 +29,6 @@
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.os.AsyncTask;
-import android.os.UserHandle;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -44,8 +43,8 @@
 
 import com.android.internal.util.UserIcons;
 import com.android.systemui.R;
-
 import com.android.systemui.statusbar.phone.SystemUIDialog;
+
 import java.util.ArrayList;
 import java.util.List;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActionListTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActionListTransformState.java
index 8c72544..6044a7e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActionListTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActionListTransformState.java
@@ -16,11 +16,7 @@
 
 package com.android.systemui.statusbar.notification;
 
-import android.text.Layout;
-import android.text.TextUtils;
 import android.util.Pools;
-import android.view.View;
-import android.widget.TextView;
 
 /**
  * A transform state of the action list
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/CustomInterpolatorTransformation.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/CustomInterpolatorTransformation.java
index de4c312..dea1a07 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/CustomInterpolatorTransformation.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/CustomInterpolatorTransformation.java
@@ -17,16 +17,11 @@
 package com.android.systemui.statusbar.notification;
 
 import android.view.View;
-import android.view.animation.Interpolator;
 
-import com.android.systemui.Interpolators;
 import com.android.systemui.statusbar.CrossFadeHelper;
 import com.android.systemui.statusbar.TransformableView;
 import com.android.systemui.statusbar.ViewTransformationHelper;
 
-import static com.android.systemui.statusbar.TransformableView.TRANSFORMING_VIEW_TITLE;
-import static com.android.systemui.statusbar.notification.TransformState.TRANSFORM_Y;
-
 /**
  * A custom transformation that modifies the interpolator
  */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageGradientColorizer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageGradientColorizer.java
index 454edbb..f5a76f0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageGradientColorizer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageGradientColorizer.java
@@ -17,7 +17,6 @@
 package com.android.systemui.statusbar.notification;
 
 import android.graphics.Bitmap;
-import android.graphics.BitmapShader;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.ColorMatrix;
@@ -27,7 +26,6 @@
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffXfermode;
 import android.graphics.Shader;
-import android.graphics.Xfermode;
 import android.graphics.drawable.Drawable;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
index 8c0d700..ab94008 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
@@ -23,9 +23,10 @@
 import android.graphics.Color;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
+import android.util.LayoutDirection;
+
 import androidx.annotation.VisibleForTesting;
 import androidx.palette.graphics.Palette;
-import android.util.LayoutDirection;
 
 import com.android.internal.util.ContrastColorUtil;
 import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingImageTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingImageTransformState.java
index b97995d..a3fb225 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingImageTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingImageTransformState.java
@@ -20,7 +20,6 @@
 import android.view.View;
 
 import com.android.internal.widget.MessagingImageMessage;
-import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.ViewTransformationHelper;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java
index fb362c5..ef042ba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java
@@ -26,7 +26,7 @@
 
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.NotificationPanelView;
+import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 
 import java.util.function.Consumer;
 
@@ -63,13 +63,14 @@
         }
     }
 
+    // TODO: this should be using StatusBarStateController#getDozeAmount
     public void startIntensityAnimation(ValueAnimator.AnimatorUpdateListener updateListener,
             boolean dark, long delay, Animator.AnimatorListener listener) {
         float startIntensity = dark ? 0f : 1f;
         float endIntensity = dark ? 1f : 0f;
         ValueAnimator animator = ValueAnimator.ofFloat(startIntensity, endIntensity);
         animator.addUpdateListener(updateListener);
-        animator.setDuration(NotificationPanelView.DOZE_ANIMATION_DURATION);
+        animator.setDuration(StackStateAnimator.ANIMATION_DURATION_WAKEUP);
         animator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
         animator.setStartDelay(delay);
         if (listener != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
index 07b8c35..337f312 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
@@ -29,9 +29,9 @@
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.CrossFadeHelper;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.TransformableView;
 import com.android.systemui.statusbar.ViewTransformationHelper;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 
 /**
  * A transform state of a view.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
index da8954a..75613a4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
@@ -16,9 +16,10 @@
 
 package com.android.systemui.statusbar.notification;
 
-import androidx.collection.ArraySet;
 import android.view.View;
 
+import androidx.collection.ArraySet;
+
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
index 1a4ef09..16796dd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
@@ -16,10 +16,13 @@
 
 package com.android.systemui.statusbar.notification.row;
 
+import static android.service.notification.NotificationListenerService.Ranking
+        .USER_SENTIMENT_NEGATIVE;
+
 import android.content.Context;
+import android.util.Log;
 
 import androidx.annotation.VisibleForTesting;
-import android.util.Log;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.Dependency;
@@ -31,8 +34,6 @@
 import java.util.HashSet;
 import java.util.Set;
 
-import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
-
 /**
  * Manager for the notification blocking helper - tracks and helps create the blocking helper
  * affordance.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSnooze.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSnooze.java
index 75b05c2..d65f2c5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSnooze.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSnooze.java
@@ -16,16 +16,6 @@
 
 package com.android.systemui.statusbar.notification.row;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
-import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
-
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
@@ -53,8 +43,17 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
+import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
+import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
 
 public class NotificationSnooze extends LinearLayout
         implements NotificationGuts.GutsContent, View.OnClickListener {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowInflaterTask.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowInflaterTask.java
index a21794b..1741a0b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowInflaterTask.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowInflaterTask.java
@@ -17,11 +17,12 @@
 package com.android.systemui.statusbar.notification.row;
 
 import android.content.Context;
-import androidx.asynclayoutinflater.view.AsyncLayoutInflater;
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
 
+import androidx.asynclayoutinflater.view.AsyncLayoutInflater;
+
 import com.android.systemui.R;
 import com.android.systemui.statusbar.InflationTask;
 import com.android.systemui.statusbar.notification.NotificationData;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java
index 8a061a6..1b40c06 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java
@@ -24,7 +24,6 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.Interpolators;
-import com.android.systemui.statusbar.notification.row.ExpandableView;
 
 /**
  * A common base class for all views in the notification stack scroller which don't have a
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigTextTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigTextTemplateViewWrapper.java
index 133df3c..4261df3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigTextTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigTextTemplateViewWrapper.java
@@ -21,8 +21,8 @@
 import android.view.View;
 
 import com.android.internal.widget.ImageFloatingTextView;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.TransformableView;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 
 /**
  * Wraps a notification containing a big text template
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
index 6ca07ed..a8ced7a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
@@ -16,9 +16,9 @@
 
 package com.android.systemui.statusbar.notification.row.wrapper;
 
+import static com.android.systemui.statusbar.notification.TransformState.TRANSFORM_Y;
 import static com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
         .DEFAULT_HEADER_VISIBLE_AMOUNT;
-import static com.android.systemui.statusbar.notification.TransformState.TRANSFORM_Y;
 
 import android.app.Notification;
 import android.content.Context;
@@ -34,12 +34,12 @@
 import com.android.internal.widget.NotificationExpandButton;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
+import com.android.systemui.statusbar.TransformableView;
+import com.android.systemui.statusbar.ViewTransformationHelper;
 import com.android.systemui.statusbar.notification.CustomInterpolatorTransformation;
 import com.android.systemui.statusbar.notification.ImageTransformState;
 import com.android.systemui.statusbar.notification.TransformState;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.TransformableView;
-import com.android.systemui.statusbar.ViewTransformationHelper;
 
 import java.util.Stack;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
index 37d2f6b..5a9a568 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
@@ -19,8 +19,8 @@
 import android.content.Context;
 import android.view.View;
 
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.TransformableView;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 
 /**
  * Wraps a notification containing a media template
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMessagingTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMessagingTemplateViewWrapper.java
index 13c5960..c9a2742 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMessagingTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMessagingTemplateViewWrapper.java
@@ -16,15 +16,15 @@
 
 package com.android.systemui.statusbar.notification.row.wrapper;
 
+import android.content.Context;
+import android.view.View;
+
 import com.android.internal.widget.MessagingLayout;
 import com.android.internal.widget.MessagingLinearLayout;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 
-import android.content.Context;
-import android.view.View;
-
 /**
  * Wraps a notification containing a messaging template
  */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
index d934902..ff5e15b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
@@ -37,11 +37,11 @@
 import com.android.systemui.R;
 import com.android.systemui.UiOffloadThread;
 import com.android.systemui.statusbar.CrossFadeHelper;
+import com.android.systemui.statusbar.TransformableView;
+import com.android.systemui.statusbar.ViewTransformationHelper;
 import com.android.systemui.statusbar.notification.ImageTransformState;
 import com.android.systemui.statusbar.notification.TransformState;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.TransformableView;
-import com.android.systemui.statusbar.ViewTransformationHelper;
 import com.android.systemui.statusbar.notification.row.HybridNotificationView;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
index f76284d..1efdc56 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
@@ -24,9 +24,9 @@
 import android.view.View;
 
 import com.android.systemui.statusbar.CrossFadeHelper;
+import com.android.systemui.statusbar.TransformableView;
 import com.android.systemui.statusbar.notification.TransformState;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.TransformableView;
 
 /**
  * Wraps the actual notification content view; used to implement behaviors which are different for
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationFilter.java
index c6f953c..ba56a94 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationFilter.java
@@ -16,10 +16,11 @@
 
 package com.android.systemui.statusbar.notification.stack;
 
-import androidx.collection.ArraySet;
 import android.util.Property;
 import android.view.View;
 
+import androidx.collection.ArraySet;
+
 import java.util.ArrayList;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
index da089b3..74b4aa2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -33,13 +33,13 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.CrossFadeHelper;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.NotificationHeaderUtil;
+import com.android.systemui.statusbar.notification.NotificationUtils;
+import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.HybridGroupManager;
 import com.android.systemui.statusbar.notification.row.HybridNotificationView;
-import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
-import com.android.systemui.statusbar.notification.VisualStabilityManager;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java
index cfb6d99..4d100a4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java
@@ -16,17 +16,18 @@
 
 package com.android.systemui.statusbar.notification.stack;
 
-import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
+import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator
+        .ExpandAnimationParameters;
 
 import android.view.View;
 import android.view.ViewGroup;
 
 import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
+import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.ExpandableView;
-import com.android.systemui.statusbar.notification.NotificationData;
-import com.android.systemui.statusbar.notification.logging.NotificationLogger;
 
 /**
  * Interface representing the entity that contains notifications. It can have
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 9daba83..a7329b0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -2312,7 +2312,7 @@
             View child = getChildAt(i);
             if (child.getVisibility() != View.GONE && child instanceof ExpandableNotificationRow) {
                 ExpandableNotificationRow row = (ExpandableNotificationRow) child;
-                if (mEntryManager.getNotificationData().isHighPriority(
+                if (!mEntryManager.getNotificationData().isHighPriority(
                         row.getStatusBarNotification())) {
                     break;
                 } else {
@@ -4399,16 +4399,6 @@
     }
 
     @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
-    public long getDarkAnimationDuration(boolean dark) {
-        long duration = StackStateAnimator.ANIMATION_DURATION_WAKEUP;
-        // Longer animation when sleeping with more than 1 notification
-        if (dark && getNotGoneChildCount() > 2) {
-            duration *= 1.2f;
-        }
-        return duration;
-    }
-
-    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private int findDarkAnimationOriginIndex(@Nullable PointF screenLocation) {
         if (screenLocation == null || screenLocation.y < mTopPadding) {
             return AnimationEvent.DARK_ANIMATION_ORIGIN_INDEX_ABOVE;
@@ -5796,7 +5786,13 @@
 
         @Override
         public boolean canChildBeDismissedInDirection(View v, boolean isRightOrDown) {
-            return (isLayoutRtl() ? !isRightOrDown : isRightOrDown) && canChildBeDismissed(v);
+            boolean isValidDirection;
+            if (NotificationUtils.useNewInterruptionModel(mContext)) {
+                isValidDirection = isLayoutRtl() ? !isRightOrDown : isRightOrDown;
+            } else {
+                isValidDirection = true;
+            }
+            return isValidDirection && canChildBeDismissed(v);
         }
     };
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
index da3fb66..a94401b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
@@ -26,10 +26,10 @@
 import com.android.keyguard.KeyguardSliceView;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.notification.row.ExpandableView;
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.StatusBarIconView;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.ExpandableView;
 
 import java.util.ArrayList;
 import java.util.HashSet;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
index a15fd70..b00068c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
@@ -28,9 +28,9 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.notification.row.ExpandableView;
 import com.android.systemui.statusbar.notification.AnimatableProperty;
 import com.android.systemui.statusbar.notification.PropertyAnimator;
+import com.android.systemui.statusbar.notification.row.ExpandableView;
 import com.android.systemui.statusbar.policy.HeadsUpUtil;
 
 import java.io.FileDescriptor;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
index ab58660..1d7e899 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
@@ -15,8 +15,10 @@
 package com.android.systemui.statusbar.phone;
 
 import android.content.Context;
+import android.hardware.display.ColorDisplayManager;
 import android.os.Handler;
 import android.provider.Settings.Secure;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.ColorDisplayController;
 import com.android.systemui.Dependency;
@@ -80,7 +82,7 @@
             Dependency.get(ManagedProfileController.class).addCallback(mProfileCallback);
         }
         if (!mAutoTracker.isAdded(NIGHT)
-            && ColorDisplayController.isAvailable(mContext)) {
+                && ColorDisplayManager.isNightDisplayAvailable(mContext)) {
             Dependency.get(ColorDisplayController.class).setListener(mColorDisplayCallback);
         }
     }
@@ -93,7 +95,9 @@
         Dependency.get(HotspotController.class).removeCallback(mHotspotCallback);
         Dependency.get(DataSaverController.class).removeCallback(mDataSaverListener);
         Dependency.get(ManagedProfileController.class).removeCallback(mProfileCallback);
-        Dependency.get(ColorDisplayController.class).setListener(null);
+        if (ColorDisplayManager.isNightDisplayAvailable(mContext)) {
+            Dependency.get(ColorDisplayController.class).setListener(null);
+        }
     }
 
     public void unmarkTileAsAutoAdded(String tabSpec) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
index c32dcea..3d81473 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.statusbar.phone;
 
-import android.app.ActivityManager;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Canvas;
@@ -25,9 +24,9 @@
 import android.graphics.Paint;
 import android.graphics.PixelFormat;
 import android.graphics.PorterDuff;
+import android.graphics.PorterDuff.Mode;
 import android.graphics.PorterDuffColorFilter;
 import android.graphics.Rect;
-import android.graphics.PorterDuff.Mode;
 import android.graphics.drawable.Drawable;
 import android.os.SystemClock;
 import android.util.Log;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index 8325bf8..302d630 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -16,18 +16,18 @@
 
 package com.android.systemui.statusbar.phone;
 
-import android.hardware.biometrics.BiometricSourceType;
 import android.content.Context;
+import android.hardware.biometrics.BiometricSourceType;
 import android.os.Handler;
 import android.os.PowerManager;
 import android.os.SystemClock;
 import android.os.Trace;
 import android.util.Log;
 
+import com.android.internal.util.LatencyTracker;
 import com.android.keyguard.KeyguardConstants;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
-import com.android.internal.util.LatencyTracker;
 import com.android.systemui.Dependency;
 import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.keyguard.ScreenLifecycle;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
index 119f01a..4ced702 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
@@ -21,8 +21,8 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
 import android.view.View;
-
 import android.view.View.AccessibilityDelegate;
+
 import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonInterface;
 import com.android.systemui.statusbar.policy.KeyButtonDrawable;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButtonGroup.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButtonGroup.java
index 9703043..cc8adde 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButtonGroup.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButtonGroup.java
@@ -19,6 +19,7 @@
 import android.annotation.IdRes;
 import android.annotation.NonNull;
 import android.view.View;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
index e052e53..3425dd2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
@@ -24,20 +24,20 @@
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
 import android.widget.LinearLayout;
 
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.systemui.DemoMode;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.StatusIconDisplayable;
 import com.android.systemui.statusbar.StatusBarIconView;
 import com.android.systemui.statusbar.StatusBarMobileView;
 import com.android.systemui.statusbar.StatusBarWifiView;
+import com.android.systemui.statusbar.StatusIconDisplayable;
 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
+
 import java.util.ArrayList;
 
 public class DemoStatusIcons extends StatusIconContainer implements DemoMode, DarkReceiver {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ExpandableIndicator.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ExpandableIndicator.java
index 8f49c85..efc2891 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ExpandableIndicator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ExpandableIndicator.java
@@ -18,6 +18,7 @@
 import android.graphics.drawable.AnimatedVectorDrawable;
 import android.util.AttributeSet;
 import android.widget.ImageView;
+
 import com.android.systemui.R;
 
 public class ExpandableIndicator extends ImageView {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
index c66bbb1..40f9f45 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
@@ -26,12 +26,12 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.CrossFadeHelper;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.HeadsUpStatusBarView;
 import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher;
 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 
 import java.util.function.BiConsumer;
 import java.util.function.Consumer;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index 976327a..d05893d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -21,8 +21,6 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
-import androidx.collection.ArraySet;
-
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.graphics.Region.Op;
@@ -33,16 +31,18 @@
 import android.view.View;
 import android.view.ViewTreeObserver;
 
+import androidx.collection.ArraySet;
+
 import com.android.systemui.Dependency;
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.ScreenDecorations;
 import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.StatusBarStateController.StateListener;
+import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
index e4a5caa..be4df45 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
@@ -21,10 +21,9 @@
 import android.view.ViewConfiguration;
 
 import com.android.systemui.Gefingerpoken;
+import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.ExpandableView;
-import com.android.systemui.statusbar.notification.NotificationData;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 
 /**
  * A helper class to handle touches on the heads-up views.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 5439497..21c506b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -54,6 +54,7 @@
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.util.MathUtils;
 import android.util.TypedValue;
 import android.view.View;
 import android.view.ViewGroup;
@@ -568,6 +569,7 @@
         mDarkAmount = darkAmount;
         mIndicationController.setDarkAmount(darkAmount);
         mLockIcon.setDarkAmount(darkAmount);
+        dozeTimeTick();
     }
 
     private static boolean isSuccessfulLaunch(int result) {
@@ -840,12 +842,10 @@
     }
 
     public void dozeTimeTick() {
-        if (mDarkAmount == 1) {
-            // Move views every minute to avoid burn-in
-            int burnInYOffset = getBurnInOffset(mBurnInYOffset * 2, false /* xAxis */)
-                    - mBurnInYOffset;
-            mLockIcon.setTranslationY(burnInYOffset);
-        }
+        // Move views every minute to avoid burn-in
+        int burnInYOffset = -getBurnInOffset(mBurnInYOffset, false /* xAxis */);
+        burnInYOffset = (int) MathUtils.lerp(0, burnInYOffset, mDarkAmount);
+        mLockIcon.setTranslationY(burnInYOffset);
     }
 
     public void setBurnInXOffset(int burnInXOffset) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 235629b..c0d1818 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -16,8 +16,8 @@
 
 package com.android.systemui.statusbar.phone;
 
-import static com.android.systemui.plugins.ActivityStarter.OnDismissAction;
 import static com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+import static com.android.systemui.plugins.ActivityStarter.OnDismissAction;
 
 import android.content.Context;
 import android.content.res.ColorStateList;
@@ -268,6 +268,8 @@
     }
 
     public void hide(boolean destroyView) {
+        // TODO(b/113914868): investigation log for disappearing home button
+        Log.i(TAG, "KeyguardBouncer.hide (b/113914868): destroyView=" + destroyView);
         if (isShowing()) {
             StatsLog.write(StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED,
                 StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__HIDDEN);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
index 8cace72..e0c5516 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
@@ -16,7 +16,9 @@
 
 package com.android.systemui.statusbar.phone;
 
-import android.app.WallpaperColors;
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
+
 import android.content.Context;
 import android.graphics.Color;
 import android.graphics.Rect;
@@ -32,9 +34,6 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
-import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
-import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
-
 /**
  * Controls how light status bar flag applies to the icons.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
index b0ac6ec..b29889d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
@@ -21,6 +21,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.SystemClock;
+import android.util.MathUtils;
 import android.util.TimeUtils;
 
 import com.android.systemui.Dependency;
@@ -29,6 +30,7 @@
 import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.CommandQueue.Callbacks;
+import com.android.systemui.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
 
 import java.io.FileDescriptor;
@@ -37,7 +39,8 @@
 /**
  * Class to control all aspects about light bar changes.
  */
-public class LightBarTransitionsController implements Dumpable, Callbacks {
+public class LightBarTransitionsController implements Dumpable, Callbacks,
+        StatusBarStateController.StateListener {
 
     public static final long DEFAULT_TINT_ANIMATION_DURATION = 120;
     private static final String EXTRA_DARK_INTENSITY = "dark_intensity";
@@ -45,6 +48,7 @@
     private final Handler mHandler;
     private final DarkIntensityApplier mApplier;
     private final KeyguardMonitor mKeyguardMonitor;
+    private final StatusBarStateController mStatusBarStateController;
 
     private boolean mTransitionDeferring;
     private long mTransitionDeferringStartTime;
@@ -55,6 +59,7 @@
     private ValueAnimator mTintAnimator;
     private float mDarkIntensity;
     private float mNextDarkIntensity;
+    private float mDozeAmount;
     private final Runnable mTransitionDeferringDoneRunnable = new Runnable() {
         @Override
         public void run() {
@@ -66,13 +71,17 @@
         mApplier = applier;
         mHandler = new Handler();
         mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
+        mStatusBarStateController = Dependency.get(StatusBarStateController.class);
         SysUiServiceProvider.getComponent(context, CommandQueue.class)
                 .addCallbacks(this);
+        mStatusBarStateController.addListener(this);
+        mDozeAmount = mStatusBarStateController.getDozeAmount();
     }
 
     public void destroy(Context context) {
         SysUiServiceProvider.getComponent(context, CommandQueue.class)
                 .removeCallbacks(this);
+        mStatusBarStateController.removeListener(this);
     }
 
     public void saveState(Bundle outState) {
@@ -173,7 +182,11 @@
 
     private void setIconTintInternal(float darkIntensity) {
         mDarkIntensity = darkIntensity;
-        mApplier.applyDarkIntensity(darkIntensity);
+        dispatchDark();
+    }
+
+    private void dispatchDark() {
+        mApplier.applyDarkIntensity(MathUtils.lerp(mDarkIntensity, 0f, mDozeAmount));
     }
 
     @Override
@@ -196,6 +209,15 @@
         pw.print(" mNextDarkIntensity="); pw.println(mNextDarkIntensity);
     }
 
+    @Override
+    public void onStateChanged(int newState) { }
+
+    @Override
+    public void onDozeAmountChanged(float linear, float eased) {
+        mDozeAmount = eased;
+        dispatchDark();
+    }
+
     /**
      * Interface to apply a specific dark intensity.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java
index 2779820..7621887 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java
@@ -19,7 +19,6 @@
 import android.metrics.LogMaker;
 import android.util.ArrayMap;
 
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
index 673cdb7..d2023ec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
@@ -20,6 +20,7 @@
 import android.app.ActivityManager;
 import android.app.IWallpaperManager;
 import android.app.IWallpaperManagerCallback;
+import android.app.WallpaperColors;
 import android.app.WallpaperManager;
 import android.content.Context;
 import android.content.res.Resources;
@@ -36,7 +37,6 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
-import android.app.WallpaperColors;
 import android.util.Log;
 
 import com.android.keyguard.KeyguardUpdateMonitor;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 4406b14..0cf1b3d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -144,6 +144,7 @@
 
     private OverviewProxyService mOverviewProxyService;
 
+    private boolean mIsOnDefaultDisplay = true;
     public boolean mHomeBlockedThisTouch;
 
     private final OverviewProxyListener mOverviewProxyListener = new OverviewProxyListener() {
@@ -241,6 +242,11 @@
     public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
         mNavigationBarView = (NavigationBarView) view;
+        final Display display = view.getDisplay();
+        // It may not have display when running unit test.
+        if (display != null) {
+            mIsOnDefaultDisplay = display.getDisplayId() == Display.DEFAULT_DISPLAY;
+        }
 
         mNavigationBarView.setComponents(mStatusBar.getPanel());
         mNavigationBarView.setDisabledFlags(mDisabledFlags1);
@@ -253,8 +259,6 @@
         prepareNavigationBarView();
         checkNavBarModes();
 
-        setDisabled2Flags(mDisabledFlags2);
-
         IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
         filter.addAction(Intent.ACTION_SCREEN_ON);
         filter.addAction(Intent.ACTION_USER_SWITCHED);
@@ -262,16 +266,23 @@
         notifyNavigationBarScreenOn();
         mOverviewProxyService.addCallback(mOverviewProxyListener);
 
-        RotationContextButton rotationButton = mNavigationBarView.getRotateSuggestionButton();
-        rotationButton.setListener(mRotationButtonListener);
-        rotationButton.addRotationCallback(mRotationWatcher);
+        // Currently there is no accelerometer sensor on non-default display.
+        if (mIsOnDefaultDisplay) {
+            final RotationContextButton rotationButton =
+                    mNavigationBarView.getRotateSuggestionButton();
+            rotationButton.setListener(mRotationButtonListener);
+            rotationButton.addRotationCallback(mRotationWatcher);
 
-        // Reset user rotation pref to match that of the WindowManager if starting in locked mode
-        // This will automatically happen when switching from auto-rotate to locked mode
-        if (rotationButton.isRotationLocked()) {
-            final int winRotation = mWindowManager.getDefaultDisplay().getRotation();
-            rotationButton.setRotationLockedAtAngle(winRotation);
+            // Reset user rotation pref to match that of the WindowManager if starting in locked
+            // mode. This will automatically happen when switching from auto-rotate to locked mode.
+            if (display != null && rotationButton.isRotationLocked()) {
+                final int winRotation = display.getRotation();
+                rotationButton.setRotationLockedAtAngle(winRotation);
+            }
+        } else {
+            mDisabledFlags2 |= StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS;
         }
+        setDisabled2Flags(mDisabledFlags2);
     }
 
     @Override
@@ -389,7 +400,7 @@
 
     @Override
     public void onRotationProposal(final int rotation, boolean isValid) {
-        final int winRotation = mWindowManager.getDefaultDisplay().getRotation();
+        final int winRotation = mNavigationBarView.getDisplay().getRotation();
         final boolean rotateSuggestionsDisabled = RotationContextButton
                 .hasDisable2RotateSuggestionFlag(mDisabledFlags2);
         if (RotationContextButton.DEBUG_ROTATION) {
@@ -477,10 +488,13 @@
             updateScreenPinningGestures();
         }
 
-        final int masked2 = state2 & (StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS);
-        if (masked2 != mDisabledFlags2) {
-            mDisabledFlags2 = masked2;
-            setDisabled2Flags(masked2);
+        // Only default display supports rotation suggestions.
+        if (mIsOnDefaultDisplay) {
+            final int masked2 = state2 & (StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS);
+            if (masked2 != mDisabledFlags2) {
+                mDisabledFlags2 = masked2;
+                setDisabled2Flags(masked2);
+            }
         }
     }
 
@@ -881,13 +895,23 @@
         if (DEBUG) Log.v(TAG, "addNavigationBar: about to add " + navigationBarView);
         if (navigationBarView == null) return null;
 
+        final NavigationBarFragment fragment = new NavigationBarFragment();
+        navigationBarView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
+            @Override
+            public void onViewAttachedToWindow(View v) {
+                final FragmentHostManager fragmentHost = FragmentHostManager.get(v);
+                fragmentHost.getFragmentManager().beginTransaction()
+                        .replace(R.id.navigation_bar_frame, fragment, TAG)
+                        .commit();
+                fragmentHost.addTagListener(TAG, listener);
+            }
+
+            @Override
+            public void onViewDetachedFromWindow(View v) {
+                FragmentHostManager.removeAndDestroy(v);
+            }
+        });
         context.getSystemService(WindowManager.class).addView(navigationBarView, lp);
-        FragmentHostManager fragmentHost = FragmentHostManager.get(navigationBarView);
-        NavigationBarFragment fragment = new NavigationBarFragment();
-        fragmentHost.getFragmentManager().beginTransaction()
-                .replace(R.id.navigation_bar_frame, fragment, TAG)
-                .commit();
-        fragmentHost.addTagListener(TAG, listener);
         return navigationBarView;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index 22b6ba6..7c31dae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -14,6 +14,8 @@
 
 package com.android.systemui.statusbar.phone;
 
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -34,11 +36,11 @@
 import android.widget.Space;
 
 import com.android.systemui.Dependency;
-import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.R;
 import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider;
+import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.statusbar.phone.ReverseLinearLayout.ReverseRelativeLayout;
 import com.android.systemui.statusbar.policy.KeyButtonView;
 import com.android.systemui.tuner.TunerService;
@@ -48,8 +50,6 @@
 import java.util.List;
 import java.util.Objects;
 
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-
 public class NavigationBarInflaterView extends FrameLayout
         implements Tunable, PluginListener<NavBarButtonProvider> {
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
index d58b554..12a0cc8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
@@ -26,7 +26,6 @@
 import android.view.IWindowManager;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.View.OnLayoutChangeListener;
 
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.systemui.Dependency;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 2c3c27f..2f58ca1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -17,10 +17,15 @@
 package com.android.systemui.statusbar.phone;
 
 import static android.view.MotionEvent.ACTION_DOWN;
+
+import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_QUICK_SCRUB;
+import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON;
 import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_BACK;
 import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_DEAD_ZONE;
 import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_HOME;
 import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_NONE;
+import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_OVERVIEW;
+import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_ROTATION;
 
 import android.animation.LayoutTransition;
 import android.animation.LayoutTransition.TransitionListener;
@@ -60,15 +65,15 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.DockedStackExistsListener;
 import com.android.systemui.Interpolators;
-import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.R;
 import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.plugins.statusbar.phone.NavGesture;
 import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
+import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.RecentsOnboarding;
+import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.NavigationBarCompat;
 import com.android.systemui.shared.system.WindowManagerWrapper;
@@ -79,11 +84,6 @@
 import java.io.PrintWriter;
 import java.util.function.Consumer;
 
-import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_QUICK_SCRUB;
-import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON;
-import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_OVERVIEW;
-import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_ROTATION;
-
 public class NavigationBarView extends FrameLayout implements PluginListener<NavGesture> {
     final static boolean DEBUG = false;
     final static String TAG = "StatusBar/NavBarView";
@@ -264,8 +264,7 @@
     public NavigationBarView(Context context, AttributeSet attrs) {
         super(context, attrs);
 
-        mDisplay = ((WindowManager) context.getSystemService(
-                Context.WINDOW_SERVICE)).getDefaultDisplay();
+        mDisplay = context.getDisplay();
 
         mVertical = false;
         mLongClickableAccessibilityButton = false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationGestureAction.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationGestureAction.java
index 593bfae..83067f6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationGestureAction.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationGestureAction.java
@@ -26,7 +26,6 @@
 import android.graphics.Canvas;
 import android.view.MotionEvent;
 
-import android.view.WindowManagerPolicyConstants;
 import com.android.systemui.recents.OverviewProxyService;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java
index 1524f80..2a11c26 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java
@@ -16,17 +16,14 @@
 
 import android.content.Context;
 import android.content.res.Configuration;
-import android.graphics.Rect;
-import androidx.annotation.VisibleForTesting;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.util.Pair;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
 
-import com.android.systemui.R;
+import androidx.annotation.VisibleForTesting;
 
 import java.util.ArrayList;
 import java.util.Comparator;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index ecf6b6a..fa71df2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -22,7 +22,6 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.app.ActivityManager;
 import android.app.Fragment;
@@ -41,7 +40,6 @@
 import android.os.PowerManager;
 import android.os.SystemProperties;
 import android.util.AttributeSet;
-import android.util.FloatProperty;
 import android.util.Log;
 import android.util.MathUtils;
 import android.view.LayoutInflater;
@@ -51,7 +49,6 @@
 import android.view.ViewGroup;
 import android.view.WindowInsets;
 import android.view.accessibility.AccessibilityManager;
-import android.view.animation.Interpolator;
 import android.widget.FrameLayout;
 
 import com.android.internal.logging.MetricsLogger;
@@ -104,7 +101,7 @@
         View.OnClickListener, NotificationStackScrollLayout.OnOverscrollTopChangedListener,
         KeyguardAffordanceHelper.Callback, NotificationStackScrollLayout.OnEmptySpaceClickListener,
         OnHeadsUpChangedListener, QS.HeightListener, ZenModeController.Callback,
-        ConfigurationController.ConfigurationListener {
+        ConfigurationController.ConfigurationListener, StateListener {
 
     private static final boolean DEBUG = false;
 
@@ -139,25 +136,9 @@
 
     private static final Rect mDummyDirtyRect = new Rect(0, 0, 1, 1);
 
-    public static final long DOZE_ANIMATION_DURATION = 700;
-
     private static final AnimationProperties CLOCK_ANIMATION_PROPERTIES = new AnimationProperties()
             .setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
-    private static final FloatProperty<NotificationPanelView> SET_DARK_AMOUNT_PROPERTY =
-            new FloatProperty<NotificationPanelView>("mInterpolatedDarkAmount") {
 
-                @Override
-                public void setValue(NotificationPanelView object, float value) {
-                    object.setDarkAmount(value, object.mDarkInterpolator.getInterpolation(value));
-                }
-
-                @Override
-                public Float get(NotificationPanelView object) {
-                    return object.mLinearDarkAmount;
-                }
-            };
-
-    private Interpolator mDarkInterpolator;
     private final PowerManager mPowerManager;
     private final AccessibilityManager mAccessibilityManager;
 
@@ -295,11 +276,9 @@
      */
     private boolean mSemiAwake;
 
-    private float mDarkAmountTarget;
     private boolean mPulsing;
     private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
     private boolean mNoVisibleNotifications = true;
-    private ValueAnimator mDarkAnimator;
     private boolean mUserSetupComplete;
     private int mQsNotificationTopPadding;
     private float mExpandOffset;
@@ -339,7 +318,6 @@
     private final NotificationEntryManager mEntryManager =
             Dependency.get(NotificationEntryManager.class);
 
-    private final StateListener mListener = this::setBarState;
     private final CommandQueue mCommandQueue;
     private final NotificationLockscreenUserManager mLockscreenUserManager =
             Dependency.get(NotificationLockscreenUserManager.class);
@@ -388,7 +366,7 @@
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
         FragmentHostManager.get(this).addTagListener(QS.TAG, mFragmentListener);
-        Dependency.get(StatusBarStateController.class).addListener(mListener);
+        Dependency.get(StatusBarStateController.class).addListener(this);
         Dependency.get(ZenModeController.class).addCallback(this);
         Dependency.get(ConfigurationController.class).addCallback(this);
     }
@@ -397,7 +375,7 @@
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
         FragmentHostManager.get(this).removeTagListener(QS.TAG, mFragmentListener);
-        Dependency.get(StatusBarStateController.class).removeListener(mListener);
+        Dependency.get(StatusBarStateController.class).removeListener(this);
         Dependency.get(ZenModeController.class).removeCallback(this);
         Dependency.get(ConfigurationController.class).removeCallback(this);
     }
@@ -475,7 +453,8 @@
         mKeyguardBottomArea.initFrom(oldBottomArea);
         addView(mKeyguardBottomArea, index);
         initBottomArea();
-        setDarkAmount(mLinearDarkAmount, mInterpolatedDarkAmount);
+        onDozeAmountChanged(mStatusBarStateController.getDozeAmount(),
+                mStatusBarStateController.getInterpolatedDozeAmount());
 
         if (mKeyguardStatusBar != null) {
             mKeyguardStatusBar.onThemeChanged();
@@ -1221,7 +1200,8 @@
         }
     }
 
-    private void setBarState(int statusBarState) {
+    @Override
+    public void onStateChanged(int statusBarState) {
         boolean goingToFullShade = mStatusBarStateController.goingToFullShade();
         boolean keyguardFadingAway = mKeyguardMonitor.isKeyguardFadingAway();
         int oldState = mBarState;
@@ -2806,24 +2786,10 @@
             updateDozingVisibilities(animate);
         }
 
-        final float darkAmount = dozing ? 1 : 0;
-        if (mDarkAnimator != null && mDarkAnimator.isRunning()) {
-            if (animate && mDarkAmountTarget == darkAmount) {
-                return;
-            } else {
-                mDarkAnimator.cancel();
-            }
-            if (mSemiAwake) {
-                setDarkAmount(0, 0);
-            }
-        }
-        mDarkAmountTarget = darkAmount;
-        if (!mSemiAwake) {
-            if (animate) {
-                startDarkAnimation();
-            } else {
-                setDarkAmount(darkAmount, darkAmount);
-            }
+        final float darkAmount = dozing && !mSemiAwake ? 1 : 0;
+        mStatusBarStateController.setDozeAmount(darkAmount, animate);
+        if (animate) {
+            mNotificationStackScroller.notifyDarkAnimationStart(mDozing);
         }
     }
 
@@ -2831,21 +2797,8 @@
         return mSemiAwake;
     }
 
-    private void startDarkAnimation() {
-        if (mInterpolatedDarkAmount == 0f || mInterpolatedDarkAmount == 1f) {
-            mDarkInterpolator = mDozing
-                    ? Interpolators.FAST_OUT_SLOW_IN
-                    : Interpolators.TOUCH_RESPONSE_REVERSE;
-        }
-        mNotificationStackScroller.notifyDarkAnimationStart(mDozing);
-        mDarkAnimator = ObjectAnimator.ofFloat(this, SET_DARK_AMOUNT_PROPERTY, mDozing ? 1 : 0);
-        mDarkAnimator.setInterpolator(Interpolators.LINEAR);
-        mDarkAnimator.setDuration(
-                mNotificationStackScroller.getDarkAnimationDuration(mDozing));
-        mDarkAnimator.start();
-    }
-
-    private void setDarkAmount(float linearAmount, float amount) {
+    @Override
+    public void onDozeAmountChanged(float linearAmount, float amount) {
         mInterpolatedDarkAmount = amount;
         mLinearDarkAmount = linearAmount;
         mKeyguardStatusBar.setDarkAmount(mInterpolatedDarkAmount);
@@ -3047,7 +3000,8 @@
             mSemiAwake = false;
             mNotificationStackScroller.setDark(false /* dark */, true /* animate */,
                     null /* touchLocation */);
-            startDarkAnimation();
+            mStatusBarStateController.setDozeAmount(0f, true /* animated */);
+            mNotificationStackScroller.notifyDarkAnimationStart(mDozing);
             mStatusBar.updateScrimController();
 
             return WAKE_UP_TO_SHADE;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
index e7ede6f..ca762cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
@@ -20,7 +20,6 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.Canvas;
-import androidx.annotation.DimenRes;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewStub;
@@ -28,6 +27,8 @@
 import android.view.WindowInsets;
 import android.widget.FrameLayout;
 
+import androidx.annotation.DimenRes;
+
 import com.android.systemui.R;
 import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index deac669e..65b0ecc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -22,7 +22,6 @@
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.MotionEvent;
-import android.view.View;
 import android.widget.FrameLayout;
 
 public abstract class PanelBar extends FrameLayout {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubAction.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubAction.java
index c64e124..74744f1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubAction.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubAction.java
@@ -34,7 +34,6 @@
 import android.graphics.Rect;
 import android.graphics.Shader;
 import android.os.RemoteException;
-
 import android.util.FloatProperty;
 import android.util.Log;
 import android.view.MotionEvent;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
index 37c4c58a..0eff4d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
@@ -42,10 +42,10 @@
 
 import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
-import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
 import com.android.systemui.R;
-import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
+import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.shared.recents.IOverviewProxy;
 import com.android.systemui.shared.recents.utilities.Utilities;
 import com.android.systemui.shared.system.NavigationBarCompat;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
index c6e98e0..a7b8eff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
@@ -39,10 +39,10 @@
 import android.view.View;
 import android.view.WindowManagerGlobal;
 
-import com.android.systemui.Dependency;
-import com.android.systemui.Interpolators;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.systemui.Dependency;
+import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.TaskStackChangeListener;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenPinningNotify.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenPinningNotify.java
index 2a5028b..f8731b4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenPinningNotify.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenPinningNotify.java
@@ -19,7 +19,6 @@
 import android.content.Context;
 import android.os.SystemClock;
 import android.util.Slog;
-import android.view.WindowManager;
 import android.widget.Toast;
 
 import com.android.systemui.R;
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 1bed26d..9f34cbb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -23,7 +23,6 @@
 import android.app.WallpaperManager;
 import android.content.Context;
 import android.graphics.Color;
-import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.os.Trace;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java
index e546119..f926218 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java
@@ -15,6 +15,7 @@
 package com.android.systemui.statusbar.phone;
 
 import android.view.View;
+
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 12fbf2d..a6a9d74 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -342,7 +342,8 @@
     private int mStatusBarWindowState = WINDOW_STATE_SHOWING;
     protected StatusBarWindowController mStatusBarWindowController;
     protected UnlockMethodCache mUnlockMethodCache;
-    private DozeServiceHost mDozeServiceHost = new DozeServiceHost();
+    @VisibleForTesting
+    DozeServiceHost mDozeServiceHost = new DozeServiceHost();
     private boolean mWakeUpComingFromTouch;
     private PointF mWakeUpTouchLocation;
 
@@ -479,7 +480,7 @@
     private boolean mLaunchCameraOnScreenTurningOn;
     private boolean mLaunchCameraOnFinishedGoingToSleep;
     private int mLastCameraLaunchSource;
-    private PowerManager.WakeLock mGestureWakeLock;
+    protected PowerManager.WakeLock mGestureWakeLock;
     private Vibrator mVibrator;
     private long[] mCameraLaunchGestureVibePattern;
 
@@ -3609,6 +3610,7 @@
         }
     }
 
+    @VisibleForTesting
     final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() {
         @Override
         public void onFinishedGoingToSleep() {
@@ -3650,6 +3652,7 @@
             mNotificationPanel.setTouchAndAnimationDisabled(false);
             updateVisibleToUser();
             updateIsKeyguard();
+            mDozeServiceHost.stopDozing();
         }
     };
 
@@ -3856,7 +3859,8 @@
         return mStatusBarKeyguardViewManager.isShowing();
     }
 
-    private final class DozeServiceHost implements DozeHost {
+    @VisibleForTesting
+    final class DozeServiceHost implements DozeHost {
         private final ArrayList<Callback> mCallbacks = new ArrayList<>();
         private boolean mAnimateWakeup;
         private boolean mAnimateScreenOff;
@@ -3944,7 +3948,6 @@
                 mDozingRequested = false;
                 DozeLog.traceDozing(mContext, mDozing);
                 updateDozing();
-                mWakefulnessLifecycle.dispatchStartedWakingUp();
             }
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index 0d6cb5c..26c9d28 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -16,16 +16,15 @@
 
 import static android.app.StatusBarManager.DISABLE2_SYSTEM_ICONS;
 import static android.app.StatusBarManager.DISABLE_NONE;
+
 import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_ICON;
 import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_MOBILE;
 import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_WIFI;
 
 import android.content.Context;
 import android.os.Bundle;
-import androidx.annotation.VisibleForTesting;
 import android.text.TextUtils;
 import android.util.ArraySet;
-import android.util.Log;
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
@@ -33,19 +32,22 @@
 import android.widget.LinearLayout;
 import android.widget.LinearLayout.LayoutParams;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.systemui.DemoMode;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.StatusIconDisplayable;
 import com.android.systemui.statusbar.StatusBarIconView;
 import com.android.systemui.statusbar.StatusBarMobileView;
 import com.android.systemui.statusbar.StatusBarWifiView;
+import com.android.systemui.statusbar.StatusIconDisplayable;
 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
 import com.android.systemui.util.Utils.DisableStateTracker;
+
 import java.util.List;
 
 public interface StatusBarIconController {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
index 24a5896..7c17c01 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
@@ -45,8 +45,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import static com.android.systemui.statusbar.phone.StatusBarIconController.TAG_PRIMARY;
-
 /**
  * Receives the callbacks from CommandQueue related to icons and tracks the state of
  * all the icons. Dispatches this state to any IconManagers that are currently
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
index c4ff85f..88d0035 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.graphics.drawable.Icon;
 import android.os.UserHandle;
+
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
index b7e1cfb..2e41617 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
@@ -16,16 +16,17 @@
 
 package com.android.systemui.statusbar.phone;
 
+import static com.android.systemui.statusbar.phone.StatusBarIconController.TAG_PRIMARY;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.statusbar.StatusBarIcon;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 
-import static com.android.systemui.statusbar.phone.StatusBarIconController.TAG_PRIMARY;
-
 public class StatusBarIconList {
     private ArrayList<Slot> mSlots = new ArrayList<>();
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
index f81ffe9..8286d26 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
@@ -17,29 +17,20 @@
 package com.android.systemui.statusbar.phone;
 
 import android.content.Context;
-import android.content.res.ColorStateList;
-import android.graphics.Rect;
 import android.os.Handler;
-import android.os.Looper;
 import android.telephony.SubscriptionInfo;
 import android.util.ArraySet;
 import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.accessibility.AccessibilityEvent;
-import android.widget.ImageView;
-import com.android.settingslib.graph.SignalDrawable;
+
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher;
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl;
 import com.android.systemui.statusbar.policy.SecurityController;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerService.Tunable;
+
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index ad9b9b3..978a72d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -33,7 +33,6 @@
 import android.media.session.MediaSessionLegacyHelper;
 import android.net.Uri;
 import android.os.Bundle;
-import android.os.IBinder;
 import android.os.SystemClock;
 import android.util.AttributeSet;
 import android.view.ActionMode;
@@ -50,8 +49,6 @@
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 import android.view.Window;
-import android.view.WindowManager;
-import android.view.WindowManagerGlobal;
 import android.widget.FrameLayout;
 
 import com.android.internal.annotations.VisibleForTesting;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
index 56a177e..6495910 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
@@ -16,9 +16,9 @@
 
 package com.android.systemui.statusbar.phone;
 
-import static com.android.systemui.statusbar.StatusBarIconView.STATE_ICON;
 import static com.android.systemui.statusbar.StatusBarIconView.STATE_DOT;
 import static com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN;
+import static com.android.systemui.statusbar.StatusBarIconView.STATE_ICON;
 
 import android.annotation.Nullable;
 import android.content.Context;
@@ -28,14 +28,15 @@
 import android.graphics.Paint.Style;
 import android.util.AttributeSet;
 import android.util.Log;
-
 import android.view.View;
+
 import com.android.keyguard.AlphaOptimizedLinearLayout;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.StatusIconDisplayable;
 import com.android.systemui.statusbar.notification.stack.AnimationFilter;
 import com.android.systemui.statusbar.notification.stack.AnimationProperties;
 import com.android.systemui.statusbar.notification.stack.ViewState;
+
 import java.util.ArrayList;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
index e5925f0..bdd76c8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
@@ -16,8 +16,8 @@
 
 package com.android.systemui.statusbar.phone;
 
-import android.hardware.biometrics.BiometricSourceType;
 import android.content.Context;
+import android.hardware.biometrics.BiometricSourceType;
 import android.os.Trace;
 
 import com.android.internal.widget.LockPatternUtils;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java
index 2ed2edb..ba55f2d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java
@@ -20,7 +20,6 @@
 import android.content.res.ColorStateList;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
-import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.View;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java
index d85e18c..67da8a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java
@@ -14,14 +14,11 @@
 
 package com.android.systemui.statusbar.policy;
 
-import android.accessibilityservice.AccessibilityServiceInfo;
 import android.content.Context;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener;
 
-import java.util.List;
-
 /**
  * For mocking because AccessibilityManager is final for some reason...
  */
@@ -62,8 +59,8 @@
         mAccessibilityManager.sendAccessibilityEvent(event);
     }
 
-    public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(
-            int feedbackTypeFlags) {
-        return mAccessibilityManager.getEnabledAccessibilityServiceList(feedbackTypeFlags);
+    /** Returns a recommended ui timeout value in milliseconds. */
+    public int getRecommendedTimeoutMillis(int originalTimeout, int uiContentFlags) {
+        return mAccessibilityManager.getRecommendedTimeoutMillis(originalTimeout, uiContentFlags);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
index 6f4026d..f65f826 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
@@ -55,4 +55,11 @@
         default void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {}
         default void onPowerSaveChanged(boolean isPowerSave) {}
     }
+
+    /**
+     * If available, get the estimated battery time remaining as a string
+     */
+    default String getEstimatedTimeRemainingString() {
+        return null;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
index 7221efa..ddcfbf6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
@@ -29,9 +29,14 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.settingslib.fuelgauge.BatterySaverUtils;
+import com.android.settingslib.utils.PowerUtil;
+import com.android.systemui.Dependency;
+import com.android.systemui.power.EnhancedEstimates;
+import com.android.systemui.power.Estimate;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.text.NumberFormat;
 import java.util.ArrayList;
 
 /**
@@ -44,7 +49,9 @@
     public static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST";
 
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+    private static final int UPDATE_GRANULARITY_MSEC = 1000 * 60;
 
+    private final EnhancedEstimates mEstimates = Dependency.get(EnhancedEstimates.class);
     private final ArrayList<BatteryController.BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>();
     private final PowerManager mPowerManager;
     private final Handler mHandler;
@@ -58,6 +65,8 @@
     protected boolean mAodPowerSave;
     private boolean mTestmode = false;
     private boolean mHasReceivedBattery = false;
+    private Estimate mEstimate;
+    private long mLastEstimateTimestamp = -1;
 
     public BatteryControllerImpl(Context context) {
         this(context, context.getSystemService(PowerManager.class));
@@ -71,6 +80,7 @@
 
         registerReceiver();
         updatePowerSave();
+        updateEstimate();
     }
 
     private void registerReceiver() {
@@ -180,6 +190,26 @@
         return mAodPowerSave;
     }
 
+    @Override
+    public String getEstimatedTimeRemainingString() {
+        if (mEstimate == null
+                || System.currentTimeMillis() > mLastEstimateTimestamp + UPDATE_GRANULARITY_MSEC) {
+            updateEstimate();
+        }
+        // Estimates may not exist yet even if we've checked
+        if (mEstimate == null) {
+            return null;
+        }
+        final String percentage = NumberFormat.getPercentInstance().format((double) mLevel / 100.0);
+        return PowerUtil.getBatteryRemainingShortStringFormatted(
+                mContext, mEstimate.estimateMillis);
+    }
+
+    private void updateEstimate() {
+        mEstimate = mEstimates.getEstimate();
+        mLastEstimateTimestamp = System.currentTimeMillis();
+    }
+
     private void updatePowerSave() {
         setPowerSave(mPowerManager.isPowerSaveMode());
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
index b76d536..e1bb19a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
@@ -19,6 +19,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.telephony.SubscriptionInfo;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
index 533bd86..ccfe073 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.policy;
 
+import static android.media.MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY;
+
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
@@ -30,6 +32,8 @@
 import android.util.ArraySet;
 import android.util.Log;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.internal.annotations.GuardedBy;
 import com.android.systemui.R;
 
@@ -40,10 +44,6 @@
 import java.util.Set;
 import java.util.UUID;
 
-import static android.media.MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY;
-
-import androidx.annotation.VisibleForTesting;
-
 
 /** Platform implementation of the cast controller. **/
 public class CastControllerImpl implements CastController {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java
index 2ede327..911715f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java
@@ -21,8 +21,6 @@
 import android.os.Looper;
 import android.os.RemoteException;
 
-import com.android.systemui.statusbar.policy.DataSaverController.Listener;
-
 import java.util.ArrayList;
 
 public class DataSaverControllerImpl implements DataSaverController {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
index dcce77c..74a30fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
@@ -27,7 +27,6 @@
 import android.util.AttributeSet;
 import android.widget.TextView;
 
-import com.android.settingslib.Utils;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedController.java
index cae76b4..7b4c35a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedController.java
@@ -14,8 +14,6 @@
 
 package com.android.systemui.statusbar.policy;
 
-import android.content.Context;
-
 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
 
 public interface DeviceProvisionedController extends CallbackController<DeviceProvisionedListener> {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java
index c726189..0d6178b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java
@@ -23,13 +23,9 @@
 import android.content.IntentFilter;
 import android.net.ConnectivityManager;
 import android.provider.Settings;
-import android.telephony.ServiceState;
 import android.telephony.SubscriptionInfo;
 import android.text.TextUtils;
 import android.util.AttributeSet;
-import android.util.Log;
-import android.view.ViewGroup;
-import android.view.ViewParent;
 import android.widget.TextView;
 
 import com.android.internal.telephony.IccCardConstants;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
index 11fc408..e23ce2d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
@@ -30,8 +30,6 @@
 import android.text.TextUtils;
 import android.util.Log;
 
-import com.android.systemui.statusbar.policy.FlashlightController.FlashlightListener;
-
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index b4d24d16..6b83b70b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -16,22 +16,23 @@
 
 package com.android.systemui.statusbar.policy;
 
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_HEADS_UP;
+import static com.android.systemui.statusbar.notification.row.NotificationInflater
+        .FLAG_CONTENT_VIEW_HEADS_UP;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Resources;
 import android.database.ContentObserver;
-import android.util.ArrayMap;
 import android.provider.Settings;
+import android.util.ArrayMap;
 import android.util.Log;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.AlertingNotificationManager;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IconLoggerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IconLoggerImpl.java
index 5fd79a4..aee021c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IconLoggerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IconLoggerImpl.java
@@ -23,9 +23,10 @@
 import android.metrics.LogMaker;
 import android.os.Handler;
 import android.os.Looper;
-import androidx.annotation.VisibleForTesting;
 import android.util.ArraySet;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.internal.logging.MetricsLogger;
 
 import java.util.Arrays;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
index 2340786..03c89c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
@@ -37,6 +37,7 @@
 import android.graphics.drawable.Drawable;
 import android.util.FloatProperty;
 import android.view.ContextThemeWrapper;
+
 import com.android.settingslib.Utils;
 import com.android.systemui.R;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
index 59bd85e..8b86996 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
@@ -25,9 +25,9 @@
 import android.graphics.ColorFilter;
 import android.graphics.Paint;
 import android.graphics.PixelFormat;
+import android.graphics.RecordingCanvas;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
-import android.graphics.RecordingCanvas;
 import android.view.RenderNodeAnimator;
 import android.view.View;
 import android.view.ViewConfiguration;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index 6fa73ef..2c756ce 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -45,12 +45,13 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.ImageView;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
-import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.R;
 import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonInterface;
+import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.shared.system.NavigationBarCompat;
 
 public class KeyButtonView extends ImageView implements ButtonInterface {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
index fcd7e09..840e77e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
@@ -29,12 +29,14 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
-import android.os.Process;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+
 import androidx.annotation.VisibleForTesting;
+
 import com.android.systemui.util.Utils;
+
 import java.util.ArrayList;
 import java.util.List;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 8ca1415..e943261 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -35,8 +35,8 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.cdma.EriInfo;
-import com.android.settingslib.graph.SignalDrawable;
 import com.android.settingslib.Utils;
+import com.android.settingslib.graph.SignalDrawable;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java
index dfdeae1..dac878c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java
@@ -23,8 +23,6 @@
 import android.content.IntentFilter;
 import android.os.UserHandle;
 
-import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
-
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnHeadsUpChangedListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnHeadsUpChangedListener.java
index 5028fd1..d434768 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnHeadsUpChangedListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnHeadsUpChangedListener.java
@@ -16,8 +16,8 @@
 
 package com.android.systemui.statusbar.policy;
 
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 
 /**
  * A listener to heads up changes
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index 7dd0d0f..a485fa8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -55,8 +55,8 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.RemoteInputController;
+import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
 import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
index 91c208d..9ec30d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
@@ -15,16 +15,17 @@
  */
 package com.android.systemui.statusbar.policy;
 
+import static com.android.systemui.statusbar.policy.NetworkControllerImpl.TAG;
+
 import android.content.Context;
 import android.text.format.DateFormat;
 import android.util.Log;
+
 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 
 import java.io.PrintWriter;
 import java.util.BitSet;
 
-import static com.android.systemui.statusbar.policy.NetworkControllerImpl.TAG;
-
 
 /**
  * Common base class for handling signal for both wifi and mobile data.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
index 7b0b8004..71d6e54 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.statusbar.policy;
 
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.res.Resources;
 import android.database.ContentObserver;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
index aa4782f..42f1378 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
@@ -28,11 +28,11 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ContrastColorUtil;
-import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
 import com.android.systemui.statusbar.SmartReplyController;
+import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java
index f5ae88b..fed8032 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java
@@ -37,7 +37,6 @@
 import com.android.internal.util.UserIcons;
 import com.android.settingslib.drawable.UserIconDrawable;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
 
 import java.util.ArrayList;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index b5d92a5..cd379c5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -25,7 +25,6 @@
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.systemui.SystemUI;
-import com.android.systemui.pip.tv.PipManager;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.CommandQueue.Callbacks;
 
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java
index 499be42..905b9a3 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java
@@ -14,19 +14,21 @@
 
 package com.android.systemui.tuner;
 
+import static android.provider.Settings.System.SHOW_BATTERY_PERCENT;
+
 import android.content.Context;
 import android.provider.Settings;
-import androidx.preference.DropDownPreference;
 import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.AttributeSet;
+
+import androidx.preference.DropDownPreference;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 
-import static android.provider.Settings.System.SHOW_BATTERY_PERCENT;
-
 public class BatteryPreference extends DropDownPreference implements TunerService.Tunable {
 
     private static final String PERCENT = "percent";
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/BetterListPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/BetterListPreference.java
index 702abea..265823a 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/BetterListPreference.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/BetterListPreference.java
@@ -15,9 +15,10 @@
 package com.android.systemui.tuner;
 
 import android.content.Context;
-import androidx.preference.ListPreference;
 import android.util.AttributeSet;
 
+import androidx.preference.ListPreference;
+
 public class BetterListPreference extends ListPreference {
 
     private CharSequence mSummary;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/ClockPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/ClockPreference.java
index 16ab65c..a526603 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/ClockPreference.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/ClockPreference.java
@@ -14,11 +14,12 @@
 package com.android.systemui.tuner;
 
 import android.content.Context;
-import androidx.preference.DropDownPreference;
 import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.AttributeSet;
 
+import androidx.preference.DropDownPreference;
+
 import com.android.systemui.Dependency;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.policy.Clock;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/CustomListPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/CustomListPreference.java
index 8da0043..ade1f82 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/CustomListPreference.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/CustomListPreference.java
@@ -14,7 +14,6 @@
 
 package com.android.systemui.tuner;
 
-import android.annotation.Nullable;
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.DialogFragment;
@@ -22,12 +21,10 @@
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnClickListener;
 import android.os.Bundle;
-import androidx.preference.ListPreferenceDialogFragment;
-import androidx.preference.ListPreference;
 import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
+
+import androidx.preference.ListPreference;
+import androidx.preference.ListPreferenceDialogFragment;
 
 public class CustomListPreference extends ListPreference {
 
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
index a0f278b..a60ca62 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
@@ -23,12 +23,13 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.provider.Settings;
-import androidx.preference.PreferenceFragment;
-import androidx.preference.SwitchPreference;
+import android.view.MenuItem;
+
 import androidx.preference.Preference;
 import androidx.preference.Preference.OnPreferenceChangeListener;
+import androidx.preference.PreferenceFragment;
 import androidx.preference.PreferenceScreen;
-import android.view.MenuItem;
+import androidx.preference.SwitchPreference;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java
index d63235c..4dbceac 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java
@@ -21,32 +21,25 @@
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.LauncherActivityInfo;
-import android.content.pm.LauncherApps;
-import android.content.pm.LauncherApps.ShortcutQuery;
 import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ShortcutInfo;
 import android.graphics.drawable.Drawable;
-import android.graphics.drawable.ScaleDrawable;
 import android.os.Bundle;
 import android.os.Handler;
-import android.os.Process;
-import androidx.preference.PreferenceFragment;
-import androidx.preference.SwitchPreference;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceGroup;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.recyclerview.widget.RecyclerView.ViewHolder;
 import android.text.TextUtils;
-import android.util.Log;
 import android.util.TypedValue;
-import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import androidx.preference.Preference;
+import androidx.preference.PreferenceFragment;
+import androidx.preference.SwitchPreference;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.ViewHolder;
+
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.plugins.IntentButtonProvider.IntentButton;
@@ -57,7 +50,6 @@
 import com.android.systemui.tuner.TunerService.Tunable;
 
 import java.util.ArrayList;
-import java.util.List;
 import java.util.Map;
 import java.util.function.Consumer;
 
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java b/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java
index e3a452a..fa531b5 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java
@@ -34,9 +34,6 @@
 import android.graphics.drawable.Icon;
 import android.os.Bundle;
 import android.os.Handler;
-import androidx.preference.ListPreference;
-import androidx.preference.Preference;
-import androidx.preference.Preference.OnPreferenceChangeListener;
 import android.text.SpannableStringBuilder;
 import android.text.style.ImageSpan;
 import android.util.Log;
@@ -44,6 +41,10 @@
 import android.view.KeyEvent;
 import android.widget.EditText;
 
+import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+import androidx.preference.Preference.OnPreferenceChangeListener;
+
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.tuner.TunerService.Tunable;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/OtherPrefs.java b/packages/SystemUI/src/com/android/systemui/tuner/OtherPrefs.java
index d766145..7239c8a 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/OtherPrefs.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/OtherPrefs.java
@@ -15,7 +15,9 @@
 package com.android.systemui.tuner;
 
 import android.os.Bundle;
+
 import androidx.preference.PreferenceFragment;
+
 import com.android.systemui.R;
 
 public class OtherPrefs extends PreferenceFragment {
@@ -23,4 +25,4 @@
     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
         addPreferencesFromResource(R.xml.other_settings);
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java
index ecb830c..dae1472 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java
@@ -29,6 +29,11 @@
 import android.util.ArraySet;
 import android.view.View;
 
+import androidx.preference.PreferenceFragment;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.PreferenceViewHolder;
+import androidx.preference.SwitchPreference;
+
 import com.android.internal.util.ArrayUtils;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
@@ -41,11 +46,6 @@
 import java.util.List;
 import java.util.Set;
 
-import androidx.preference.PreferenceFragment;
-import androidx.preference.PreferenceScreen;
-import androidx.preference.PreferenceViewHolder;
-import androidx.preference.SwitchPreference;
-
 public class PluginFragment extends PreferenceFragment {
 
     public static final String ACTION_PLUGIN_SETTINGS
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/PowerNotificationControlsFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/PowerNotificationControlsFragment.java
index 8740a3c..80f9de6 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/PowerNotificationControlsFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/PowerNotificationControlsFragment.java
@@ -15,10 +15,6 @@
  */
 package com.android.systemui.tuner;
 
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.R;
-
 import android.annotation.Nullable;
 import android.app.Fragment;
 import android.os.Bundle;
@@ -29,6 +25,10 @@
 import android.widget.Switch;
 import android.widget.TextView;
 
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.systemui.R;
+
 public class PowerNotificationControlsFragment extends Fragment {
 
     private static final String KEY_SHOW_PNC = "show_importance_slider";
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/RadioListPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/RadioListPreference.java
index d80c649..79811c5 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/RadioListPreference.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/RadioListPreference.java
@@ -17,21 +17,19 @@
 import android.app.AlertDialog.Builder;
 import android.app.Dialog;
 import android.app.DialogFragment;
-import android.app.Fragment;
 import android.content.Context;
 import android.content.DialogInterface.OnClickListener;
 import android.os.Bundle;
-import androidx.preference.PreferenceFragment;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.View;
 import android.widget.Toolbar;
 
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
 import com.android.settingslib.Utils;
-import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.R;
+import com.android.systemui.fragments.FragmentHostManager;
 
 import java.util.Objects;
 
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/SelectablePreference.java b/packages/SystemUI/src/com/android/systemui/tuner/SelectablePreference.java
index dded464..0be793e 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/SelectablePreference.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/SelectablePreference.java
@@ -16,9 +16,10 @@
 
 import android.content.Context;
 import android.graphics.drawable.Drawable;
-import androidx.preference.CheckBoxPreference;
 import android.util.TypedValue;
 
+import androidx.preference.CheckBoxPreference;
+
 import com.android.systemui.statusbar.ScalingDrawableWrapper;
 
 public class SelectablePreference extends CheckBoxPreference {
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/ShortcutPicker.java b/packages/SystemUI/src/com/android/systemui/tuner/ShortcutPicker.java
index 3c9d25d..11e1f27 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/ShortcutPicker.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/ShortcutPicker.java
@@ -20,12 +20,12 @@
 import android.content.pm.LauncherActivityInfo;
 import android.content.pm.LauncherApps;
 import android.content.pm.PackageManager.NameNotFoundException;
-import android.graphics.drawable.ColorDrawable;
 import android.os.Bundle;
 import android.os.Process;
-import androidx.preference.PreferenceFragment;
+
 import androidx.preference.Preference;
 import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceFragment;
 import androidx.preference.PreferenceScreen;
 import androidx.preference.PreferenceViewHolder;
 
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
index 670fcc2..6f23e20 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
@@ -19,10 +19,11 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.provider.Settings;
-import androidx.preference.SwitchPreference;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 
+import androidx.preference.SwitchPreference;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
index 5aa3035..ecf1784 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
@@ -22,12 +22,13 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.provider.Settings;
-import androidx.preference.PreferenceFragment;
-import androidx.preference.Preference;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 
+import androidx.preference.Preference;
+import androidx.preference.PreferenceFragment;
+
 import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerPreferenceFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerPreferenceFragment.java
index a22277e..9cc8943 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerPreferenceFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerPreferenceFragment.java
@@ -15,9 +15,9 @@
 package com.android.systemui.tuner;
 
 import android.app.DialogFragment;
-import android.os.Bundle;
-import androidx.preference.PreferenceFragment;
+
 import androidx.preference.Preference;
+import androidx.preference.PreferenceFragment;
 
 public abstract class TunerPreferenceFragment extends PreferenceFragment {
 
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
index 3a9d1c7..3bccdab 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
@@ -26,8 +26,6 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 
-import static android.provider.Settings.System.SHOW_BATTERY_PERCENT;
-import com.android.systemui.DemoMode;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java
index f53d516..2df9000 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java
@@ -3,9 +3,10 @@
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.provider.Settings;
-import androidx.preference.SwitchPreference;
 import android.util.AttributeSet;
 
+import androidx.preference.SwitchPreference;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index 2f8dfdc..329d029 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.app.Notification;
 import android.app.Notification.Action;
-import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
index ec5030b..fa3ff64 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.usb;
 
+import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
+
 import android.content.ActivityNotFoundException;
 import android.content.Intent;
 import android.content.pm.ResolveInfo;
@@ -38,8 +40,6 @@
 import java.util.ArrayList;
 import java.util.Iterator;
 
-import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
-
 /* Activity for choosing an application for a USB device or accessory */
 public class UsbResolverActivity extends ResolverActivity {
     public static final String TAG = "UsbResolverActivity";
diff --git a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
index c468fef..f35af90 100644
--- a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
+++ b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
@@ -16,7 +16,6 @@
 
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
-
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.media.AudioAttributes;
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java b/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java
index 9b15b00..efd6e03 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java
@@ -20,9 +20,10 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Build;
-import androidx.core.content.FileProvider;
 import android.util.Log;
 
+import androidx.core.content.FileProvider;
+
 import com.android.systemui.Dependency;
 
 import java.io.BufferedInputStream;
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
index 3c88d29..b2cc269 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
@@ -37,7 +37,6 @@
 import android.os.Process;
 import android.os.SystemProperties;
 import android.provider.Settings;
-import androidx.annotation.VisibleForTesting;
 import android.service.quicksettings.Tile;
 import android.text.format.DateUtils;
 import android.util.Log;
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/LeakDetector.java b/packages/SystemUI/src/com/android/systemui/util/leak/LeakDetector.java
index 574fdb98..c50e8f8 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/LeakDetector.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/LeakDetector.java
@@ -24,7 +24,6 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.io.Writer;
 import java.util.Collection;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java b/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java
index 8ea5fd4..a47e99d 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java
@@ -27,9 +27,10 @@
 import android.os.Debug;
 import android.os.SystemProperties;
 import android.os.UserHandle;
-import androidx.core.content.FileProvider;
 import android.util.Log;
 
+import androidx.core.content.FileProvider;
+
 import com.google.android.collect.Lists;
 
 import java.io.File;
diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/SettableWakeLock.java b/packages/SystemUI/src/com/android/systemui/util/wakelock/SettableWakeLock.java
index f2ed55f3..13729df 100644
--- a/packages/SystemUI/src/com/android/systemui/util/wakelock/SettableWakeLock.java
+++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/SettableWakeLock.java
@@ -16,9 +16,6 @@
 
 package com.android.systemui.util.wakelock;
 
-import android.os.Handler;
-import android.os.PowerManager;
-
 import com.android.internal.util.Preconditions;
 
 public class SettableWakeLock {
diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java b/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java
index 16ce35c..b0f1b54 100644
--- a/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java
+++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.os.PowerManager;
+
 import androidx.annotation.VisibleForTesting;
 
 /** WakeLock wrapper for testability */
@@ -71,4 +72,4 @@
             }
         };
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
index 9077b6b..9b616e0 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
@@ -34,8 +34,8 @@
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.graphics.Color;
-import android.graphics.drawable.ColorDrawable;
 import android.graphics.PixelFormat;
+import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.media.AudioAttributes;
 import android.media.AudioManager;
@@ -65,17 +65,17 @@
 import androidx.car.widget.PagedListView;
 import androidx.car.widget.SeekbarListItem;
 
-import java.util.Iterator;
+import com.android.systemui.R;
+import com.android.systemui.plugins.VolumeDialog;
+
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 
-import com.android.systemui.R;
-import com.android.systemui.plugins.VolumeDialog;
-
 /**
  * Car version of the volume dialog.
  *
diff --git a/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java b/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java
index c97095e..361604c 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java
@@ -27,7 +27,6 @@
 import android.view.KeyEvent;
 import android.view.WindowManager;
 
-
 import com.android.systemui.statusbar.phone.SystemUIDialog;
 
 abstract public class SafetyWarningDialog extends SystemUIDialog
@@ -116,4 +115,4 @@
             }
         }
     };
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeComponent.java
index 36c673c..4239337 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeComponent.java
@@ -19,7 +19,6 @@
 import android.content.res.Configuration;
 
 import com.android.systemui.DemoMode;
-import com.android.systemui.statusbar.policy.ZenModeController;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 798f8bc..b588305 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -16,8 +16,6 @@
 
 package com.android.systemui.volume;
 
-import static android.accessibilityservice.AccessibilityServiceInfo.FEEDBACK_ALL_MASK;
-import static android.accessibilityservice.AccessibilityServiceInfo.FEEDBACK_GENERIC;
 import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
 import static android.media.AudioManager.RINGER_MODE_NORMAL;
 import static android.media.AudioManager.RINGER_MODE_SILENT;
@@ -32,7 +30,6 @@
 
 import static com.android.systemui.volume.Events.DISMISS_REASON_SETTINGS_CLICKED;
 
-import android.accessibilityservice.AccessibilityServiceInfo;
 import android.animation.ObjectAnimator;
 import android.annotation.SuppressLint;
 import android.app.ActivityManager;
@@ -68,13 +65,12 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.View.AccessibilityDelegate;
-import android.view.View.OnAttachStateChangeListener;
 import android.view.ViewGroup;
 import android.view.ViewPropertyAnimator;
 import android.view.Window;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener;
+import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.DecelerateInterpolator;
 import android.widget.FrameLayout;
@@ -113,6 +109,10 @@
     private static final long USER_ATTEMPT_GRACE_PERIOD = 1000;
     private static final int UPDATE_ANIMATION_DURATION = 80;
 
+    static final int DIALOG_TIMEOUT_MILLIS = 3000;
+    static final int DIALOG_SAFETYWARNING_TIMEOUT_MILLIS = 5000;
+    static final int DIALOG_HOVERING_TIMEOUT_MILLIS = 16000;
+
     private final Context mContext;
     private final H mHandler = new H();
     private final VolumeDialogController mController;
@@ -170,7 +170,6 @@
 
     @Override
     public void destroy() {
-        mAccessibility.destroy();
         mController.removeCallback(mControllerCallbackH);
         mHandler.removeCallbacksAndMessages(null);
     }
@@ -356,8 +355,6 @@
         writer.print("  mDynamic: "); writer.println(mDynamic);
         writer.print("  mAutomute: "); writer.println(mAutomute);
         writer.print("  mSilentMode: "); writer.println(mSilentMode);
-        writer.print("  mAccessibility.mFeedbackEnabled: ");
-        writer.println(mAccessibility.mFeedbackEnabled);
     }
 
     private static int getImpliedLevel(SeekBar seekBar, int progress) {
@@ -571,10 +568,18 @@
     }
 
     private int computeTimeoutH() {
-        if (mAccessibility.mFeedbackEnabled) return 20000;
-        if (mHovering) return 16000;
-        if (mSafetyWarning != null) return 5000;
-        return 3000;
+        if (mHovering) {
+            return mAccessibilityMgr.getRecommendedTimeoutMillis(DIALOG_HOVERING_TIMEOUT_MILLIS,
+                    AccessibilityManager.FLAG_CONTENT_CONTROLS);
+        }
+        if (mSafetyWarning != null) {
+            return mAccessibilityMgr.getRecommendedTimeoutMillis(
+                    DIALOG_SAFETYWARNING_TIMEOUT_MILLIS,
+                    AccessibilityManager.FLAG_CONTENT_TEXT
+                            | AccessibilityManager.FLAG_CONTENT_CONTROLS);
+        }
+        return mAccessibilityMgr.getRecommendedTimeoutMillis(DIALOG_TIMEOUT_MILLIS,
+                AccessibilityManager.FLAG_CONTENT_CONTROLS);
     }
 
     protected void dismissH(int reason) {
@@ -1261,28 +1266,8 @@
     }
 
     private final class Accessibility extends AccessibilityDelegate {
-        private boolean mFeedbackEnabled;
-
         public void init() {
-            mDialogView.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
-                @Override
-                public void onViewDetachedFromWindow(View v) {
-                    if (D.BUG) Log.d(TAG, "onViewDetachedFromWindow");
-                }
-
-                @Override
-                public void onViewAttachedToWindow(View v) {
-                    if (D.BUG) Log.d(TAG, "onViewAttachedToWindow");
-                    updateFeedbackEnabled();
-                }
-            });
             mDialogView.setAccessibilityDelegate(this);
-            mAccessibilityMgr.addCallback(mListener);
-            updateFeedbackEnabled();
-        }
-
-        public void destroy() {
-            mAccessibilityMgr.removeCallback(mListener);
         }
 
         @Override
@@ -1298,25 +1283,6 @@
             rescheduleTimeoutH();
             return super.onRequestSendAccessibilityEvent(host, child, event);
         }
-
-        private void updateFeedbackEnabled() {
-            mFeedbackEnabled = computeFeedbackEnabled();
-        }
-
-        private boolean computeFeedbackEnabled() {
-            // are there any enabled non-generic a11y services?
-            final List<AccessibilityServiceInfo> services =
-                    mAccessibilityMgr.getEnabledAccessibilityServiceList(FEEDBACK_ALL_MASK);
-            for (AccessibilityServiceInfo asi : services) {
-                if (asi.feedbackType != 0 && asi.feedbackType != FEEDBACK_GENERIC) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        private final AccessibilityServicesStateChangeListener mListener =
-                enabled -> updateFeedbackEnabled();
     }
 
     private static class VolumeRow {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
index 6f65b08..e4f37de 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
@@ -23,8 +23,6 @@
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
 import com.android.systemui.qs.tiles.DndTile;
-import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.statusbar.policy.ZenModeControllerImpl;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
new file mode 100644
index 0000000..48491d7
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2018 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.privacy
+
+import android.app.AppOpsManager
+import android.os.Handler
+import android.support.test.filters.SmallTest
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.testing.TestableLooper.RunWithLooper
+import com.android.systemui.Dependency
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.appops.AppOpItem
+import com.android.systemui.appops.AppOpsController
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.anyList
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.Mock
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.verify
+
+import org.mockito.MockitoAnnotations
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+@RunWithLooper
+class PrivacyItemControllerTest : SysuiTestCase() {
+
+    @Mock
+    private lateinit var appOpsController: AppOpsController
+    @Mock
+    private lateinit var callback: PrivacyItemController.Callback
+
+    private lateinit var testableLooper: TestableLooper
+    private lateinit var privacyItemController: PrivacyItemController
+
+    @Before
+    fun setup() {
+        MockitoAnnotations.initMocks(this)
+        testableLooper = TestableLooper.get(this)
+
+        appOpsController = mDependency.injectMockDependency(AppOpsController:: class.java)
+        mDependency.injectTestDependency(Dependency.BG_LOOPER, testableLooper.looper)
+        mDependency.injectTestDependency(Dependency.MAIN_HANDLER, Handler(testableLooper.looper))
+
+        doReturn(listOf(AppOpItem(AppOpsManager.OP_CAMERA, 0, "", 0)))
+                .`when`(appOpsController).getActiveAppOpsForUser(anyInt())
+
+        privacyItemController = PrivacyItemController(mContext, callback)
+    }
+    @Test
+    fun testSetListeningTrue() {
+        privacyItemController.setListening(true)
+        verify(appOpsController).addCallback(eq(PrivacyItemController.OPS),
+                any(AppOpsController.Callback::class.java))
+        testableLooper.processAllMessages()
+        verify(callback).privacyChanged(anyList())
+    }
+
+    @Test
+    fun testSetListeningFalse() {
+        privacyItemController.setListening(true)
+        privacyItemController.setListening(false)
+        verify(appOpsController).removeCallback(eq(PrivacyItemController.OPS),
+                any(AppOpsController.Callback:: class.java))
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
index 098fa62..dcd5946 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
@@ -44,6 +44,7 @@
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -55,6 +56,7 @@
  * Tests for {@link NotificationSwipeHelper}.
  */
 @SmallTest
+@Ignore
 @RunWith(AndroidJUnit4.class)
 @UiThreadTest
 public class NotificationSwipeHelperTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
index 23365a4..1481aef 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
@@ -19,22 +19,22 @@
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 
+import android.hardware.display.ColorDisplayManager;
 import android.os.Handler;
 import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
+
 import com.android.internal.app.ColorDisplayController;
-import com.android.systemui.Dependency;
-import com.android.systemui.Prefs;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.qs.AutoAddTracker;
 import com.android.systemui.qs.QSTileHost;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
 @RunWith(AndroidTestingRunner.class)
@@ -56,7 +56,7 @@
 
     @Test
     public void nightTileAdded_whenActivated() {
-        if (!ColorDisplayController.isAvailable(mContext)) {
+        if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) {
             return;
         }
         mAutoTileManager.mColorDisplayCallback.onActivated(true);
@@ -65,7 +65,7 @@
 
     @Test
     public void nightTileNotAdded_whenDeactivated() {
-        if (!ColorDisplayController.isAvailable(mContext)) {
+        if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) {
             return;
         }
         mAutoTileManager.mColorDisplayCallback.onActivated(false);
@@ -74,7 +74,7 @@
 
     @Test
     public void nightTileAdded_whenNightModeTwilight() {
-        if (!ColorDisplayController.isAvailable(mContext)) {
+        if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) {
             return;
         }
         mAutoTileManager.mColorDisplayCallback.onAutoModeChanged(
@@ -84,7 +84,7 @@
 
     @Test
     public void nightTileAdded_whenNightModeCustom() {
-        if (!ColorDisplayController.isAvailable(mContext)) {
+        if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) {
             return;
         }
         mAutoTileManager.mColorDisplayCallback.onAutoModeChanged(
@@ -94,7 +94,7 @@
 
     @Test
     public void nightTileNotAdded_whenNightModeDisabled() {
-        if (!ColorDisplayController.isAvailable(mContext)) {
+        if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) {
             return;
         }
         mAutoTileManager.mColorDisplayCallback.onAutoModeChanged(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarTransitionsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarTransitionsControllerTest.java
new file mode 100644
index 0000000..0031c32
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarTransitionsControllerTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2012 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.phone;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.phone.LightBarTransitionsController.DarkIntensityApplier;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class LightBarTransitionsControllerTest extends SysuiTestCase {
+
+    @Mock
+    private DarkIntensityApplier mApplier;
+    private LightBarTransitionsController mLightBarTransitionsController;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mContext.putComponent(CommandQueue.class, mock(CommandQueue.class));
+        mLightBarTransitionsController = new LightBarTransitionsController(mContext, mApplier);
+    }
+
+    @Test
+    public void setIconsDark_lightAndDark() {
+        mLightBarTransitionsController.setIconsDark(true /* dark */, false /* animate */);
+        verify(mApplier).applyDarkIntensity(eq(1f));
+
+        mLightBarTransitionsController.setIconsDark(false /* dark */, false /* animate */);
+        verify(mApplier).applyDarkIntensity(eq(0f));
+    }
+
+    @Test
+    public void onDozeAmountChanged_lightWhenDozing() {
+        mLightBarTransitionsController.onDozeAmountChanged(1f /* linear */, 1f /* eased */);
+        mLightBarTransitionsController.setIconsDark(true /* dark */, false /* animate */);
+        verify(mApplier, times(2)).applyDarkIntensity(eq(0f));
+
+        reset(mApplier);
+        mLightBarTransitionsController.setIconsDark(false /* dark */, false /* animate */);
+        verify(mApplier).applyDarkIntensity(eq(0f));
+    }
+
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 882f261..d442de2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -593,6 +593,30 @@
         verify(mStatusBarStateController).setState(eq(StatusBarState.FULLSCREEN_USER_SWITCHER));
     }
 
+    @Test
+    public void testStartStopDozing() {
+        mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD);
+        when(mStatusBarStateController.isKeyguardRequested()).thenReturn(true);
+
+        mStatusBar.mDozeServiceHost.startDozing();
+        verify(mStatusBarStateController).setIsDozing(eq(true));
+
+        mStatusBar.mDozeServiceHost.stopDozing();
+        verify(mStatusBarStateController).setIsDozing(eq(false));
+    }
+
+    @Test
+    public void testOnStartedWakingUp_isNotDozing() {
+        mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD);
+        when(mStatusBarStateController.isKeyguardRequested()).thenReturn(true);
+
+        mStatusBar.mDozeServiceHost.startDozing();
+        verify(mStatusBarStateController).setIsDozing(eq(true));
+
+        mStatusBar.mWakefulnessObserver.onStartedWakingUp();
+        verify(mStatusBarStateController).setIsDozing(eq(false));
+    }
+
     static class TestableStatusBar extends StatusBar {
         public TestableStatusBar(StatusBarKeyguardViewManager man,
                 UnlockMethodCache unlock, KeyguardIndicationController key,
@@ -642,6 +666,7 @@
             mLockscreenUserManager = notificationLockscreenUserManager;
             mCommandQueue = commandQueue;
             mPresenter = notificationPresenter;
+            mGestureWakeLock = mock(PowerManager.WakeLock.class);
         }
 
         private WakefulnessLifecycle createAwakeWakefulnessLifecycle() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
index c536dca..5f02fad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
@@ -27,18 +27,23 @@
 
 import static junit.framework.Assert.assertTrue;
 
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.KeyguardManager;
 import android.media.AudioManager;
+import android.os.SystemClock;
 import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.text.TextUtils;
+import android.view.InputDevice;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityManager;
 import android.widget.ImageView;
 
 import com.android.systemui.R;
@@ -48,10 +53,11 @@
 import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
 
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
 import java.util.function.Predicate;
@@ -59,7 +65,6 @@
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
-@Ignore
 public class VolumeDialogImplTest extends SysuiTestCase {
 
     VolumeDialogImpl mDialog;
@@ -113,6 +118,45 @@
                     + " failed test", condition.test(view));
         }
     }
+
+    @Test
+    public void testComputeTimeout() {
+        Mockito.reset(mAccessibilityMgr);
+        mDialog.rescheduleTimeoutH();
+        verify(mAccessibilityMgr).getRecommendedTimeoutMillis(
+                VolumeDialogImpl.DIALOG_TIMEOUT_MILLIS,
+                AccessibilityManager.FLAG_CONTENT_CONTROLS);
+    }
+
+    @Test
+    public void testComputeTimeout_withHovering() {
+        Mockito.reset(mAccessibilityMgr);
+        View dialog = mDialog.getDialogView();
+        long uptimeMillis = SystemClock.uptimeMillis();
+        MotionEvent event = MotionEvent.obtain(uptimeMillis, uptimeMillis,
+                MotionEvent.ACTION_HOVER_ENTER, 0, 0, 0);
+        event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+        dialog.dispatchGenericMotionEvent(event);
+        event.recycle();
+        verify(mAccessibilityMgr).getRecommendedTimeoutMillis(
+                VolumeDialogImpl.DIALOG_HOVERING_TIMEOUT_MILLIS,
+                AccessibilityManager.FLAG_CONTENT_CONTROLS);
+    }
+
+    @Test
+    public void testComputeTimeout_withSafetyWarningOn() {
+        Mockito.reset(mAccessibilityMgr);
+        ArgumentCaptor<VolumeDialogController.Callbacks> controllerCallbackCapture =
+                ArgumentCaptor.forClass(VolumeDialogController.Callbacks.class);
+        verify(mController).addCallback(controllerCallbackCapture.capture(), any());
+        VolumeDialogController.Callbacks callbacks = controllerCallbackCapture.getValue();
+        callbacks.onShowSafetyWarning(AudioManager.FLAG_SHOW_UI);
+        verify(mAccessibilityMgr).getRecommendedTimeoutMillis(
+                VolumeDialogImpl.DIALOG_SAFETYWARNING_TIMEOUT_MILLIS,
+                AccessibilityManager.FLAG_CONTENT_TEXT
+                        | AccessibilityManager.FLAG_CONTENT_CONTROLS);
+    }
+
 /*
     @Test
     public void testContentDescriptions() {
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index a947ea1..8ae5872 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -6584,6 +6584,18 @@
     // OS: Q
     TOP_LEVEL_PRIVACY = 1587;
 
+    // OPEN: Settings > Sound & notification > Do Not Disturb > See all exceptions >
+    // Allow apps to override
+    // CATEGORY: SETTINGS
+    // OS: Q
+    NOTIFICATION_ZEN_MODE_OVERRIDING_APPS = 1588;
+
+    // OPEN: Settings > Sound & notification > Do Not Disturb > See all exceptions >
+    // Allow apps to override > Choose app
+    // CATEGORY: SETTINGS
+    // OS: Q
+    NOTIFICATION_ZEN_MODE_OVERRIDING_APP = 1589;
+
     // ---- End Q Constants, all Q constants go above this line ----
 
     // Add new aosp constants above this line.
diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto
index 033e996..11963d2 100644
--- a/proto/src/wifi.proto
+++ b/proto/src/wifi.proto
@@ -1674,4 +1674,20 @@
 
   // Total time the wifi radio is scanning in ms over the logging duration.
   optional int64 radio_scan_time_ms = 5;
+
+  // Total time the wifi radio spent doing nan scans in ms over the logging duration.
+  optional int64 radio_nan_scan_time_ms = 6;
+
+  // Total time the wifi radio spent doing background scans in ms over the logging duration.
+  optional int64 radio_background_scan_time_ms = 7;
+
+  // Total time the wifi radio spent doing roam scans in ms over the logging duration.
+  optional int64 radio_roam_scan_time_ms = 8;
+
+  // Total time the wifi radio spent doing pno scans in ms over the logging duration.
+  optional int64 radio_pno_scan_time_ms = 9;
+
+  // Total time the wifi radio spent doing hotspot 2.0 scans and GAS exchange
+  // in ms over the logging duration.
+  optional int64 radio_hs20_scan_time_ms = 10;
 }
\ No newline at end of file
diff --git a/services/Android.bp b/services/Android.bp
index bea51be..3390438 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -23,6 +23,7 @@
         "services.companion",
         "services.coverage",
         "services.devicepolicy",
+        "services.intelligence",
         "services.midi",
         "services.net",
         "services.print",
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index d1fe970c..7a65a53 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -218,8 +218,8 @@
             ViewGroup container = decor.findViewById(R.id.autofill_dataset_picker);
             final View content;
             try {
-                response.getPresentation().setApplyTheme(mThemeId);
-                content = response.getPresentation().apply(mContext, decor, interceptionHandler);
+                content = response.getPresentation().applyWithTheme(
+                        mContext, decor, interceptionHandler, mThemeId);
                 container.addView(content);
             } catch (RuntimeException e) {
                 callback.onCanceled();
@@ -259,8 +259,7 @@
             RemoteViews.OnClickHandler clickBlocker = null;
             if (headerPresentation != null) {
                 clickBlocker = newClickBlocker();
-                headerPresentation.setApplyTheme(mThemeId);
-                mHeader = headerPresentation.apply(mContext, null, clickBlocker);
+                mHeader = headerPresentation.applyWithTheme(mContext, null, clickBlocker, mThemeId);
                 final LinearLayout headerContainer =
                         decor.findViewById(R.id.autofill_dataset_header);
                 if (sVerbose) Slog.v(TAG, "adding header");
@@ -277,8 +276,8 @@
                     if (clickBlocker == null) { // already set for header
                         clickBlocker = newClickBlocker();
                     }
-                    footerPresentation.setApplyTheme(mThemeId);
-                    mFooter = footerPresentation.apply(mContext, null, clickBlocker);
+                    mFooter = footerPresentation.applyWithTheme(
+                            mContext, null, clickBlocker, mThemeId);
                     // Footer not supported on some platform e.g. TV
                     if (sVerbose) Slog.v(TAG, "adding footer");
                     footerContainer.addView(mFooter);
@@ -304,8 +303,8 @@
                     final View view;
                     try {
                         if (sVerbose) Slog.v(TAG, "setting remote view for " + focusedViewId);
-                        presentation.setApplyTheme(mThemeId);
-                        view = presentation.apply(mContext, null, interceptionHandler);
+                        view = presentation.applyWithTheme(
+                                mContext, null, interceptionHandler, mThemeId);
                     } catch (RuntimeException e) {
                         Slog.e(TAG, "Error inflating remote views", e);
                         continue;
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index 1e30c8a..843aa74 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -339,8 +339,8 @@
 
         try {
             // Create the remote view peer.
-            template.setApplyTheme(mThemeId);
-            final View customSubtitleView = template.apply(context, null, handler);
+            final View customSubtitleView = template.applyWithTheme(
+                    context, null, handler, mThemeId);
 
             // Apply batch updates (if any).
             final ArrayList<Pair<InternalValidator, BatchUpdates>> updates =
diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/cdc/ContentDefinedChunker.java b/services/backup/java/com/android/server/backup/encryption/chunking/cdc/ContentDefinedChunker.java
new file mode 100644
index 0000000..18011f6
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/encryption/chunking/cdc/ContentDefinedChunker.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2018 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.backup.encryption.chunking.cdc;
+
+import static com.android.internal.util.Preconditions.checkArgument;
+
+import com.android.server.backup.encryption.chunking.Chunker;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.GeneralSecurityException;
+import java.util.Arrays;
+
+/** Splits a stream of bytes into variable-sized chunks, using content-defined chunking. */
+public class ContentDefinedChunker implements Chunker {
+    private static final int WINDOW_SIZE = 31;
+    private static final byte DEFAULT_OUT_BYTE = (byte) 0;
+
+    private final byte[] mChunkBuffer;
+    private final RabinFingerprint64 mRabinFingerprint64;
+    private final FingerprintMixer mFingerprintMixer;
+    private final BreakpointPredicate mBreakpointPredicate;
+    private final int mMinChunkSize;
+    private final int mMaxChunkSize;
+
+    /**
+     * Constructor.
+     *
+     * @param minChunkSize The minimum size of a chunk. No chunk will be produced of a size smaller
+     *     than this except possibly at the very end of the stream.
+     * @param maxChunkSize The maximum size of a chunk. No chunk will be produced of a larger size.
+     * @param rabinFingerprint64 Calculates fingerprints, with which to determine breakpoints.
+     * @param breakpointPredicate Given a Rabin fingerprint, returns whether this ought to be a
+     *     breakpoint.
+     */
+    public ContentDefinedChunker(
+            int minChunkSize,
+            int maxChunkSize,
+            RabinFingerprint64 rabinFingerprint64,
+            FingerprintMixer fingerprintMixer,
+            BreakpointPredicate breakpointPredicate) {
+        checkArgument(
+                minChunkSize >= WINDOW_SIZE,
+                "Minimum chunk size must be greater than window size.");
+        checkArgument(
+                maxChunkSize >= minChunkSize,
+                "Maximum chunk size cannot be smaller than minimum chunk size.");
+        mChunkBuffer = new byte[maxChunkSize];
+        mRabinFingerprint64 = rabinFingerprint64;
+        mBreakpointPredicate = breakpointPredicate;
+        mFingerprintMixer = fingerprintMixer;
+        mMinChunkSize = minChunkSize;
+        mMaxChunkSize = maxChunkSize;
+    }
+
+    /**
+     * Breaks the input stream into variable-sized chunks.
+     *
+     * @param inputStream The input bytes to break into chunks.
+     * @param chunkConsumer A function to process each chunk as it's generated.
+     * @throws IOException Thrown if there is an issue reading from the input stream.
+     * @throws GeneralSecurityException Thrown if the {@link ChunkConsumer} throws it.
+     */
+    @Override
+    public void chunkify(InputStream inputStream, ChunkConsumer chunkConsumer)
+            throws IOException, GeneralSecurityException {
+        int chunkLength;
+        int initialReadLength = mMinChunkSize - WINDOW_SIZE;
+
+        // Performance optimization - there is no reason to calculate fingerprints for windows
+        // ending before the minimum chunk size.
+        while ((chunkLength =
+                        inputStream.read(mChunkBuffer, /*off=*/ 0, /*len=*/ initialReadLength))
+                != -1) {
+            int b;
+            long fingerprint = 0L;
+
+            while ((b = inputStream.read()) != -1) {
+                byte inByte = (byte) b;
+                byte outByte = getCurrentWindowStartByte(chunkLength);
+                mChunkBuffer[chunkLength++] = inByte;
+
+                fingerprint =
+                        mRabinFingerprint64.computeFingerprint64(inByte, outByte, fingerprint);
+
+                if (chunkLength >= mMaxChunkSize
+                        || (chunkLength >= mMinChunkSize
+                                && mBreakpointPredicate.isBreakpoint(
+                                        mFingerprintMixer.mix(fingerprint)))) {
+                    chunkConsumer.accept(Arrays.copyOf(mChunkBuffer, chunkLength));
+                    chunkLength = 0;
+                    break;
+                }
+            }
+
+            if (chunkLength > 0) {
+                chunkConsumer.accept(Arrays.copyOf(mChunkBuffer, chunkLength));
+            }
+        }
+    }
+
+    private byte getCurrentWindowStartByte(int chunkLength) {
+        if (chunkLength < mMinChunkSize) {
+            return DEFAULT_OUT_BYTE;
+        } else {
+            return mChunkBuffer[chunkLength - WINDOW_SIZE];
+        }
+    }
+
+    /** Whether the current fingerprint indicates the end of a chunk. */
+    public interface BreakpointPredicate {
+
+        /**
+         * Returns {@code true} if the fingerprint of the last {@code WINDOW_SIZE} bytes indicates
+         * the chunk ought to end at this position.
+         *
+         * @param fingerprint Fingerprint of the last {@code WINDOW_SIZE} bytes.
+         * @return Whether this ought to be a chunk breakpoint.
+         */
+        boolean isBreakpoint(long fingerprint);
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/cdc/FingerprintMixer.java b/services/backup/java/com/android/server/backup/encryption/chunking/cdc/FingerprintMixer.java
new file mode 100644
index 0000000..e9f3050
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/encryption/chunking/cdc/FingerprintMixer.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2018 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.backup.encryption.chunking.cdc;
+
+import static com.android.internal.util.Preconditions.checkArgument;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.security.InvalidKeyException;
+
+import javax.crypto.SecretKey;
+
+/**
+ * Helper for mixing fingerprint with key material.
+ *
+ * <p>We do this as otherwise the Rabin fingerprint leaks information about the plaintext. i.e., if
+ * two users have the same file, it will be partitioned by Rabin in the same way, allowing us to
+ * infer that it is the same as another user's file.
+ *
+ * <p>By mixing the fingerprint with the user's secret key, the chunking method is different on a
+ * per key basis. Each application has its own {@link SecretKey}, so we cannot infer that a file is
+ * the same even across multiple applications owned by the same user, never mind across multiple
+ * users.
+ *
+ * <p>Instead of directly mixing the fingerprint with the user's secret, we first securely and
+ * deterministically derive a secondary chunking key. As Rabin is not a cryptographically secure
+ * hash, it might otherwise leak information about the user's secret. This prevents that from
+ * happening.
+ */
+public class FingerprintMixer {
+    public static final int SALT_LENGTH_BYTES = 256 / Byte.SIZE;
+    private static final String DERIVED_KEY_NAME = "RabinFingerprint64Mixer";
+
+    private final long mAddend;
+    private final long mMultiplicand;
+
+    /**
+     * A new instance from a given secret key and salt. Salt must be the same across incremental
+     * backups, or a different chunking strategy will be used each time, defeating the dedup.
+     *
+     * @param secretKey The application-specific secret.
+     * @param salt The salt.
+     * @throws InvalidKeyException If the encoded form of {@code secretKey} is inaccessible.
+     */
+    public FingerprintMixer(SecretKey secretKey, byte[] salt) throws InvalidKeyException {
+        checkArgument(salt.length == SALT_LENGTH_BYTES, "Requires a 256-bit salt.");
+        byte[] keyBytes = secretKey.getEncoded();
+        if (keyBytes == null) {
+            throw new InvalidKeyException("SecretKey must support encoding for FingerprintMixer.");
+        }
+        byte[] derivedKey =
+                Hkdf.hkdf(keyBytes, salt, DERIVED_KEY_NAME.getBytes(StandardCharsets.UTF_8));
+        ByteBuffer buffer = ByteBuffer.wrap(derivedKey);
+        mAddend = buffer.getLong();
+        // Multiplicand must be odd - otherwise we lose some bits of the Rabin fingerprint when
+        // mixing
+        mMultiplicand = buffer.getLong() | 1;
+    }
+
+    /**
+     * Mixes the fingerprint with the derived key material. This is performed by adding part of the
+     * derived key and multiplying by another part of the derived key (which is forced to be odd, so
+     * that the operation is reversible).
+     *
+     * @param fingerprint A 64-bit Rabin fingerprint.
+     * @return The mixed fingerprint.
+     */
+    long mix(long fingerprint) {
+        return ((fingerprint + mAddend) * mMultiplicand);
+    }
+
+    /** The addend part of the derived key. */
+    long getAddend() {
+        return mAddend;
+    }
+
+    /** The multiplicand part of the derived key. */
+    long getMultiplicand() {
+        return mMultiplicand;
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/cdc/Hkdf.java b/services/backup/java/com/android/server/backup/encryption/chunking/cdc/Hkdf.java
new file mode 100644
index 0000000..6f4f549
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/encryption/chunking/cdc/Hkdf.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2018 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.backup.encryption.chunking.cdc;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * Secure HKDF utils. Allows client to deterministically derive additional key material from a base
+ * secret. If the derived key material is compromised, this does not in of itself compromise the
+ * root secret.
+ *
+ * <p>TODO(b/116575321): After all code is ported, rename this class to HkdfUtils.
+ */
+public final class Hkdf {
+    private static final byte[] CONSTANT_01 = {0x01};
+    private static final String HmacSHA256 = "HmacSHA256";
+    private static final String AES = "AES";
+
+    /**
+     * Implements HKDF (RFC 5869) with the SHA-256 hash and a 256-bit output key length.
+     *
+     * <p>IMPORTANT: The use or edit of this method requires a security review.
+     *
+     * @param masterKey Master key from which to derive sub-keys.
+     * @param salt A randomly generated 256-bit byte string.
+     * @param data Arbitrary information that is bound to the derived key (i.e., used in its
+     *     creation).
+     * @return Raw derived key bytes = HKDF-SHA256(masterKey, salt, data).
+     * @throws InvalidKeyException If the salt can not be used as a valid key.
+     */
+    static byte[] hkdf(byte[] masterKey, byte[] salt, byte[] data) throws InvalidKeyException {
+        checkNotNull(masterKey, "HKDF requires master key to be set.");
+        checkNotNull(salt, "HKDF requires a salt.");
+        checkNotNull(data, "No data provided to HKDF.");
+        return hkdfSha256Expand(hkdfSha256Extract(masterKey, salt), data);
+    }
+
+    private Hkdf() {}
+
+    /**
+     * The HKDF (RFC 5869) extraction function, using the SHA-256 hash function. This function is
+     * used to pre-process the {@code inputKeyMaterial} and mix it with the {@code salt}, producing
+     * output suitable for use with HKDF expansion function (which produces the actual derived key).
+     *
+     * <p>IMPORTANT: The use or edit of this method requires a security review.
+     *
+     * @see #hkdfSha256Expand(byte[], byte[])
+     * @return HMAC-SHA256(salt, inputKeyMaterial) (salt is the "key" for the HMAC)
+     * @throws InvalidKeyException If the salt can not be used as a valid key.
+     */
+    private static byte[] hkdfSha256Extract(byte[] inputKeyMaterial, byte[] salt)
+            throws InvalidKeyException {
+        // Note that the SecretKey encoding format is defined to be RAW, so the encoded form should
+        // be consistent across implementations.
+        Mac sha256;
+        try {
+            sha256 = Mac.getInstance(HmacSHA256);
+        } catch (NoSuchAlgorithmException e) {
+            // This can not happen - HmacSHA256 is supported by the platform.
+            throw new AssertionError(e);
+        }
+        sha256.init(new SecretKeySpec(salt, AES));
+
+        return sha256.doFinal(inputKeyMaterial);
+    }
+
+    /**
+     * Special case of HKDF (RFC 5869) expansion function, using the SHA-256 hash function and
+     * allowing for a maximum output length of 256 bits.
+     *
+     * <p>IMPORTANT: The use or edit of this method requires a security review.
+     *
+     * @param pseudoRandomKey Generated by {@link #hkdfSha256Extract(byte[], byte[])}.
+     * @param info Arbitrary information the derived key should be bound to.
+     * @return Raw derived key bytes = HMAC-SHA256(pseudoRandomKey, info | 0x01).
+     * @throws InvalidKeyException If the salt can not be used as a valid key.
+     */
+    private static byte[] hkdfSha256Expand(byte[] pseudoRandomKey, byte[] info)
+            throws InvalidKeyException {
+        // Note that RFC 5869 computes number of blocks N = ceil(hash length / output length), but
+        // here we only deal with a 256 bit hash up to a 256 bit output, yielding N=1.
+        Mac sha256;
+        try {
+            sha256 = Mac.getInstance(HmacSHA256);
+        } catch (NoSuchAlgorithmException e) {
+            // This can not happen - HmacSHA256 is supported by the platform.
+            throw new AssertionError(e);
+        }
+        sha256.init(new SecretKeySpec(pseudoRandomKey, AES));
+
+        sha256.update(info);
+        sha256.update(CONSTANT_01);
+        return sha256.doFinal();
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/cdc/IsChunkBreakpoint.java b/services/backup/java/com/android/server/backup/encryption/chunking/cdc/IsChunkBreakpoint.java
new file mode 100644
index 0000000..e867e7c
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/encryption/chunking/cdc/IsChunkBreakpoint.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2018 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.backup.encryption.chunking.cdc;
+
+import static com.android.internal.util.Preconditions.checkArgument;
+
+import com.android.server.backup.encryption.chunking.cdc.ContentDefinedChunker.BreakpointPredicate;
+
+/**
+ * Function to determine whether a 64-bit fingerprint ought to be a chunk breakpoint.
+ *
+ * <p>This works by checking whether there are at least n leading zeros in the fingerprint. n is
+ * calculated to on average cause a breakpoint after a given number of trials (provided in the
+ * constructor). This allows us to choose a number of trials that gives a desired average chunk
+ * size. This works because the fingerprint is pseudo-randomly distributed.
+ */
+public class IsChunkBreakpoint implements BreakpointPredicate {
+    private final int mLeadingZeros;
+    private final long mBitmask;
+
+    /**
+     * A new instance that causes a breakpoint after a given number of trials on average.
+     *
+     * @param averageNumberOfTrialsUntilBreakpoint The number of trials after which on average to
+     *     create a new chunk. If this is not a power of 2, some precision is sacrificed (i.e., on
+     *     average, breaks will actually happen after the nearest power of 2 to the average number
+     *     of trials passed in).
+     */
+    public IsChunkBreakpoint(long averageNumberOfTrialsUntilBreakpoint) {
+        checkArgument(
+                averageNumberOfTrialsUntilBreakpoint >= 0,
+                "Average number of trials must be non-negative");
+
+        // Want n leading zeros after t trials.
+        // P(leading zeros = n) = 1/2^n
+        // Expected num trials to get n leading zeros = 1/2^-n
+        // t = 1/2^-n
+        // n = log2(t)
+        mLeadingZeros = (int) Math.round(log2(averageNumberOfTrialsUntilBreakpoint));
+        mBitmask = ~(~0L >>> mLeadingZeros);
+    }
+
+    /**
+     * Returns {@code true} if {@code fingerprint} indicates that there should be a chunk
+     * breakpoint.
+     */
+    @Override
+    public boolean isBreakpoint(long fingerprint) {
+        return (fingerprint & mBitmask) == 0;
+    }
+
+    /** Returns the number of leading zeros in the fingerprint that causes a breakpoint. */
+    public int getLeadingZeros() {
+        return mLeadingZeros;
+    }
+
+    /**
+     * Calculates log base 2 of x. Not the most efficient possible implementation, but it's simple,
+     * obviously correct, and is only invoked on object construction.
+     */
+    private static double log2(double x) {
+        return Math.log(x) / Math.log(2);
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/cdc/RabinFingerprint64.java b/services/backup/java/com/android/server/backup/encryption/chunking/cdc/RabinFingerprint64.java
new file mode 100644
index 0000000..1e14ffa
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/encryption/chunking/cdc/RabinFingerprint64.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2018 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.backup.encryption.chunking.cdc;
+
+/** Helper to calculate a 64-bit Rabin fingerprint over a 31-byte window. */
+public class RabinFingerprint64 {
+    private static final long DEFAULT_IRREDUCIBLE_POLYNOMIAL_64 = 0x000000000000001BL;
+    private static final int POLYNOMIAL_DEGREE = 64;
+    private static final int SLIDING_WINDOW_SIZE_BYTES = 31;
+
+    private final long mPoly64;
+    // Auxiliary tables to speed up the computation of Rabin fingerprints.
+    private final long[] mTableFP64 = new long[256];
+    private final long[] mTableOutByte = new long[256];
+
+    /**
+     * Constructs a new instance over the given irreducible 64-degree polynomial. It is up to the
+     * caller to determine that the polynomial is irreducible. If it is not the fingerprinting will
+     * not behave as expected.
+     *
+     * @param poly64 The polynomial.
+     */
+    public RabinFingerprint64(long poly64) {
+        mPoly64 = poly64;
+    }
+
+    /** Constructs a new instance using {@code x^64 + x^4 + x + 1} as the irreducible polynomial. */
+    public RabinFingerprint64() {
+        this(DEFAULT_IRREDUCIBLE_POLYNOMIAL_64);
+        computeFingerprintTables64();
+        computeFingerprintTables64Windowed();
+    }
+
+    /**
+     * Computes the fingerprint for the new sliding window given the fingerprint of the previous
+     * sliding window, the byte sliding in, and the byte sliding out.
+     *
+     * @param inChar The new char coming into the sliding window.
+     * @param outChar The left most char sliding out of the window.
+     * @param fingerPrint Fingerprint for previous window.
+     * @return New fingerprint for the new sliding window.
+     */
+    public long computeFingerprint64(byte inChar, byte outChar, long fingerPrint) {
+        return (fingerPrint << 8)
+                ^ (inChar & 0xFF)
+                ^ mTableFP64[(int) (fingerPrint >>> 56)]
+                ^ mTableOutByte[outChar & 0xFF];
+    }
+
+    /** Compute auxiliary tables to speed up the fingerprint computation. */
+    private void computeFingerprintTables64() {
+        long[] degreesRes64 = new long[POLYNOMIAL_DEGREE];
+        degreesRes64[0] = mPoly64;
+        for (int i = 1; i < POLYNOMIAL_DEGREE; i++) {
+            if ((degreesRes64[i - 1] & (1L << 63)) == 0) {
+                degreesRes64[i] = degreesRes64[i - 1] << 1;
+            } else {
+                degreesRes64[i] = (degreesRes64[i - 1] << 1) ^ mPoly64;
+            }
+        }
+        for (int i = 0; i < 256; i++) {
+            int currIndex = i;
+            for (int j = 0; (currIndex > 0) && (j < 8); j++) {
+                if ((currIndex & 0x1) == 1) {
+                    mTableFP64[i] ^= degreesRes64[j];
+                }
+                currIndex >>>= 1;
+            }
+        }
+    }
+
+    /**
+     * Compute auxiliary table {@code mTableOutByte} to facilitate the computing of fingerprints for
+     * sliding windows. This table is to take care of the effect on the fingerprint when the
+     * leftmost byte in the window slides out.
+     */
+    private void computeFingerprintTables64Windowed() {
+        // Auxiliary array degsRes64[8] defined by: <code>degsRes64[i] = x^(8 *
+        // SLIDING_WINDOW_SIZE_BYTES + i) mod this.mPoly64.</code>
+        long[] degsRes64 = new long[8];
+        degsRes64[0] = mPoly64;
+        for (int i = 65; i < 8 * (SLIDING_WINDOW_SIZE_BYTES + 1); i++) {
+            if ((degsRes64[(i - 1) % 8] & (1L << 63)) == 0) {
+                degsRes64[i % 8] = degsRes64[(i - 1) % 8] << 1;
+            } else {
+                degsRes64[i % 8] = (degsRes64[(i - 1) % 8] << 1) ^ mPoly64;
+            }
+        }
+        for (int i = 0; i < 256; i++) {
+            int currIndex = i;
+            for (int j = 0; (currIndex > 0) && (j < 8); j++) {
+                if ((currIndex & 0x1) == 1) {
+                    mTableOutByte[i] ^= degsRes64[j];
+                }
+                currIndex >>>= 1;
+            }
+        }
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
index 3a5232a..d6f2a87 100644
--- a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
+++ b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
@@ -260,6 +260,10 @@
     @Nullable private ParcelFileDescriptor mSavedState;
     @Nullable private ParcelFileDescriptor mBackupData;
     @Nullable private ParcelFileDescriptor mNewState;
+    // Indicates whether there was any data to be backed up, i.e. the queue was not empty
+    // and at least one of the packages had data. Used to avoid updating current token for
+    // empty backups.
+    private boolean mHasDataToBackup;
 
     /**
      * This {@link ConditionVariable} is used to signal that the cancel operation has been
@@ -332,6 +336,8 @@
     public void run() {
         Process.setThreadPriority(THREAD_PRIORITY);
 
+        mHasDataToBackup = false;
+
         int status = BackupTransport.TRANSPORT_OK;
         try {
             startTask();
@@ -529,10 +535,10 @@
 
         String callerLogString = "KVBT.finishTask()";
 
-        // If we succeeded and this is the first time we've done a backup, we can record the current
-        // backup dataset token.
+        // If the backup data was not empty, we succeeded and this is the first time
+        // we've done a backup, we can record the current backup dataset token.
         long currentToken = mBackupManagerService.getCurrentToken();
-        if ((status == BackupTransport.TRANSPORT_OK) && (currentToken == 0)) {
+        if (mHasDataToBackup && (status == BackupTransport.TRANSPORT_OK) && (currentToken == 0)) {
             try {
                 IBackupTransport transport = mTransportClient.connectOrThrow(callerLogString);
                 mBackupManagerService.setCurrentToken(transport.getCurrentRestoreSet());
@@ -838,6 +844,8 @@
             return BackupTransport.TRANSPORT_OK;
         }
 
+        mHasDataToBackup = true;
+
         int status;
         try (ParcelFileDescriptor backupData =
                 ParcelFileDescriptor.open(backupDataFile, MODE_READ_ONLY)) {
diff --git a/services/core/java/com/android/server/AbstractPerUserSystemService.java b/services/core/java/com/android/server/AbstractPerUserSystemService.java
index 201abe6..97977df 100644
--- a/services/core/java/com/android/server/AbstractPerUserSystemService.java
+++ b/services/core/java/com/android/server/AbstractPerUserSystemService.java
@@ -167,7 +167,7 @@
     @GuardedBy("mLock")
     protected final int getServiceUidLocked() {
         if (mServiceInfo == null) {
-            Slog.w(mTag, "getServiceUidLocked(): no mServiceInfo");
+            if (mMaster.verbose) Slog.v(mTag, "getServiceUidLocked(): no mServiceInfo");
             return Process.INVALID_UID;
         }
         return mServiceInfo.applicationInfo.uid;
@@ -267,8 +267,18 @@
     @GuardedBy("mLock")
     protected void dumpLocked(@NonNull String prefix, @NonNull PrintWriter pw) {
         pw.print(prefix); pw.print("User: "); pw.println(mUserId);
-        pw.print(prefix); pw.print("Disabled: "); pw.println(mDisabled);
+        pw.print(prefix); pw.print("Disabled by UserManager: "); pw.println(mDisabled);
         pw.print(prefix); pw.print("Setup complete: "); pw.println(mSetupComplete);
-        pw.print(prefix); pw.print("Service name: "); pw.println(getComponentNameFromSettings());
+        if (mServiceInfo != null) {
+            pw.print(prefix); pw.print("Service UID: ");
+            pw.println(mServiceInfo.applicationInfo.uid);
+        }
+        final String componentName = getComponentNameFromSettings();
+        if (componentName != null) {
+            pw.print(prefix); pw.print("Service name: ");
+            pw.println(componentName);
+        } else {
+            pw.println("No service package set");
+        }
     }
 }
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 5b3ab85..923ac00 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -186,8 +186,6 @@
     private static final boolean ENABLE_ISOLATED_STORAGE = SystemProperties
             .getBoolean(StorageManager.PROP_ISOLATED_STORAGE, false);
 
-    private static final String SHARED_SANDBOX_ID_PREFIX = "shared:";
-
     public static class Lifecycle extends SystemService {
         private StorageManagerService mStorageManagerService;
 
@@ -1235,6 +1233,9 @@
         } else if (vol.type == VolumeInfo.TYPE_PRIVATE) {
             mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
 
+        } else if (vol.type == VolumeInfo.TYPE_STUB) {
+            vol.mountUserId = mCurrentUserId;
+            mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
         } else {
             Slog.d(TAG, "Skipping automatic mounting of " + vol);
         }
@@ -1245,6 +1246,7 @@
             case VolumeInfo.TYPE_PRIVATE:
             case VolumeInfo.TYPE_PUBLIC:
             case VolumeInfo.TYPE_EMULATED:
+            case VolumeInfo.TYPE_STUB:
                 break;
             default:
                 return false;
@@ -1321,7 +1323,8 @@
             }
         }
 
-        if (vol.type == VolumeInfo.TYPE_PUBLIC && vol.state == VolumeInfo.STATE_EJECTING) {
+        if ((vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_STUB)
+                    && vol.state == VolumeInfo.STATE_EJECTING) {
             // TODO: this should eventually be handled by new ObbVolume state changes
             /*
              * Some OBBs might have been unmounted when this volume was
@@ -1403,7 +1406,8 @@
         }
 
         boolean isTypeRestricted = false;
-        if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE) {
+        if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE
+                || vol.type == VolumeInfo.TYPE_STUB) {
             isTypeRestricted = userManager
                     .hasUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
                     Binder.getCallingUserHandle());
@@ -1495,7 +1499,8 @@
     }
 
     private static String getSandboxId(String packageName, String sharedUserId) {
-        return sharedUserId == null ? packageName : SHARED_SANDBOX_ID_PREFIX + sharedUserId;
+        return sharedUserId == null
+                ? packageName : StorageManager.SHARED_SANDBOX_PREFIX + sharedUserId;
     }
 
     private void connect() {
@@ -2834,6 +2839,7 @@
                 final VolumeInfo vol = mVolumes.valueAt(i);
                 switch (vol.getType()) {
                     case VolumeInfo.TYPE_PUBLIC:
+                    case VolumeInfo.TYPE_STUB:
                     case VolumeInfo.TYPE_EMULATED:
                         break;
                     default:
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 2d3912b..b5217ad 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -17,40 +17,69 @@
 package com.android.server.am;
 
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static com.android.server.am.ActivityManagerDebugConfig.*;
 
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-import java.util.function.Predicate;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BACKGROUND_CHECK;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOREGROUND_SERVICE;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SERVICE;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SERVICE_EXECUTING;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_MU;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SERVICE;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SERVICE_EXECUTING;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 
+import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
 import android.app.ActivityThread;
+import android.app.AppGlobals;
 import android.app.AppOpsManager;
+import android.app.IApplicationThread;
+import android.app.IServiceConnection;
+import android.app.Notification;
 import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
 import android.app.ServiceStartArgs;
+import android.content.ComponentName;
 import android.content.ComponentName.WithComponentName;
+import android.content.Context;
 import android.content.IIntentSender;
+import android.content.Intent;
 import android.content.IntentSender;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
 import android.content.pm.ParceledListSlice;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
 import android.net.Uri;
+import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.DeadObjectException;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.Looper;
+import android.os.Message;
+import android.os.Process;
 import android.os.RemoteCallback;
+import android.os.RemoteException;
+import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.TransactionTooLargeException;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.ArrayMap;
 import android.util.ArraySet;
+import android.util.EventLog;
+import android.util.PrintWriterPrinter;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.StatsLog;
+import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
+import android.webkit.WebViewZygote;
 
 import com.android.internal.R;
 import com.android.internal.app.procstats.ServiceState;
@@ -64,39 +93,20 @@
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.am.ActivityManagerService.ItemMatcher;
-
-import android.app.ActivityManager;
-import android.app.AppGlobals;
-import android.app.IApplicationThread;
-import android.app.IServiceConnection;
-import android.app.Notification;
-import android.app.PendingIntent;
-import android.app.Service;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.Message;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.os.UserHandle;
-import android.util.EventLog;
-import android.util.PrintWriterPrinter;
-import android.util.Slog;
-import android.util.StatsLog;
-import android.util.SparseArray;
-import android.util.TimeUtils;
-import android.util.proto.ProtoOutputStream;
-import android.webkit.WebViewZygote;
 import com.android.server.uri.NeededUriGrants;
 import com.android.server.wm.ActivityServiceConnectionsHolder;
 
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Predicate;
+
 public final class ActiveServices {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActiveServices" : TAG_AM;
     private static final String TAG_MU = TAG + POSTFIX_MU;
@@ -182,10 +192,10 @@
         public void stopForegroundServicesForUidPackage(final int uid, final String packageName) {
             synchronized (mAm) {
                 final ServiceMap smap = getServiceMapLocked(UserHandle.getUserId(uid));
-                final int N = smap.mServicesByName.size();
+                final int N = smap.mServicesByInstanceName.size();
                 final ArrayList<ServiceRecord> toStop = new ArrayList<>(N);
                 for (int i = 0; i < N; i++) {
-                    final ServiceRecord r = smap.mServicesByName.valueAt(i);
+                    final ServiceRecord r = smap.mServicesByInstanceName.valueAt(i);
                     if (uid == r.serviceInfo.applicationInfo.uid
                             || packageName.equals(r.serviceInfo.packageName)) {
                         if (r.isForeground) {
@@ -236,7 +246,7 @@
      */
     final class ServiceMap extends Handler {
         final int mUserId;
-        final ArrayMap<ComponentName, ServiceRecord> mServicesByName = new ArrayMap<>();
+        final ArrayMap<ComponentName, ServiceRecord> mServicesByInstanceName = new ArrayMap<>();
         final ArrayMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent = new ArrayMap<>();
 
         final ArrayList<ServiceRecord> mDelayedStartList = new ArrayList<>();
@@ -358,7 +368,7 @@
         // TODO: Deal with global services
         if (DEBUG_MU)
             Slog.v(TAG_MU, "getServiceByNameLocked(" + name + "), callingUser = " + callingUser);
-        return getServiceMapLocked(callingUser).mServicesByName.get(name);
+        return getServiceMapLocked(callingUser).mServicesByInstanceName.get(name);
     }
 
     boolean hasBackgroundServicesLocked(int callingUser) {
@@ -376,7 +386,7 @@
     }
 
     ArrayMap<ComponentName, ServiceRecord> getServicesLocked(int callingUser) {
-        return getServiceMapLocked(callingUser).mServicesByName;
+        return getServiceMapLocked(callingUser).mServicesByInstanceName;
     }
 
     private boolean appRestrictedAnyInBackground(final int uid, final String packageName) {
@@ -406,7 +416,7 @@
         }
 
         ServiceLookupResult res =
-            retrieveServiceLocked(service, resolvedType, callingPackage,
+            retrieveServiceLocked(service, null, resolvedType, callingPackage,
                     callingPid, callingUid, userId, true, callerFg, false, false);
         if (res == null) {
             return null;
@@ -434,7 +444,7 @@
         boolean forcedStandby = false;
         if (bgLaunch && appRestrictedAnyInBackground(r.appInfo.uid, r.packageName)) {
             if (DEBUG_FOREGROUND_SERVICE) {
-                Slog.d(TAG, "Forcing bg-only service start only for " + r.shortName
+                Slog.d(TAG, "Forcing bg-only service start only for " + r.shortInstanceName
                         + " : bgLaunch=" + bgLaunch + " callerFg=" + callerFg);
             }
             forcedStandby = true;
@@ -454,7 +464,7 @@
                     // Not allowed, fall back to normal start service, failing siliently
                     // if background check restricts that.
                     Slog.w(TAG, "startForegroundService not allowed due to app op: service "
-                            + service + " to " + r.name.flattenToShortString()
+                            + service + " to " + r.shortInstanceName
                             + " from pid=" + callingPid + " uid=" + callingUid
                             + " pkg=" + callingPackage);
                     fgRequired = false;
@@ -474,7 +484,7 @@
                     r.appInfo.targetSdkVersion, callingPid, false, false, forcedStandby);
             if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
                 Slog.w(TAG, "Background start not allowed: service "
-                        + service + " to " + r.name.flattenToShortString()
+                        + service + " to " + r.shortInstanceName
                         + " from pid=" + callingPid + " uid=" + callingUid
                         + " pkg=" + callingPackage + " startFg?=" + fgRequired);
                 if (allowed == ActivityManager.APP_START_MODE_DELAYED || forceSilentAbort) {
@@ -731,7 +741,7 @@
         }
 
         // If this service is active, make sure it is stopped.
-        ServiceLookupResult r = retrieveServiceLocked(service, resolvedType, null,
+        ServiceLookupResult r = retrieveServiceLocked(service, null, resolvedType, null,
                 Binder.getCallingPid(), Binder.getCallingUid(), userId, false, false, false, false);
         if (r != null) {
             if (r.record != null) {
@@ -755,8 +765,8 @@
         ServiceMap services = mServiceMap.get(UserHandle.getUserId(uid));
         ArrayList<ServiceRecord> stopping = null;
         if (services != null) {
-            for (int i=services.mServicesByName.size()-1; i>=0; i--) {
-                ServiceRecord service = services.mServicesByName.valueAt(i);
+            for (int i = services.mServicesByInstanceName.size() - 1; i >= 0; i--) {
+                ServiceRecord service = services.mServicesByInstanceName.valueAt(i);
                 if (service.appInfo.uid == uid && service.startRequested) {
                     if (mAm.getAppStartModeLocked(service.appInfo.uid, service.packageName,
                             service.appInfo.targetSdkVersion, -1, false, false, false)
@@ -764,7 +774,7 @@
                         if (stopping == null) {
                             stopping = new ArrayList<>();
                         }
-                        String compName = service.name.flattenToShortString();
+                        String compName = service.shortInstanceName;
                         EventLogTags.writeAmStopIdleService(service.appInfo.uid, compName);
                         StringBuilder sb = new StringBuilder(64);
                         sb.append("Stopping service due to app idle: ");
@@ -791,7 +801,7 @@
     }
 
     IBinder peekServiceLocked(Intent service, String resolvedType, String callingPackage) {
-        ServiceLookupResult r = retrieveServiceLocked(service, resolvedType, callingPackage,
+        ServiceLookupResult r = retrieveServiceLocked(service, null, resolvedType, callingPackage,
                 Binder.getCallingPid(), Binder.getCallingUid(),
                 UserHandle.getCallingUserId(), false, false, false, false);
 
@@ -1218,7 +1228,7 @@
                     case AppOpsManager.MODE_IGNORED:
                         // Whoops, silently ignore this.
                         Slog.w(TAG, "Service.startForeground() not allowed due to app op: service "
-                                + r.shortName);
+                                + r.shortInstanceName);
                         ignoreForeground = true;
                         break;
                     default:
@@ -1229,7 +1239,7 @@
                         appRestrictedAnyInBackground(r.appInfo.uid, r.packageName)) {
                     Slog.w(TAG,
                             "Service.startForeground() not allowed due to bg restriction: service "
-                            + r.shortName);
+                            + r.shortInstanceName);
                     // Back off of any foreground expectations around this service, since we've
                     // just turned down its fg request.
                     updateServiceForegroundLocked(r.app, false);
@@ -1283,8 +1293,9 @@
                                 AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName,
                                 true);
                         StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED,
-                                r.appInfo.uid, r.shortName,
+                                r.appInfo.uid, r.shortInstanceName,
                                 StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER);
+                        mAm.updateForegroundServiceUsageStats(r.name, r.userId, true);
                     }
                     r.postNotification();
                     if (r.app != null) {
@@ -1332,8 +1343,9 @@
                         AppOpsManager.getToken(mAm.mAppOpsService),
                         AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName);
                 StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED,
-                        r.appInfo.uid, r.shortName,
+                        r.appInfo.uid, r.shortInstanceName,
                         StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT);
+                mAm.updateForegroundServiceUsageStats(r.name, r.userId, false);
                 if (r.app != null) {
                     mAm.updateLruProcessLocked(r.app, false, null);
                     updateServiceForegroundLocked(r.app, true);
@@ -1361,8 +1373,8 @@
             // due the other service.
             ServiceMap sm = getServiceMapLocked(r.userId);
             if (sm != null) {
-                for (int i = sm.mServicesByName.size()-1; i >= 0; i--) {
-                    ServiceRecord other = sm.mServicesByName.valueAt(i);
+                for (int i = sm.mServicesByInstanceName.size() - 1; i >= 0; i--) {
+                    ServiceRecord other = sm.mServicesByInstanceName.valueAt(i);
                     if (other != r && other.foregroundId == r.foregroundId
                             && other.packageName.equals(r.packageName)) {
                         // Found one!  Abort the cancel.
@@ -1454,7 +1466,8 @@
 
     int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
             String resolvedType, final IServiceConnection connection, int flags,
-            String callingPackage, final int userId) throws TransactionTooLargeException {
+            String instanceName, String callingPackage, final int userId)
+            throws TransactionTooLargeException {
         if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "bindService: " + service
                 + " type=" + resolvedType + " conn=" + connection.asBinder()
                 + " flags=0x" + Integer.toHexString(flags));
@@ -1518,8 +1531,9 @@
         final boolean allowInstant = (flags & Context.BIND_ALLOW_INSTANT) != 0;
 
         ServiceLookupResult res =
-            retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(),
-                    Binder.getCallingUid(), userId, true, callerFg, isBindExternal, allowInstant);
+            retrieveServiceLocked(service, instanceName, resolvedType, callingPackage,
+                    Binder.getCallingPid(), Binder.getCallingUid(), userId, true,
+                    callerFg, isBindExternal, allowInstant);
         if (res == null) {
             return 0;
         }
@@ -1625,7 +1639,7 @@
 
             mAm.startAssociationLocked(callerApp.uid, callerApp.processName,
                     callerApp.getCurProcState(), s.appInfo.uid, s.appInfo.longVersionCode,
-                    s.name, s.processName);
+                    s.instanceName, s.processName);
             // Once the apps have become associated, if one of them is caller is ephemeral
             // the target app should now be able to see the calling app
             mAm.grantEphemeralAccessLocked(callerApp.userId, service,
@@ -1697,7 +1711,7 @@
                 try {
                     c.conn.connected(s.name, b.intent.binder, false);
                 } catch (Exception e) {
-                    Slog.w(TAG, "Failure sending service " + s.shortName
+                    Slog.w(TAG, "Failure sending service " + s.shortInstanceName
                             + " to connection " + c.conn.asBinder()
                             + " (in " + c.binding.client.processName + ")", e);
                 }
@@ -1751,9 +1765,9 @@
                             try {
                                 c.conn.connected(r.name, service, false);
                             } catch (Exception e) {
-                                Slog.w(TAG, "Failure sending service " + r.name +
-                                      " to connection " + c.conn.asBinder() +
-                                      " (in " + c.binding.client.processName + ")", e);
+                                Slog.w(TAG, "Failure sending service " + r.shortInstanceName
+                                      + " to connection " + c.conn.asBinder()
+                                      + " (in " + c.binding.client.processName + ")", e);
                             }
                         }
                     }
@@ -1886,7 +1900,8 @@
     }
 
     private ServiceLookupResult retrieveServiceLocked(Intent service,
-            String resolvedType, String callingPackage, int callingPid, int callingUid, int userId,
+            String instanceName, String resolvedType, String callingPackage,
+            int callingPid, int callingUid, int userId,
             boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal,
             boolean allowInstant) {
         ServiceRecord r = null;
@@ -1897,12 +1912,23 @@
                 ActivityManagerInternal.ALLOW_NON_FULL_IN_PROFILE, "service", null);
 
         ServiceMap smap = getServiceMapLocked(userId);
-        final ComponentName comp = service.getComponent();
+        final ComponentName comp;
+        if (instanceName == null) {
+            comp = service.getComponent();
+        } else {
+            final ComponentName realComp = service.getComponent();
+            if (realComp == null) {
+                throw new IllegalArgumentException("Can't use custom instance name '" + instanceName
+                        + "' without expicit component in Intent");
+            }
+            comp = new ComponentName(realComp.getPackageName(),
+                    realComp.getClassName() + ":" + instanceName);
+        }
         if (comp != null) {
-            r = smap.mServicesByName.get(comp);
+            r = smap.mServicesByInstanceName.get(comp);
             if (DEBUG_SERVICE && r != null) Slog.v(TAG_SERVICE, "Retrieved by component: " + r);
         }
-        if (r == null && !isBindExternal) {
+        if (r == null && !isBindExternal && instanceName == null) {
             Intent.FilterComparison filter = new Intent.FilterComparison(service);
             r = smap.mServicesByIntent.get(filter);
             if (DEBUG_SERVICE && r != null) Slog.v(TAG_SERVICE, "Retrieved by intent: " + r);
@@ -1924,24 +1950,29 @@
                 // TODO: come back and remove this assumption to triage all services
                 ResolveInfo rInfo = mAm.getPackageManagerInternalLocked().resolveService(service,
                         resolvedType, flags, userId, callingUid);
-                ServiceInfo sInfo =
-                    rInfo != null ? rInfo.serviceInfo : null;
+                ServiceInfo sInfo = rInfo != null ? rInfo.serviceInfo : null;
                 if (sInfo == null) {
                     Slog.w(TAG_SERVICE, "Unable to start service " + service + " U=" + userId +
                           ": not found");
                     return null;
                 }
-                ComponentName name = new ComponentName(
+                if (instanceName != null
+                        && (sInfo.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) == 0) {
+                    throw new IllegalArgumentException("Can't use instance name '" + instanceName
+                            + "' with non-isolated service '" + sInfo.name + "'");
+                }
+                ComponentName className = new ComponentName(
                         sInfo.applicationInfo.packageName, sInfo.name);
+                ComponentName name = comp != null ? comp : className;
                 if ((sInfo.flags & ServiceInfo.FLAG_EXTERNAL_SERVICE) != 0) {
                     if (isBindExternal) {
                         if (!sInfo.exported) {
-                            throw new SecurityException("BIND_EXTERNAL_SERVICE failed, " + name +
-                                    " is not exported");
+                            throw new SecurityException("BIND_EXTERNAL_SERVICE failed, "
+                                    + className + " is not exported");
                         }
                         if ((sInfo.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) == 0) {
-                            throw new SecurityException("BIND_EXTERNAL_SERVICE failed, " + name +
-                                    " is not an isolatedProcess");
+                            throw new SecurityException("BIND_EXTERNAL_SERVICE failed, "
+                                    + className + " is not an isolatedProcess");
                         }
                         // Run the service under the calling package's application.
                         ApplicationInfo aInfo = AppGlobals.getPackageManager().getApplicationInfo(
@@ -1955,6 +1986,9 @@
                         sInfo.applicationInfo.packageName = aInfo.packageName;
                         sInfo.applicationInfo.uid = aInfo.uid;
                         name = new ComponentName(aInfo.packageName, name.getClassName());
+                        className = new ComponentName(aInfo.packageName,
+                                instanceName == null ? className.getClassName()
+                                        : (className.getClassName() + ":" + instanceName));
                         service.setComponent(name);
                     } else {
                         throw new SecurityException("BIND_EXTERNAL_SERVICE required for " +
@@ -1974,7 +2008,7 @@
                     sInfo = new ServiceInfo(sInfo);
                     sInfo.applicationInfo = mAm.getAppInfoForUser(sInfo.applicationInfo, userId);
                 }
-                r = smap.mServicesByName.get(name);
+                r = smap.mServicesByInstanceName.get(name);
                 if (DEBUG_SERVICE && r != null) Slog.v(TAG_SERVICE,
                         "Retrieved via pm by intent: " + r);
                 if (r == null && createIfNeeded) {
@@ -1985,19 +2019,20 @@
                     final BatteryStatsImpl stats = mAm.mBatteryStatsService.getActiveStatistics();
                     synchronized (stats) {
                         ss = stats.getServiceStatsLocked(
-                                sInfo.applicationInfo.uid, sInfo.packageName,
-                                sInfo.name);
+                                sInfo.applicationInfo.uid, name.getPackageName(),
+                                name.getClassName());
                     }
-                    r = new ServiceRecord(mAm, ss, name, filter, sInfo, callingFromFg, res);
+                    r = new ServiceRecord(mAm, ss, className, name, filter, sInfo, callingFromFg,
+                            res);
                     res.setService(r);
-                    smap.mServicesByName.put(name, r);
+                    smap.mServicesByInstanceName.put(name, r);
                     smap.mServicesByIntent.put(filter, r);
 
                     // Make sure this component isn't in the pending list.
                     for (int i=mPendingServices.size()-1; i>=0; i--) {
                         final ServiceRecord pr = mPendingServices.get(i);
                         if (pr.serviceInfo.applicationInfo.uid == sInfo.applicationInfo.uid
-                                && pr.name.equals(name)) {
+                                && pr.instanceName.equals(name)) {
                             if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Remove pending: " + pr);
                             mPendingServices.remove(i);
                         }
@@ -2012,14 +2047,14 @@
             if (mAm.checkComponentPermission(r.permission,
                     callingPid, callingUid, r.appInfo.uid, r.exported) != PERMISSION_GRANTED) {
                 if (!r.exported) {
-                    Slog.w(TAG, "Permission Denial: Accessing service " + r.name
+                    Slog.w(TAG, "Permission Denial: Accessing service " + r.shortInstanceName
                             + " from pid=" + callingPid
                             + ", uid=" + callingUid
                             + " that is not exported from uid " + r.appInfo.uid);
                     return new ServiceLookupResult(null, "not exported from uid "
                             + r.appInfo.uid);
                 }
-                Slog.w(TAG, "Permission Denial: Accessing service " + r.name
+                Slog.w(TAG, "Permission Denial: Accessing service " + r.shortInstanceName
                         + " from pid=" + callingPid
                         + ", uid=" + callingUid
                         + " requires " + r.permission);
@@ -2028,7 +2063,7 @@
                 final int opCode = AppOpsManager.permissionToOpCode(r.permission);
                 if (opCode != AppOpsManager.OP_NONE && mAm.mAppOpsService.noteOperation(
                         opCode, callingUid, callingPackage) != AppOpsManager.MODE_ALLOWED) {
-                    Slog.w(TAG, "Appop Denial: Accessing service " + r.name
+                    Slog.w(TAG, "Appop Denial: Accessing service " + r.shortInstanceName
                             + " from pid=" + callingPid
                             + ", uid=" + callingUid
                             + " requires appop " + AppOpsManager.opToName(opCode));
@@ -2049,7 +2084,7 @@
         if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, ">>> EXECUTING "
                 + why + " of " + r + " in app " + r.app);
         else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING, ">>> EXECUTING "
-                + why + " of " + r.shortName);
+                + why + " of " + r.shortInstanceName);
 
         // For b/34123235: Services within the system server won't start until SystemServer
         // does Looper.loop(), so we shouldn't try to start/bind to them too early in the boot
@@ -2134,14 +2169,14 @@
         boolean canceled = false;
 
         if (mAm.mAtmInternal.isShuttingDown()) {
-            Slog.w(TAG, "Not scheduling restart of crashed service " + r.shortName
+            Slog.w(TAG, "Not scheduling restart of crashed service " + r.shortInstanceName
                     + " - system is shutting down");
             return false;
         }
 
         ServiceMap smap = getServiceMapLocked(r.userId);
-        if (smap.mServicesByName.get(r.name) != r) {
-            ServiceRecord cur = smap.mServicesByName.get(r.name);
+        if (smap.mServicesByInstanceName.get(r.instanceName) != r) {
+            ServiceRecord cur = smap.mServicesByInstanceName.get(r.instanceName);
             Slog.wtf(TAG, "Attempting to schedule restart of " + r
                     + " when found in map: " + cur);
             return false;
@@ -2172,7 +2207,7 @@
                         if (resetTime < dur) resetTime = dur;
                     } else {
                         Slog.w(TAG, "Canceling start item " + si.intent + " in service "
-                                + r.name);
+                                + r.shortInstanceName);
                         canceled = true;
                     }
                 }
@@ -2244,9 +2279,9 @@
         mAm.mHandler.postAtTime(r.restarter, r.nextRestartTime);
         r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
         Slog.w(TAG, "Scheduling restart of crashed service "
-                + r.shortName + " in " + r.restartDelay + "ms");
+                + r.shortInstanceName + " in " + r.restartDelay + "ms");
         EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
-                r.userId, r.shortName, r.restartDelay);
+                r.userId, r.shortInstanceName, r.restartDelay);
 
         return canceled;
     }
@@ -2381,7 +2416,7 @@
                 } catch (TransactionTooLargeException e) {
                     throw e;
                 } catch (RemoteException e) {
-                    Slog.w(TAG, "Exception when starting service " + r.shortName, e);
+                    Slog.w(TAG, "Exception when starting service " + r.shortInstanceName, e);
                 }
 
                 // If a dead object exception was thrown -- fall through to
@@ -2405,7 +2440,7 @@
         // to be executed when the app comes up.
         if (app == null && !permissionsReviewRequired) {
             if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
-                    hostingType, r.name, false, isolated, false)) == null) {
+                    hostingType, r.instanceName, false, isolated, false)) == null) {
                 String msg = "Unable to launch app "
                         + r.appInfo.packageName + "/"
                         + r.appInfo.uid + " for service "
@@ -2476,8 +2511,9 @@
         try {
             if (LOG_SERVICE_START_STOP) {
                 String nameTerm;
-                int lastPeriod = r.shortName.lastIndexOf('.');
-                nameTerm = lastPeriod >= 0 ? r.shortName.substring(lastPeriod) : r.shortName;
+                int lastPeriod = r.shortInstanceName.lastIndexOf('.');
+                nameTerm = lastPeriod >= 0 ? r.shortInstanceName.substring(lastPeriod)
+                        : r.shortInstanceName;
                 EventLogTags.writeAmCreateService(
                         r.userId, System.identityHashCode(r), nameTerm, r.app.uid, r.app.pid);
             }
@@ -2693,9 +2729,9 @@
                 try {
                     cr.conn.connected(r.name, null, true);
                 } catch (Exception e) {
-                    Slog.w(TAG, "Failure disconnecting service " + r.name +
-                          " to connection " + c.get(i).conn.asBinder() +
-                          " (in " + c.get(i).binding.client.processName + ")", e);
+                    Slog.w(TAG, "Failure disconnecting service " + r.shortInstanceName
+                          + " to connection " + c.get(i).conn.asBinder()
+                          + " (in " + c.get(i).binding.client.processName + ")", e);
                 }
             }
         }
@@ -2716,7 +2752,7 @@
                                 ibr.intent.getIntent());
                     } catch (Exception e) {
                         Slog.w(TAG, "Exception when unbinding service "
-                                + r.shortName, e);
+                                + r.shortInstanceName, e);
                         serviceProcessGoneLocked(r);
                     }
                 }
@@ -2761,14 +2797,14 @@
         }
 
         final ServiceMap smap = getServiceMapLocked(r.userId);
-        ServiceRecord found = smap.mServicesByName.remove(r.name);
+        ServiceRecord found = smap.mServicesByInstanceName.remove(r.instanceName);
 
         // Note when this method is called by bringUpServiceLocked(), the service is not found
-        // in mServicesByName and found will be null.
+        // in mServicesByInstanceName and found will be null.
         if (found != null && found != r) {
             // This is not actually the service we think is running...  this should not happen,
             // but if it does, fail hard.
-            smap.mServicesByName.put(r.name, found);
+            smap.mServicesByInstanceName.put(r.instanceName, found);
             throw new IllegalStateException("Bringing down " + r + " but actually running "
                     + found);
         }
@@ -2795,8 +2831,9 @@
             mAm.mAppOpsService.finishOperation(
                     AppOpsManager.getToken(mAm.mAppOpsService),
                     AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName);
-            StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED, r.appInfo.uid, r.shortName,
-                    StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT);
+            StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED, r.appInfo.uid,
+                    r.shortInstanceName, StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT);
+            mAm.updateForegroundServiceUsageStats(r.name, r.userId, false);
         }
 
         r.isForeground = false;
@@ -2825,7 +2862,7 @@
                     r.app.thread.scheduleStopService(r);
                 } catch (Exception e) {
                     Slog.w(TAG, "Exception when destroying service "
-                            + r.shortName, e);
+                            + r.shortInstanceName, e);
                     serviceProcessGoneLocked(r);
                 }
             } else {
@@ -2902,7 +2939,7 @@
         }
 
         mAm.stopAssociationLocked(b.client.uid, b.client.processName, s.appInfo.uid,
-                s.appInfo.longVersionCode, s.name, s.processName);
+                s.appInfo.longVersionCode, s.instanceName, s.processName);
 
         if (b.connections.size() == 0) {
             b.intent.apps.remove(b.client);
@@ -2929,7 +2966,7 @@
                     b.intent.doRebind = false;
                     s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
                 } catch (Exception e) {
-                    Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
+                    Slog.w(TAG, "Exception when unbinding service " + s.shortInstanceName, e);
                     serviceProcessGoneLocked(s);
                 }
             }
@@ -3048,17 +3085,17 @@
                 + ": nesting=" + r.executeNesting
                 + ", inDestroying=" + inDestroying + ", app=" + r.app);
         else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING,
-                "<<< DONE EXECUTING " + r.shortName);
+                "<<< DONE EXECUTING " + r.shortInstanceName);
         r.executeNesting--;
         if (r.executeNesting <= 0) {
             if (r.app != null) {
                 if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
-                        "Nesting at 0 of " + r.shortName);
+                        "Nesting at 0 of " + r.shortInstanceName);
                 r.app.execServicesFg = false;
                 r.app.executingServices.remove(r);
                 if (r.app.executingServices.size() == 0) {
                     if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING,
-                            "No more executingServices of " + r.shortName);
+                            "No more executingServices of " + r.shortInstanceName);
                     mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
                 } else if (r.executeFg) {
                     // Need to re-evaluate whether the app still needs to be in the foreground.
@@ -3128,7 +3165,7 @@
                 }
             } catch (RemoteException e) {
                 Slog.w(TAG, "Exception in new application when starting service "
-                        + sr.shortName, e);
+                        + sr.shortInstanceName, e);
                 throw e;
             }
         }
@@ -3214,7 +3251,8 @@
         if (userId == UserHandle.USER_ALL) {
             for (int i = mServiceMap.size() - 1; i >= 0; i--) {
                 didSomething |= collectPackageServicesLocked(packageName, filterByClasses,
-                        evenPersistent, doit, killProcess, mServiceMap.valueAt(i).mServicesByName);
+                        evenPersistent, doit, killProcess,
+                        mServiceMap.valueAt(i).mServicesByInstanceName);
                 if (!doit && didSomething) {
                     return true;
                 }
@@ -3225,7 +3263,7 @@
         } else {
             ServiceMap smap = mServiceMap.get(userId);
             if (smap != null) {
-                ArrayMap<ComponentName, ServiceRecord> items = smap.mServicesByName;
+                ArrayMap<ComponentName, ServiceRecord> items = smap.mServicesByInstanceName;
                 didSomething = collectPackageServicesLocked(packageName, filterByClasses,
                         evenPersistent, doit, killProcess, items);
             }
@@ -3275,7 +3313,7 @@
             ServiceRecord sr = services.get(i);
             if (sr.startRequested) {
                 if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) {
-                    Slog.i(TAG, "Stopping service " + sr.shortName + ": remove task");
+                    Slog.i(TAG, "Stopping service " + sr.shortInstanceName + ": remove task");
                     stopServiceLocked(sr);
                 } else {
                     sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
@@ -3313,7 +3351,7 @@
                                 } catch (Exception e) {
                                     // todo: this should be asynchronous!
                                     Slog.w(TAG, "Exception thrown disconnected servce "
-                                          + r.shortName
+                                          + r.shortInstanceName
                                           + " from app " + app.processName, e);
                                 }
                             }
@@ -3387,7 +3425,7 @@
                     if (false && proc != null && !proc.isPersistent() && proc.thread != null
                             && proc.pid != 0 && proc.pid != ActivityManagerService.MY_PID
                             && proc.setProcState >= ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
-                        proc.kill("bound to service " + sr.name.flattenToShortString()
+                        proc.kill("bound to service " + sr.shortInstanceName
                                 + " in dying proc " + (app != null ? app.processName : "??"), true);
                     }
                 }
@@ -3408,7 +3446,7 @@
 
             // Sanity check: if the service listed for the app is not one
             // we actually are maintaining, just let it drop.
-            final ServiceRecord curRec = smap.mServicesByName.get(sr.name);
+            final ServiceRecord curRec = smap.mServicesByInstanceName.get(sr.instanceName);
             if (curRec != sr) {
                 if (curRec != null) {
                     Slog.wtf(TAG, "Service " + sr + " in process " + app
@@ -3425,7 +3463,7 @@
                 Slog.w(TAG, "Service crashed " + sr.crashCount
                         + " times, stopping: " + sr);
                 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
-                        sr.userId, sr.crashCount, sr.shortName, app.pid);
+                        sr.userId, sr.crashCount, sr.shortInstanceName, app.pid);
                 bringDownServiceLocked(sr);
             } else if (!allowRestart
                     || !mAm.mUserController.isUserRunning(sr.userId, 0)) {
@@ -3631,7 +3669,7 @@
                 mLastAnrDump = sw.toString();
                 mAm.mHandler.removeCallbacks(mLastAnrDumpClearer);
                 mAm.mHandler.postDelayed(mLastAnrDumpClearer, LAST_ANR_LIFETIME_DURATION_MSECS);
-                anrMessage = "executing service " + timeout.shortName;
+                anrMessage = "executing service " + timeout.shortInstanceName;
             } else {
                 Message msg = mAm.mHandler.obtainMessage(
                         ActivityManagerService.SERVICE_TIMEOUT_MSG);
@@ -3677,7 +3715,8 @@
         final int userId = UserHandle.getUserId(applicationInfo.uid);
         ServiceMap serviceMap = mServiceMap.get(userId);
         if (serviceMap != null) {
-            ArrayMap<ComponentName, ServiceRecord> servicesByName = serviceMap.mServicesByName;
+            ArrayMap<ComponentName, ServiceRecord> servicesByName
+                    = serviceMap.mServicesByInstanceName;
             for (int j = servicesByName.size() - 1; j >= 0; j--) {
                 ServiceRecord serviceRecord = servicesByName.valueAt(j);
                 if (applicationInfo.packageName.equals(serviceRecord.appInfo.packageName)) {
@@ -3748,9 +3787,9 @@
             final int[] users = mAm.mUserController.getUsers();
             for (int user : users) {
                 ServiceMap smap = getServiceMapLocked(user);
-                if (smap.mServicesByName.size() > 0) {
-                    for (int si=0; si<smap.mServicesByName.size(); si++) {
-                        ServiceRecord r = smap.mServicesByName.valueAt(si);
+                if (smap.mServicesByInstanceName.size() > 0) {
+                    for (int si=0; si<smap.mServicesByInstanceName.size(); si++) {
+                        ServiceRecord r = smap.mServicesByInstanceName.valueAt(si);
                         if (!matcher.match(r, r.name)) {
                             continue;
                         }
@@ -4151,7 +4190,7 @@
                 }
                 long token = proto.start(ActiveServicesProto.SERVICES_BY_USERS);
                 proto.write(ActiveServicesProto.ServicesByUser.USER_ID, user);
-                ArrayMap<ComponentName, ServiceRecord> alls = smap.mServicesByName;
+                ArrayMap<ComponentName, ServiceRecord> alls = smap.mServicesByInstanceName;
                 for (int i=0; i<alls.size(); i++) {
                     alls.valueAt(i).writeToProto(proto,
                             ActiveServicesProto.ServicesByUser.SERVICE_RECORDS);
@@ -4184,7 +4223,7 @@
                 if (smap == null) {
                     continue;
                 }
-                ArrayMap<ComponentName, ServiceRecord> alls = smap.mServicesByName;
+                ArrayMap<ComponentName, ServiceRecord> alls = smap.mServicesByInstanceName;
                 for (int i=0; i<alls.size(); i++) {
                     ServiceRecord r1 = alls.valueAt(i);
 
@@ -4222,7 +4261,7 @@
         String innerPrefix = prefix + "  ";
         synchronized (mAm) {
             pw.print(prefix); pw.print("SERVICE ");
-                    pw.print(r.shortName); pw.print(" ");
+                    pw.print(r.shortInstanceName); pw.print(" ");
                     pw.print(Integer.toHexString(System.identityHashCode(r)));
                     pw.print(" pid=");
                     if (r.app != null) pw.println(r.app.pid);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 2c22e53..771d376 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -68,9 +68,7 @@
 import static android.os.Process.THREAD_GROUP_RESTRICTED;
 import static android.os.Process.THREAD_GROUP_TOP_APP;
 import static android.os.Process.THREAD_PRIORITY_FOREGROUND;
-import static android.os.Process.getPidsForCommands;
 import static android.os.Process.getTotalMemory;
-import static android.os.Process.getUidForPid;
 import static android.os.Process.isThreadInProcess;
 import static android.os.Process.killProcess;
 import static android.os.Process.killProcessQuiet;
@@ -127,11 +125,8 @@
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_UID_OBSERVERS;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.am.MemoryStatUtil.MEMORY_STAT_INTERESTING_NATIVE_PROCESSES;
 import static com.android.server.am.MemoryStatUtil.hasMemcg;
-import static com.android.server.am.MemoryStatUtil.readCmdlineFromProcfs;
 import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
-import static com.android.server.am.MemoryStatUtil.readMemoryStatFromProcfs;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
@@ -2060,8 +2055,7 @@
         private String mExemptionsStr;
         private List<String> mExemptions = Collections.emptyList();
         private int mLogSampleRate = -1;
-        @HiddenApiEnforcementPolicy private int mPolicyPreP = HIDDEN_API_ENFORCEMENT_DEFAULT;
-        @HiddenApiEnforcementPolicy private int mPolicyP = HIDDEN_API_ENFORCEMENT_DEFAULT;
+        @HiddenApiEnforcementPolicy private int mPolicy = HIDDEN_API_ENFORCEMENT_DEFAULT;
 
         public HiddenApiSettings(Handler handler, Context context) {
             super(handler);
@@ -2078,11 +2072,7 @@
                     false,
                     this);
             mContext.getContentResolver().registerContentObserver(
-                    Settings.Global.getUriFor(Settings.Global.HIDDEN_API_POLICY_PRE_P_APPS),
-                    false,
-                    this);
-            mContext.getContentResolver().registerContentObserver(
-                    Settings.Global.getUriFor(Settings.Global.HIDDEN_API_POLICY_P_APPS),
+                    Settings.Global.getUriFor(Settings.Global.HIDDEN_API_POLICY),
                     false,
                     this);
             update();
@@ -2117,8 +2107,7 @@
                 mLogSampleRate = logSampleRate;
                 zygoteProcess.setHiddenApiAccessLogSampleRate(mLogSampleRate);
             }
-            mPolicyPreP = getValidEnforcementPolicy(Settings.Global.HIDDEN_API_POLICY_PRE_P_APPS);
-            mPolicyP = getValidEnforcementPolicy(Settings.Global.HIDDEN_API_POLICY_P_APPS);
+            mPolicy = getValidEnforcementPolicy(Settings.Global.HIDDEN_API_POLICY);
         }
 
         private @HiddenApiEnforcementPolicy int getValidEnforcementPolicy(String settingsKey) {
@@ -2135,12 +2124,8 @@
             return mBlacklistDisabled;
         }
 
-        @HiddenApiEnforcementPolicy int getPolicyForPrePApps() {
-            return mPolicyPreP;
-        }
-
-        @HiddenApiEnforcementPolicy int getPolicyForPApps() {
-            return mPolicyP;
+        @HiddenApiEnforcementPolicy int getPolicy() {
+            return mPolicy;
         }
 
         public void onChange(boolean selfChange) {
@@ -2691,8 +2676,10 @@
     }
 
     void updateUsageStats(ComponentName activity, int uid, int userId, boolean resumed) {
-        if (DEBUG_SWITCH) Slog.d(TAG_SWITCH,
-                "updateUsageStats: comp=" + activity + "res=" + resumed);
+        if (DEBUG_SWITCH) {
+            Slog.d(TAG_SWITCH,
+                    "updateUsageStats: comp=" + activity + "res=" + resumed);
+        }
         final BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
         StatsLog.write(StatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED,
             uid, activity.getPackageName(),
@@ -2719,6 +2706,20 @@
         }
     }
 
+    void updateForegroundServiceUsageStats(ComponentName service, int userId, boolean started) {
+        if (DEBUG_SWITCH) {
+            Slog.d(TAG_SWITCH, "updateForegroundServiceUsageStats: comp="
+                    + service + "started=" + started);
+        }
+        synchronized (this) {
+            if (mUsageStatsService != null) {
+                mUsageStatsService.reportEvent(service, userId,
+                        started ? UsageEvents.Event.FOREGROUND_SERVICE_START
+                                : UsageEvents.Event.FOREGROUND_SERVICE_STOP);
+            }
+        }
+    }
+
     CompatibilityInfo compatibilityInfoForPackage(ApplicationInfo ai) {
         return mAtmInternal.compatibilityInfoForPackage(ai);
     }
@@ -13182,8 +13183,15 @@
     }
 
     public int bindService(IApplicationThread caller, IBinder token, Intent service,
-            String resolvedType, IServiceConnection connection, int flags, String callingPackage,
-            int userId) throws TransactionTooLargeException {
+            String resolvedType, IServiceConnection connection, int flags,
+            String callingPackage, int userId) throws TransactionTooLargeException {
+        return bindIsolatedService(caller, token, service, resolvedType, connection, flags,
+                null, callingPackage, userId);
+    }
+
+    public int bindIsolatedService(IApplicationThread caller, IBinder token, Intent service,
+            String resolvedType, IServiceConnection connection, int flags, String instanceName,
+            String callingPackage, int userId) throws TransactionTooLargeException {
         enforceNotIsolatedCaller("bindService");
 
         // Refuse possible leaked file descriptors
@@ -13197,7 +13205,7 @@
 
         synchronized(this) {
             return mServices.bindServiceLocked(caller, token, service,
-                    resolvedType, connection, flags, callingPackage, userId);
+                    resolvedType, connection, flags, instanceName, callingPackage, userId);
         }
     }
 
@@ -15830,7 +15838,7 @@
                                     mayBeTop = true;
                                     mayBeTopType = "service";
                                     mayBeTopSource = cr.binding.client;
-                                    mayBeTopTarget = s.name;
+                                    mayBeTopTarget = s.instanceName;
                                     clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
                                 } else {
                                     // Special handling for above-top states (persistent
@@ -15884,7 +15892,7 @@
                                     .REASON_SERVICE_IN_USE;
                             app.adjSource = cr.binding.client;
                             app.adjSourceProcState = clientProcState;
-                            app.adjTarget = s.name;
+                            app.adjTarget = s.instanceName;
                             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType
                                         + ": " + app + ", due to " + cr.binding.client
@@ -15914,7 +15922,7 @@
                                     .REASON_SERVICE_IN_USE;
                             app.adjSource = a;
                             app.adjSourceProcState = procState;
-                            app.adjTarget = s.name;
+                            app.adjTarget = s.instanceName;
                             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                                 reportOomAdjMessageLocked(TAG_OOM_ADJ,
                                         "Raise to service w/activity: " + app);
@@ -18767,28 +18775,6 @@
         }
 
         @Override
-        public List<ProcessMemoryState> getMemoryStateForNativeProcesses() {
-            List<ProcessMemoryState> processMemoryStates = new ArrayList<>();
-            int[] pids = getPidsForCommands(MEMORY_STAT_INTERESTING_NATIVE_PROCESSES);
-            for (int i = 0; i < pids.length; i++) {
-                int pid = pids[i];
-                MemoryStat memoryStat = readMemoryStatFromProcfs(pid);
-                if (memoryStat == null) {
-                    continue;
-                }
-                int uid = getUidForPid(pid);
-                String processName = readCmdlineFromProcfs(pid);
-                int oomScore = -1; // Unused, not included in the NativeProcessMemoryState atom.
-                ProcessMemoryState processMemoryState = new ProcessMemoryState(uid, processName,
-                        oomScore, memoryStat.pgfault, memoryStat.pgmajfault,
-                        memoryStat.rssInBytes, memoryStat.cacheInBytes, memoryStat.swapInBytes,
-                        memoryStat.rssHighWatermarkInBytes, memoryStat.startTimeNanos);
-                processMemoryStates.add(processMemoryState);
-            }
-            return processMemoryStates;
-        }
-
-        @Override
         public int handleIncomingUser(int callingPid, int callingUid, int userId,
                 boolean allowAll, int allowMode, String name, String callerPackage) {
             return mUserController.handleIncomingUser(callingPid, callingUid, userId, allowAll,
@@ -19191,6 +19177,9 @@
             if (!SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, false)) {
                 return false;
             }
+            if (uid == SHELL_UID || uid == ROOT_UID) {
+                return false;
+            }
             synchronized (mPidsSelfLocked) {
                 final ProcessRecord pr = mPidsSelfLocked.get(pid);
                 return pr == null || pr.mountMode != Zygote.MOUNT_EXTERNAL_FULL;
diff --git a/services/core/java/com/android/server/am/AppBindRecord.java b/services/core/java/com/android/server/am/AppBindRecord.java
index 4eaebd0..9870420 100644
--- a/services/core/java/com/android/server/am/AppBindRecord.java
+++ b/services/core/java/com/android/server/am/AppBindRecord.java
@@ -59,12 +59,12 @@
     public String toString() {
         return "AppBindRecord{"
             + Integer.toHexString(System.identityHashCode(this))
-            + " " + service.shortName + ":" + client.processName + "}";
+            + " " + service.shortInstanceName + ":" + client.processName + "}";
     }
 
     void writeToProto(ProtoOutputStream proto, long fieldId) {
         long token = proto.start(fieldId);
-        proto.write(AppBindRecordProto.SERVICE_NAME, service.shortName);
+        proto.write(AppBindRecordProto.SERVICE_NAME, service.shortInstanceName);
         proto.write(AppBindRecordProto.CLIENT_PROC_NAME, client.processName);
         final int N = connections.size();
         for (int i=0; i<N; i++) {
diff --git a/services/core/java/com/android/server/am/ConnectionRecord.java b/services/core/java/com/android/server/am/ConnectionRecord.java
index 37d07bb..bfa3f66 100644
--- a/services/core/java/com/android/server/am/ConnectionRecord.java
+++ b/services/core/java/com/android/server/am/ConnectionRecord.java
@@ -115,16 +115,16 @@
                 && (binding.service.appInfo.uid != clientUid
                         || !binding.service.processName.equals(clientProcessName))) {
             ProcessStats.ProcessStateHolder holder = binding.service.app.pkgList.get(
-                    binding.service.name.getPackageName());
+                    binding.service.instanceName.getPackageName());
             if (holder == null) {
                 Slog.wtf(TAG_AM, "No package in referenced service "
-                        + binding.service.name.toShortString() + ": proc=" + binding.service.app);
+                        + binding.service.shortInstanceName + ": proc=" + binding.service.app);
             } else if (holder.pkg == null) {
                 Slog.wtf(TAG_AM, "Inactive holder in referenced service "
-                        + binding.service.name.toShortString() + ": proc=" + binding.service.app);
+                        + binding.service.shortInstanceName + ": proc=" + binding.service.app);
             } else {
                 association = holder.pkg.getAssociationStateLocked(holder.state,
-                        binding.service.name.getClassName()).startSource(clientUid,
+                        binding.service.instanceName.getClassName()).startSource(clientUid,
                         clientProcessName);
 
             }
@@ -202,7 +202,7 @@
         if (serviceDead) {
             sb.append("DEAD ");
         }
-        sb.append(binding.service.shortName);
+        sb.append(binding.service.shortInstanceName);
         sb.append(":@");
         sb.append(Integer.toHexString(System.identityHashCode(conn.asBinder())));
         sb.append('}');
@@ -223,7 +223,7 @@
             proto.write(ConnectionRecordProto.FLAGS, ConnectionRecordProto.DEAD);
         }
         if (binding.service != null) {
-            proto.write(ConnectionRecordProto.SERVICE_NAME, binding.service.shortName);
+            proto.write(ConnectionRecordProto.SERVICE_NAME, binding.service.shortInstanceName);
         }
         proto.end(token);
     }
diff --git a/services/core/java/com/android/server/am/IntentBindRecord.java b/services/core/java/com/android/server/am/IntentBindRecord.java
index 839b6e1..90aef3e 100644
--- a/services/core/java/com/android/server/am/IntentBindRecord.java
+++ b/services/core/java/com/android/server/am/IntentBindRecord.java
@@ -99,7 +99,7 @@
         if ((collectFlags()&Context.BIND_AUTO_CREATE) != 0) {
             sb.append("CR ");
         }
-        sb.append(service.shortName);
+        sb.append(service.shortInstanceName);
         sb.append(':');
         if (intent != null) {
             intent.getIntent().toShortString(sb, false, false, false, false);
diff --git a/services/core/java/com/android/server/am/MemoryStatUtil.java b/services/core/java/com/android/server/am/MemoryStatUtil.java
index c978c13..80b4f77 100644
--- a/services/core/java/com/android/server/am/MemoryStatUtil.java
+++ b/services/core/java/com/android/server/am/MemoryStatUtil.java
@@ -16,9 +16,9 @@
 
 package com.android.server.am;
 
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_METRICS;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_METRICS;
 
 import android.annotation.Nullable;
 import android.os.FileUtils;
@@ -45,7 +45,7 @@
      * <p>Processes are matched by their cmdline in procfs. Example: cat /proc/pid/cmdline returns
      * /system/bin/statsd for the stats daemon.
      */
-    static final String[] MEMORY_STAT_INTERESTING_NATIVE_PROCESSES = new String[]{
+    public static final String[] MEMORY_STAT_INTERESTING_NATIVE_PROCESSES = new String[]{
             "/system/bin/statsd",  // Stats daemon.
             "/system/bin/surfaceflinger",
             "/system/bin/apexd",  // APEX daemon.
@@ -146,7 +146,7 @@
      * Returns null if file is not found in procfs or if file has unrecognized contents.
      */
     @Nullable
-    static MemoryStat readMemoryStatFromProcfs(int pid) {
+    public static MemoryStat readMemoryStatFromProcfs(int pid) {
         final String statPath = String.format(Locale.US, PROC_STAT_FILE_FMT, pid);
         MemoryStat stat = parseMemoryStatFromProcfs(readFileContents(statPath));
         if (stat == null) {
@@ -163,7 +163,7 @@
      * Returns content of /proc/pid/cmdline (e.g. /system/bin/statsd) or an empty string
      * if the file is not available.
      */
-    static String readCmdlineFromProcfs(int pid) {
+    public static String readCmdlineFromProcfs(int pid) {
         String path = String.format(Locale.US, PROC_CMDLINE_FILE_FMT, pid);
         String cmdline = readFileContents(path);
         return cmdline != null ? cmdline : "";
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index c1b720e..84b364b 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -1363,8 +1363,7 @@
 
             if (!disableHiddenApiChecks && !mService.mHiddenApiBlacklist.isDisabled()) {
                 app.info.maybeUpdateHiddenApiEnforcementPolicy(
-                        mService.mHiddenApiBlacklist.getPolicyForPrePApps(),
-                        mService.mHiddenApiBlacklist.getPolicyForPApps());
+                        mService.mHiddenApiBlacklist.getPolicy());
                 @ApplicationInfo.HiddenApiEnforcementPolicy int policy =
                         app.info.getHiddenApiEnforcementPolicy();
                 int policyBits = (policy << Zygote.API_ENFORCEMENT_POLICY_SHIFT);
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index d8f94c9..09f8c3e 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -70,7 +70,8 @@
     final ActivityManagerService ams;
     final BatteryStatsImpl.Uid.Pkg.Serv stats;
     final ComponentName name; // service component.
-    final String shortName; // name.flattenToShortString().
+    final ComponentName instanceName; // service component's per-instance name.
+    final String shortInstanceName; // instanceName.flattenToShortString().
     final Intent.FilterComparison intent;
                             // original intent used to find service.
     final ServiceInfo serviceInfo;
@@ -190,7 +191,7 @@
             StringBuilder sb = new StringBuilder(128);
             sb.append("ServiceRecord{")
                 .append(Integer.toHexString(System.identityHashCode(sr)))
-                .append(' ').append(sr.shortName)
+                .append(' ').append(sr.shortInstanceName)
                 .append(" StartItem ")
                 .append(Integer.toHexString(System.identityHashCode(this)))
                 .append(" id=").append(id).append('}');
@@ -235,7 +236,7 @@
 
     void writeToProto(ProtoOutputStream proto, long fieldId) {
         long token = proto.start(fieldId);
-        proto.write(ServiceRecordProto.SHORT_NAME, this.shortName);
+        proto.write(ServiceRecordProto.SHORT_NAME, this.shortInstanceName);
         proto.write(ServiceRecordProto.IS_RUNNING, app != null);
         if (app != null) {
             proto.write(ServiceRecordProto.PID, app.pid);
@@ -448,12 +449,14 @@
 
     ServiceRecord(ActivityManagerService ams,
             BatteryStatsImpl.Uid.Pkg.Serv servStats, ComponentName name,
+            ComponentName instanceName,
             Intent.FilterComparison intent, ServiceInfo sInfo, boolean callerIsFg,
             Runnable restarter) {
         this.ams = ams;
         this.stats = servStats;
         this.name = name;
-        shortName = name.flattenToShortString();
+        this.instanceName = instanceName;
+        shortInstanceName = instanceName.flattenToShortString();
         this.intent = intent;
         serviceInfo = sInfo;
         appInfo = sInfo.applicationInfo;
@@ -618,7 +621,7 @@
                             // those dirty apps we will create a notification clearly
                             // blaming the app.
                             Slog.v(TAG, "Attempted to start a foreground service ("
-                                    + name
+                                    + shortInstanceName
                                     + ") with a broken notification (no icon: "
                                     + localForegroundNoti
                                     + ")");
@@ -701,7 +704,7 @@
                         Slog.w(TAG, "Error showing notification for service", e);
                         // If it gave us a garbage notification, it doesn't
                         // get to be foreground.
-                        ams.setServiceForeground(name, ServiceRecord.this,
+                        ams.setServiceForeground(instanceName, ServiceRecord.this,
                                 0, null, 0);
                         ams.crashApplication(appUid, appPid, localPackageName, -1,
                                 "Bad notification for startForeground: " + e);
@@ -773,7 +776,7 @@
         sb.append("ServiceRecord{")
             .append(Integer.toHexString(System.identityHashCode(this)))
             .append(" u").append(userId)
-            .append(' ').append(shortName).append('}');
+            .append(' ').append(shortInstanceName).append('}');
         return stringName = sb.toString();
     }
 
diff --git a/services/core/java/com/android/server/biometrics/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/AuthenticationClient.java
index 61836fdd..2c2d404 100644
--- a/services/core/java/com/android/server/biometrics/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/AuthenticationClient.java
@@ -358,7 +358,7 @@
             if (mBundle != null) {
                 try {
                     mStatusBarService.showBiometricDialog(mBundle, mDialogReceiver,
-                            getBiometricType(), mRequireConfirmation);
+                            getBiometricType(), mRequireConfirmation, getTargetUserId());
                 } catch (RemoteException e) {
                     Slog.e(getLogTag(), "Unable to show biometric dialog", e);
                 }
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index 278c55f..5f09189 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -246,9 +246,20 @@
         public void authenticate(IBinder token, long sessionId, int userId,
                 IBiometricServiceReceiver receiver, int flags, String opPackageName,
                 Bundle bundle, IBiometricPromptReceiver dialogReceiver) throws RemoteException {
-            // Check the USE_BIOMETRIC permission here. In the BiometricServiceBase, check do the
-            // AppOps and foreground check.
-            checkPermission();
+            final int callingUid = Binder.getCallingUid();
+            final int callingPid = Binder.getCallingPid();
+            final int callingUserId = UserHandle.getCallingUserId();
+
+            // In the BiometricServiceBase, check do the AppOps and foreground check.
+            if (userId == callingUserId) {
+                // Check the USE_BIOMETRIC permission here.
+                checkPermission();
+            } else {
+                // Only allow internal clients to authenticate with a different userId
+                Slog.w(TAG, "User " + callingUserId + " is requesting authentication of userid: "
+                        + userId);
+                checkInternalPermission();
+            }
 
             if (token == null || receiver == null || opPackageName == null || bundle == null
                     || dialogReceiver == null) {
@@ -262,10 +273,6 @@
                 checkInternalPermission();
             }
 
-            final int callingUid = Binder.getCallingUid();
-            final int callingPid = Binder.getCallingPid();
-            final int callingUserId = UserHandle.getCallingUserId();
-
             mHandler.post(() -> {
                 final Pair<Integer, Integer> result = checkAndGetBiometricModality(callingUserId);
                 final int modality = result.first;
diff --git a/services/core/java/com/android/server/biometrics/face/FaceService.java b/services/core/java/com/android/server/biometrics/face/FaceService.java
index bc3cc3b..7aa2e47 100644
--- a/services/core/java/com/android/server/biometrics/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/face/FaceService.java
@@ -485,7 +485,7 @@
                 BiometricAuthenticator.Identifier biometric, int userId)
                 throws RemoteException {
             if (mFaceServiceReceiver != null) {
-                if (biometric instanceof Face) {
+                if (biometric == null || biometric instanceof Face) {
                     mFaceServiceReceiver.onAuthenticationSucceeded(deviceId, (Face)biometric);
                 } else {
                     Slog.e(TAG, "onAuthenticationSucceeded received non-face biometric");
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index a769590..65537ad 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -55,6 +55,7 @@
 
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
+import com.android.server.intelligence.IntelligenceManagerInternal;
 import com.android.server.uri.UriGrantsManagerInternal;
 import com.android.server.wm.WindowManagerInternal;
 
@@ -157,6 +158,7 @@
     private final IUserManager mUm;
     private final PackageManager mPm;
     private final AppOpsManager mAppOps;
+    private final IntelligenceManagerInternal mIm;
     private final IBinder mPermissionOwner;
     private HostClipboardMonitor mHostClipboardMonitor = null;
     private Thread mHostMonitorThread = null;
@@ -176,6 +178,7 @@
         mPm = getContext().getPackageManager();
         mUm = (IUserManager) ServiceManager.getService(Context.USER_SERVICE);
         mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
+        mIm = LocalServices.getService(IntelligenceManagerInternal.class);
         final IBinder permOwner = mUgmInternal.newUriPermissionOwner("clipboard");
         mPermissionOwner = permOwner;
         if (IS_EMULATOR) {
@@ -635,8 +638,9 @@
             return true;
         }
         // The default IME is always allowed to access the clipboard.
+        int userId = UserHandle.getUserId(callingUid);
         String defaultIme = Settings.Secure.getStringForUser(getContext().getContentResolver(),
-                Settings.Secure.DEFAULT_INPUT_METHOD, UserHandle.getUserId(callingUid));
+                Settings.Secure.DEFAULT_INPUT_METHOD, userId);
         if (!TextUtils.isEmpty(defaultIme)) {
             final String imePkg = ComponentName.unflattenFromString(defaultIme).getPackageName();
             if (imePkg.equals(callingPackage)) {
@@ -646,13 +650,18 @@
 
         switch (op) {
             case AppOpsManager.OP_READ_CLIPBOARD:
-                // Clipboard can only be read by applications with focus.
-                boolean uidFocused = mWm.isUidFocused(callingUid);
-                if (!uidFocused) {
-                    Slog.e(TAG, "Denying clipboard access to " + callingPackage
-                            + ", application is not in focus.");
+                // Clipboard can only be read by applications with focus..
+                boolean allowed = mWm.isUidFocused(callingUid);
+                if (!allowed && mIm != null) {
+                    // ...or the Intelligence Service
+                    allowed = mIm.isIntelligenceServiceForUser(callingUid, userId);
                 }
-                return uidFocused;
+                if (!allowed) {
+                    Slog.e(TAG, "Denying clipboard access to " + callingPackage
+                            + ", application is not in focus neither is the IntelligeService for "
+                            + "user " + userId);
+                }
+                return allowed;
             case AppOpsManager.OP_WRITE_CLIPBOARD:
                 // Writing is allowed without focus.
                 return true;
diff --git a/services/core/java/com/android/server/intelligence/IntelligenceManagerInternal.java b/services/core/java/com/android/server/intelligence/IntelligenceManagerInternal.java
new file mode 100644
index 0000000..0ed56ff
--- /dev/null
+++ b/services/core/java/com/android/server/intelligence/IntelligenceManagerInternal.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2018 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.intelligence;
+
+import android.annotation.UserIdInt;
+
+/**
+ * Intelligence Manager local system service interface.
+ *
+ * @hide Only for use within the system server.
+ */
+public abstract class IntelligenceManagerInternal {
+
+    /**
+     * Checks whether the given {@code uid} owns the
+     * {@link android.service.intelligence.IntelligenceService} implementation associated with the
+     * given {@code userId}.
+     */
+    public abstract boolean isIntelligenceServiceForUser(int uid, @UserIdInt int userId);
+}
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index f074573..9e6e381 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -2075,8 +2075,8 @@
         // note that this assumes the message will not be removed from the queue before
         // it is handled (otherwise the wake lock would be leaked).
         mWakeLock.acquire();
-        if (Log.isLoggable(TAG, Log.INFO)) {
-            Log.i(TAG, "WakeLock acquired by sendMessage(" + messageIdAsString(message) + ", " + arg
+        if (DEBUG) {
+            Log.d(TAG, "WakeLock acquired by sendMessage(" + messageIdAsString(message) + ", " + arg
                     + ", " + obj + ")");
         }
         mHandler.obtainMessage(message, arg, 1, obj).sendToTarget();
@@ -2133,8 +2133,8 @@
             if (msg.arg2 == 1) {
                 // wakelock was taken for this message, release it
                 mWakeLock.release();
-                if (Log.isLoggable(TAG, Log.INFO)) {
-                    Log.i(TAG, "WakeLock released by handleMessage(" + messageIdAsString(message)
+                if (DEBUG) {
+                    Log.d(TAG, "WakeLock released by handleMessage(" + messageIdAsString(message)
                             + ", " + msg.arg1 + ", " + msg.obj + ")");
                 }
             }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index b404c41..1c7572e 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -3610,7 +3610,7 @@
                         NotificationRecord r = mNotificationsByKey.get(adjustment.getKey());
                         if (r != null && mAssistants.isSameUser(token, r.getUserId())) {
                             applyAdjustment(r, adjustment);
-                            r.applyAdjustments();
+                            r.applyImportanceFromAdjustments();
                             if (r.getImportance() == IMPORTANCE_NONE) {
                                 cancelNotificationsFromListener(token, new String[]{r.getKey()});
                             } else {
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 84d0c01..a11b03f 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -664,6 +664,18 @@
                             .addTaggedData(MetricsEvent.ADJUSTMENT_KEY_SMART_REPLIES,
                                     getSmartReplies().size()));
                 }
+            }
+            applyImportanceFromAdjustments();
+        }
+    }
+
+    /**
+     * Update importance from the adjustment.
+     */
+    public void applyImportanceFromAdjustments() {
+        synchronized (mAdjustments) {
+            for (Adjustment adjustment : mAdjustments) {
+                Bundle signals = adjustment.getSignals();
                 if (signals.containsKey(Adjustment.KEY_IMPORTANCE)) {
                     int importance = signals.getInt(Adjustment.KEY_IMPORTANCE);
                     importance = Math.max(IMPORTANCE_UNSPECIFIED, importance);
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 95c70d5..95d2154 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -49,7 +49,7 @@
 
 import dalvik.system.DexFile;
 
-import static android.content.pm.ApplicationInfo.HIDDEN_API_ENFORCEMENT_NONE;
+import static android.content.pm.ApplicationInfo.HIDDEN_API_ENFORCEMENT_DISABLED;
 
 import static com.android.server.pm.Installer.DEXOPT_BOOTCOMPLETE;
 import static com.android.server.pm.Installer.DEXOPT_DEBUGGABLE;
@@ -548,7 +548,7 @@
         // Some apps are executed with restrictions on hidden API usage. If this app is one
         // of them, pass a flag to dexopt to enable the same restrictions during compilation.
         // TODO we should pass the actual flag value to dexopt, rather than assuming blacklist
-        int hiddenApiFlag = info.getHiddenApiEnforcementPolicy() == HIDDEN_API_ENFORCEMENT_NONE
+        int hiddenApiFlag = info.getHiddenApiEnforcementPolicy() == HIDDEN_API_ENFORCEMENT_DISABLED
                 ? 0
                 : DEXOPT_ENABLE_HIDDEN_API_CHECKS;
         // Avoid generating CompactDex for modes that are latency critical.
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 26f6e96..ea190a7 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1126,101 +1126,108 @@
             throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session not sealed");
         }
 
-        if (!params.isMultiPackage) {
-            Preconditions.checkNotNull(mPackageName);
-            Preconditions.checkNotNull(mSigningDetails);
-            Preconditions.checkNotNull(mResolvedBaseFile);
+        final IPackageInstallObserver2 localObserver;
+        if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) {
+            localObserver = null;
+        } else {
+            if (!params.isMultiPackage) {
+                Preconditions.checkNotNull(mPackageName);
+                Preconditions.checkNotNull(mSigningDetails);
+                Preconditions.checkNotNull(mResolvedBaseFile);
 
-            if (needToAskForPermissionsLocked()) {
-                // User needs to confirm installation;
-                // give installer an intent they can use to involve
-                // user.
-                final Intent intent = new Intent(PackageInstaller.ACTION_CONFIRM_INSTALL);
-                intent.setPackage(mPm.getPackageInstallerPackageName());
-                intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
-                try {
-                    mRemoteObserver.onUserActionRequired(intent);
-                } catch (RemoteException ignored) {
-                }
-
-                // Commit was keeping session marked as active until now; release
-                // that extra refcount so session appears idle.
-                closeInternal(false);
-                return null;
-            }
-
-            // Inherit any packages and native libraries from existing install that
-            // haven't been overridden.
-            if (params.mode == SessionParams.MODE_INHERIT_EXISTING) {
-                try {
-                    final List<File> fromFiles = mResolvedInheritedFiles;
-                    final File toDir = resolveStageDirLocked();
-
-                    if (LOGD) Slog.d(TAG, "Inherited files: " + mResolvedInheritedFiles);
-                    if (!mResolvedInheritedFiles.isEmpty() && mInheritedFilesBase == null) {
-                        throw new IllegalStateException("mInheritedFilesBase == null");
+                if (needToAskForPermissionsLocked()) {
+                    // User needs to confirm installation;
+                    // give installer an intent they can use to involve
+                    // user.
+                    final Intent intent = new Intent(PackageInstaller.ACTION_CONFIRM_INSTALL);
+                    intent.setPackage(mPm.getPackageInstallerPackageName());
+                    intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
+                    try {
+                        mRemoteObserver.onUserActionRequired(intent);
+                    } catch (RemoteException ignored) {
                     }
 
-                    if (isLinkPossible(fromFiles, toDir)) {
-                        if (!mResolvedInstructionSets.isEmpty()) {
-                            final File oatDir = new File(toDir, "oat");
-                            createOatDirs(mResolvedInstructionSets, oatDir);
+                    // Commit was keeping session marked as active until now; release
+                    // that extra refcount so session appears idle.
+                    closeInternal(false);
+                    return null;
+                }
+
+                // Inherit any packages and native libraries from existing install that
+                // haven't been overridden.
+                if (params.mode == SessionParams.MODE_INHERIT_EXISTING) {
+                    try {
+                        final List<File> fromFiles = mResolvedInheritedFiles;
+                        final File toDir = resolveStageDirLocked();
+
+                        if (LOGD) Slog.d(TAG, "Inherited files: " + mResolvedInheritedFiles);
+                        if (!mResolvedInheritedFiles.isEmpty() && mInheritedFilesBase == null) {
+                            throw new IllegalStateException("mInheritedFilesBase == null");
                         }
-                        // pre-create lib dirs for linking if necessary
-                        if (!mResolvedNativeLibPaths.isEmpty()) {
-                            for (String libPath : mResolvedNativeLibPaths) {
-                                // "/lib/arm64" -> ["lib", "arm64"]
-                                final int splitIndex = libPath.lastIndexOf('/');
-                                if (splitIndex < 0 || splitIndex >= libPath.length() - 1) {
-                                    Slog.e(TAG,
-                                            "Skipping native library creation for linking due to "
-                                                    + "invalid path: " + libPath);
-                                    continue;
-                                }
-                                final String libDirPath = libPath.substring(1, splitIndex);
-                                final File libDir = new File(toDir, libDirPath);
-                                if (!libDir.exists()) {
-                                    NativeLibraryHelper.createNativeLibrarySubdir(libDir);
-                                }
-                                final String archDirPath = libPath.substring(splitIndex + 1);
-                                NativeLibraryHelper.createNativeLibrarySubdir(
-                                        new File(libDir, archDirPath));
+
+                        if (isLinkPossible(fromFiles, toDir)) {
+                            if (!mResolvedInstructionSets.isEmpty()) {
+                                final File oatDir = new File(toDir, "oat");
+                                createOatDirs(mResolvedInstructionSets, oatDir);
                             }
+                            // pre-create lib dirs for linking if necessary
+                            if (!mResolvedNativeLibPaths.isEmpty()) {
+                                for (String libPath : mResolvedNativeLibPaths) {
+                                    // "/lib/arm64" -> ["lib", "arm64"]
+                                    final int splitIndex = libPath.lastIndexOf('/');
+                                    if (splitIndex < 0 || splitIndex >= libPath.length() - 1) {
+                                        Slog.e(TAG,
+                                                "Skipping native library creation for linking due"
+                                                        + " to invalid path: " + libPath);
+                                        continue;
+                                    }
+                                    final String libDirPath = libPath.substring(1, splitIndex);
+                                    final File libDir = new File(toDir, libDirPath);
+                                    if (!libDir.exists()) {
+                                        NativeLibraryHelper.createNativeLibrarySubdir(libDir);
+                                    }
+                                    final String archDirPath = libPath.substring(splitIndex + 1);
+                                    NativeLibraryHelper.createNativeLibrarySubdir(
+                                            new File(libDir, archDirPath));
+                                }
+                            }
+                            linkFiles(fromFiles, toDir, mInheritedFilesBase);
+                        } else {
+                            // TODO: this should delegate to DCS so the system process
+                            // avoids holding open FDs into containers.
+                            copyFiles(fromFiles, toDir);
                         }
-                        linkFiles(fromFiles, toDir, mInheritedFilesBase);
-                    } else {
-                        // TODO: this should delegate to DCS so the system process
-                        // avoids holding open FDs into containers.
-                        copyFiles(fromFiles, toDir);
+                    } catch (IOException e) {
+                        throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
+                                "Failed to inherit existing install", e);
                     }
-                } catch (IOException e) {
-                    throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
-                            "Failed to inherit existing install", e);
                 }
+
+                // TODO: surface more granular state from dexopt
+                mInternalProgress = 0.5f;
+                computeProgressLocked(true);
+
+                // Unpack native libraries
+                extractNativeLibraries(mResolvedStageDir, params.abiOverride,
+                        mayInheritNativeLibs());
             }
 
-            // TODO: surface more granular state from dexopt
-            mInternalProgress = 0.5f;
-            computeProgressLocked(true);
+            // We've reached point of no return; call into PMS to install the stage.
+            // Regardless of success or failure we always destroy session.
+            localObserver = new IPackageInstallObserver2.Stub() {
+                @Override
+                public void onUserActionRequired(Intent intent) {
+                    throw new IllegalStateException();
+                }
 
-            // Unpack native libraries
-            extractNativeLibraries(mResolvedStageDir, params.abiOverride, mayInheritNativeLibs());
+                @Override
+                public void onPackageInstalled(String basePackageName, int returnCode, String msg,
+                        Bundle extras) {
+                    destroyInternal();
+                    dispatchSessionFinished(returnCode, msg, extras);
+                }
+            };
         }
-        // We've reached point of no return; call into PMS to install the stage.
-        // Regardless of success or failure we always destroy session.
-        final IPackageInstallObserver2 localObserver = new IPackageInstallObserver2.Stub() {
-            @Override
-            public void onUserActionRequired(Intent intent) {
-                throw new IllegalStateException();
-            }
-
-            @Override
-            public void onPackageInstalled(String basePackageName, int returnCode, String msg,
-                    Bundle extras) {
-                destroyInternal();
-                dispatchSessionFinished(returnCode, msg, extras);
-            }
-        };
 
         final UserHandle user;
         if ((params.installFlags & PackageManager.INSTALL_ALL_USERS) != 0) {
@@ -1230,11 +1237,9 @@
         }
 
         mRelinquished = true;
-        final PackageManagerService.ActiveInstallSession activeInstallSession =
-                new PackageManagerService.ActiveInstallSession(mPackageName, stageDir,
-                        localObserver, params, mInstallerPackageName, mInstallerUid, user,
-                        mSigningDetails);
-        return activeInstallSession;
+        return new PackageManagerService.ActiveInstallSession(mPackageName, stageDir,
+                localObserver, params, mInstallerPackageName, mInstallerUid, user,
+                mSigningDetails);
     }
 
     private static void maybeRenameFile(File from, File to) throws PackageManagerException {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 77045fb..8a0c416 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -9308,7 +9308,7 @@
         }
     }
 
-    private SharedLibraryInfo getSharedLibraryInfoLPr(String name, long version) {
+    private @Nullable SharedLibraryInfo getSharedLibraryInfoLPr(String name, long version) {
         LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(name);
         if (versionedLib == null) {
             return null;
@@ -9580,16 +9580,26 @@
     private void applyDefiningSharedLibraryUpdateLocked(
             PackageParser.Package pkg, SharedLibraryInfo libInfo,
             BiConsumer<SharedLibraryInfo, SharedLibraryInfo> action) {
+        // Note that libraries defined by this package may be null if:
+        // - Package manager was unable to create the shared library. The package still
+        //   gets installed, but the shared library does not get created.
+        // Or:
+        // - Package manager is in a state where package isn't scanned yet. This will
+        //   get called again after scanning to fix the dependencies.
         if (pkg.isLibrary()) {
             if (pkg.staticSharedLibName != null) {
                 SharedLibraryInfo definedLibrary = getSharedLibraryInfoLPr(
                         pkg.staticSharedLibName, pkg.staticSharedLibVersion);
-                action.accept(definedLibrary, libInfo);
+                if (definedLibrary != null) {
+                    action.accept(definedLibrary, libInfo);
+                }
             } else {
                 for (String libraryName : pkg.libraryNames) {
                     SharedLibraryInfo definedLibrary = getSharedLibraryInfoLPr(
                             libraryName, SharedLibraryInfo.VERSION_UNDEFINED);
-                    action.accept(definedLibrary, libInfo);
+                    if (definedLibrary != null) {
+                        action.accept(definedLibrary, libInfo);
+                    }
                 }
             }
         }
@@ -16337,17 +16347,6 @@
                                         + oldPackage.mSharedUserId);
                     }
 
-                    // check if the new package supports all of the abis which the old package
-                    // supports
-                    boolean oldPkgSupportMultiArch =
-                            oldPackage.applicationInfo.secondaryCpuAbi != null;
-                    boolean newPkgSupportMultiArch = pkg.applicationInfo.secondaryCpuAbi != null;
-                    if (isSystemApp(oldPackage) && oldPkgSupportMultiArch
-                            && !newPkgSupportMultiArch) {
-                        throw new PrepareFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
-                                "Update to package " + pkgName11 + " doesn't support multi arch");
-                    }
-
                     // In case of rollback, remember per-user/profile install state
                     allUsers = sUserManager.getUserIds();
                     installedUsers = ps.queryInstalledUsers(allUsers, true);
@@ -17774,30 +17773,58 @@
         return true;
     }
 
+    private static class DeletePackageAction {
+        public final PackageSetting deletingPs;
+
+        private DeletePackageAction(PackageSetting deletingPs) {
+            this.deletingPs = deletingPs;
+        }
+    }
+
+    /**
+     * @return a {@link DeletePackageAction} if the provided package may be deleted, {@code null}
+     * otherwise.
+     */
+    @Nullable
+    private DeletePackageAction mayDeletePackageLIF(@NonNull String packageName) {
+        synchronized (mPackages) {
+            final PackageSetting ps;
+            ps = mSettings.mPackages.get(packageName);
+            if (ps == null) {
+                return null;
+            }
+            return new DeletePackageAction(ps);
+        }
+    }
+
     /*
      * This method handles package deletion in general
      */
-    private boolean deletePackageLIF(String packageName, UserHandle user,
+    private boolean deletePackageLIF(@NonNull String packageName, UserHandle user,
             boolean deleteCodeAndResources, int[] allUserHandles, int flags,
             PackageRemovedInfo outInfo, boolean writeSettings,
             PackageParser.Package replacingPackage) {
-        if (packageName == null) {
-            Slog.w(TAG, "Attempt to delete null packageName.");
+        final DeletePackageAction action = mayDeletePackageLIF(packageName);
+        if (null == action) {
             return false;
         }
 
         if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageLI: " + packageName + " user " + user);
 
-        PackageSetting ps;
-        synchronized (mPackages) {
-            ps = mSettings.mPackages.get(packageName);
-            if (ps == null) {
-                Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
-                return false;
-            }
+        return executeDeletePackageLIF(action, packageName, user, deleteCodeAndResources,
+                allUserHandles, flags, outInfo, writeSettings, replacingPackage);
+    }
 
-            if (ps.parentPackageName != null && (!isSystemApp(ps)
-                    || (flags & PackageManager.DELETE_SYSTEM_APP) != 0)) {
+    private boolean executeDeletePackageLIF(DeletePackageAction action,
+            String packageName, UserHandle user, boolean deleteCodeAndResources,
+            int[] allUserHandles, int flags, PackageRemovedInfo outInfo,
+            boolean writeSettings, PackageParser.Package replacingPackage) {
+        final PackageSetting ps = action.deletingPs;
+        final boolean systemApp = isSystemApp(ps);
+        synchronized (mPackages) {
+
+            if (ps.parentPackageName != null
+                    && (!systemApp || (flags & PackageManager.DELETE_SYSTEM_APP) != 0)) {
                 if (DEBUG_REMOVE) {
                     Slog.d(TAG, "Uninstalled child package:" + packageName + " for user:"
                             + ((user == null) ? UserHandle.USER_ALL : user));
@@ -17805,9 +17832,7 @@
                 final int removedUserId = (user != null) ? user.getIdentifier()
                         : UserHandle.USER_ALL;
 
-                if (!clearPackageStateForUserLIF(ps, removedUserId, outInfo)) {
-                    return false;
-                }
+                clearPackageStateForUserLIF(ps, removedUserId, outInfo);
                 markPackageUninstalledForUserLPw(ps, user);
                 scheduleWritePackageRestrictionsLocked(user);
                 return true;
@@ -17820,7 +17845,7 @@
         }
 
 
-        if (((!isSystemApp(ps) || (flags&PackageManager.DELETE_SYSTEM_APP) != 0) && user != null
+        if (((!systemApp || (flags & PackageManager.DELETE_SYSTEM_APP) != 0) && user != null
                 && user.getIdentifier() != UserHandle.USER_ALL)) {
             // The caller is asking that the package only be deleted for a single
             // user.  To do this, we just mark its uninstalled state and delete
@@ -17829,7 +17854,7 @@
             // semantics than normal for uninstalling system apps.
             markPackageUninstalledForUserLPw(ps, user);
 
-            if (!isSystemApp(ps)) {
+            if (!systemApp) {
                 // Do not uninstall the APK if an app should be cached
                 boolean keepUninstalledPackage = shouldKeepUninstalledPackageLPr(packageName);
                 if (ps.isAnyInstalled(sUserManager.getUserIds()) || keepUninstalledPackage) {
@@ -17837,9 +17862,7 @@
                     // we need to do is clear this user's data and save that
                     // it is uninstalled.
                     if (DEBUG_REMOVE) Slog.d(TAG, "Still installed by other users");
-                    if (!clearPackageStateForUserLIF(ps, user.getIdentifier(), outInfo)) {
-                        return false;
-                    }
+                    clearPackageStateForUserLIF(ps, user.getIdentifier(), outInfo);
                     scheduleWritePackageRestrictionsLocked(user);
                     return true;
                 } else {
@@ -17855,9 +17878,7 @@
                 // we need to do is clear this user's data and save that
                 // it is uninstalled.
                 if (DEBUG_REMOVE) Slog.d(TAG, "Deleting system app");
-                if (!clearPackageStateForUserLIF(ps, user.getIdentifier(), outInfo)) {
-                    return false;
-                }
+                clearPackageStateForUserLIF(ps, user.getIdentifier(), outInfo);
                 scheduleWritePackageRestrictionsLocked(user);
                 return true;
             }
@@ -17883,8 +17904,9 @@
             }
         }
 
-        boolean ret = false;
-        if (isSystemApp(ps)) {
+        // TODO(b/109941548): break reasons for ret = false out into mayDelete method
+        final boolean ret;
+        if (systemApp) {
             if (DEBUG_REMOVE) Slog.d(TAG, "Removing system package: " + ps.name);
             // When an updated system application is deleted we delete the existing resources
             // as well and fall back to existing code in system partition
@@ -17913,7 +17935,7 @@
             // If we uninstalled an update to a system app there may be some
             // child packages that appeared as they are declared in the system
             // app but were not declared in the update.
-            if (isSystemApp(ps)) {
+            if (systemApp) {
                 synchronized (mPackages) {
                     PackageSetting updatedPs = mSettings.getPackageLPr(ps.name);
                     final int childCount = (updatedPs.childPackageNames != null)
@@ -17974,7 +17996,7 @@
         mSettings.writeKernelMappingLPr(ps);
     }
 
-    private boolean clearPackageStateForUserLIF(PackageSetting ps, int userId,
+    private void clearPackageStateForUserLIF(PackageSetting ps, int userId,
             PackageRemovedInfo outInfo) {
         final PackageParser.Package pkg;
         synchronized (mPackages) {
@@ -18010,8 +18032,6 @@
             outInfo.removedUsers = userIds;
             outInfo.broadcastUsers = userIds;
         }
-
-        return true;
     }
 
     @Override
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 4c93441..6009bd3 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -2637,7 +2637,7 @@
         }
 
         for (final SharedUserSetting sus : mSharedUsers.values()) {
-            knownSet.remove(sus.getSandboxName());
+            knownSet.remove(sus.getStorageSandboxName());
         }
 
         // Remove any unclaimed mappings
@@ -2653,7 +2653,8 @@
     void writeKernelMappingLPr(SharedUserSetting sus) {
         if (mKernelMappingFilename == null || sus == null || sus.name == null) return;
 
-        writeKernelMappingLPr(sus.getSandboxName(), sus.userId, sus.getNotInstalledUserIds());
+        writeKernelMappingLPr(sus.getStorageSandboxName(),
+                sus.userId, sus.getNotInstalledUserIds());
     }
 
     void writeKernelMappingLPr(PackageSetting ps) {
diff --git a/services/core/java/com/android/server/pm/SharedUserSetting.java b/services/core/java/com/android/server/pm/SharedUserSetting.java
index 32826e5..d67144e 100644
--- a/services/core/java/com/android/server/pm/SharedUserSetting.java
+++ b/services/core/java/com/android/server/pm/SharedUserSetting.java
@@ -19,6 +19,7 @@
 import android.annotation.Nullable;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageParser;
+import android.os.storage.StorageManager;
 import android.service.pm.PackageServiceDumpProto;
 import android.util.ArraySet;
 import android.util.proto.ProtoOutputStream;
@@ -166,8 +167,8 @@
         return excludedUserIds == null ? EmptyArray.INT : excludedUserIds;
     }
 
-    public String getSandboxName() {
-        return "shared:" + name;
+    public String getStorageSandboxName() {
+        return StorageManager.SHARED_SANDBOX_PREFIX + name;
     }
 
     /** Updates all fields in this shared user setting from another. */
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
index a55b49f..f78d263 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
@@ -20,7 +20,7 @@
 import android.content.Context;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.security.IKeystoreService;
+import android.security.keystore.IKeystoreService;
 import android.util.Slog;
 
 import com.android.internal.policy.IKeyguardService;
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 43a9c78..29d6237 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -4439,6 +4439,42 @@
         }
 
         @Override // Binder call
+        public boolean setDynamicPowerSavings(boolean dynamicPowerSavingsEnabled,
+                int disableThreshold) {
+            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.POWER_SAVER,
+                    "updateDynamicPowerSavings");
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                final ContentResolver resolver = mContext.getContentResolver();
+                boolean success = Settings.Global.putInt(resolver,
+                        Settings.Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD,
+                        disableThreshold);
+                if (success) {
+                    // abort updating if we weren't able to succeed on the threshold
+                    success &= Settings.Global.putInt(resolver,
+                            Settings.Global.DYNAMIC_POWER_SAVINGS_ENABLED,
+                            dynamicPowerSavingsEnabled ? 1 : 0);
+                }
+                return success;
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override // Binder call
+        public int getPowerSaveMode() {
+            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.POWER_SAVER, null);
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                return Settings.Global.getInt(mContext.getContentResolver(),
+                        Settings.Global.AUTOMATIC_POWER_SAVER_MODE,
+                        PowerManager.POWER_SAVER_MODE_PERCENTAGE);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override // Binder call
         public boolean isDeviceIdleMode() {
             final long ident = Binder.clearCallingIdentity();
             try {
diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
index 5569822..6400c88 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
@@ -93,8 +93,8 @@
      */
     private final Plugin[] mPlugins;
 
-    public static final int REASON_AUTOMATIC_ON = 0;
-    public static final int REASON_AUTOMATIC_OFF = 1;
+    public static final int REASON_PERCENTAGE_AUTOMATIC_ON = 0;
+    public static final int REASON_PERCENTAGE_AUTOMATIC_OFF = 1;
     public static final int REASON_MANUAL_ON = 2;
     public static final int REASON_MANUAL_OFF = 3;
     public static final int REASON_STICKY_RESTORE = 4;
@@ -102,6 +102,8 @@
     public static final int REASON_POLICY_CHANGED = 6;
     public static final int REASON_PLUGGED_IN = 7;
     public static final int REASON_SETTING_CHANGED = 8;
+    public static final int REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_ON = 9;
+    public static final int REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_OFF = 10;
 
     /**
      * Plugin interface. All methods are guaranteed to be called on the same (handler) thread.
diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java
index 20ceed43..f262f6d 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.database.ContentObserver;
 import android.os.Handler;
+import android.os.PowerManager;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.provider.Settings.Global;
@@ -87,6 +88,11 @@
     /** Config flag to track if battery saver's sticky behaviour is disabled. */
     private final boolean mBatterySaverStickyBehaviourDisabled;
 
+    /** Config flag to track default disable threshold for Dynamic Power Savings enabled battery
+     * saver. */
+    @GuardedBy("mLock")
+    private final int mDynamicPowerSavingsDefaultDisableThreshold;
+
     /**
      * Previously known value of Global.LOW_POWER_MODE_TRIGGER_LEVEL.
      * (Currently only used in dumpsys.)
@@ -94,6 +100,23 @@
     @GuardedBy("mLock")
     private int mSettingBatterySaverTriggerThreshold;
 
+    /** Previously known value of Global.AUTOMATIC_POWER_SAVER_MODE. */
+    @GuardedBy("mLock")
+    private int mSettingAutomaticBatterySaver;
+
+    /** When to disable battery saver again if it was enabled due to an external suggestion.
+     *  Corresponds to Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD.
+     */
+    @GuardedBy("mLock")
+    private int mDynamicPowerSavingsDisableThreshold;
+
+    /**
+     * Whether we've received a suggestion that battery saver should be on from an external app.
+     * Updates when Global.DYNAMIC_POWER_SAVINGS_ENABLED changes.
+     */
+    @GuardedBy("mLock")
+    private boolean mDynamicPowerSavingsBatterySaver;
+
     /**
      * Whether BS has been manually disabled while the battery level is low, in which case we
      * shouldn't auto re-enable it until the battery level is not low.
@@ -130,13 +153,15 @@
 
         mBatterySaverStickyBehaviourDisabled = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_batterySaverStickyBehaviourDisabled);
+        mDynamicPowerSavingsDefaultDisableThreshold = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_dynamicPowerSavingsDefaultDisableThreshold);
     }
 
     private boolean isBatterySaverEnabled() {
         return mBatterySaverController.isEnabled();
     }
 
-    private boolean isAutoBatterySaverConfigured() {
+    private boolean isAutoBatterySaverConfiguredLocked() {
         return mSettingBatterySaverTriggerThreshold > 0;
     }
 
@@ -165,6 +190,15 @@
             cr.registerContentObserver(Settings.Global.getUriFor(
                     Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL),
                     false, mSettingsObserver, UserHandle.USER_SYSTEM);
+            cr.registerContentObserver(Settings.Global.getUriFor(
+                    Global.AUTOMATIC_POWER_SAVER_MODE),
+                    false, mSettingsObserver, UserHandle.USER_SYSTEM);
+            cr.registerContentObserver(Settings.Global.getUriFor(
+                    Global.DYNAMIC_POWER_SAVINGS_ENABLED),
+                    false, mSettingsObserver, UserHandle.USER_SYSTEM);
+            cr.registerContentObserver(Settings.Global.getUriFor(
+                    Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD),
+                    false, mSettingsObserver, UserHandle.USER_SYSTEM);
 
             synchronized (mLock) {
 
@@ -202,11 +236,20 @@
                 Settings.Global.LOW_POWER_MODE, 0) != 0;
         final boolean lowPowerModeEnabledSticky = getGlobalSetting(
                 Settings.Global.LOW_POWER_MODE_STICKY, 0) != 0;
+        final boolean dynamicPowerSavingsBatterySaver = getGlobalSetting(
+                Global.DYNAMIC_POWER_SAVINGS_ENABLED, 0) != 0;
         final int lowPowerModeTriggerLevel = getGlobalSetting(
                 Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
+        final int automaticBatterySaver = getGlobalSetting(
+                Global.AUTOMATIC_POWER_SAVER_MODE,
+                PowerManager.POWER_SAVER_MODE_PERCENTAGE);
+        final int dynamicPowerSavingsDisableThreshold = getGlobalSetting(
+                Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD,
+                mDynamicPowerSavingsDefaultDisableThreshold);
 
         setSettingsLocked(lowPowerModeEnabled, lowPowerModeEnabledSticky,
-                lowPowerModeTriggerLevel);
+                lowPowerModeTriggerLevel, automaticBatterySaver, dynamicPowerSavingsBatterySaver,
+                dynamicPowerSavingsDisableThreshold);
     }
 
     /**
@@ -218,11 +261,16 @@
     @GuardedBy("mLock")
     @VisibleForTesting
     void setSettingsLocked(boolean batterySaverEnabled, boolean batterySaverEnabledSticky,
-            int batterySaverTriggerThreshold) {
+            int batterySaverTriggerThreshold, int automaticBatterySaver,
+            boolean dynamicPowerSavingsBatterySaver, int dynamicPowerSavingsDisableThreshold) {
         if (DEBUG) {
             Slog.d(TAG, "setSettings: enabled=" + batterySaverEnabled
                     + " sticky=" + batterySaverEnabledSticky
-                    + " threshold=" + batterySaverTriggerThreshold);
+                    + " threshold=" + batterySaverTriggerThreshold
+                    + " automaticBatterySaver=" + automaticBatterySaver
+                    + " dynamicPowerSavingsBatterySaver=" + dynamicPowerSavingsBatterySaver
+                    + " dynamicPowerSavingsDisableThreshold="
+                    + dynamicPowerSavingsDisableThreshold);
         }
 
         mSettingsLoaded = true;
@@ -232,14 +280,23 @@
                 mSettingBatterySaverEnabledSticky != batterySaverEnabledSticky;
         final boolean thresholdChanged
                 = mSettingBatterySaverTriggerThreshold != batterySaverTriggerThreshold;
+        final boolean automaticModeChanged = mSettingAutomaticBatterySaver != automaticBatterySaver;
+        final boolean dynamicPowerSavingsThresholdChanged =
+                mDynamicPowerSavingsDisableThreshold != dynamicPowerSavingsDisableThreshold;
+        final boolean dynamicPowerSavingsBatterySaverChanged =
+                mDynamicPowerSavingsBatterySaver != dynamicPowerSavingsBatterySaver;
 
-        if (!(enabledChanged || stickyChanged || thresholdChanged)) {
+        if (!(enabledChanged || stickyChanged || thresholdChanged || automaticModeChanged
+                || dynamicPowerSavingsThresholdChanged || dynamicPowerSavingsBatterySaverChanged)) {
             return;
         }
 
         mSettingBatterySaverEnabled = batterySaverEnabled;
         mSettingBatterySaverEnabledSticky = batterySaverEnabledSticky;
         mSettingBatterySaverTriggerThreshold = batterySaverTriggerThreshold;
+        mSettingAutomaticBatterySaver = automaticBatterySaver;
+        mDynamicPowerSavingsDisableThreshold = dynamicPowerSavingsDisableThreshold;
+        mDynamicPowerSavingsBatterySaver = dynamicPowerSavingsBatterySaver;
 
         if (thresholdChanged) {
             // To avoid spamming the event log, we throttle logging here.
@@ -287,6 +344,17 @@
         }
     }
 
+    @GuardedBy("mLock")
+    private boolean isBatteryLowLocked() {
+        final boolean percentageLow =
+                mSettingAutomaticBatterySaver == PowerManager.POWER_SAVER_MODE_PERCENTAGE
+                && mIsBatteryLevelLow;
+        final boolean dynamicPowerSavingsLow =
+                mSettingAutomaticBatterySaver == PowerManager.POWER_SAVER_MODE_DYNAMIC
+                && mBatteryLevel <= mDynamicPowerSavingsDisableThreshold;
+        return percentageLow || dynamicPowerSavingsLow;
+    }
+
     /**
      * Decide whether to auto-start / stop battery saver.
      */
@@ -299,12 +367,14 @@
                     + " mIsBatteryLevelLow=" + mIsBatteryLevelLow
                     + " mBatterySaverSnoozing=" + mBatterySaverSnoozing
                     + " mIsPowered=" + mIsPowered
+                    + " mSettingAutomaticBatterySaver=" + mSettingAutomaticBatterySaver
                     + " mSettingBatterySaverEnabledSticky=" + mSettingBatterySaverEnabledSticky);
         }
         if (!(mBootCompleted && mSettingsLoaded && mBatteryStatusSet)) {
             return; // Not fully initialized yet.
         }
-        if (!mIsBatteryLevelLow) {
+
+        if (!isBatteryLowLocked()) {
             updateSnoozingLocked(false, "Battery not low");
         }
         if (mIsPowered) {
@@ -319,20 +389,35 @@
                     BatterySaverController.REASON_STICKY_RESTORE,
                     "Sticky restore");
 
-        } else if (mIsBatteryLevelLow) {
-            if (!mBatterySaverSnoozing && isAutoBatterySaverConfigured()) {
+        } else if (mSettingAutomaticBatterySaver
+                == PowerManager.POWER_SAVER_MODE_PERCENTAGE
+                && isAutoBatterySaverConfiguredLocked()) {
+            if (mIsBatteryLevelLow && !mBatterySaverSnoozing) {
                 enableBatterySaverLocked(/*enable=*/ true, /*manual=*/ false,
-                        BatterySaverController.REASON_AUTOMATIC_ON,
-                        "Auto ON");
+                        BatterySaverController.REASON_PERCENTAGE_AUTOMATIC_ON,
+                        "Percentage Auto ON");
+            } else {
+                // Battery not low
+                enableBatterySaverLocked(/*enable=*/ false, /*manual=*/ false,
+                        BatterySaverController.REASON_PERCENTAGE_AUTOMATIC_OFF,
+                        "Percentage Auto OFF");
             }
-        } else { // Battery not low
-            enableBatterySaverLocked(/*enable=*/ false, /*manual=*/ false,
-                    BatterySaverController.REASON_AUTOMATIC_OFF,
-                    "Auto OFF");
+        } else if (mSettingAutomaticBatterySaver
+                == PowerManager.POWER_SAVER_MODE_DYNAMIC) {
+            if (mBatteryLevel >= mDynamicPowerSavingsDisableThreshold) {
+                enableBatterySaverLocked(/*enable=*/ false, /*manual=*/ false,
+                        BatterySaverController.REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_OFF,
+                        "Dynamic Warning Auto OFF");
+            } else if (mDynamicPowerSavingsBatterySaver && !mBatterySaverSnoozing) {
+                enableBatterySaverLocked(/*enable=*/ true, /*manual=*/ false,
+                        BatterySaverController.REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_ON,
+                        "Dynamic Warning Auto ON");
+            }
         }
+        // do nothing if automatic battery saver mode = PERCENTAGE and low warning threshold = 0%
     }
 
-    /**
+  /**
      * {@link com.android.server.power.PowerManagerService} calls it when
      * {@link android.os.PowerManager#setPowerSaveMode} is called.
      *
@@ -383,7 +468,7 @@
                 // When battery saver is disabled manually (while battery saver is enabled)
                 // when the battery level is low, we "snooze" BS -- i.e. disable auto battery saver.
                 // We resume auto-BS once the battery level is not low, or the device is plugged in.
-                if (isBatterySaverEnabled() && mIsBatteryLevelLow) {
+                if (isBatterySaverEnabled() && isBatteryLowLocked()) {
                     updateSnoozingLocked(true, "Manual snooze");
                 }
             }
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index b7d2ce2..ded075d 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -104,12 +104,18 @@
     @Override
     public void onStart() {
         publishBinderService(Context.ROLE_SERVICE, new Stub());
+        //TODO add watch for new user creation and run default grants for them
     }
 
     @Override
     public void onStartUser(@UserIdInt int userId) {
         synchronized (mLock) {
+            //TODO only call into PermissionController if it or system upgreaded (for boot time)
+            // (add package changes watch;
+            //     we can detect upgrade using build fingerprint and app version)
             getUserStateLocked(userId);
+            //TODO call permission grant policy here
+            Slog.i(LOG_TAG, "Granting default permissions...");
         }
     }
 
diff --git a/services/core/java/com/android/server/role/RoleUserState.java b/services/core/java/com/android/server/role/RoleUserState.java
index caa7c28..becc962 100644
--- a/services/core/java/com/android/server/role/RoleUserState.java
+++ b/services/core/java/com/android/server/role/RoleUserState.java
@@ -73,7 +73,7 @@
      * Maps role names to its holders' package names. The values should never be null.
      */
     @GuardedBy("RoleManagerService.mLock")
-    private ArrayMap<String, ArraySet<String>> mRoles = new ArrayMap<>();
+    private ArrayMap<String, ArraySet<String>> mRoles = null;
 
     @GuardedBy("RoleManagerService.mLock")
     private boolean mDestroyed;
@@ -188,7 +188,8 @@
             roles.put(roleName, roleHolders);
         }
         mWriteHandler.removeCallbacksAndMessages(null);
-        mWriteHandler.sendMessage(PooledLambda.obtainMessage(this::writeSync, version, roles));
+        mWriteHandler.sendMessage(PooledLambda.obtainMessage(
+                RoleUserState::writeSync, this, version, roles));
     }
 
     @WorkerThread
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 70c86a1..70220d8 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -15,7 +15,13 @@
  */
 package com.android.server.stats;
 
+import static android.os.Process.getPidsForCommands;
+import static android.os.Process.getUidForPid;
+
 import static com.android.internal.util.Preconditions.checkNotNull;
+import static com.android.server.am.MemoryStatUtil.MEMORY_STAT_INTERESTING_NATIVE_PROCESSES;
+import static com.android.server.am.MemoryStatUtil.readCmdlineFromProcfs;
+import static com.android.server.am.MemoryStatUtil.readMemoryStatFromProcfs;
 
 import android.annotation.Nullable;
 import android.app.ActivityManagerInternal;
@@ -35,6 +41,9 @@
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
 import android.hardware.fingerprint.FingerprintManager;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkRequest;
 import android.net.NetworkStats;
 import android.net.wifi.IWifiManager;
 import android.net.wifi.WifiActivityEnergyInfo;
@@ -96,6 +105,7 @@
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.SystemServiceManager;
+import com.android.server.am.MemoryStatUtil.MemoryStat;
 import com.android.server.storage.DiskStatsFileLogger;
 import com.android.server.storage.DiskStatsLoggingService;
 
@@ -264,6 +274,12 @@
             Slog.e(TAG, "cannot find thermalservice, no throttling push notifications");
         }
 
+        // Default NetworkRequest should cover all transport types.
+        final NetworkRequest request = new NetworkRequest.Builder().build();
+        final ConnectivityManager connectivityManager =
+                (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+        connectivityManager.registerNetworkCallback(request, new ConnectivityStatsCallback());
+
         HandlerThread handlerThread = new HandlerThread(TAG);
         handlerThread.start();
         mHandler = new CompanionHandler(handlerThread.getLooper());
@@ -350,6 +366,8 @@
         List<Integer> uids = new ArrayList<>();
         List<Long> versions = new ArrayList<>();
         List<String> apps = new ArrayList<>();
+        List<String> versionStrings = new ArrayList<>();
+        List<String> installers = new ArrayList<>();
 
         // Add in all the apps for every user/profile.
         for (UserInfo profile : users) {
@@ -357,14 +375,24 @@
                     pm.getInstalledPackagesAsUser(PackageManager.MATCH_KNOWN_PACKAGES, profile.id);
             for (int j = 0; j < pi.size(); j++) {
                 if (pi.get(j).applicationInfo != null) {
+                    String installer;
+                    try {
+                        installer = pm.getInstallerPackageName(pi.get(j).packageName);
+                    } catch (IllegalArgumentException e) {
+                        installer = "";
+                    }
+                    installers.add(installer == null ? "" : installer);
                     uids.add(pi.get(j).applicationInfo.uid);
                     versions.add(pi.get(j).getLongVersionCode());
+                    versionStrings.add(pi.get(j).versionName);
                     apps.add(pi.get(j).packageName);
                 }
             }
         }
-        sStatsd.informAllUidData(toIntArray(uids), toLongArray(versions), apps.toArray(new
-                String[apps.size()]));
+        sStatsd.informAllUidData(toIntArray(uids), toLongArray(versions),
+                versionStrings.toArray(new String[versionStrings.size()]),
+                apps.toArray(new String[apps.size()]),
+                installers.toArray(new String[installers.size()]));
         if (DEBUG) {
             Slog.d(TAG, "Sent data for " + uids.size() + " apps");
         }
@@ -406,7 +434,14 @@
                         int uid = b.getInt(Intent.EXTRA_UID);
                         String app = intent.getData().getSchemeSpecificPart();
                         PackageInfo pi = pm.getPackageInfo(app, PackageManager.MATCH_ANY_USER);
-                        sStatsd.informOnePackage(app, uid, pi.getLongVersionCode());
+                        String installer;
+                        try {
+                            installer = pm.getInstallerPackageName(app);
+                        } catch (IllegalArgumentException e) {
+                            installer = "";
+                        }
+                        sStatsd.informOnePackage(app, uid, pi.getLongVersionCode(), pi.versionName,
+                                installer == null ? "" : installer);
                     }
                 } catch (Exception e) {
                     Slog.w(TAG, "Failed to inform statsd of an app update", e);
@@ -1012,17 +1047,23 @@
     private void pullNativeProcessMemoryState(
             int tagId, long elapsedNanos, long wallClockNanos,
             List<StatsLogEventWrapper> pulledData) {
-        List<ProcessMemoryState> processMemoryStates = LocalServices.getService(
-                ActivityManagerInternal.class).getMemoryStateForNativeProcesses();
-        for (ProcessMemoryState processMemoryState : processMemoryStates) {
+        int[] pids = getPidsForCommands(MEMORY_STAT_INTERESTING_NATIVE_PROCESSES);
+        for (int i = 0; i < pids.length; i++) {
+            int pid = pids[i];
+            MemoryStat memoryStat = readMemoryStatFromProcfs(pid);
+            if (memoryStat == null) {
+                continue;
+            }
+            int uid = getUidForPid(pid);
+            String processName = readCmdlineFromProcfs(pid);
             StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
-            e.writeInt(processMemoryState.uid);
-            e.writeString(processMemoryState.processName);
-            e.writeLong(processMemoryState.pgfault);
-            e.writeLong(processMemoryState.pgmajfault);
-            e.writeLong(processMemoryState.rssInBytes);
-            e.writeLong(processMemoryState.rssHighWatermarkInBytes);
-            e.writeLong(processMemoryState.startTimeNanos);
+            e.writeInt(uid);
+            e.writeString(processName);
+            e.writeLong(memoryStat.pgfault);
+            e.writeLong(memoryStat.pgmajfault);
+            e.writeLong(memoryStat.rssInBytes);
+            e.writeLong(memoryStat.rssHighWatermarkInBytes);
+            e.writeLong(memoryStat.startTimeNanos);
             pulledData.add(e);
         }
     }
@@ -1862,4 +1903,19 @@
                     temp.getValue());
         }
     }
+
+    private static final class ConnectivityStatsCallback extends
+            ConnectivityManager.NetworkCallback {
+        @Override
+        public void onAvailable(Network network) {
+            StatsLog.write(StatsLog.CONNECTIVITY_STATE_CHANGED, network.netId,
+                    StatsLog.CONNECTIVITY_STATE_CHANGED__STATE__CONNECTED);
+        }
+
+        @Override
+        public void onLost(Network network) {
+            StatsLog.write(StatsLog.CONNECTIVITY_STATE_CHANGED, network.netId,
+                    StatsLog.CONNECTIVITY_STATE_CHANGED__STATE__DISCONNECTED);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index ec78560..3e07ebe 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -37,6 +37,7 @@
 import android.service.notification.NotificationStats;
 import android.text.TextUtils;
 import android.util.ArrayMap;
+import android.util.Log;
 import android.util.Slog;
 
 import com.android.internal.R;
@@ -567,11 +568,11 @@
 
     @Override
     public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver, int type,
-            boolean requireConfirmation) {
+            boolean requireConfirmation, int userId) {
         enforceBiometricDialog();
         if (mBar != null) {
             try {
-                mBar.showBiometricDialog(bundle, receiver, type, requireConfirmation);
+                mBar.showBiometricDialog(bundle, receiver, type, requireConfirmation, userId);
             } catch (RemoteException ex) {
             }
         }
@@ -671,6 +672,20 @@
         // Ensure state for the current user is applied, even if passed a non-current user.
         final int net1 = gatherDisableActionsLocked(mCurrentUserId, 1);
         final int net2 = gatherDisableActionsLocked(mCurrentUserId, 2);
+
+        // TODO(b/113914868): investigation log for disappearing home button
+        if (whichFlag == 1 && pkg.contains("systemui")) {
+            String disabledData = "{ ";
+            for (int i = 0; i < mDisableRecords.size(); i++) {
+                DisableRecord tok = mDisableRecords.get(i);
+                disabledData += "    ([" + i + "] " + tok + "), ";
+            }
+            disabledData += " }";
+            Log.d(TAG, "disabledlocked (b/113914868): net1=" + net1 + ", mDisabled1=" + mDisabled1
+                    + ", token=" + token + ", mDisableRecords=" + mDisableRecords.size() + " => "
+                    + disabledData);
+        }
+
         if (net1 != mDisabled1 || net2 != mDisabled2) {
             mDisabled1 = net1;
             mDisabled2 = net2;
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 61e1414..1c08d03 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -383,7 +383,7 @@
             return;
         }
 
-        if (launchedActivity != null && launchedActivity.nowVisible) {
+        if (launchedActivity != null && launchedActivity.mDrawn) {
             // Launched activity is already visible. We cannot measure windows drawn delay.
             reset(true /* abort */, info, "launched activity already visible");
             return;
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 23f8125..c43e64e 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -20,6 +20,7 @@
 import static android.app.ActivityManager.TaskDescription.ATTR_TASKDESCRIPTION_PREFIX;
 import static android.app.ActivityOptions.ANIM_SCENE_TRANSITION;
 import static android.app.ActivityTaskManager.INVALID_STACK_ID;
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
 import static android.app.AppOpsManager.MODE_ALLOWED;
 import static android.app.AppOpsManager.OP_PICTURE_IN_PICTURE;
 import static android.app.WaitResult.INVALID_DELAY;
@@ -75,6 +76,25 @@
 import static android.view.Display.INVALID_DISPLAY;
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
 
+import static com.android.server.am.ActivityRecordProto.CONFIGURATION_CONTAINER;
+import static com.android.server.am.ActivityRecordProto.FRONT_OF_TASK;
+import static com.android.server.am.ActivityRecordProto.IDENTIFIER;
+import static com.android.server.am.ActivityRecordProto.PROC_ID;
+import static com.android.server.am.ActivityRecordProto.STATE;
+import static com.android.server.am.ActivityRecordProto.TRANSLUCENT;
+import static com.android.server.am.ActivityRecordProto.VISIBLE;
+import static com.android.server.am.EventLogTags.AM_RELAUNCH_ACTIVITY;
+import static com.android.server.am.EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY;
+import static com.android.server.wm.ActivityStack.ActivityState.INITIALIZING;
+import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
+import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
+import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
+import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
+import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
+import static com.android.server.wm.ActivityStack.LAUNCH_TICK;
+import static com.android.server.wm.ActivityStack.LAUNCH_TICK_MSG;
+import static com.android.server.wm.ActivityStack.PAUSE_TIMEOUT_MSG;
+import static com.android.server.wm.ActivityStack.STOP_TIMEOUT_MSG;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_FOCUS;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SAVED_STATE;
@@ -89,34 +109,14 @@
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.am.ActivityRecordProto.CONFIGURATION_CONTAINER;
-import static com.android.server.am.ActivityRecordProto.FRONT_OF_TASK;
-import static com.android.server.am.ActivityRecordProto.IDENTIFIER;
-import static com.android.server.am.ActivityRecordProto.PROC_ID;
-import static com.android.server.am.ActivityRecordProto.STATE;
-import static com.android.server.am.ActivityRecordProto.TRANSLUCENT;
-import static com.android.server.am.ActivityRecordProto.VISIBLE;
-import static com.android.server.wm.ActivityStack.ActivityState.INITIALIZING;
-import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
-import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
-import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
-import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
-import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
-import static com.android.server.wm.ActivityStack.LAUNCH_TICK;
-import static com.android.server.wm.ActivityStack.LAUNCH_TICK_MSG;
-import static com.android.server.wm.ActivityStack.PAUSE_TIMEOUT_MSG;
-import static com.android.server.wm.ActivityStack.STOP_TIMEOUT_MSG;
 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
-import static com.android.server.am.EventLogTags.AM_RELAUNCH_ACTIVITY;
-import static com.android.server.am.EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY;
-import static com.android.server.wm.TaskPersister.DEBUG;
-import static com.android.server.wm.TaskPersister.IMAGE_EXTENSION;
-import static android.app.ActivityTaskManager.INVALID_TASK_ID;
 import static com.android.server.wm.IdentifierProto.HASH_CODE;
 import static com.android.server.wm.IdentifierProto.TITLE;
 import static com.android.server.wm.IdentifierProto.USER_ID;
+import static com.android.server.wm.TaskPersister.DEBUG;
+import static com.android.server.wm.TaskPersister.IMAGE_EXTENSION;
 
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 import static org.xmlpull.v1.XmlPullParser.END_TAG;
@@ -179,9 +179,9 @@
 import com.android.server.AttributeCache.Entry;
 import com.android.server.am.AppTimeTracker;
 import com.android.server.am.PendingIntentRecord;
+import com.android.server.uri.UriPermissionOwner;
 import com.android.server.wm.ActivityMetricsLogger.WindowingModeTransitionInfoSnapshot;
 import com.android.server.wm.ActivityStack.ActivityState;
-import com.android.server.uri.UriPermissionOwner;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -303,6 +303,7 @@
                                         // process that it is hidden.
     boolean sleeping;       // have we told the activity to sleep?
     boolean nowVisible;     // is this activity's window visible?
+    boolean mDrawn;          // is this activity's window drawn?
     boolean mClientVisibilityDeferred;// was the visibility change message to client deferred?
     boolean idle;           // has the activity gone idle?
     boolean hasBeenLaunched;// has this activity ever been launched?
@@ -869,6 +870,7 @@
         inHistory = false;
         visible = false;
         nowVisible = false;
+        mDrawn = false;
         idle = false;
         hasBeenLaunched = false;
         mStackSupervisor = supervisor;
@@ -1944,8 +1946,12 @@
     }
 
     @Override
-    public void onWindowsDrawn(long timestamp) {
+    public void onWindowsDrawn(boolean drawn, long timestamp) {
         synchronized (service.mGlobalLock) {
+            mDrawn = drawn;
+            if (!drawn) {
+                return;
+            }
             final WindowingModeTransitionInfoSnapshot info = mStackSupervisor
                     .getActivityMetricsLogger().notifyWindowsDrawn(getWindowingMode(), timestamp);
             final int windowsDrawnDelayMs = info != null ? info.windowsDrawnDelayMs : INVALID_DELAY;
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 97eaafc..37a65cd 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -145,6 +145,7 @@
 import android.hardware.display.DisplayManagerInternal;
 import android.hardware.power.V1_0.PowerHint;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Debug;
 import android.os.FactoryTest;
@@ -835,9 +836,13 @@
         }
 
         final boolean supportMultipleInstance = homeInfo.launchMode != LAUNCH_SINGLE_TASK
-                && homeInfo.launchMode != LAUNCH_SINGLE_INSTANCE;
+                && homeInfo.launchMode != LAUNCH_SINGLE_INSTANCE
+                && homeInfo.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q;
         if (!supportMultipleInstance) {
-            // Can't launch home on other displays if it requested to be single instance.
+            // Can't launch home on other displays if it requested to be single instance. Also we
+            // don't allow home applications that target before Q to have multiple home activity
+            // instances because they may not be expected to have multiple home scenario and
+            // haven't explicitly request for single instance.
             return false;
         }
 
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index 3cbb2577..bd1460a 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -82,6 +82,7 @@
     private final class H extends Handler {
         public static final int NOTIFY_WINDOWS_DRAWN = 1;
         public static final int NOTIFY_STARTING_WINDOW_DRAWN = 2;
+        public static final int NOTIFY_WINDOWS_NOTDRAWN = 3;
 
         public H(Looper looper) {
             super(looper);
@@ -96,16 +97,24 @@
                     }
                     if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting drawn in "
                             + AppWindowContainerController.this.mToken);
-                    mListener.onWindowsDrawn(msg.getWhen());
+                    mListener.onWindowsDrawn(true /* drawn */, msg.getWhen());
                     break;
                 case NOTIFY_STARTING_WINDOW_DRAWN:
                     if (mListener == null) {
                         return;
                     }
-                    if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting drawn in "
+                    if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting starting window drawn in "
                             + AppWindowContainerController.this.mToken);
                     mListener.onStartingWindowDrawn(msg.getWhen());
                     break;
+                case NOTIFY_WINDOWS_NOTDRAWN:
+                    if (mListener == null) {
+                        return;
+                    }
+                    if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting not drawn in "
+                            + AppWindowContainerController.this.mToken);
+                    mListener.onWindowsDrawn(false /* drawn */, msg.getWhen());
+                    break;
                 default:
                     break;
             }
@@ -762,6 +771,10 @@
         mHandler.sendMessage(mHandler.obtainMessage(H.NOTIFY_WINDOWS_DRAWN));
     }
 
+    void reportWindowsNotDrawn() {
+        mHandler.sendMessage(mHandler.obtainMessage(H.NOTIFY_WINDOWS_NOTDRAWN));
+    }
+
     void reportWindowsVisible() {
         mHandler.post(mOnWindowsVisible);
     }
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerListener.java b/services/core/java/com/android/server/wm/AppWindowContainerListener.java
index 8a39a74..ad27669 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerListener.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerListener.java
@@ -18,8 +18,8 @@
 
 /** Interface used by the creator of the controller to listen to changes with the container. */
 public interface AppWindowContainerListener extends WindowContainerListener {
-    /** Called when the windows associated app window container are drawn. */
-    void onWindowsDrawn(long timestamp);
+    /** Called when the windows associated app window container drawn state changes. */
+    void onWindowsDrawn(boolean drawn, long timestamp);
     /** Called when the windows associated app window container are visible. */
     void onWindowsVisible();
     /** Called when the windows associated app window container are no longer visible. */
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index d30cd19..111c921 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -366,6 +366,10 @@
                 if (controller != null) {
                     controller.reportWindowsDrawn();
                 }
+            } else {
+                if (controller != null) {
+                    controller.reportWindowsNotDrawn();
+                }
             }
             reportedDrawn = nowDrawn;
         }
@@ -1749,6 +1753,7 @@
                 .setName(getSurfaceControl() + " - animation-bounds")
                 .setSize(getSurfaceWidth(), getSurfaceHeight());
         final SurfaceControl boundsLayer = builder.build();
+        t.setWindowCrop(boundsLayer, getSurfaceWidth(), getSurfaceHeight());
         t.show(boundsLayer);
         return boundsLayer;
     }
@@ -2014,9 +2019,7 @@
         clearThumbnail();
         setClientHidden(isHidden() && hiddenRequested);
 
-        if (mService.mInputMethodTarget != null && mService.mInputMethodTarget.mAppToken == this) {
-            getDisplayContent().computeImeTarget(true /* updateImeTarget */);
-        }
+        getDisplayContent().computeImeTargetIfNeeded(this);
 
         if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
                 + ": reportedVisible=" + reportedVisible
diff --git a/services/core/java/com/android/server/wm/BlackFrame.java b/services/core/java/com/android/server/wm/BlackFrame.java
index e358ad5..9633864 100644
--- a/services/core/java/com/android/server/wm/BlackFrame.java
+++ b/services/core/java/com/android/server/wm/BlackFrame.java
@@ -52,7 +52,7 @@
                     .setColorLayer(true)
                     .setParent(null) // TODO: Work-around for b/69259549
                     .build();
-
+            transaction.setWindowCrop(surface, w, h);
             transaction.setLayerStack(surface, dc.getDisplayId());
             transaction.setAlpha(surface, 1);
             transaction.setLayer(surface, layer);
diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java
index 65c8e96..cc14afc 100644
--- a/services/core/java/com/android/server/wm/Dimmer.java
+++ b/services/core/java/com/android/server/wm/Dimmer.java
@@ -126,9 +126,10 @@
         DimState(SurfaceControl dimLayer) {
             mDimLayer = dimLayer;
             mDimming = true;
-            mSurfaceAnimator = new SurfaceAnimator(new DimAnimatable(dimLayer), () -> {
+            final DimAnimatable dimAnimatable = new DimAnimatable(dimLayer);
+            mSurfaceAnimator = new SurfaceAnimator(dimAnimatable, () -> {
                 if (!mDimming) {
-                    mDimLayer.destroy();
+                    dimAnimatable.getPendingTransaction().destroy(mDimLayer);
                 }
             }, mHost.mService);
         }
@@ -309,6 +310,7 @@
             // TODO: Once we use geometry from hierarchy this falls away.
             t.setSize(mDimState.mDimLayer, bounds.width(), bounds.height());
             t.setPosition(mDimState.mDimLayer, bounds.left, bounds.top);
+            t.setWindowCrop(mDimState.mDimLayer, bounds.width(), bounds.height());
             if (!mDimState.isVisible) {
                 mDimState.isVisible = true;
                 t.show(mDimState.mDimLayer);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 767a6ef..a3e8029 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -100,7 +100,6 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.WindowManagerService.CUSTOM_SCREEN_ROTATION;
-import static com.android.server.wm.WindowManagerService.H.REPORT_FOCUS_CHANGE;
 import static com.android.server.wm.WindowManagerService.H.REPORT_LOSING_FOCUS;
 import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
 import static com.android.server.wm.WindowManagerService.H.UPDATE_DOCKED_STACK_DIVIDER;
@@ -496,6 +495,15 @@
      */
     WindowState mInputMethodWindow;
 
+    /**
+     * This just indicates the window the input method is on top of, not
+     * necessarily the window its input is going to.
+     */
+    WindowState mInputMethodTarget;
+
+    /** If true hold off on modifying the animation layer of mInputMethodTarget */
+    boolean mInputMethodTargetWaitingAnim;
+
     private final PointerEventDispatcher mPointerEventDispatcher;
 
     private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> {
@@ -699,7 +707,7 @@
 
     private final Consumer<WindowState> mApplyPostLayoutPolicy =
             w -> mService.mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs, w.getParentWindow(),
-                    mService.mInputMethodTarget);
+                    mInputMethodTarget);
 
     private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> {
         final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
@@ -1928,7 +1936,7 @@
      * rather than directly above their target.
      */
     private boolean skipTraverseChild(WindowContainer child) {
-        if (child == mImeWindowsContainers && mService.mInputMethodTarget != null
+        if (child == mImeWindowsContainers && mInputMethodTarget != null
                 && !hasSplitScreenPrimaryStack()) {
             return true;
         }
@@ -2800,13 +2808,12 @@
         if (mCurrentFocus == newFocus) {
             return false;
         }
-        mService.mH.obtainMessage(REPORT_FOCUS_CHANGE, this).sendToTarget();
         boolean imWindowChanged = false;
         // TODO (b/111080190): Multi-Session IME
         if (!focusFound) {
             final WindowState imWindow = mInputMethodWindow;
             if (imWindow != null) {
-                final WindowState prevTarget = mService.mInputMethodTarget;
+                final WindowState prevTarget = mInputMethodTarget;
 
                 final WindowState newTarget = computeImeTarget(true /* updateImeTarget*/);
                 imWindowChanged = prevTarget != newTarget;
@@ -2998,13 +3005,13 @@
             // There isn't an IME so there shouldn't be a target...That was easy!
             if (updateImeTarget) {
                 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from "
-                        + mService.mInputMethodTarget + " to null since mInputMethodWindow is null");
-                setInputMethodTarget(null, mService.mInputMethodTargetWaitingAnim);
+                        + mInputMethodTarget + " to null since mInputMethodWindow is null");
+                setInputMethodTarget(null, mInputMethodTargetWaitingAnim);
             }
             return null;
         }
 
-        final WindowState curTarget = mService.mInputMethodTarget;
+        final WindowState curTarget = mInputMethodTarget;
         if (!canUpdateImeTarget()) {
             if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Defer updating IME target");
             return curTarget;
@@ -3031,7 +3038,7 @@
         }
 
         if (DEBUG_INPUT_METHOD && updateImeTarget) Slog.v(TAG_WM,
-                "Proposed new IME target: " + target);
+                "Proposed new IME target: " + target + " for display: " + getDisplayId());
 
         // Now, a special case -- if the last target's window is in the process of exiting, but
         // not removed, and the new target is home, keep on the last target to avoid flicker.
@@ -3052,7 +3059,7 @@
                 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget
                         + " to null." + (SHOW_STACK_CRAWLS ? " Callers="
                         + Debug.getCallers(4) : ""));
-                setInputMethodTarget(null, mService.mInputMethodTargetWaitingAnim);
+                setInputMethodTarget(null, mInputMethodTargetWaitingAnim);
             }
 
             return null;
@@ -3091,14 +3098,23 @@
         return target;
     }
 
+    /**
+     * Calling {@link #computeImeTarget(boolean)} to update the input method target window in
+     * the candidate app window token if needed.
+     */
+    void computeImeTargetIfNeeded(AppWindowToken candidate) {
+        if (mInputMethodTarget != null && mInputMethodTarget.mAppToken == candidate) {
+            computeImeTarget(true /* updateImeTarget */);
+        }
+    }
+
     private void setInputMethodTarget(WindowState target, boolean targetWaitingAnim) {
-        if (target == mService.mInputMethodTarget
-                && mService.mInputMethodTargetWaitingAnim == targetWaitingAnim) {
+        if (target == mInputMethodTarget && mInputMethodTargetWaitingAnim == targetWaitingAnim) {
             return;
         }
 
-        mService.mInputMethodTarget = target;
-        mService.mInputMethodTargetWaitingAnim = targetWaitingAnim;
+        mInputMethodTarget = target;
+        mInputMethodTargetWaitingAnim = targetWaitingAnim;
         assignWindowLayers(false /* setLayoutNeeded */);
     }
 
@@ -4487,7 +4503,7 @@
         mTaskStackContainers.assignLayer(t, 1);
         mAboveAppWindowsContainers.assignLayer(t, 2);
 
-        WindowState imeTarget = mService.mInputMethodTarget;
+        final WindowState imeTarget = mInputMethodTarget;
         boolean needAssignIme = true;
 
         // In the case where we have an IME target that is not in split-screen
diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java
index 4eb021c..b49d304 100644
--- a/services/core/java/com/android/server/wm/Letterbox.java
+++ b/services/core/java/com/android/server/wm/Letterbox.java
@@ -187,6 +187,7 @@
                 }
                 t.setPosition(mSurface, mSurfaceFrame.left, mSurfaceFrame.top);
                 t.setSize(mSurface, mSurfaceFrame.width(), mSurfaceFrame.height());
+                t.setWindowCrop(mSurface, mSurfaceFrame.width(), mSurfaceFrame.height());
                 t.show(mSurface);
             } else if (mSurface != null) {
                 t.hide(mSurface);
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 01b05c3..1baca32 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -122,7 +122,7 @@
 
     // The ID of the display which is responsible for receiving display-unspecified key and pointer
     // events.
-    private int mTopFocusedDisplayId = INVALID_DISPLAY;
+    int mTopFocusedDisplayId = INVALID_DISPLAY;
 
     // Only a seperate transaction until we seperate the apply surface changes
     // transaction from the global transaction.
@@ -156,7 +156,8 @@
     boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
         boolean changed = false;
         int topFocusedDisplayId = INVALID_DISPLAY;
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
+
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
             final DisplayContent dc = mChildren.get(i);
             changed |= dc.updateFocusedWindowLocked(mode, updateInputWindows,
                     topFocusedDisplayId != INVALID_DISPLAY /* focusFound */);
@@ -167,12 +168,35 @@
         if (topFocusedDisplayId == INVALID_DISPLAY) {
             topFocusedDisplayId = DEFAULT_DISPLAY;
         }
+        // TODO(b/118865114): Review if need callback top focus display change to view component.
+        // (i.e. Activity or View)
+        // Currently we only tracked topFocusedDisplayChanged for notifying InputMethodManager via
+        // ViewRootImpl.windowFocusChanged to refocus IME window when top display focus changed
+        // but window focus remain the same case.
+        // It may need to review if any use case that need to add new callback for reporting
+        // this change.
+        final boolean topFocusedDisplayChanged =
+                mTopFocusedDisplayId != topFocusedDisplayId && mode == UPDATE_FOCUS_NORMAL;
         if (mTopFocusedDisplayId != topFocusedDisplayId) {
             mTopFocusedDisplayId = topFocusedDisplayId;
-            mService.mInputManager.setFocusedDisplay(topFocusedDisplayId);
+            mService.mInputManager.setFocusedDisplay(mTopFocusedDisplayId);
             if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "New topFocusedDisplayId="
-                    + topFocusedDisplayId);
+                    + mTopFocusedDisplayId);
         }
+
+        // Report window focus or top display focus changed through REPORT_FOCUS_CHANGE.
+        forAllDisplays((dc) -> {
+            final boolean windowFocusChanged =
+                    dc.mCurrentFocus != null && dc.mCurrentFocus != dc.mLastFocus;
+            final boolean isTopFocusedDisplay =
+                    topFocusedDisplayChanged && dc.getDisplayId() == mTopFocusedDisplayId;
+            if (windowFocusChanged || isTopFocusedDisplay) {
+                final Message msg = mService.mH.obtainMessage(
+                        WindowManagerService.H.REPORT_FOCUS_CHANGE, dc);
+                msg.arg1 = topFocusedDisplayChanged ? 1 : 0;
+                mService.mH.sendMessage(msg);
+            }
+        });
         final WindowState topFocusedWindow = getTopFocusedDisplayContent().mCurrentFocus;
         mService.mInputManager.setFocusedWindow(
                 topFocusedWindow != null ? topFocusedWindow.mInputWindowHandle : null);
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
index 3ea615a..66063c40 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimator.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java
@@ -16,12 +16,12 @@
 
 package com.android.server.wm;
 
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.SurfaceAnimatorProto.ANIMATION_ADAPTER;
 import static com.android.server.wm.SurfaceAnimatorProto.ANIMATION_START_DELAYED;
 import static com.android.server.wm.SurfaceAnimatorProto.LEASH;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -305,6 +305,7 @@
                 .setName(surface + " - animation-leash")
                 .setSize(width, height);
         final SurfaceControl leash = builder.build();
+        t.setWindowCrop(surface, width, height);
         if (!hidden) {
             t.show(leash);
         }
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 3493111..073601d 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -259,6 +259,7 @@
         final Rect stackBounds = getBounds();
         getPendingTransaction()
                 .setSize(mAnimationBackgroundSurface, mTmpRect.width(), mTmpRect.height())
+                .setWindowCrop(mAnimationBackgroundSurface, mTmpRect.width(), mTmpRect.height())
                 .setPosition(mAnimationBackgroundSurface, mTmpRect.left - stackBounds.left,
                         mTmpRect.top - stackBounds.top);
         scheduleAnimation();
@@ -789,6 +790,7 @@
             return;
         }
         transaction.setSize(mSurfaceControl, width, height);
+        transaction.setWindowCrop(mSurfaceControl, width, height);
         mLastSurfaceSize.set(width, height);
     }
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 02904d4..d7d3e71 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -623,13 +623,6 @@
      */
     final Handler mAnimationHandler = new Handler(AnimationThread.getHandler().getLooper());
 
-    /** This just indicates the window the input method is on top of, not
-     * necessarily the window its input is going to. */
-    WindowState mInputMethodTarget = null;
-
-    /** If true hold off on modifying the animation layer of mInputMethodTarget */
-    boolean mInputMethodTargetWaitingAnim;
-
     boolean mHardKeyboardAvailable;
     WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
     SettingsObserver mSettingsObserver;
@@ -4400,6 +4393,7 @@
 
                     AccessibilityController accessibilityController = null;
 
+                    final boolean topFocusedDisplayChanged = msg.arg1 != 0;
                     synchronized (mGlobalLock) {
                         // TODO(multidisplay): Accessibility supported only of default desiplay.
                         if (mAccessibilityController != null && displayContent.isDefaultDisplay) {
@@ -4409,7 +4403,19 @@
                         lastFocus = displayContent.mLastFocus;
                         newFocus = displayContent.mCurrentFocus;
                         if (lastFocus == newFocus) {
-                            // Focus is not changing, so nothing to do.
+                            // Report focus to ViewRootImpl when top focused display changes.
+                            // Or, nothing to do for no window focus change.
+                            if (topFocusedDisplayChanged && newFocus != null) {
+                                if (DEBUG_FOCUS_LIGHT) {
+                                    Slog.d(TAG, "Reporting focus: " + newFocus
+                                            + " due to top focused display change.");
+                                }
+                                // See {@link IWindow#windowFocusChanged} to know why set
+                                // reportToClient as false.
+                                newFocus.reportFocusChangedSerialized(true, mInTouchMode,
+                                        false /* reportToClient */);
+                                notifyFocusChanged();
+                            }
                             return;
                         }
                         displayContent.mLastFocus = newFocus;
@@ -4430,13 +4436,15 @@
 
                     if (newFocus != null) {
                         if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Gaining focus: " + newFocus);
-                        newFocus.reportFocusChangedSerialized(true, mInTouchMode);
+                        newFocus.reportFocusChangedSerialized(true, mInTouchMode,
+                                true /* reportToClient */);
                         notifyFocusChanged();
                     }
 
                     if (lastFocus != null) {
                         if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing focus: " + lastFocus);
-                        lastFocus.reportFocusChangedSerialized(false, mInTouchMode);
+                        lastFocus.reportFocusChangedSerialized(false, mInTouchMode,
+                                true /* reportToClient */);
                     }
                 } break;
 
@@ -4453,7 +4461,8 @@
                     for (int i = 0; i < N; i++) {
                         if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing delayed focus: " +
                                 losers.get(i));
-                        losers.get(i).reportFocusChangedSerialized(false, mInTouchMode);
+                        losers.get(i).reportFocusChangedSerialized(false, mInTouchMode,
+                                true /* reportToClient */);
                     }
                 } break;
 
@@ -5930,9 +5939,13 @@
         pw.print("  mGlobalConfiguration="); pw.println(mRoot.getConfiguration());
         pw.print("  mHasPermanentDpad="); pw.println(mHasPermanentDpad);
         mRoot.dumpTopFocusedDisplayId(pw);
-        if (mInputMethodTarget != null) {
-            pw.print("  mInputMethodTarget="); pw.println(mInputMethodTarget);
-        }
+        mRoot.forAllDisplays(dc -> {
+            final WindowState inputMethodTarget = dc.mInputMethodTarget;
+            if (inputMethodTarget != null) {
+                pw.print("  mInputMethodTarget in display# "); pw.print(dc.getDisplayId());
+                pw.print(' '); pw.println(inputMethodTarget);
+            }
+        });
         pw.print("  mInTouchMode="); pw.println(mInTouchMode);
         pw.print("  mLastDisplayFreezeDuration=");
                 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 99f65c3..2b5076a 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2841,12 +2841,13 @@
      * Report a focus change.  Must be called with no locks held, and consistently
      * from the same serialized thread (such as dispatched from a handler).
      */
-    void reportFocusChangedSerialized(boolean focused, boolean inTouchMode) {
+    void reportFocusChangedSerialized(boolean focused, boolean inTouchMode,
+            boolean reportToClient) {
         try {
-            mClient.windowFocusChanged(focused, inTouchMode);
+            mClient.windowFocusChanged(focused, inTouchMode, reportToClient);
         } catch (RemoteException e) {
         }
-        if (mFocusCallbacks != null) {
+        if (mFocusCallbacks != null && reportToClient) {
             final int N = mFocusCallbacks.beginBroadcast();
             for (int i=0; i<N; i++) {
                 IWindowFocusObserver obs = mFocusCallbacks.getBroadcastItem(i);
@@ -4476,8 +4477,9 @@
 
     @Override
     boolean needsZBoost() {
-        if (mIsImWindow && mService.mInputMethodTarget != null) {
-            final AppWindowToken appToken = mService.mInputMethodTarget.mAppToken;
+        final WindowState inputMethodTarget = getDisplayContent().mInputMethodTarget;
+        if (mIsImWindow && inputMethodTarget != null) {
+            final AppWindowToken appToken = inputMethodTarget.mAppToken;
             if (appToken != null) {
                 return appToken.needsZBoost();
             }
@@ -4607,7 +4609,7 @@
             // Likewise if we share a token with the Input method target and are ordered
             // above it but not necessarily a child (e.g. a Dialog) then we also need
             // this promotion.
-            final WindowState imeTarget = mService.mInputMethodTarget;
+            final WindowState imeTarget = getDisplayContent().mInputMethodTarget;
             boolean inTokenWithAndAboveImeTarget = imeTarget != null && imeTarget != this
                     && imeTarget.mToken == mToken && imeTarget.compareTo(this) <= 0;
             return inTokenWithAndAboveImeTarget;
@@ -4684,7 +4686,7 @@
 
     @Override
     public boolean isInputMethodTarget() {
-        return mService.mInputMethodTarget == this;
+        return getDisplayContent().mInputMethodTarget == this;
     }
 
     long getFrameNumber() {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index b88165e..a7542d7 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -491,6 +491,11 @@
      */
     final boolean mIsWatch;
 
+    /**
+     * Whether this device has the telephony feature.
+     */
+    final boolean mHasTelephonyFeature;
+
     private final CertificateMonitor mCertificateMonitor;
     private final SecurityLogMonitor mSecurityLogMonitor;
 
@@ -2133,6 +2138,8 @@
         mHasFeature = mInjector.hasFeature();
         mIsWatch = mInjector.getPackageManager()
                 .hasSystemFeature(PackageManager.FEATURE_WATCH);
+        mHasTelephonyFeature = mInjector.getPackageManager()
+                .hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
         mBackgroundHandler = BackgroundThread.getHandler();
 
         // Needed when mHasFeature == false, because it controls the certificate warning text.
@@ -12927,7 +12934,7 @@
 
     @Override
     public int addOverrideApn(@NonNull ComponentName who, @NonNull ApnSetting apnSetting) {
-        if (!mHasFeature) {
+        if (!mHasFeature || !mHasTelephonyFeature) {
             return -1;
         }
         Preconditions.checkNotNull(who, "ComponentName is null in addOverrideApn");
@@ -12956,7 +12963,7 @@
     @Override
     public boolean updateOverrideApn(@NonNull ComponentName who, int apnId,
             @NonNull ApnSetting apnSetting) {
-        if (!mHasFeature) {
+        if (!mHasFeature || !mHasTelephonyFeature) {
             return false;
         }
         Preconditions.checkNotNull(who, "ComponentName is null in updateOverrideApn");
@@ -12978,7 +12985,7 @@
 
     @Override
     public boolean removeOverrideApn(@NonNull ComponentName who, int apnId) {
-        if (!mHasFeature) {
+        if (!mHasFeature || !mHasTelephonyFeature) {
             return false;
         }
         Preconditions.checkNotNull(who, "ComponentName is null in removeOverrideApn");
@@ -13004,7 +13011,7 @@
 
     @Override
     public List<ApnSetting> getOverrideApns(@NonNull ComponentName who) {
-        if (!mHasFeature) {
+        if (!mHasFeature || !mHasTelephonyFeature) {
             return Collections.emptyList();
         }
         Preconditions.checkNotNull(who, "ComponentName is null in getOverrideApns");
@@ -13040,7 +13047,7 @@
 
     @Override
     public void setOverrideApnsEnabled(@NonNull ComponentName who, boolean enabled) {
-        if (!mHasFeature) {
+        if (!mHasFeature || !mHasTelephonyFeature) {
             return;
         }
         Preconditions.checkNotNull(who, "ComponentName is null in setOverrideApnEnabled");
@@ -13063,7 +13070,7 @@
 
     @Override
     public boolean isOverrideApnEnabled(@NonNull ComponentName who) {
-        if (!mHasFeature) {
+        if (!mHasFeature || !mHasTelephonyFeature) {
             return false;
         }
         Preconditions.checkNotNull(who, "ComponentName is null in isOverrideApnEnabled");
diff --git a/services/intelligence/Android.bp b/services/intelligence/Android.bp
new file mode 100644
index 0000000..2df1235
--- /dev/null
+++ b/services/intelligence/Android.bp
@@ -0,0 +1,5 @@
+java_library_static {
+    name: "services.intelligence",
+    srcs: ["java/**/*.java"],
+    libs: ["services.core"],
+}
diff --git a/services/autofill/java/com/android/server/intelligence/ContentCaptureSession.java b/services/intelligence/java/com/android/server/intelligence/ContentCaptureSession.java
similarity index 85%
rename from services/autofill/java/com/android/server/intelligence/ContentCaptureSession.java
rename to services/intelligence/java/com/android/server/intelligence/ContentCaptureSession.java
index 9cab1ed..b7d34d7 100644
--- a/services/autofill/java/com/android/server/intelligence/ContentCaptureSession.java
+++ b/services/intelligence/java/com/android/server/intelligence/ContentCaptureSession.java
@@ -76,7 +76,7 @@
     }
 
     /**
-     * Cleans up the session and remove itself from the service.
+     * Cleans up the session and removes it from the service.
      *
      * @param notifyRemoteService whether it should trigger a {@link
      * IntelligenceService#onDestroyInteractionSession(InteractionSessionId)}
@@ -85,14 +85,30 @@
     @GuardedBy("mLock")
     public void removeSelfLocked(boolean notifyRemoteService) {
         try {
-            if (notifyRemoteService) {
-                mRemoteService.onSessionLifecycleRequest(/* context= */ null, mId);
-            }
+            destroyLocked(notifyRemoteService);
         } finally {
             mService.removeSessionLocked(mId);
         }
     }
 
+    /**
+     * Cleans up the session, but not removes it from the service.
+     *
+     * @param notifyRemoteService whether it should trigger a {@link
+     * IntelligenceService#onDestroyInteractionSession(InteractionSessionId)}
+     * request.
+     */
+    @GuardedBy("mLock")
+    public void destroyLocked(boolean notifyRemoteService) {
+        if (mService.isVerbose()) {
+            Slog.v(TAG, "destroyLocked(notifyRemoteService=" + notifyRemoteService + ")");
+        }
+        // TODO(b/111276913): must call client to set session as FINISHED_BY_SERVER
+        if (notifyRemoteService) {
+            mRemoteService.onSessionLifecycleRequest(/* context= */ null, mId);
+        }
+    }
+
     @Override // from RemoteScreenObservationServiceCallbacks
     public void onServiceDied(AbstractRemoteService service) {
         // TODO(b/111276913): implement (remove session from PerUserSession?)
diff --git a/services/autofill/java/com/android/server/intelligence/IntelligenceManagerService.java b/services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java
similarity index 84%
rename from services/autofill/java/com/android/server/intelligence/IntelligenceManagerService.java
rename to services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java
index 43d4a44..dc3cd62 100644
--- a/services/autofill/java/com/android/server/intelligence/IntelligenceManagerService.java
+++ b/services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java
@@ -53,6 +53,8 @@
     @GuardedBy("mLock")
     private ActivityManagerInternal mAm;
 
+    private final LocalService mLocalService = new LocalService();
+
     public IntelligenceManagerService(Context context) {
         super(context, UserManager.DISALLOW_INTELLIGENCE_CAPTURE);
     }
@@ -73,6 +75,16 @@
     public void onStart() {
         publishBinderService(INTELLIGENCE_MANAGER_SERVICE,
                 new IntelligenceManagerServiceStub());
+        publishLocalService(IntelligenceManagerInternal.class, mLocalService);
+    }
+
+    @Override // from AbstractMasterSystemService
+    protected IntelligencePerUserService removeCachedServiceLocked(int userId) {
+        final IntelligencePerUserService service = super.removeCachedServiceLocked(userId);
+        if (service != null) {
+            service.destroyLocked();
+        }
+        return service;
     }
 
     private ActivityManagerInternal getAmInternal() {
@@ -139,4 +151,19 @@
             }
         }
     }
+
+    private final class LocalService extends IntelligenceManagerInternal {
+
+        @Override
+        public boolean isIntelligenceServiceForUser(int uid, int userId) {
+            synchronized (mLock) {
+                final IntelligencePerUserService service = peekServiceForUserLocked(userId);
+                if (service != null) {
+                    return service.isIntelligenceServiceForUserLocked(uid);
+                }
+            }
+
+            return false;
+        }
+    }
 }
diff --git a/services/autofill/java/com/android/server/intelligence/IntelligencePerUserService.java b/services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java
similarity index 82%
rename from services/autofill/java/com/android/server/intelligence/IntelligencePerUserService.java
rename to services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java
index 584b872..471b40f 100644
--- a/services/autofill/java/com/android/server/intelligence/IntelligencePerUserService.java
+++ b/services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java
@@ -88,12 +88,18 @@
             @NonNull ComponentName componentName, int taskId, int displayId,
             @NonNull InteractionSessionId sessionId, int flags,
             @NonNull IResultReceiver resultReceiver) {
+        if (!isEnabledLocked()) {
+            sendToClient(resultReceiver, IntelligenceManager.STATE_DISABLED);
+            return;
+        }
         final ComponentName serviceComponentName = getServiceComponentName();
         if (serviceComponentName == null) {
             // TODO(b/111276913): this happens when the system service is starting, we should
             // probably handle it in a more elegant way (like waiting for boot_complete or
             // something like that
-            Slog.w(TAG, "startSession(" + activityToken + "): hold your horses");
+            if (mMaster.debug) {
+                Slog.d(TAG, "startSession(" + activityToken + "): hold your horses");
+            }
             return;
         }
 
@@ -128,9 +134,15 @@
     // TODO(b/111276913): log metrics
     @GuardedBy("mLock")
     public void finishSessionLocked(@NonNull InteractionSessionId sessionId) {
+        if (!isEnabledLocked()) {
+            return;
+        }
+
         final ContentCaptureSession session = mSessions.get(sessionId);
         if (session == null) {
-            Slog.w(TAG, "finishSession(): no session with id" + sessionId);
+            if (mMaster.debug) {
+                Slog.d(TAG, "finishSession(): no session with id" + sessionId);
+            }
             return;
         }
         if (mMaster.verbose) {
@@ -139,12 +151,19 @@
         session.removeSelfLocked(true);
     }
 
+    // TODO(b/111276913): need to figure out why some events are sent before session is started;
+    // probably because IntelligenceManager is not buffering them until it gets the session back
     @GuardedBy("mLock")
     public void sendEventsLocked(@NonNull InteractionSessionId sessionId,
             @NonNull List<ContentCaptureEvent> events) {
+        if (!isEnabledLocked()) {
+            return;
+        }
         final ContentCaptureSession session = mSessions.get(sessionId);
         if (session == null) {
-            Slog.w(TAG, "sendEvents(): no session for " + sessionId);
+            if (mMaster.verbose) {
+                Slog.v(TAG, "sendEvents(): no session for " + sessionId);
+            }
             return;
         }
         if (mMaster.verbose) {
@@ -158,6 +177,27 @@
         mSessions.remove(sessionId);
     }
 
+    @GuardedBy("mLock")
+    public boolean isIntelligenceServiceForUserLocked(int uid) {
+        return uid == getServiceUidLocked();
+    }
+
+    /**
+     * Destroys the service and all state associated with it.
+     *
+     * <p>Called when the service was disabled (for example, if the settings change).
+     */
+    @GuardedBy("mLock")
+    public void destroyLocked() {
+        if (mMaster.debug) Slog.d(TAG, "destroyLocked()");
+        final int numSessions = mSessions.size();
+        for (int i = 0; i < numSessions; i++) {
+            final ContentCaptureSession session = mSessions.valueAt(i);
+            session.destroyLocked(true);
+        }
+        mSessions.clear();
+    }
+
     @Override
     protected void dumpLocked(String prefix, PrintWriter pw) {
         super.dumpLocked(prefix, pw);
diff --git a/services/autofill/java/com/android/server/intelligence/RemoteIntelligenceService.java b/services/intelligence/java/com/android/server/intelligence/RemoteIntelligenceService.java
similarity index 100%
rename from services/autofill/java/com/android/server/intelligence/RemoteIntelligenceService.java
rename to services/intelligence/java/com/android/server/intelligence/RemoteIntelligenceService.java
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 86eb6f3..3bb8ce3 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -35,6 +35,7 @@
 import android.content.res.Resources.Theme;
 import android.database.sqlite.SQLiteCompatibilityWalFlags;
 import android.database.sqlite.SQLiteGlobal;
+import android.hardware.display.ColorDisplayManager;
 import android.hardware.display.DisplayManagerInternal;
 import android.os.BaseBundle;
 import android.os.Binder;
@@ -62,7 +63,6 @@
 import android.view.WindowManager;
 
 import com.android.internal.R;
-import com.android.internal.app.ColorDisplayController;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.os.BinderInternal;
@@ -118,6 +118,7 @@
 import com.android.server.power.ShutdownThread;
 import com.android.server.power.ThermalManagerService;
 import com.android.server.restrictions.RestrictionsManagerService;
+import com.android.server.role.RoleManagerService;
 import com.android.server.security.KeyAttestationApplicationIdProviderService;
 import com.android.server.security.KeyChainSystemService;
 import com.android.server.soundtrigger.SoundTriggerService;
@@ -149,6 +150,7 @@
 import java.util.concurrent.Future;
 
 public final class SystemServer {
+
     private static final String TAG = "SystemServer";
 
     // Tag for timing measurement of main thread.
@@ -262,9 +264,8 @@
     private static final int sMaxBinderThreads = 31;
 
     /**
-     * Default theme used by the system context. This is used to style
-     * system-provided dialogs, such as the Power Off dialog, and other
-     * visual content.
+     * Default theme used by the system context. This is used to style system-provided dialogs, such
+     * as the Power Off dialog, and other visual content.
      */
     private static final int DEFAULT_SYSTEM_THEME =
             com.android.internal.R.style.Theme_DeviceDefault_System;
@@ -305,8 +306,7 @@
     private static native void startSensorService();
 
     /**
-     * Start all HIDL services that are run inside the system server. This
-     * may take some time.
+     * Start all HIDL services that are run inside the system server. This may take some time.
      */
     private static native void startHidlServices();
 
@@ -342,7 +342,7 @@
             //
             // Default the timezone property to GMT if not set.
             //
-            String timezoneProperty =  SystemProperties.get("persist.sys.timezone");
+            String timezoneProperty = SystemProperties.get("persist.sys.timezone");
             if (timezoneProperty == null || timezoneProperty.isEmpty()) {
                 Slog.w(TAG, "Timezone not set; setting to GMT.");
                 SystemProperties.set("persist.sys.timezone", "GMT");
@@ -423,7 +423,7 @@
 
             // Prepare the main looper thread (this thread).
             android.os.Process.setThreadPriority(
-                android.os.Process.THREAD_PRIORITY_FOREGROUND);
+                    android.os.Process.THREAD_PRIORITY_FOREGROUND);
             android.os.Process.setCanSelfBackground(false);
             Looper.prepareMainLooper();
             Looper.getMainLooper().setSlowLogThresholdMs(
@@ -528,7 +528,7 @@
                     if (filename != null && filename.startsWith("/data")) {
                         if (!new File(BLOCK_MAP_FILE).exists()) {
                             Slog.e(TAG, "Can't find block map file, uncrypt failed or " +
-                                       "unexpected runtime restart?");
+                                    "unexpected runtime restart?");
                             return;
                         }
                     }
@@ -561,11 +561,10 @@
     }
 
     /**
-     * Starts the small tangle of critical services that are needed to get
-     * the system off the ground.  These services have complex mutual dependencies
-     * which is why we initialize them all in one place here.  Unless your service
-     * is also entwined in these dependencies, it should be initialized in one of
-     * the other functions.
+     * Starts the small tangle of critical services that are needed to get the system off the
+     * ground.  These services have complex mutual dependencies which is why we initialize them all
+     * in one place here.  Unless your service is also entwined in these dependencies, it should be
+     * initialized in one of the other functions.
      */
     private void startBootstrapServices() {
         Slog.i(TAG, "Reading configuration...");
@@ -782,8 +781,7 @@
     }
 
     /**
-     * Starts a miscellaneous grab bag of stuff that has yet to be refactored
-     * and organized.
+     * Starts a miscellaneous grab bag of stuff that has yet to be refactored and organized.
      */
     private void startOtherServices() {
         final Context context = mSystemContext;
@@ -794,7 +792,7 @@
         NetworkStatsService networkStats = null;
         NetworkPolicyManagerService networkPolicy = null;
         ConnectivityService connectivity = null;
-        NsdService serviceDiscovery= null;
+        NsdService serviceDiscovery = null;
         WindowManagerService wm = null;
         SerialService serial = null;
         NetworkTimeUpdateService networkTimeUpdater = null;
@@ -983,7 +981,7 @@
             } else if (mFactoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL) {
                 Slog.i(TAG, "No Bluetooth Service (factory test)");
             } else if (!context.getPackageManager().hasSystemFeature
-                       (PackageManager.FEATURE_BLUETOOTH)) {
+                    (PackageManager.FEATURE_BLUETOOTH)) {
                 Slog.i(TAG, "No Bluetooth Service (Bluetooth Hardware Not Present)");
             } else {
                 traceBeginAndSlog("StartBluetoothService");
@@ -1097,7 +1095,7 @@
             try {
                 mSystemServiceManager.startService(LOCK_SETTINGS_SERVICE_CLASS);
                 lockSettings = ILockSettings.Stub.asInterface(
-                    ServiceManager.getService("lock_settings"));
+                        ServiceManager.getService("lock_settings"));
             } catch (Throwable e) {
                 reportWtf("starting LockSettingsService service", e);
             }
@@ -1138,6 +1136,13 @@
                 traceEnd();
             }
 
+            if (!disableIntelligence) {
+                traceBeginAndSlog("StartIntelligenceService");
+                mSystemServiceManager.startService(INTELLIGENCE_MANAGER_SERVICE_CLASS);
+                traceEnd();
+            }
+
+            // NOTE: ClipboardService indirectly depends on IntelligenceService
             traceBeginAndSlog("StartClipboardService");
             mSystemServiceManager.startService(ClipboardService.class);
             traceEnd();
@@ -1166,7 +1171,8 @@
 
             if (!disableSystemTextClassifier) {
                 traceBeginAndSlog("StartTextClassificationManagerService");
-                mSystemServiceManager.startService(TextClassificationManagerService.Lifecycle.class);
+                mSystemServiceManager
+                        .startService(TextClassificationManagerService.Lifecycle.class);
                 traceEnd();
             }
 
@@ -1195,41 +1201,41 @@
 
             if (!mOnlyCore) {
                 if (context.getPackageManager().hasSystemFeature(
-                            PackageManager.FEATURE_WIFI)) {
+                        PackageManager.FEATURE_WIFI)) {
                     // Wifi Service must be started first for wifi-related services.
                     traceBeginAndSlog("StartWifi");
                     mSystemServiceManager.startService(WIFI_SERVICE_CLASS);
                     traceEnd();
                     traceBeginAndSlog("StartWifiScanning");
                     mSystemServiceManager.startService(
-                        "com.android.server.wifi.scanner.WifiScanningService");
+                            "com.android.server.wifi.scanner.WifiScanningService");
                     traceEnd();
                 }
 
                 if (context.getPackageManager().hasSystemFeature(
-                    PackageManager.FEATURE_WIFI_RTT)) {
+                        PackageManager.FEATURE_WIFI_RTT)) {
                     traceBeginAndSlog("StartRttService");
                     mSystemServiceManager.startService(
-                        "com.android.server.wifi.rtt.RttService");
+                            "com.android.server.wifi.rtt.RttService");
                     traceEnd();
                 }
 
                 if (context.getPackageManager().hasSystemFeature(
-                    PackageManager.FEATURE_WIFI_AWARE)) {
+                        PackageManager.FEATURE_WIFI_AWARE)) {
                     traceBeginAndSlog("StartWifiAware");
                     mSystemServiceManager.startService(WIFI_AWARE_SERVICE_CLASS);
                     traceEnd();
                 }
 
                 if (context.getPackageManager().hasSystemFeature(
-                    PackageManager.FEATURE_WIFI_DIRECT)) {
+                        PackageManager.FEATURE_WIFI_DIRECT)) {
                     traceBeginAndSlog("StartWifiP2P");
                     mSystemServiceManager.startService(WIFI_P2P_SERVICE_CLASS);
                     traceEnd();
                 }
 
                 if (context.getPackageManager().hasSystemFeature(
-                    PackageManager.FEATURE_LOWPAN)) {
+                        PackageManager.FEATURE_LOWPAN)) {
                     traceBeginAndSlog("StartLowpan");
                     mSystemServiceManager.startService(LOWPAN_SERVICE_CLASS);
                     traceEnd();
@@ -1237,7 +1243,7 @@
             }
 
             if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET) ||
-                mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
+                    mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
                 traceBeginAndSlog("StartEthernet");
                 mSystemServiceManager.startService(ETHERNET_SERVICE_CLASS);
                 traceEnd();
@@ -1246,10 +1252,10 @@
             traceBeginAndSlog("StartConnectivityService");
             try {
                 connectivity = new ConnectivityService(
-                    context, networkManagement, networkStats, networkPolicy);
+                        context, networkManagement, networkStats, networkPolicy);
                 ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity,
-                            /* allowIsolated= */ false,
-                    DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL);
+                        /* allowIsolated= */ false,
+                        DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL);
                 networkStats.bindConnectivityManager(connectivity);
                 networkPolicy.bindConnectivityManager(connectivity);
             } catch (Throwable e) {
@@ -1261,7 +1267,7 @@
             try {
                 serviceDiscovery = NsdService.create(context);
                 ServiceManager.addService(
-                    Context.NSD_SERVICE, serviceDiscovery);
+                        Context.NSD_SERVICE, serviceDiscovery);
             } catch (Throwable e) {
                 reportWtf("starting Service Discovery Service", e);
             }
@@ -1279,7 +1285,7 @@
             traceBeginAndSlog("StartUpdateLockService");
             try {
                 ServiceManager.addService(Context.UPDATE_LOCK_SERVICE,
-                    new UpdateLockService(context));
+                        new UpdateLockService(context));
             } catch (Throwable e) {
                 reportWtf("starting UpdateLockService", e);
             }
@@ -1397,9 +1403,9 @@
             }
 
             if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)
-                || mPackageManager.hasSystemFeature(
-                PackageManager.FEATURE_USB_ACCESSORY)
-                || isEmulator) {
+                    || mPackageManager.hasSystemFeature(
+                    PackageManager.FEATURE_USB_ACCESSORY)
+                    || isEmulator) {
                 // Manage USB host and device support
                 traceBeginAndSlog("StartUsbService");
                 mSystemServiceManager.startService(USB_SERVICE_CLASS);
@@ -1431,7 +1437,7 @@
             try {
                 hardwarePropertiesService = new HardwarePropertiesManagerService(context);
                 ServiceManager.addService(Context.HARDWARE_PROPERTIES_SERVICE,
-                    hardwarePropertiesService);
+                        hardwarePropertiesService);
             } catch (Throwable e) {
                 Slog.e(TAG, "Failure starting HardwarePropertiesManagerService", e);
             }
@@ -1441,8 +1447,8 @@
             mSystemServiceManager.startService(TwilightService.class);
             traceEnd();
 
-            if (ColorDisplayController.isAvailable(context)) {
-                traceBeginAndSlog("StartNightDisplay");
+            if (ColorDisplayManager.isNightDisplayAvailable(context)) {
+                traceBeginAndSlog("StartColorDisplay");
                 mSystemServiceManager.startService(ColorDisplayService.class);
                 traceEnd();
             }
@@ -1466,7 +1472,7 @@
             }
 
             if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS)
-                || context.getResources().getBoolean(R.bool.config_enableAppWidgetService)) {
+                    || context.getResources().getBoolean(R.bool.config_enableAppWidgetService)) {
                 traceBeginAndSlog("StartAppWidgetService");
                 mSystemServiceManager.startService(APPWIDGET_SERVICE_CLASS);
                 traceEnd();
@@ -1552,7 +1558,7 @@
 
             traceBeginAndSlog("AddGraphicsStatsService");
             ServiceManager.addService(GraphicsStatsService.GRAPHICS_STATS_SERVICE,
-                new GraphicsStatsService(context));
+                    new GraphicsStatsService(context));
             traceEnd();
 
             if (CoverageService.ENABLED) {
@@ -1768,12 +1774,6 @@
             traceEnd();
         }
 
-        if (!disableIntelligence) {
-            traceBeginAndSlog("StartIntelligenceService");
-            mSystemServiceManager.startService(INTELLIGENCE_MANAGER_SERVICE_CLASS);
-            traceEnd();
-        }
-
         traceBeginAndSlog("AppServiceManager");
         mSystemServiceManager.startService(AppBindingService.Lifecycle.class);
         traceEnd();
@@ -1824,7 +1824,7 @@
         // propagate to it.
         final Configuration config = wm.computeNewConfiguration(DEFAULT_DISPLAY);
         DisplayMetrics metrics = new DisplayMetrics();
-        WindowManager w = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
+        WindowManager w = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
         w.getDefaultDisplay().getMetrics(metrics);
         context.getResources().updateConfiguration(config, metrics);
 
@@ -1911,6 +1911,11 @@
             }
             traceEnd();
 
+            // Grants default permissions and defines roles
+            traceBeginAndSlog("StartRoleManagerService");
+            mSystemServiceManager.startService(RoleManagerService.class);
+            traceEnd();
+
             // No dependency on Webview preparation in system server. But this should
             // be completed before allowing 3rd party
             final String WEBVIEW_PREPARATION = "WebViewFactoryPreparation";
@@ -1943,7 +1948,9 @@
             traceEnd();
             traceBeginAndSlog("MakeNetworkManagementServiceReady");
             try {
-                if (networkManagementF != null) networkManagementF.systemReady();
+                if (networkManagementF != null) {
+                    networkManagementF.systemReady();
+                }
             } catch (Throwable e) {
                 reportWtf("making Network Managment Service ready", e);
             }
@@ -1955,21 +1962,27 @@
             traceEnd();
             traceBeginAndSlog("MakeIpSecServiceReady");
             try {
-                if (ipSecServiceF != null) ipSecServiceF.systemReady();
+                if (ipSecServiceF != null) {
+                    ipSecServiceF.systemReady();
+                }
             } catch (Throwable e) {
                 reportWtf("making IpSec Service ready", e);
             }
             traceEnd();
             traceBeginAndSlog("MakeNetworkStatsServiceReady");
             try {
-                if (networkStatsF != null) networkStatsF.systemReady();
+                if (networkStatsF != null) {
+                    networkStatsF.systemReady();
+                }
             } catch (Throwable e) {
                 reportWtf("making Network Stats Service ready", e);
             }
             traceEnd();
             traceBeginAndSlog("MakeConnectivityServiceReady");
             try {
-                if (connectivityF != null) connectivityF.systemReady();
+                if (connectivityF != null) {
+                    connectivityF.systemReady();
+                }
             } catch (Throwable e) {
                 reportWtf("making Connectivity Service ready", e);
             }
@@ -2004,21 +2017,27 @@
 
             traceBeginAndSlog("MakeLocationServiceReady");
             try {
-                if (locationF != null) locationF.systemRunning();
+                if (locationF != null) {
+                    locationF.systemRunning();
+                }
             } catch (Throwable e) {
                 reportWtf("Notifying Location Service running", e);
             }
             traceEnd();
             traceBeginAndSlog("MakeCountryDetectionServiceReady");
             try {
-                if (countryDetectorF != null) countryDetectorF.systemRunning();
+                if (countryDetectorF != null) {
+                    countryDetectorF.systemRunning();
+                }
             } catch (Throwable e) {
                 reportWtf("Notifying CountryDetectorService running", e);
             }
             traceEnd();
             traceBeginAndSlog("MakeNetworkTimeUpdateReady");
             try {
-                if (networkTimeUpdaterF != null) networkTimeUpdaterF.systemRunning();
+                if (networkTimeUpdaterF != null) {
+                    networkTimeUpdaterF.systemRunning();
+                }
             } catch (Throwable e) {
                 reportWtf("Notifying NetworkTimeService running", e);
             }
@@ -2026,28 +2045,36 @@
             traceBeginAndSlog("MakeInputManagerServiceReady");
             try {
                 // TODO(BT) Pass parameter to input manager
-                if (inputManagerF != null) inputManagerF.systemRunning();
+                if (inputManagerF != null) {
+                    inputManagerF.systemRunning();
+                }
             } catch (Throwable e) {
                 reportWtf("Notifying InputManagerService running", e);
             }
             traceEnd();
             traceBeginAndSlog("MakeTelephonyRegistryReady");
             try {
-                if (telephonyRegistryF != null) telephonyRegistryF.systemRunning();
+                if (telephonyRegistryF != null) {
+                    telephonyRegistryF.systemRunning();
+                }
             } catch (Throwable e) {
                 reportWtf("Notifying TelephonyRegistry running", e);
             }
             traceEnd();
             traceBeginAndSlog("MakeMediaRouterServiceReady");
             try {
-                if (mediaRouterF != null) mediaRouterF.systemRunning();
+                if (mediaRouterF != null) {
+                    mediaRouterF.systemRunning();
+                }
             } catch (Throwable e) {
                 reportWtf("Notifying MediaRouterService running", e);
             }
             traceEnd();
             traceBeginAndSlog("MakeMmsServiceReady");
             try {
-                if (mmsServiceF != null) mmsServiceF.systemRunning();
+                if (mmsServiceF != null) {
+                    mmsServiceF.systemRunning();
+                }
             } catch (Throwable e) {
                 reportWtf("Notifying MmsService running", e);
             }
@@ -2059,7 +2086,9 @@
                 // in the build and should reliably be there.
                 final IIncidentManager incident = IIncidentManager.Stub.asInterface(
                         ServiceManager.getService(Context.INCIDENT_SERVICE));
-                if (incident != null) incident.systemRunning();
+                if (incident != null) {
+                    incident.systemRunning();
+                }
             } catch (Throwable e) {
                 reportWtf("Notifying incident daemon running", e);
             }
@@ -2070,7 +2099,7 @@
     static final void startSystemUi(Context context, WindowManagerService windowManager) {
         Intent intent = new Intent();
         intent.setComponent(new ComponentName("com.android.systemui",
-                    "com.android.systemui.SystemUIService"));
+                "com.android.systemui.SystemUIService"));
         intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
         //Slog.d(TAG, "Starting service: " + intent);
         context.startServiceAsUser(intent, UserHandle.SYSTEM);
diff --git a/services/robotests/Android.mk b/services/robotests/Android.mk
index e67f8d3..565152c 100644
--- a/services/robotests/Android.mk
+++ b/services/robotests/Android.mk
@@ -12,10 +12,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-
-##############################################################
-# FrameworksServicesLib app just for Robolectric test target #
-##############################################################
+###################################################################
+# FrameworksServicesLib app just for Robolectric test target      #
+###################################################################
 LOCAL_PATH := $(call my-dir)
 
 include $(CLEAR_VARS)
@@ -28,85 +27,56 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     services.backup \
-    services.core
+    services.core \
+    services.net
 
 include $(BUILD_PACKAGE)
 
-##############################################
-# FrameworksServices Robolectric test target #
-##############################################
+###################################################################
+# FrameworksServicesLib Robolectric test target.                  #
+###################################################################
 include $(CLEAR_VARS)
 
-# Dependency platform-robolectric-android-all-stubs below contains a bunch of Android classes as
-# stubs that throw RuntimeExceptions when we use them. The goal is to include hidden APIs that
-# weren't included in Robolectric's Android jar files. However, we are testing the framework itself
-# here, so if we write stuff that is being used in the tests and exist in
-# platform-robolectric-android-all-stubs, the class loader is going to pick up the latter, and thus
-# we are going to test what we don't want. To solve this:
-#
-#   1. If the class being used should be visible to bundled apps:
-#      => Bypass the stubs target by including them in LOCAL_SRC_FILES and LOCAL_AIDL_INCLUDES
-#         (if aidl).
-#
-#   2. If it's not visible:
-#      => Remove the class from the stubs jar (common/robolectric/android-all/android-all-stubs.jar)
-#         and add the class path to
-#         common/robolectric/android-all/android-all-stubs_removed_classes.txt.
-#
+LOCAL_MODULE := FrameworksServicesRoboTests
 
-INTERNAL_BACKUP := ../../core/java/com/android/internal/backup
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_SRC_FILES := \
-    $(call all-java-files-under, src) \
-    $(call all-Iaidl-files-under, $(INTERNAL_BACKUP)) \
-    $(call all-java-files-under, ../../core/java/android/app/backup) \
-    $(call all-Iaidl-files-under, ../../core/java/android/app/backup) \
-    $(call all-java-files-under, ../../core/java/android/util/proto) \
-    ../../core/java/android/content/pm/PackageInfo.java \
-    ../../core/java/android/app/IBackupAgent.aidl \
-    ../../core/java/android/util/KeyValueSettingObserver.java \
-    ../../core/java/android/content/pm/PackageParser.java \
-    ../../core/java/android/content/pm/SigningInfo.java
+LOCAL_RESOURCE_DIR := \
+    $(LOCAL_PATH)/res
 
-LOCAL_AIDL_INCLUDES := \
-    $(call all-Iaidl-files-under, $(INTERNAL_BACKUP)) \
-    $(call all-Iaidl-files-under, ../../core/java/android/app/backup) \
-    ../../core/java/android/app/IBackupAgent.aidl
+LOCAL_JAVA_RESOURCE_DIRS := config
 
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    platform-robolectric-android-all-stubs \
-    android-support-test \
-    guava \
-    mockito-robolectric-prebuilt \
+# Include the testing libraries
+LOCAL_JAVA_LIBRARIES := \
     platform-test-annotations \
+    robolectric_android-all-stub \
+    Robolectric_all-target \
+    mockito-robolectric-prebuilt \
     truth-prebuilt \
     testng
 
-LOCAL_JAVA_LIBRARIES := \
-    junit \
-    platform-robolectric-3.6.2-prebuilt
-
 LOCAL_INSTRUMENTATION_FOR := FrameworksServicesLib
-LOCAL_MODULE := FrameworksServicesRoboTests
 
 LOCAL_MODULE_TAGS := optional
 
 include $(BUILD_STATIC_JAVA_LIBRARY)
 
-###############################################################
-# FrameworksServices runner target to run the previous target #
-###############################################################
+###################################################################
+# FrameworksServicesLib runner target to run the previous target. #
+###################################################################
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := RunFrameworksServicesRoboTests
 
-LOCAL_SDK_VERSION := current
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    FrameworksServicesRoboTests
+LOCAL_JAVA_LIBRARIES := \
+    FrameworksServicesRoboTests \
+    platform-test-annotations \
+    robolectric_android-all-stub \
+    Robolectric_all-target \
+    mockito-robolectric-prebuilt \
+    truth-prebuilt \
+    testng
 
 LOCAL_TEST_PACKAGE := FrameworksServicesLib
 
-LOCAL_INSTRUMENT_SOURCE_DIRS := $(dir $(LOCAL_PATH))backup/java
-
-include prebuilts/misc/common/robolectric/3.6.2/run_robotests.mk
+include external/robolectric-shadows/run_robotests.mk
\ No newline at end of file
diff --git a/services/robotests/config/robolectric.properties b/services/robotests/config/robolectric.properties
new file mode 100644
index 0000000..850557a
--- /dev/null
+++ b/services/robotests/config/robolectric.properties
@@ -0,0 +1 @@
+sdk=NEWEST_SDK
\ No newline at end of file
diff --git a/services/robotests/src/android/app/backup/BackupUtilsTest.java b/services/robotests/src/android/app/backup/BackupUtilsTest.java
index 04a2a14..099cde0 100644
--- a/services/robotests/src/android/app/backup/BackupUtilsTest.java
+++ b/services/robotests/src/android/app/backup/BackupUtilsTest.java
@@ -22,14 +22,11 @@
 import android.content.Context;
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 import org.robolectric.annotation.internal.DoNotInstrument;
 
 import java.io.File;
@@ -38,9 +35,7 @@
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"android.app.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 @DoNotInstrument
 public class BackupUtilsTest {
diff --git a/services/robotests/src/com/android/server/backup/BackupAgentTimeoutParametersTest.java b/services/robotests/src/com/android/server/backup/BackupAgentTimeoutParametersTest.java
index 0d2c221..5b226f3 100644
--- a/services/robotests/src/com/android/server/backup/BackupAgentTimeoutParametersTest.java
+++ b/services/robotests/src/com/android/server/backup/BackupAgentTimeoutParametersTest.java
@@ -25,22 +25,16 @@
 import android.os.Handler;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
-import android.util.KeyValueSettingObserver;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderClasses;
-import com.android.server.testing.SystemLoaderPackages;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
 /** Tests for {@link BackupAgentTimeoutParameters}. */
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
-@SystemLoaderClasses({KeyValueSettingObserver.class})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class BackupAgentTimeoutParametersTest {
     private ContentResolver mContentResolver;
diff --git a/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java b/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java
index 2a32c2e..affa1f3 100644
--- a/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java
+++ b/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java
@@ -23,21 +23,15 @@
 import android.os.Handler;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
-import android.util.KeyValueSettingObserver;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderClasses;
-import com.android.server.testing.SystemLoaderPackages;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
-@SystemLoaderClasses({KeyValueSettingObserver.class})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class BackupManagerConstantsTest {
     private static final String PACKAGE_NAME = "some.package.name";
diff --git a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
index de915ab..c4cb593 100644
--- a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
+++ b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
@@ -22,7 +22,9 @@
 import static com.android.server.backup.testing.TransportData.localTransport;
 import static com.android.server.backup.testing.TransportTestUtils.setUpCurrentTransport;
 import static com.android.server.backup.testing.TransportTestUtils.setUpTransports;
+
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
@@ -45,24 +47,23 @@
 import android.os.PowerSaveState;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
+
 import com.android.server.backup.testing.BackupManagerServiceTestUtils;
 import com.android.server.backup.testing.TransportData;
 import com.android.server.backup.testing.TransportTestUtils.TransportMock;
 import com.android.server.backup.transport.TransportNotRegisteredException;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
 import com.android.server.testing.shadows.ShadowAppBackupUtils;
 import com.android.server.testing.shadows.ShadowBinder;
 import com.android.server.testing.shadows.ShadowKeyValueBackupJob;
 import com.android.server.testing.shadows.ShadowKeyValueBackupTask;
-import java.io.File;
-import java.util.List;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 import org.robolectric.annotation.Implements;
@@ -71,9 +72,11 @@
 import org.robolectric.shadows.ShadowPackageManager;
 import org.robolectric.shadows.ShadowSettings;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26, shadows = {ShadowAppBackupUtils.class})
-@SystemLoaderPackages({"com.android.server.backup"})
+import java.io.File;
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowAppBackupUtils.class})
 @Presubmit
 public class BackupManagerServiceTest {
     private static final String TAG = "BMSTest";
diff --git a/services/robotests/src/com/android/server/backup/KeyValueBackupJobTest.java b/services/robotests/src/com/android/server/backup/KeyValueBackupJobTest.java
index dd0a58d..8e17209 100644
--- a/services/robotests/src/com/android/server/backup/KeyValueBackupJobTest.java
+++ b/services/robotests/src/com/android/server/backup/KeyValueBackupJobTest.java
@@ -22,19 +22,14 @@
 import android.os.Handler;
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class KeyValueBackupJobTest {
     private Context mContext;
diff --git a/services/robotests/src/com/android/server/backup/TransportManagerTest.java b/services/robotests/src/com/android/server/backup/TransportManagerTest.java
index 051a4a0..693092d 100644
--- a/services/robotests/src/com/android/server/backup/TransportManagerTest.java
+++ b/services/robotests/src/com/android/server/backup/TransportManagerTest.java
@@ -56,17 +56,14 @@
 import com.android.server.backup.transport.TransportClient;
 import com.android.server.backup.transport.TransportClientManager;
 import com.android.server.backup.transport.TransportNotRegisteredException;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-import com.android.server.testing.shadows.FrameworkShadowContextImpl;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowPackageManager;
 
 import java.util.ArrayList;
@@ -75,12 +72,7 @@
 import java.util.Set;
 import java.util.stream.Stream;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        sdk = 26,
-        shadows = {FrameworkShadowContextImpl.class})
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class TransportManagerTest {
     private static final String PACKAGE_A = "some.package.a";
@@ -682,7 +674,7 @@
                     transport.getTransportComponent().getPackageName(),
                     ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
         }
-        setUpTransports(transportSet.toArray(new TransportData[transportSet.size()]));
+        setUpTransports(transportSet.toArray(new TransportData[0]));
         TransportManager transportManager = createTransportManager(selectedTransport, transports);
         transportManager.registerTransports();
         return transportManager;
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkHashTest.java b/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkHashTest.java
index 3b6e038..3f57240 100644
--- a/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkHashTest.java
+++ b/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkHashTest.java
@@ -19,17 +19,16 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.platform.test.annotations.Presubmit;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
+
 import com.google.common.primitives.Bytes;
-import java.util.Arrays;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+import java.util.Arrays;
+
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class ChunkHashTest {
     private static final int HASH_LENGTH_BYTES = 256 / 8;
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkListingTest.java b/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkListingTest.java
index 383bf1d..4354db7 100644
--- a/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkListingTest.java
+++ b/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkListingTest.java
@@ -21,22 +21,20 @@
 import android.platform.test.annotations.Presubmit;
 import android.util.proto.ProtoInputStream;
 import android.util.proto.ProtoOutputStream;
+
 import com.android.internal.util.Preconditions;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
+
 import com.google.common.base.Charsets;
-import java.io.ByteArrayInputStream;
-import java.util.Arrays;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-// Include android.util.proto in addition to classes under test because the latest versions of
-// android.util.proto.Proto{Input|Output}Stream are not part of Robolectric.
-@SystemLoaderPackages({"com.android.server.backup", "android.util.proto"})
+import java.io.ByteArrayInputStream;
+import java.util.Arrays;
+
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class ChunkListingTest {
     private static final String CHUNK_A = "CHUNK_A";
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkTest.java b/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkTest.java
index 1dd7dc8..17c9a86 100644
--- a/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkTest.java
+++ b/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkTest.java
@@ -21,21 +21,18 @@
 import android.platform.test.annotations.Presubmit;
 import android.util.proto.ProtoInputStream;
 import android.util.proto.ProtoOutputStream;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
+
 import com.google.common.base.Charsets;
-import java.io.ByteArrayInputStream;
-import java.util.Arrays;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-// Include android.util.proto in addition to classes under test because the latest versions of
-// android.util.proto.Proto{Input|Output}Stream are not part of Robolectric.
-@SystemLoaderPackages({"com.android.server.backup", "android.util.proto"})
+import java.io.ByteArrayInputStream;
+import java.util.Arrays;
+
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class ChunkTest {
     private static final String CHUNK_A = "CHUNK_A";
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunk/EncryptedChunkOrderingTest.java b/services/robotests/src/com/android/server/backup/encryption/chunk/EncryptedChunkOrderingTest.java
index 1cd1528..0bf1417 100644
--- a/services/robotests/src/com/android/server/backup/encryption/chunk/EncryptedChunkOrderingTest.java
+++ b/services/robotests/src/com/android/server/backup/encryption/chunk/EncryptedChunkOrderingTest.java
@@ -19,16 +19,14 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.platform.test.annotations.Presubmit;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
+
 import com.google.common.primitives.Bytes;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class EncryptedChunkOrderingTest {
     private static final byte[] TEST_BYTE_ARRAY_1 = new byte[] {1, 2, 3, 4, 5};
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/ChunkEncryptorTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/ChunkEncryptorTest.java
index 2cc3ef8..d0e5fb3 100644
--- a/services/robotests/src/com/android/server/backup/encryption/chunking/ChunkEncryptorTest.java
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/ChunkEncryptorTest.java
@@ -17,32 +17,35 @@
 package com.android.server.backup.encryption.chunking;
 
 import static com.android.server.backup.testing.CryptoTestUtils.generateAesKey;
+
 import static com.google.common.truth.Truth.assertThat;
-import static java.nio.charset.StandardCharsets.UTF_8;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 
+import static java.nio.charset.StandardCharsets.UTF_8;
+
 import android.platform.test.annotations.Presubmit;
+
 import com.android.server.backup.encryption.chunk.ChunkHash;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-import java.security.SecureRandom;
-import javax.crypto.Cipher;
-import javax.crypto.Mac;
-import javax.crypto.SecretKey;
-import javax.crypto.spec.GCMParameterSpec;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+import java.security.SecureRandom;
+
+import javax.crypto.Cipher;
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.GCMParameterSpec;
+
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class ChunkEncryptorTest {
     private static final String MAC_ALGORITHM = "HmacSHA256";
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/ChunkHasherTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/ChunkHasherTest.java
index 11796c0..2bbbf28 100644
--- a/services/robotests/src/com/android/server/backup/encryption/chunking/ChunkHasherTest.java
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/ChunkHasherTest.java
@@ -19,20 +19,19 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.platform.test.annotations.Presubmit;
+
 import com.android.server.backup.encryption.chunk.ChunkHash;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-import javax.crypto.Mac;
-import javax.crypto.SecretKey;
-import javax.crypto.spec.SecretKeySpec;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class ChunkHasherTest {
     private static final String KEY_ALGORITHM = "AES";
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/EncryptedChunkTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/EncryptedChunkTest.java
index c5f9b10..8e801a1 100644
--- a/services/robotests/src/com/android/server/backup/encryption/chunking/EncryptedChunkTest.java
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/EncryptedChunkTest.java
@@ -17,21 +17,22 @@
 package com.android.server.backup.encryption.chunking;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.testng.Assert.assertThrows;
 
 import android.platform.test.annotations.Presubmit;
+
 import com.android.server.backup.encryption.chunk.ChunkHash;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
+
 import com.google.common.primitives.Bytes;
-import java.util.Arrays;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+import java.util.Arrays;
+
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class EncryptedChunkTest {
     private static final byte[] CHUNK_HASH_1_BYTES =
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/InlineLengthsEncryptedChunkEncoderTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/InlineLengthsEncryptedChunkEncoderTest.java
index b162557..2f872be 100644
--- a/services/robotests/src/com/android/server/backup/encryption/chunking/InlineLengthsEncryptedChunkEncoderTest.java
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/InlineLengthsEncryptedChunkEncoderTest.java
@@ -17,25 +17,25 @@
 package com.android.server.backup.encryption.chunking;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 
 import android.platform.test.annotations.Presubmit;
+
 import com.android.server.backup.encryption.chunk.ChunkHash;
 import com.android.server.backup.encryption.chunk.ChunksMetadataProto;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-import java.util.Arrays;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.InOrder;
 import org.mockito.Mock;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+import java.util.Arrays;
+
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class InlineLengthsEncryptedChunkEncoderTest {
 
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/LengthlessEncryptedChunkEncoderTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/LengthlessEncryptedChunkEncoderTest.java
index b61dbe9..978bddb 100644
--- a/services/robotests/src/com/android/server/backup/encryption/chunking/LengthlessEncryptedChunkEncoderTest.java
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/LengthlessEncryptedChunkEncoderTest.java
@@ -17,25 +17,25 @@
 package com.android.server.backup.encryption.chunking;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 
 import android.platform.test.annotations.Presubmit;
+
 import com.android.server.backup.encryption.chunk.ChunkHash;
 import com.android.server.backup.encryption.chunk.ChunksMetadataProto;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-import java.util.Arrays;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.InOrder;
 import org.mockito.Mock;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+import java.util.Arrays;
+
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class LengthlessEncryptedChunkEncoderTest {
     private static final byte[] TEST_NONCE =
@@ -74,7 +74,7 @@
     }
 
     @Test
-    public void getChunkOrderingType_returnsExplicitStartsType() throws Exception {
+    public void getChunkOrderingType_returnsExplicitStartsType() {
         assertThat(mEncoder.getChunkOrderingType()).isEqualTo(ChunksMetadataProto.EXPLICIT_STARTS);
     }
 }
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/RawBackupWriterTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/RawBackupWriterTest.java
index 8b54e1e..19ef8fb 100644
--- a/services/robotests/src/com/android/server/backup/encryption/chunking/RawBackupWriterTest.java
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/RawBackupWriterTest.java
@@ -17,23 +17,23 @@
 package com.android.server.backup.encryption.chunking;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.testng.Assert.assertThrows;
 
 import android.platform.test.annotations.Presubmit;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
+
 import com.google.common.primitives.Bytes;
-import java.io.ByteArrayOutputStream;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+import java.io.ByteArrayOutputStream;
+
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class RawBackupWriterTest {
     private static final byte[] TEST_BYTES = {1, 2, 3, 4, 5, 6};
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/ContentDefinedChunkerTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/ContentDefinedChunkerTest.java
new file mode 100644
index 0000000..77b7347
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/ContentDefinedChunkerTest.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2018 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.backup.encryption.chunking.cdc;
+
+import static com.android.server.backup.testing.CryptoTestUtils.generateAesKey;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.assertThrows;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import android.platform.test.annotations.Presubmit;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.security.GeneralSecurityException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Random;
+
+import javax.crypto.SecretKey;
+
+/** Tests for {@link ContentDefinedChunker}. */
+@RunWith(RobolectricTestRunner.class)
+@Presubmit
+public class ContentDefinedChunkerTest {
+    private static final int WINDOW_SIZE_BYTES = 31;
+    private static final int MIN_SIZE_BYTES = 40;
+    private static final int MAX_SIZE_BYTES = 300;
+    private static final String CHUNK_BOUNDARY = "<----------BOUNDARY----------->";
+    private static final byte[] CHUNK_BOUNDARY_BYTES = CHUNK_BOUNDARY.getBytes(UTF_8);
+    private static final String CHUNK_1 = "This is the first chunk";
+    private static final String CHUNK_2 = "And this is the second chunk";
+    private static final String CHUNK_3 = "And finally here is the third chunk";
+    private static final String SMALL_CHUNK = "12345678";
+
+    private FingerprintMixer mFingerprintMixer;
+    private RabinFingerprint64 mRabinFingerprint64;
+    private ContentDefinedChunker mChunker;
+
+    /** Set up a {@link ContentDefinedChunker} and dependencies for use in the tests. */
+    @Before
+    public void setUp() throws Exception {
+        SecretKey secretKey = generateAesKey();
+        byte[] salt = new byte[FingerprintMixer.SALT_LENGTH_BYTES];
+        Random random = new Random();
+        random.nextBytes(salt);
+        mFingerprintMixer = new FingerprintMixer(secretKey, salt);
+
+        mRabinFingerprint64 = new RabinFingerprint64();
+        long chunkBoundaryFingerprint = calculateFingerprint(CHUNK_BOUNDARY_BYTES);
+        mChunker =
+                new ContentDefinedChunker(
+                        MIN_SIZE_BYTES,
+                        MAX_SIZE_BYTES,
+                        mRabinFingerprint64,
+                        mFingerprintMixer,
+                        (fingerprint) -> fingerprint == chunkBoundaryFingerprint);
+    }
+
+    /**
+     * Creating a {@link ContentDefinedChunker} with a minimum chunk size that is smaller than the
+     * window size should throw an {@link IllegalArgumentException}.
+     */
+    @Test
+    public void create_withMinChunkSizeSmallerThanWindowSize_throwsIllegalArgumentException() {
+        assertThrows(
+                IllegalArgumentException.class,
+                () ->
+                        new ContentDefinedChunker(
+                                WINDOW_SIZE_BYTES - 1,
+                                MAX_SIZE_BYTES,
+                                mRabinFingerprint64,
+                                mFingerprintMixer,
+                                null));
+    }
+
+    /**
+     * Creating a {@link ContentDefinedChunker} with a maximum chunk size that is smaller than the
+     * minimum chunk size should throw an {@link IllegalArgumentException}.
+     */
+    @Test
+    public void create_withMaxChunkSizeSmallerThanMinChunkSize_throwsIllegalArgumentException() {
+        assertThrows(
+                IllegalArgumentException.class,
+                () ->
+                        new ContentDefinedChunker(
+                                MIN_SIZE_BYTES,
+                                MIN_SIZE_BYTES - 1,
+                                mRabinFingerprint64,
+                                mFingerprintMixer,
+                                null));
+    }
+
+    /**
+     * {@link ContentDefinedChunker#chunkify(InputStream, Chunker.ChunkConsumer)} should split the
+     * input stream across chunk boundaries by default.
+     */
+    @Test
+    public void chunkify_withLargeChunks_splitsIntoChunksAcrossBoundaries() throws Exception {
+        byte[] input =
+                (CHUNK_1 + CHUNK_BOUNDARY + CHUNK_2 + CHUNK_BOUNDARY + CHUNK_3).getBytes(UTF_8);
+        ByteArrayInputStream inputStream = new ByteArrayInputStream(input);
+        ArrayList<String> result = new ArrayList<>();
+
+        mChunker.chunkify(inputStream, (chunk) -> result.add(new String(chunk, UTF_8)));
+
+        assertThat(result)
+                .containsExactly(CHUNK_1 + CHUNK_BOUNDARY, CHUNK_2 + CHUNK_BOUNDARY, CHUNK_3)
+                .inOrder();
+    }
+
+    /** Chunks should be combined across boundaries until they reach the minimum chunk size. */
+    @Test
+    public void chunkify_withSmallChunks_combinesChunksUntilMinSize() throws Exception {
+        byte[] input =
+                (SMALL_CHUNK + CHUNK_BOUNDARY + CHUNK_2 + CHUNK_BOUNDARY + CHUNK_3).getBytes(UTF_8);
+        ByteArrayInputStream inputStream = new ByteArrayInputStream(input);
+        ArrayList<String> result = new ArrayList<>();
+
+        mChunker.chunkify(inputStream, (chunk) -> result.add(new String(chunk, UTF_8)));
+
+        assertThat(result)
+                .containsExactly(SMALL_CHUNK + CHUNK_BOUNDARY + CHUNK_2 + CHUNK_BOUNDARY, CHUNK_3)
+                .inOrder();
+        assertThat(result.get(0).length()).isAtLeast(MIN_SIZE_BYTES);
+    }
+
+    /** Chunks can not be larger than the maximum chunk size. */
+    @Test
+    public void chunkify_doesNotProduceChunksLargerThanMaxSize() throws Exception {
+        byte[] largeInput = new byte[MAX_SIZE_BYTES * 10];
+        Arrays.fill(largeInput, "a".getBytes(UTF_8)[0]);
+        ByteArrayInputStream inputStream = new ByteArrayInputStream(largeInput);
+        ArrayList<String> result = new ArrayList<>();
+
+        mChunker.chunkify(inputStream, (chunk) -> result.add(new String(chunk, UTF_8)));
+
+        byte[] expectedChunkBytes = new byte[MAX_SIZE_BYTES];
+        Arrays.fill(expectedChunkBytes, "a".getBytes(UTF_8)[0]);
+        String expectedChunk = new String(expectedChunkBytes, UTF_8);
+        assertThat(result)
+                .containsExactly(
+                        expectedChunk,
+                        expectedChunk,
+                        expectedChunk,
+                        expectedChunk,
+                        expectedChunk,
+                        expectedChunk,
+                        expectedChunk,
+                        expectedChunk,
+                        expectedChunk,
+                        expectedChunk)
+                .inOrder();
+    }
+
+    /**
+     * If the input stream signals zero availablility, {@link
+     * ContentDefinedChunker#chunkify(InputStream, Chunker.ChunkConsumer)} should still work.
+     */
+    @Test
+    public void chunkify_withInputStreamReturningZeroAvailability_returnsChunks() throws Exception {
+        byte[] input = (SMALL_CHUNK + CHUNK_BOUNDARY + CHUNK_2).getBytes(UTF_8);
+        ZeroAvailabilityInputStream zeroAvailabilityInputStream =
+                new ZeroAvailabilityInputStream(input);
+        ArrayList<String> result = new ArrayList<>();
+
+        mChunker.chunkify(
+                zeroAvailabilityInputStream, (chunk) -> result.add(new String(chunk, UTF_8)));
+
+        assertThat(result).containsExactly(SMALL_CHUNK + CHUNK_BOUNDARY + CHUNK_2).inOrder();
+    }
+
+    /**
+     * {@link ContentDefinedChunker#chunkify(InputStream, Chunker.ChunkConsumer)} should rethrow any
+     * exception thrown by its consumer.
+     */
+    @Test
+    public void chunkify_whenConsumerThrowsException_rethrowsException() throws Exception {
+        ByteArrayInputStream inputStream = new ByteArrayInputStream(new byte[] {1});
+
+        assertThrows(
+                GeneralSecurityException.class,
+                () ->
+                        mChunker.chunkify(
+                                inputStream,
+                                (chunk) -> {
+                                    throw new GeneralSecurityException();
+                                }));
+    }
+
+    private long calculateFingerprint(byte[] bytes) {
+        long fingerprint = 0;
+        for (byte inByte : bytes) {
+            fingerprint =
+                    mRabinFingerprint64.computeFingerprint64(
+                            /*inChar=*/ inByte, /*outChar=*/ (byte) 0, fingerprint);
+        }
+        return mFingerprintMixer.mix(fingerprint);
+    }
+
+    private static class ZeroAvailabilityInputStream extends ByteArrayInputStream {
+        ZeroAvailabilityInputStream(byte[] wrapped) {
+            super(wrapped);
+        }
+
+        @Override
+        public synchronized int available() {
+            return 0;
+        }
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/FingerprintMixerTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/FingerprintMixerTest.java
new file mode 100644
index 0000000..936b5dc
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/FingerprintMixerTest.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2018 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.backup.encryption.chunking.cdc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.assertThrows;
+
+import android.platform.test.annotations.Presubmit;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.util.HashSet;
+import java.util.Random;
+
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
+/** Tests for {@link FingerprintMixer}. */
+@RunWith(RobolectricTestRunner.class)
+@Presubmit
+public class FingerprintMixerTest {
+    private static final String KEY_ALGORITHM = "AES";
+    private static final int SEED = 42;
+    private static final int SALT_LENGTH_BYTES = 256 / 8;
+    private static final int KEY_SIZE_BITS = 256;
+
+    private Random mSeededRandom;
+    private FingerprintMixer mFingerprintMixer;
+
+    /** Set up a {@link FingerprintMixer} with deterministic key and salt generation. */
+    @Before
+    public void setUp() throws Exception {
+        // Seed so that the tests are deterministic.
+        mSeededRandom = new Random(SEED);
+        mFingerprintMixer = new FingerprintMixer(randomKey(), randomSalt());
+    }
+
+    /**
+     * Construcing a {@link FingerprintMixer} with a salt that is too small should throw an {@link
+     * IllegalArgumentException}.
+     */
+    @Test
+    public void create_withIncorrectSaltSize_throwsIllegalArgumentException() {
+        byte[] tooSmallSalt = new byte[SALT_LENGTH_BYTES - 1];
+
+        assertThrows(
+                IllegalArgumentException.class,
+                () -> new FingerprintMixer(randomKey(), tooSmallSalt));
+    }
+
+    /**
+     * Constructing a {@link FingerprintMixer} with a secret key that can't be encoded should throw
+     * an {@link InvalidKeyException}.
+     */
+    @Test
+    public void create_withUnencodableSecretKey_throwsInvalidKeyException() {
+        byte[] keyBytes = new byte[KEY_SIZE_BITS / 8];
+        UnencodableSecretKeySpec keySpec =
+                new UnencodableSecretKeySpec(keyBytes, 0, keyBytes.length, KEY_ALGORITHM);
+
+        assertThrows(InvalidKeyException.class, () -> new FingerprintMixer(keySpec, randomSalt()));
+    }
+
+    /**
+     * {@link FingerprintMixer#getAddend()} should not return the same addend for two different
+     * keys.
+     */
+    @Test
+    public void getAddend_withDifferentKey_returnsDifferentResult() throws Exception {
+        int iterations = 100_000;
+        HashSet<Long> returnedAddends = new HashSet<>();
+        byte[] salt = randomSalt();
+
+        for (int i = 0; i < iterations; i++) {
+            FingerprintMixer fingerprintMixer = new FingerprintMixer(randomKey(), salt);
+            long addend = fingerprintMixer.getAddend();
+            returnedAddends.add(addend);
+        }
+
+        assertThat(returnedAddends).containsNoDuplicates();
+    }
+
+    /**
+     * {@link FingerprintMixer#getMultiplicand()} should not return the same multiplicand for two
+     * different keys.
+     */
+    @Test
+    public void getMultiplicand_withDifferentKey_returnsDifferentResult() throws Exception {
+        int iterations = 100_000;
+        HashSet<Long> returnedMultiplicands = new HashSet<>();
+        byte[] salt = randomSalt();
+
+        for (int i = 0; i < iterations; i++) {
+            FingerprintMixer fingerprintMixer = new FingerprintMixer(randomKey(), salt);
+            long multiplicand = fingerprintMixer.getMultiplicand();
+            returnedMultiplicands.add(multiplicand);
+        }
+
+        assertThat(returnedMultiplicands).containsNoDuplicates();
+    }
+
+    /** The multiplicant returned by {@link FingerprintMixer} should always be odd. */
+    @Test
+    public void getMultiplicand_isOdd() throws Exception {
+        int iterations = 100_000;
+
+        for (int i = 0; i < iterations; i++) {
+            FingerprintMixer fingerprintMixer = new FingerprintMixer(randomKey(), randomSalt());
+
+            long multiplicand = fingerprintMixer.getMultiplicand();
+
+            assertThat(isOdd(multiplicand)).isTrue();
+        }
+    }
+
+    /** {@link FingerprintMixer#mix(long)} should have a random distribution. */
+    @Test
+    public void mix_randomlyDistributesBits() throws Exception {
+        int iterations = 100_000;
+        float tolerance = 0.1f;
+        int[] totals = new int[64];
+
+        for (int i = 0; i < iterations; i++) {
+            long n = mFingerprintMixer.mix(mSeededRandom.nextLong());
+            for (int j = 0; j < 64; j++) {
+                int bit = (int) (n >> j & 1);
+                totals[j] += bit;
+            }
+        }
+
+        for (int i = 0; i < 64; i++) {
+            float mean = ((float) totals[i]) / iterations;
+            float diff = Math.abs(mean - 0.5f);
+            assertThat(diff).isLessThan(tolerance);
+        }
+    }
+
+    /**
+     * {@link FingerprintMixer#mix(long)} should always produce a number that's different from the
+     * input.
+     */
+    @Test
+    public void mix_doesNotProduceSameNumberAsInput() {
+        int iterations = 100_000;
+
+        for (int i = 0; i < iterations; i++) {
+            assertThat(mFingerprintMixer.mix(i)).isNotEqualTo(i);
+        }
+    }
+
+    private byte[] randomSalt() {
+        byte[] salt = new byte[SALT_LENGTH_BYTES];
+        mSeededRandom.nextBytes(salt);
+        return salt;
+    }
+
+    /**
+     * Not a secure way of generating keys. We want to deterministically generate the same keys for
+     * each test run, though, to ensure the test is deterministic.
+     */
+    private SecretKey randomKey() {
+        byte[] keyBytes = new byte[KEY_SIZE_BITS / 8];
+        mSeededRandom.nextBytes(keyBytes);
+        return new SecretKeySpec(keyBytes, 0, keyBytes.length, KEY_ALGORITHM);
+    }
+
+    private static boolean isOdd(long n) {
+        return Math.abs(n % 2) == 1;
+    }
+
+    /**
+     * Subclass of {@link SecretKeySpec} that does not provide an encoded version. As per its
+     * contract in {@link Key}, that means {@code getEncoded()} always returns null.
+     */
+    private class UnencodableSecretKeySpec extends SecretKeySpec {
+        UnencodableSecretKeySpec(byte[] key, int offset, int len, String algorithm) {
+            super(key, offset, len, algorithm);
+        }
+
+        @Override
+        public byte[] getEncoded() {
+            return null;
+        }
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/HkdfTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/HkdfTest.java
new file mode 100644
index 0000000..5494374
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/HkdfTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2018 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.backup.encryption.chunking.cdc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.assertThrows;
+
+import android.platform.test.annotations.Presubmit;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+/** Tests for {@link Hkdf}. */
+@RunWith(RobolectricTestRunner.class)
+@Presubmit
+public class HkdfTest {
+    /** HKDF Test Case 1 IKM from RFC 5869 */
+    private static final byte[] HKDF_CASE1_IKM = {
+        0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+        0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+        0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+        0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+        0x0b, 0x0b
+    };
+
+    /** HKDF Test Case 1 salt from RFC 5869 */
+    private static final byte[] HKDF_CASE1_SALT = {
+        0x00, 0x01, 0x02, 0x03, 0x04,
+        0x05, 0x06, 0x07, 0x08, 0x09,
+        0x0a, 0x0b, 0x0c
+    };
+
+    /** HKDF Test Case 1 info from RFC 5869 */
+    private static final byte[] HKDF_CASE1_INFO = {
+        (byte) 0xf0, (byte) 0xf1, (byte) 0xf2, (byte) 0xf3, (byte) 0xf4,
+        (byte) 0xf5, (byte) 0xf6, (byte) 0xf7, (byte) 0xf8, (byte) 0xf9
+    };
+
+    /** First 32 bytes of HKDF Test Case 1 OKM (output) from RFC 5869 */
+    private static final byte[] HKDF_CASE1_OKM = {
+        (byte) 0x3c, (byte) 0xb2, (byte) 0x5f, (byte) 0x25, (byte) 0xfa,
+        (byte) 0xac, (byte) 0xd5, (byte) 0x7a, (byte) 0x90, (byte) 0x43,
+        (byte) 0x4f, (byte) 0x64, (byte) 0xd0, (byte) 0x36, (byte) 0x2f,
+        (byte) 0x2a, (byte) 0x2d, (byte) 0x2d, (byte) 0x0a, (byte) 0x90,
+        (byte) 0xcf, (byte) 0x1a, (byte) 0x5a, (byte) 0x4c, (byte) 0x5d,
+        (byte) 0xb0, (byte) 0x2d, (byte) 0x56, (byte) 0xec, (byte) 0xc4,
+        (byte) 0xc5, (byte) 0xbf
+    };
+
+    /** Test the example from RFC 5869. */
+    @Test
+    public void hkdf_derivesKeyMaterial() throws Exception {
+        byte[] result = Hkdf.hkdf(HKDF_CASE1_IKM, HKDF_CASE1_SALT, HKDF_CASE1_INFO);
+
+        assertThat(result).isEqualTo(HKDF_CASE1_OKM);
+    }
+
+    /** Providing a key that is null should throw a {@link java.lang.NullPointerException}. */
+    @Test
+    public void hkdf_withNullKey_throwsNullPointerException() throws Exception {
+        assertThrows(
+                NullPointerException.class,
+                () -> Hkdf.hkdf(null, HKDF_CASE1_SALT, HKDF_CASE1_INFO));
+    }
+
+    /** Providing a salt that is null should throw a {@link java.lang.NullPointerException}. */
+    @Test
+    public void hkdf_withNullSalt_throwsNullPointerException() throws Exception {
+        assertThrows(
+                NullPointerException.class, () -> Hkdf.hkdf(HKDF_CASE1_IKM, null, HKDF_CASE1_INFO));
+    }
+
+    /** Providing data that is null should throw a {@link java.lang.NullPointerException}. */
+    @Test
+    public void hkdf_withNullData_throwsNullPointerException() throws Exception {
+        assertThrows(
+                NullPointerException.class, () -> Hkdf.hkdf(HKDF_CASE1_IKM, HKDF_CASE1_SALT, null));
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/IsChunkBreakpointTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/IsChunkBreakpointTest.java
new file mode 100644
index 0000000..277dc37
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/IsChunkBreakpointTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2018 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.backup.encryption.chunking.cdc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.assertThrows;
+
+import android.platform.test.annotations.Presubmit;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.Random;
+
+/** Tests for {@link IsChunkBreakpoint}. */
+@RunWith(RobolectricTestRunner.class)
+@Presubmit
+public class IsChunkBreakpointTest {
+    private static final int RANDOM_SEED = 42;
+    private static final double TOLERANCE = 0.01;
+    private static final int NUMBER_OF_TESTS = 10000;
+    private static final int BITS_PER_LONG = 64;
+
+    private Random mRandom;
+
+    /** Make sure that tests are deterministic. */
+    @Before
+    public void setUp() {
+        mRandom = new Random(RANDOM_SEED);
+    }
+
+    /**
+     * Providing a negative average number of trials should throw an {@link
+     * IllegalArgumentException}.
+     */
+    @Test
+    public void create_withNegativeAverageNumberOfTrials_throwsIllegalArgumentException() {
+        assertThrows(IllegalArgumentException.class, () -> new IsChunkBreakpoint(-1));
+    }
+
+    // Note: the following three tests are compute-intensive, so be cautious adding more.
+
+    /**
+     * If the provided average number of trials is zero, a breakpoint should be expected after one
+     * trial on average.
+     */
+    @Test
+    public void
+            isBreakpoint_withZeroAverageNumberOfTrials_isTrueOnAverageAfterOneTrial() {
+        assertExpectedTrials(new IsChunkBreakpoint(0), /*expectedTrials=*/ 1);
+    }
+
+    /**
+     * If the provided average number of trials is 512, a breakpoint should be expected after 512
+     * trials on average.
+     */
+    @Test
+    public void
+            isBreakpoint_with512AverageNumberOfTrials_isTrueOnAverageAfter512Trials() {
+        assertExpectedTrials(new IsChunkBreakpoint(512), /*expectedTrials=*/ 512);
+    }
+
+    /**
+     * If the provided average number of trials is 1024, a breakpoint should be expected after 1024
+     * trials on average.
+     */
+    @Test
+    public void
+            isBreakpoint_with1024AverageNumberOfTrials_isTrueOnAverageAfter1024Trials() {
+        assertExpectedTrials(new IsChunkBreakpoint(1024), /*expectedTrials=*/ 1024);
+    }
+
+    /** The number of leading zeros should be the logarithm of the average number of trials. */
+    @Test
+    public void getLeadingZeros_squaredIsAverageNumberOfTrials() {
+        for (int i = 0; i < BITS_PER_LONG; i++) {
+            long averageNumberOfTrials = (long) Math.pow(2, i);
+
+            int leadingZeros = new IsChunkBreakpoint(averageNumberOfTrials).getLeadingZeros();
+
+            assertThat(leadingZeros).isEqualTo(i);
+        }
+    }
+
+    private void assertExpectedTrials(IsChunkBreakpoint isChunkBreakpoint, long expectedTrials) {
+        long sum = 0;
+        for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+            sum += numberOfTrialsTillBreakpoint(isChunkBreakpoint);
+        }
+        long averageTrials = sum / NUMBER_OF_TESTS;
+        assertThat((double) Math.abs(averageTrials - expectedTrials))
+                .isLessThan(TOLERANCE * expectedTrials);
+    }
+
+    private int numberOfTrialsTillBreakpoint(IsChunkBreakpoint isChunkBreakpoint) {
+        int trials = 0;
+
+        while (true) {
+            trials++;
+            if (isChunkBreakpoint.isBreakpoint(mRandom.nextLong())) {
+                return trials;
+            }
+        }
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/RabinFingerprint64Test.java b/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/RabinFingerprint64Test.java
new file mode 100644
index 0000000..729580c
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/RabinFingerprint64Test.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2018 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.backup.encryption.chunking.cdc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import android.platform.test.annotations.Presubmit;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+/** Tests for {@link RabinFingerprint64}. */
+@RunWith(RobolectricTestRunner.class)
+@Presubmit
+public class RabinFingerprint64Test {
+    private static final int WINDOW_SIZE = 31;
+    private static final ImmutableList<String> TEST_STRINGS =
+            ImmutableList.of(
+                    "ervHTtChYXO6eXivYqThlyyzqkbRaOR",
+                    "IxaVunH9ZC3qneWfhj1GkBH4ys9CYqz",
+                    "wZRVjlE1p976icCFPX9pibk4PEBvjSH",
+                    "pHIVaT8x8If9D6s9croksgNmJpmGYWI");
+
+    private final RabinFingerprint64 mRabinFingerprint64 = new RabinFingerprint64();
+
+    /**
+     * No matter where in the input buffer a string occurs, {@link
+     * RabinFingerprint64#computeFingerprint64(byte, byte, long)} should return the same
+     * fingerprint.
+     */
+    @Test
+    public void computeFingerprint64_forSameWindow_returnsSameFingerprint() {
+        long fingerprint1 =
+                computeFingerprintAtPosition(getBytes(TEST_STRINGS.get(0)), WINDOW_SIZE - 1);
+        long fingerprint2 =
+                computeFingerprintAtPosition(
+                        getBytes(TEST_STRINGS.get(1), TEST_STRINGS.get(0)), WINDOW_SIZE * 2 - 1);
+        long fingerprint3 =
+                computeFingerprintAtPosition(
+                        getBytes(TEST_STRINGS.get(2), TEST_STRINGS.get(3), TEST_STRINGS.get(0)),
+                        WINDOW_SIZE * 3 - 1);
+        String stub = "abc";
+        long fingerprint4 =
+                computeFingerprintAtPosition(
+                        getBytes(stub, TEST_STRINGS.get(0)), WINDOW_SIZE + stub.length() - 1);
+
+        // Assert that all fingerprints are exactly the same
+        assertThat(ImmutableSet.of(fingerprint1, fingerprint2, fingerprint3, fingerprint4))
+                .hasSize(1);
+    }
+
+    /** The computed fingerprint should be different for different inputs. */
+    @Test
+    public void computeFingerprint64_withDifferentInput_returnsDifferentFingerprint() {
+        long fingerprint1 = computeFingerprintOf(TEST_STRINGS.get(0));
+        long fingerprint2 = computeFingerprintOf(TEST_STRINGS.get(1));
+        long fingerprint3 = computeFingerprintOf(TEST_STRINGS.get(2));
+        long fingerprint4 = computeFingerprintOf(TEST_STRINGS.get(3));
+
+        assertThat(ImmutableList.of(fingerprint1, fingerprint2, fingerprint3, fingerprint4))
+                .containsNoDuplicates();
+    }
+
+    /**
+     * An input with the same characters in a different order should return a different fingerprint.
+     */
+    @Test
+    public void computeFingerprint64_withSameInputInDifferentOrder_returnsDifferentFingerprint() {
+        long fingerprint1 = computeFingerprintOf("abcdefghijklmnopqrstuvwxyz12345");
+        long fingerprint2 = computeFingerprintOf("54321zyxwvutsrqponmlkjihgfedcba");
+        long fingerprint3 = computeFingerprintOf("4bcdefghijklmnopqrstuvwxyz123a5");
+        long fingerprint4 = computeFingerprintOf("bacdefghijklmnopqrstuvwxyz12345");
+
+        assertThat(ImmutableList.of(fingerprint1, fingerprint2, fingerprint3, fingerprint4))
+                .containsNoDuplicates();
+    }
+
+    /** UTF-8 bytes of all the given strings in order. */
+    private byte[] getBytes(String... strings) {
+        StringBuilder sb = new StringBuilder();
+        for (String s : strings) {
+            sb.append(s);
+        }
+        return sb.toString().getBytes(UTF_8);
+    }
+
+    /**
+     * The Rabin fingerprint of a window of bytes ending at {@code position} in the {@code bytes}
+     * array.
+     */
+    private long computeFingerprintAtPosition(byte[] bytes, int position) {
+        assertThat(position).isAtMost(bytes.length - 1);
+        long fingerprint = 0;
+        for (int i = 0; i <= position; i++) {
+            byte outChar;
+            if (i >= WINDOW_SIZE) {
+                outChar = bytes[i - WINDOW_SIZE];
+            } else {
+                outChar = (byte) 0;
+            }
+            fingerprint =
+                    mRabinFingerprint64.computeFingerprint64(
+                            /*inChar=*/ bytes[i], outChar, fingerprint);
+        }
+        return fingerprint;
+    }
+
+    private long computeFingerprintOf(String s) {
+        assertThat(s.length()).isEqualTo(WINDOW_SIZE);
+        return computeFingerprintAtPosition(s.getBytes(UTF_8), WINDOW_SIZE - 1);
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/fullbackup/AppMetadataBackupWriterTest.java b/services/robotests/src/com/android/server/backup/fullbackup/AppMetadataBackupWriterTest.java
index b771039..fd7ced2 100644
--- a/services/robotests/src/com/android/server/backup/fullbackup/AppMetadataBackupWriterTest.java
+++ b/services/robotests/src/com/android/server/backup/fullbackup/AppMetadataBackupWriterTest.java
@@ -7,6 +7,7 @@
 import static com.android.server.backup.BackupManagerService.BACKUP_WIDGET_METADATA_TOKEN;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.robolectric.Shadows.shadowOf;
 import static org.testng.Assert.expectThrows;
 
@@ -21,17 +22,24 @@
 import android.content.pm.Signature;
 import android.content.pm.SigningInfo;
 import android.os.Build;
-import android.os.Build.VERSION_CODES;
 import android.os.Environment;
 import android.os.ParcelFileDescriptor;
 import android.os.UserHandle;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderClasses;
-import com.android.server.testing.SystemLoaderPackages;
 import com.android.server.testing.shadows.ShadowBackupDataInput;
 import com.android.server.testing.shadows.ShadowBackupDataOutput;
 import com.android.server.testing.shadows.ShadowFullBackup;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplicationPackageManager;
+import org.robolectric.shadows.ShadowEnvironment;
+
 import java.io.ByteArrayOutputStream;
 import java.io.DataOutputStream;
 import java.io.File;
@@ -41,32 +49,20 @@
 import java.nio.file.Files;
 import java.nio.file.attribute.FileTime;
 
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowApplicationPackageManager;
-import org.robolectric.shadows.ShadowEnvironment;
-
-@RunWith(FrameworkRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
 @Config(
-        manifest = Config.NONE,
-        sdk = 26,
         shadows = {
             ShadowBackupDataInput.class,
             ShadowBackupDataOutput.class,
             ShadowEnvironment.class,
             ShadowFullBackup.class,
         })
-@SystemLoaderPackages({"com.android.server.backup", "android.app.backup"})
-@SystemLoaderClasses({PackageInfo.class, SigningInfo.class})
 public class AppMetadataBackupWriterTest {
     private static final String TEST_PACKAGE = "com.test.package";
     private static final String TEST_PACKAGE_INSTALLER = "com.test.package.installer";
     private static final Long TEST_PACKAGE_VERSION_CODE = 100L;
 
+    private PackageManager mPackageManager;
     private ShadowApplicationPackageManager mShadowPackageManager;
     private File mFilesDir;
     private File mBackupDataOutputFile;
@@ -76,8 +72,8 @@
     public void setUp() throws Exception {
         Application application = RuntimeEnvironment.application;
 
-        PackageManager packageManager = application.getPackageManager();
-        mShadowPackageManager = (ShadowApplicationPackageManager) shadowOf(packageManager);
+        mPackageManager = application.getPackageManager();
+        mShadowPackageManager = (ShadowApplicationPackageManager) shadowOf(mPackageManager);
 
         mFilesDir = RuntimeEnvironment.application.getFilesDir();
         mBackupDataOutputFile = new File(mFilesDir, "output");
@@ -87,7 +83,7 @@
                         mBackupDataOutputFile, ParcelFileDescriptor.MODE_READ_WRITE);
         FullBackupDataOutput output =
                 new FullBackupDataOutput(pfd, /* quota */ -1, /* transportFlags */ 0);
-        mBackupWriter = new AppMetadataBackupWriter(output, packageManager);
+        mBackupWriter = new AppMetadataBackupWriter(output, mPackageManager);
     }
 
     @After
@@ -211,36 +207,6 @@
      *     N* (signature byte array in ascii format per Signature.toCharsString())
      * </pre>
      */
-    @Config(sdk = VERSION_CODES.O)
-    @Test
-    public void testBackupManifest_whenApiO_writesCorrectApi() throws Exception {
-        PackageInfo packageInfo =
-                createPackageInfo(TEST_PACKAGE, TEST_PACKAGE_INSTALLER, TEST_PACKAGE_VERSION_CODE);
-        File manifestFile = createFile(BACKUP_MANIFEST_FILENAME);
-
-        mBackupWriter.backupManifest(packageInfo, manifestFile, mFilesDir, /* withApk */ false);
-
-        byte[] manifestBytes = getWrittenBytes(mBackupDataOutputFile, /* includeTarHeader */ false);
-        String[] manifest = new String(manifestBytes, StandardCharsets.UTF_8).split("\n");
-        assertThat(manifest.length).isEqualTo(7);
-        assertThat(manifest[3]).isEqualTo(Integer.toString(VERSION_CODES.O)); // platform version
-        manifestFile.delete();
-    }
-
-    /**
-     * The manifest format is:
-     *
-     * <pre>
-     *     BACKUP_MANIFEST_VERSION
-     *     package name
-     *     package version code
-     *     platform version code
-     *     installer package name (can be empty)
-     *     boolean (1 if archive includes .apk, otherwise 0)
-     *     # of signatures N
-     *     N* (signature byte array in ascii format per Signature.toCharsString())
-     * </pre>
-     */
     @Test
     public void testBackupManifest_withoutInstallerPackage_writesEmptyInstaller() throws Exception {
         PackageInfo packageInfo = createPackageInfo(TEST_PACKAGE, null, TEST_PACKAGE_VERSION_CODE);
@@ -394,7 +360,7 @@
     }
 
     @Test
-    public void testBackupObb_withNoObbData_doesNotWriteBytesToOutput() throws Exception {
+    public void testBackupObb_withNoObbData_doesNotWriteBytesToOutput() {
         PackageInfo packageInfo =
                 createPackageInfo(TEST_PACKAGE, TEST_PACKAGE_INSTALLER, TEST_PACKAGE_VERSION_CODE);
         File obbDir = createObbDirForPackage(packageInfo.packageName);
@@ -416,7 +382,7 @@
         packageInfo.setLongVersionCode(versionCode);
         mShadowPackageManager.addPackage(packageInfo);
         if (installerPackageName != null) {
-            mShadowPackageManager.setInstallerPackageName(packageName, installerPackageName);
+            mPackageManager.setInstallerPackageName(packageName, installerPackageName);
         }
         return packageInfo;
     }
diff --git a/services/robotests/src/com/android/server/backup/internal/PerformInitializeTaskTest.java b/services/robotests/src/com/android/server/backup/internal/PerformInitializeTaskTest.java
index 646367e..6ee6eb6 100644
--- a/services/robotests/src/com/android/server/backup/internal/PerformInitializeTaskTest.java
+++ b/services/robotests/src/com/android/server/backup/internal/PerformInitializeTaskTest.java
@@ -46,20 +46,18 @@
 import com.android.internal.backup.IBackupTransport;
 import com.android.server.backup.BackupManagerService;
 import com.android.server.backup.TransportManager;
-import com.android.server.backup.testing.TransportTestUtils;
 import com.android.server.backup.testing.TransportData;
+import com.android.server.backup.testing.TransportTestUtils;
 import com.android.server.backup.testing.TransportTestUtils.TransportMock;
 import com.android.server.backup.transport.TransportClient;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
 import com.android.server.testing.shadows.ShadowSlog;
 
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 
@@ -69,9 +67,8 @@
 import java.util.List;
 import java.util.stream.Stream;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26, shadows = ShadowSlog.class)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = ShadowSlog.class)
 @Presubmit
 public class PerformInitializeTaskTest {
     @Mock private BackupManagerService mBackupManagerService;
diff --git a/services/robotests/src/com/android/server/backup/keyvalue/AgentExceptionTest.java b/services/robotests/src/com/android/server/backup/keyvalue/AgentExceptionTest.java
index 3730335..b00b922 100644
--- a/services/robotests/src/com/android/server/backup/keyvalue/AgentExceptionTest.java
+++ b/services/robotests/src/com/android/server/backup/keyvalue/AgentExceptionTest.java
@@ -20,29 +20,24 @@
 
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
 import java.io.IOException;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class AgentExceptionTest {
     @Test
-    public void testTransitory_isTransitory() throws Exception {
+    public void testTransitory_isTransitory() {
         AgentException exception = AgentException.transitory();
 
         assertThat(exception.isTransitory()).isTrue();
     }
 
     @Test
-    public void testTransitory_withCause() throws Exception {
+    public void testTransitory_withCause() {
         Exception cause = new IOException();
 
         AgentException exception = AgentException.transitory(cause);
@@ -52,14 +47,14 @@
     }
 
     @Test
-    public void testPermanent_isNotTransitory() throws Exception {
+    public void testPermanent_isNotTransitory() {
         AgentException exception = AgentException.permanent();
 
         assertThat(exception.isTransitory()).isFalse();
     }
 
     @Test
-    public void testPermanent_withCause() throws Exception {
+    public void testPermanent_withCause() {
         Exception cause = new IOException();
 
         AgentException exception = AgentException.permanent(cause);
diff --git a/services/robotests/src/com/android/server/backup/keyvalue/BackupExceptionTest.java b/services/robotests/src/com/android/server/backup/keyvalue/BackupExceptionTest.java
index 5ea74f1..d5603d6 100644
--- a/services/robotests/src/com/android/server/backup/keyvalue/BackupExceptionTest.java
+++ b/services/robotests/src/com/android/server/backup/keyvalue/BackupExceptionTest.java
@@ -20,18 +20,13 @@
 
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
 import java.io.IOException;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class BackupExceptionTest {
     @Test
diff --git a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupReporterTest.java b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupReporterTest.java
index 31e8333..a0afb5e 100644
--- a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupReporterTest.java
+++ b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupReporterTest.java
@@ -27,9 +27,6 @@
 import android.util.Log;
 
 import com.android.server.backup.BackupManagerService;
-import com.android.server.backup.remote.RemoteResult;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
 import com.android.server.testing.shadows.ShadowEventLog;
 import com.android.server.testing.shadows.ShadowSlog;
 
@@ -37,17 +34,11 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowLog;
 
-import java.lang.reflect.Field;
-
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        sdk = 26,
-        shadows = {ShadowEventLog.class, ShadowSlog.class})
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowEventLog.class, ShadowSlog.class})
 @Presubmit
 public class KeyValueBackupReporterTest {
     @Mock private BackupManagerService mBackupManagerService;
@@ -57,33 +48,31 @@
     private KeyValueBackupReporter mReporter;
 
     @Before
-    public void setUp() throws Exception {
+    public void setUp() {
         mReporter = new KeyValueBackupReporter(mBackupManagerService, mObserver, mMonitor);
     }
 
     @Test
-    public void testMoreDebug_isFalse() throws Exception {
-        boolean moreDebug = KeyValueBackupReporter.MORE_DEBUG;
-
-        assertThat(moreDebug).isFalse();
+    public void testMoreDebug_isFalse() {
+        assertThat(KeyValueBackupReporter.MORE_DEBUG).isFalse();
     }
 
     @Test
-    public void testOnNewThread_logsCorrectly() throws Exception {
+    public void testOnNewThread_logsCorrectly() {
         KeyValueBackupReporter.onNewThread("foo");
 
         assertLogcat(TAG, Log.DEBUG);
     }
 
     @Test
-    public void testGetMonitor_returnsMonitor() throws Exception {
+    public void testGetMonitor_returnsMonitor() {
         IBackupManagerMonitor monitor = mReporter.getMonitor();
 
         assertThat(monitor).isEqualTo(mMonitor);
     }
 
     @Test
-    public void testGetObserver_returnsObserver() throws Exception {
+    public void testGetObserver_returnsObserver() {
         IBackupObserver observer = mReporter.getObserver();
 
         assertThat(observer).isEqualTo(mObserver);
diff --git a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
index ba1d83e..a69f007 100644
--- a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
+++ b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
@@ -25,9 +25,12 @@
 import static android.app.backup.ForwardingBackupAgent.forward;
 
 import static com.android.server.backup.testing.BackupManagerServiceTestUtils.createBackupWakeLock;
-import static com.android.server.backup.testing.BackupManagerServiceTestUtils.createInitializedBackupManagerService;
-import static com.android.server.backup.testing.BackupManagerServiceTestUtils.setUpBackupManagerServiceBasics;
-import static com.android.server.backup.testing.BackupManagerServiceTestUtils.setUpBinderCallerAndApplicationAsSystem;
+import static com.android.server.backup.testing.BackupManagerServiceTestUtils
+        .createInitializedBackupManagerService;
+import static com.android.server.backup.testing.BackupManagerServiceTestUtils
+        .setUpBackupManagerServiceBasics;
+import static com.android.server.backup.testing.BackupManagerServiceTestUtils
+        .setUpBinderCallerAndApplicationAsSystem;
 import static com.android.server.backup.testing.PackageData.PM_PACKAGE;
 import static com.android.server.backup.testing.PackageData.fullBackupPackage;
 import static com.android.server.backup.testing.PackageData.keyValuePackage;
@@ -62,8 +65,8 @@
 import static org.mockito.Mockito.when;
 import static org.robolectric.Shadows.shadowOf;
 import static org.robolectric.shadow.api.Shadow.extract;
-import static org.testng.Assert.fail;
 import static org.testng.Assert.expectThrows;
+import static org.testng.Assert.fail;
 
 import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
 import static java.util.Collections.emptyList;
@@ -114,9 +117,6 @@
 import com.android.server.backup.testing.TransportData;
 import com.android.server.backup.testing.TransportTestUtils;
 import com.android.server.backup.testing.TransportTestUtils.TransportMock;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderClasses;
-import com.android.server.testing.SystemLoaderPackages;
 import com.android.server.testing.shadows.FrameworkShadowLooper;
 import com.android.server.testing.shadows.ShadowBackupDataInput;
 import com.android.server.testing.shadows.ShadowBackupDataOutput;
@@ -134,6 +134,7 @@
 import org.mockito.MockitoAnnotations;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowApplication;
@@ -156,10 +157,8 @@
 import java.util.stream.Stream;
 
 // TODO: Test agents timing out
-@RunWith(FrameworkRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
 @Config(
-        manifest = Config.NONE,
-        sdk = 26,
         shadows = {
             FrameworkShadowLooper.class,
             ShadowBackupDataInput.class,
@@ -167,8 +166,6 @@
             ShadowEventLog.class,
             ShadowQueuedWork.class,
         })
-@SystemLoaderPackages({"com.android.server.backup", "android.app.backup"})
-@SystemLoaderClasses({IBackupTransport.class, IBackupAgent.class, PackageInfo.class})
 @Presubmit
 public class KeyValueBackupTaskTest {
     private static final PackageData PACKAGE_1 = keyValuePackage(1);
@@ -187,6 +184,7 @@
     private Handler mBackupHandler;
     private PowerManager.WakeLock mWakeLock;
     private KeyValueBackupReporter mReporter;
+    private PackageManager mPackageManager;
     private ShadowPackageManager mShadowPackageManager;
     private FakeIBackupManager mBackupManager;
     private File mBaseStateDir;
@@ -219,8 +217,8 @@
         mDataDir.mkdirs();
         assertThat(mDataDir.isDirectory()).isTrue();
 
-        PackageManager packageManager = mApplication.getPackageManager();
-        mShadowPackageManager = shadowOf(packageManager);
+        mPackageManager = mApplication.getPackageManager();
+        mShadowPackageManager = shadowOf(mPackageManager);
 
         mWakeLock = createBackupWakeLock(mApplication);
         mBackupManager = spy(FakeIBackupManager.class);
@@ -235,7 +233,7 @@
                 mBackupManagerService,
                 mApplication,
                 mTransportManager,
-                packageManager,
+                mPackageManager,
                 mBackupManagerService.getBackupHandler(),
                 mWakeLock,
                 mBackupManagerService.getAgentTimeoutParameters());
@@ -332,6 +330,22 @@
                 .isEqualTo("packageState".getBytes());
     }
 
+    /**
+     * Do not update backup token if the backup queue was empty
+     */
+    @Test
+    public void testRunTask_whenQueueEmptyOnFirstBackup_doesNotUpdateCurrentToken()
+            throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, true);
+        mBackupManagerService.setCurrentToken(0L);
+        when(transportMock.transport.getCurrentRestoreSet()).thenReturn(1234L);
+
+        runTask(task);
+
+        assertThat(mBackupManagerService.getCurrentToken()).isEqualTo(0L);
+    }
+
     @Test
     public void testRunTask_whenOnePackageAndTransportUnavailable() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport.unavailable());
@@ -2302,6 +2316,24 @@
         expectThrows(IllegalArgumentException.class, () -> task.handleCancel(false));
     }
 
+    /**
+     * Do not update backup token if no data was moved.
+     */
+    @Test
+    public void testRunTask_whenNoDataToBackupOnFirstBackup_doesNotUpdateCurrentToken()
+            throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        mBackupManagerService.setCurrentToken(0L);
+        when(transportMock.transport.getCurrentRestoreSet()).thenReturn(1234L);
+        // Set up agent with no data.
+        setUpAgent(PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, true, PACKAGE_1);
+
+        runTask(task);
+
+        assertThat(mBackupManagerService.getCurrentToken()).isEqualTo(0L);
+    }
+
     private void runTask(KeyValueBackupTask task) {
         // Pretend we are not on the main-thread to prevent RemoteCall from complaining
         mShadowMainLooper.setCurrentThread(false);
@@ -2406,7 +2438,7 @@
 
     private AgentMock setUpAgent(PackageData packageData) {
         try {
-            mShadowPackageManager.setApplicationEnabledSetting(
+            mPackageManager.setApplicationEnabledSetting(
                     packageData.packageName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
             PackageInfo packageInfo = getPackageInfo(packageData);
             mShadowPackageManager.addPackage(packageInfo);
diff --git a/services/robotests/src/com/android/server/backup/keyvalue/TaskExceptionTest.java b/services/robotests/src/com/android/server/backup/keyvalue/TaskExceptionTest.java
index 4b79657..3698b79 100644
--- a/services/robotests/src/com/android/server/backup/keyvalue/TaskExceptionTest.java
+++ b/services/robotests/src/com/android/server/backup/keyvalue/TaskExceptionTest.java
@@ -23,18 +23,13 @@
 import android.app.backup.BackupTransport;
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
 import java.io.IOException;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class TaskExceptionTest {
     @Test
diff --git a/services/robotests/src/com/android/server/backup/remote/FutureBackupCallbackTest.java b/services/robotests/src/com/android/server/backup/remote/FutureBackupCallbackTest.java
index f3621e2..5ac26f4 100644
--- a/services/robotests/src/com/android/server/backup/remote/FutureBackupCallbackTest.java
+++ b/services/robotests/src/com/android/server/backup/remote/FutureBackupCallbackTest.java
@@ -20,18 +20,13 @@
 
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
 import java.util.concurrent.CompletableFuture;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class FutureBackupCallbackTest {
     @Test
diff --git a/services/robotests/src/com/android/server/backup/remote/RemoteCallTest.java b/services/robotests/src/com/android/server/backup/remote/RemoteCallTest.java
index 1d92bed..7ec2a4e 100644
--- a/services/robotests/src/com/android/server/backup/remote/RemoteCallTest.java
+++ b/services/robotests/src/com/android/server/backup/remote/RemoteCallTest.java
@@ -32,23 +32,19 @@
 import android.platform.test.annotations.Presubmit;
 
 import com.android.server.backup.testing.TestUtils.ThrowingRunnable;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
 import java.util.concurrent.Callable;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.Future;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class RemoteCallTest {
     /** A {@link RemoteCallable} that calls the callback immediately. */
@@ -267,9 +263,4 @@
     private static void postDelayed(Handler handler, ThrowingRunnable runnable, long delayMillis) {
         handler.postDelayed(() -> uncheck(runnable), delayMillis);
     }
-
-    /** Unchecked version of {@link Handler#post(Runnable)}. */
-    private static void post(Handler handler, ThrowingRunnable runnable) {
-        handler.post(() -> uncheck(runnable));
-    }
 }
diff --git a/services/robotests/src/com/android/server/backup/remote/RemoteResultTest.java b/services/robotests/src/com/android/server/backup/remote/RemoteResultTest.java
index 7f6fd57..b9a77fb 100644
--- a/services/robotests/src/com/android/server/backup/remote/RemoteResultTest.java
+++ b/services/robotests/src/com/android/server/backup/remote/RemoteResultTest.java
@@ -22,16 +22,11 @@
 
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class RemoteResultTest {
     @Test
diff --git a/services/robotests/src/com/android/server/backup/remote/ServiceBackupCallbackTest.java b/services/robotests/src/com/android/server/backup/remote/ServiceBackupCallbackTest.java
index e0d3c0c..38a54da 100644
--- a/services/robotests/src/com/android/server/backup/remote/ServiceBackupCallbackTest.java
+++ b/services/robotests/src/com/android/server/backup/remote/ServiceBackupCallbackTest.java
@@ -22,16 +22,11 @@
 import android.app.backup.IBackupManager;
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class ServiceBackupCallbackTest {
     @Test
diff --git a/services/robotests/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java b/services/robotests/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java
index 2717120..0e2b95b 100644
--- a/services/robotests/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java
+++ b/services/robotests/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java
@@ -19,7 +19,6 @@
 import static com.android.server.backup.testing.BackupManagerServiceTestUtils.createBackupWakeLock;
 import static com.android.server.backup.testing.BackupManagerServiceTestUtils.setUpBackupManagerServiceBasics;
 import static com.android.server.backup.testing.BackupManagerServiceTestUtils.startBackupThreadAndGetLooper;
-
 import static com.android.server.backup.testing.TestUtils.assertEventLogged;
 import static com.android.server.backup.testing.TestUtils.assertEventNotLogged;
 import static com.android.server.backup.testing.TransportData.backupTransport;
@@ -58,8 +57,6 @@
 import com.android.server.backup.testing.TransportData;
 import com.android.server.backup.testing.TransportTestUtils;
 import com.android.server.backup.testing.TransportTestUtils.TransportMock;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
 import com.android.server.testing.shadows.ShadowEventLog;
 import com.android.server.testing.shadows.ShadowPerformUnifiedRestoreTask;
 
@@ -69,6 +66,7 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowApplication;
@@ -78,18 +76,14 @@
 
 import java.util.ArrayDeque;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        sdk = 26,
-        shadows = {ShadowEventLog.class, ShadowPerformUnifiedRestoreTask.class, ShadowBinder.class})
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowEventLog.class, ShadowPerformUnifiedRestoreTask.class, ShadowBinder.class})
 @Presubmit
 public class ActiveRestoreSessionTest {
     private static final String PACKAGE_1 = "com.example.package1";
     private static final String PACKAGE_2 = "com.example.package2";
-    public static final long TOKEN_1 = 1L;
-    public static final long TOKEN_2 = 2L;
+    private static final long TOKEN_1 = 1L;
+    private static final long TOKEN_2 = 2L;
 
     @Mock private BackupManagerService mBackupManagerService;
     @Mock private TransportManager mTransportManager;
diff --git a/services/robotests/src/com/android/server/backup/transport/TransportClientManagerTest.java b/services/robotests/src/com/android/server/backup/transport/TransportClientManagerTest.java
index bbec7af..7dd0d92 100644
--- a/services/robotests/src/com/android/server/backup/transport/TransportClientManagerTest.java
+++ b/services/robotests/src/com/android/server/backup/transport/TransportClientManagerTest.java
@@ -17,6 +17,7 @@
 package com.android.server.backup.transport;
 
 import static com.android.server.backup.TransportManager.SERVICE_ACTION_TRANSPORT_HOST;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.argThat;
@@ -32,19 +33,15 @@
 import android.os.UserHandle;
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentMatcher;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class TransportClientManagerTest {
     private static final String PACKAGE_NAME = "random.package.name";
diff --git a/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java b/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java
index f843b50..7281a3c 100644
--- a/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java
+++ b/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java
@@ -49,8 +49,6 @@
 
 import com.android.internal.backup.IBackupTransport;
 import com.android.server.EventLogTags;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
 import com.android.server.testing.shadows.FrameworkShadowLooper;
 import com.android.server.testing.shadows.ShadowCloseGuard;
 import com.android.server.testing.shadows.ShadowEventLog;
@@ -62,6 +60,7 @@
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowLog;
 import org.robolectric.shadows.ShadowLooper;
@@ -69,17 +68,13 @@
 import java.util.concurrent.CompletableFuture;
 import java.util.function.Supplier;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        sdk = 26,
-        shadows = {
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {
             ShadowEventLog.class,
             ShadowCloseGuard.class,
             ShadowSlog.class,
             FrameworkShadowLooper.class
         })
-@SystemLoaderPackages({"com.android.server.backup"})
 @Presubmit
 public class TransportClientTest {
     private static final String PACKAGE_NAME = "some.package.name";
@@ -137,7 +132,7 @@
     }
 
     @Test
-    public void testConnectAsync_callsBindService() throws Exception {
+    public void testConnectAsync_callsBindService() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller");
 
         verify(mContext)
@@ -149,7 +144,7 @@
     }
 
     @Test
-    public void testConnectAsync_callsListenerWhenConnected() throws Exception {
+    public void testConnectAsync_callsListenerWhenConnected() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
 
@@ -161,8 +156,7 @@
     }
 
     @Test
-    public void testConnectAsync_whenPendingConnection_callsAllListenersWhenConnected()
-            throws Exception {
+    public void testConnectAsync_whenPendingConnection_callsAllListenersWhenConnected() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
 
@@ -177,7 +171,7 @@
     }
 
     @Test
-    public void testConnectAsync_whenAlreadyConnected_callsListener() throws Exception {
+    public void testConnectAsync_whenAlreadyConnected_callsListener() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
         connection.onServiceConnected(mTransportComponent, mTransportBinder);
@@ -190,7 +184,7 @@
     }
 
     @Test
-    public void testConnectAsync_whenFrameworkDoesntBind_callsListener() throws Exception {
+    public void testConnectAsync_whenFrameworkDoesntBind_callsListener() {
         when(mContext.bindServiceAsUser(
                         eq(mBindIntent),
                         any(ServiceConnection.class),
@@ -206,7 +200,7 @@
     }
 
     @Test
-    public void testConnectAsync_whenFrameworkDoesNotBind_releasesConnection() throws Exception {
+    public void testConnectAsync_whenFrameworkDoesNotBind_releasesConnection() {
         when(mContext.bindServiceAsUser(
                         eq(mBindIntent),
                         any(ServiceConnection.class),
@@ -221,8 +215,7 @@
     }
 
     @Test
-    public void testConnectAsync_afterOnServiceDisconnectedBeforeNewConnection_callsListener()
-            throws Exception {
+    public void testConnectAsync_afterOnServiceDisconnectedBeforeNewConnection_callsListener() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
         connection.onServiceConnected(mTransportComponent, mTransportBinder);
@@ -235,8 +228,7 @@
     }
 
     @Test
-    public void testConnectAsync_afterOnServiceDisconnectedAfterNewConnection_callsListener()
-            throws Exception {
+    public void testConnectAsync_afterOnServiceDisconnectedAfterNewConnection_callsListener() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
         connection.onServiceConnected(mTransportComponent, mTransportBinder);
@@ -251,7 +243,7 @@
     }
 
     @Test
-    public void testConnectAsync_callsListenerIfBindingDies() throws Exception {
+    public void testConnectAsync_callsListenerIfBindingDies() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
 
@@ -263,8 +255,7 @@
     }
 
     @Test
-    public void testConnectAsync_whenPendingConnection_callsListenersIfBindingDies()
-            throws Exception {
+    public void testConnectAsync_whenPendingConnection_callsListenersIfBindingDies() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
 
@@ -412,14 +403,14 @@
     }
 
     @Test
-    public void testMarkAsDisposed_whenCreated() throws Throwable {
+    public void testMarkAsDisposed_whenCreated() {
         mTransportClient.markAsDisposed();
 
         // No exception thrown
     }
 
     @Test
-    public void testMarkAsDisposed_afterOnBindingDied() throws Throwable {
+    public void testMarkAsDisposed_afterOnBindingDied() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
         connection.onBindingDied(mTransportComponent);
@@ -430,7 +421,7 @@
     }
 
     @Test
-    public void testMarkAsDisposed_whenConnectedAndUnbound() throws Throwable {
+    public void testMarkAsDisposed_whenConnectedAndUnbound() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
         connection.onServiceConnected(mTransportComponent, mTransportBinder);
@@ -442,7 +433,7 @@
     }
 
     @Test
-    public void testMarkAsDisposed_afterOnServiceDisconnected() throws Throwable {
+    public void testMarkAsDisposed_afterOnServiceDisconnected() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
         connection.onServiceConnected(mTransportComponent, mTransportBinder);
@@ -454,14 +445,14 @@
     }
 
     @Test
-    public void testMarkAsDisposed_whenBound() throws Throwable {
+    public void testMarkAsDisposed_whenBound() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
 
         expectThrows(RuntimeException.class, mTransportClient::markAsDisposed);
     }
 
     @Test
-    public void testMarkAsDisposed_whenConnected() throws Throwable {
+    public void testMarkAsDisposed_whenConnected() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
         connection.onServiceConnected(mTransportComponent, mTransportBinder);
diff --git a/services/robotests/src/com/android/server/backup/transport/TransportStatsTest.java b/services/robotests/src/com/android/server/backup/transport/TransportStatsTest.java
index 322db85..f01a6b0 100644
--- a/services/robotests/src/com/android/server/backup/transport/TransportStatsTest.java
+++ b/services/robotests/src/com/android/server/backup/transport/TransportStatsTest.java
@@ -25,17 +25,13 @@
 import android.platform.test.annotations.Presubmit;
 
 import com.android.server.backup.transport.TransportStats.Stats;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class TransportStatsTest {
     private static final double TOLERANCE = 0.0001;
diff --git a/services/robotests/src/com/android/server/location/GnssBatchingProviderTest.java b/services/robotests/src/com/android/server/location/GnssBatchingProviderTest.java
index 5046094..d58c3f7 100644
--- a/services/robotests/src/com/android/server/location/GnssBatchingProviderTest.java
+++ b/services/robotests/src/com/android/server/location/GnssBatchingProviderTest.java
@@ -1,9 +1,10 @@
 package com.android.server.location;
 
 import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.eq;
+
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -11,27 +12,18 @@
 import android.platform.test.annotations.Presubmit;
 
 import com.android.server.location.GnssBatchingProvider.GnssBatchingProviderNative;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
 /**
  * Unit tests for {@link GnssBatchingProvider}.
  */
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        shadows = {
-        },
-        sdk = 27
-)
-@SystemLoaderPackages({"com.android.server.location"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class GnssBatchingProviderTest {
 
diff --git a/services/robotests/src/com/android/server/location/GnssGeofenceProviderTest.java b/services/robotests/src/com/android/server/location/GnssGeofenceProviderTest.java
index 187303c..beb5941 100644
--- a/services/robotests/src/com/android/server/location/GnssGeofenceProviderTest.java
+++ b/services/robotests/src/com/android/server/location/GnssGeofenceProviderTest.java
@@ -1,8 +1,8 @@
 package com.android.server.location;
 
-import static org.mockito.Matchers.anyDouble;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.anyDouble;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -11,25 +11,17 @@
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
 /**
  * Unit tests for {@link GnssGeofenceProvider}.
  */
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        sdk = 27
-)
-@SystemLoaderPackages({"com.android.server.location"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class GnssGeofenceProviderTest {
     private static final int GEOFENCE_ID = 12345;
diff --git a/services/robotests/src/com/android/server/location/GnssMeasurementsProviderTest.java b/services/robotests/src/com/android/server/location/GnssMeasurementsProviderTest.java
index 23d6cf6..b349b67 100644
--- a/services/robotests/src/com/android/server/location/GnssMeasurementsProviderTest.java
+++ b/services/robotests/src/com/android/server/location/GnssMeasurementsProviderTest.java
@@ -1,6 +1,7 @@
 package com.android.server.location;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -10,26 +11,18 @@
 import android.os.Looper;
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
 /**
  * Unit tests for {@link GnssMeasurementsProvider}.
  */
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        sdk = 27
-)
-@SystemLoaderPackages({"com.android.server.location"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class GnssMeasurementsProviderTest {
     @Mock
diff --git a/services/robotests/src/com/android/server/location/GnssNavigationMessageProviderTest.java b/services/robotests/src/com/android/server/location/GnssNavigationMessageProviderTest.java
index 8d3de3c..59e9a15 100644
--- a/services/robotests/src/com/android/server/location/GnssNavigationMessageProviderTest.java
+++ b/services/robotests/src/com/android/server/location/GnssNavigationMessageProviderTest.java
@@ -10,25 +10,17 @@
 import android.os.Looper;
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
 /**
  * Unit tests for {@link GnssNavigationMessageProvider}.
  */
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        sdk = 27
-)
-@SystemLoaderPackages({"com.android.server.location"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class GnssNavigationMessageProviderTest {
     @Mock
diff --git a/services/robotests/src/com/android/server/location/GnssPositionModeTest.java b/services/robotests/src/com/android/server/location/GnssPositionModeTest.java
index e6d53551..f37f50e 100644
--- a/services/robotests/src/com/android/server/location/GnssPositionModeTest.java
+++ b/services/robotests/src/com/android/server/location/GnssPositionModeTest.java
@@ -4,24 +4,16 @@
 
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
 import java.util.HashSet;
 
 /**
  * Unit tests for {@link GnssPositionMode}.
  */
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        sdk = 27
-)
-@SystemLoaderPackages({"com.android.server.location"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class GnssPositionModeTest {
 
diff --git a/services/robotests/src/com/android/server/location/GnssSatelliteBlacklistHelperTest.java b/services/robotests/src/com/android/server/location/GnssSatelliteBlacklistHelperTest.java
index d6f5446..ba4a753 100644
--- a/services/robotests/src/com/android/server/location/GnssSatelliteBlacklistHelperTest.java
+++ b/services/robotests/src/com/android/server/location/GnssSatelliteBlacklistHelperTest.java
@@ -2,7 +2,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.Matchers.any;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 
@@ -13,18 +13,15 @@
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.Shadows;
-import org.robolectric.annotation.Config;
 
 import java.util.Collection;
 import java.util.List;
@@ -32,18 +29,10 @@
 /**
  * Unit tests for {@link GnssSatelliteBlacklistHelper}.
  */
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        shadows = {
-        },
-        sdk = 27
-)
-@SystemLoaderPackages({"com.android.server.location"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class GnssSatelliteBlacklistHelperTest {
 
-    private Context mContext;
     private ContentResolver mContentResolver;
     @Mock
     private GnssSatelliteBlacklistHelper.GnssSatelliteBlacklistCallback mCallback;
@@ -51,9 +40,9 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mContext = RuntimeEnvironment.application;
-        mContentResolver = mContext.getContentResolver();
-        new GnssSatelliteBlacklistHelper(mContext, Looper.myLooper(), mCallback);
+        Context context = RuntimeEnvironment.application;
+        mContentResolver = context.getContentResolver();
+        new GnssSatelliteBlacklistHelper(context, Looper.myLooper(), mCallback);
     }
 
     @Test
diff --git a/services/robotests/src/com/android/server/location/NtpTimeHelperTest.java b/services/robotests/src/com/android/server/location/NtpTimeHelperTest.java
index a68b579..aac0a34 100644
--- a/services/robotests/src/com/android/server/location/NtpTimeHelperTest.java
+++ b/services/robotests/src/com/android/server/location/NtpTimeHelperTest.java
@@ -9,16 +9,14 @@
 import android.util.NtpTrustedTime;
 
 import com.android.server.location.NtpTimeHelper.InjectNtpTimeCallback;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowLooper;
 import org.robolectric.shadows.ShadowSystemClock;
 
@@ -28,12 +26,7 @@
 /**
  * Unit tests for {@link NtpTimeHelper}.
  */
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        sdk = 27
-)
-@SystemLoaderPackages({"com.android.server.location"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class NtpTimeHelperTest {
 
diff --git a/services/robotests/src/com/android/server/testing/FrameworkRobolectricTestRunner.java b/services/robotests/src/com/android/server/testing/FrameworkRobolectricTestRunner.java
deleted file mode 100644
index d2a4d06..0000000
--- a/services/robotests/src/com/android/server/testing/FrameworkRobolectricTestRunner.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * 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.testing;
-
-import static java.util.Arrays.asList;
-
-import com.google.common.collect.ImmutableSet;
-
-import org.junit.runners.model.FrameworkMethod;
-import org.junit.runners.model.InitializationError;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.internal.SandboxFactory;
-import org.robolectric.internal.SdkEnvironment;
-import org.robolectric.internal.bytecode.InstrumentationConfiguration;
-import org.robolectric.internal.bytecode.SandboxClassLoader;
-import org.robolectric.util.Util;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.Arrays;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.stream.Stream;
-
-import javax.annotation.Nonnull;
-
-/**
- * HACK
- * Robolectric loads up Android environment from prebuilt android jars before running a method.
- * These jars are versioned according to the SDK level configured for the method (or class). The
- * jars represent a snapshot of the Android APIs in that SDK level. For Robolectric tests that are
- * testing Android components themselves we don't want certain classes (usually the
- * class-under-test) to be loaded from the prebuilt jar, we want it instead to be loaded from the
- * dependencies of our test target, i.e. the system class loader. That way we can write tests
- * against the actual classes that are in the tree, not a past version of them. Ideally we would
- * have a locally built jar referenced by Robolectric, but until that happens one can use this
- * class.
- * This class reads the {@link SystemLoaderClasses} or {@link SystemLoaderPackages} annotations on
- * test classes, for classes that match the annotations it will bypass the android jar and load it
- * from the system class loader. Allowing the test to test the actual class in the tree.
- *
- * Implementation note: One could think about overriding
- * {@link RobolectricTestRunner#createClassLoaderConfig(FrameworkMethod)} method and putting the
- * classes in the annotation in the {@link InstrumentationConfiguration} list of classes not to
- * acquire. Unfortunately, this will not work because we will not be instrumenting the class.
- * Instead, we have to load the class bytes from the system class loader but still instrument it, we
- * do this by overriding {@link SandboxClassLoader#getByteCode(String)} and loading the class bytes
- * from the system class loader if it in the {@link SystemLoaderClasses} annotation. This way the
- * {@link SandboxClassLoader} still instruments the class, but it's not loaded from the android jar.
- * Finally, we inject the custom class loader in place of the default one.
- *
- * TODO: Remove this when we are using locally built android jars in the method's environment.
- */
-public class FrameworkRobolectricTestRunner extends RobolectricTestRunner {
-    private final SandboxFactory mSandboxFactory;
-
-    public FrameworkRobolectricTestRunner(Class<?> testClass) throws InitializationError {
-        super(testClass);
-        Set<String> classPrefixes = getSystemLoaderClassPrefixes(testClass);
-        mSandboxFactory = new FrameworkSandboxFactory(classPrefixes);
-    }
-
-    private Set<String> getSystemLoaderClassPrefixes(Class<?> testClass) {
-        Set<String> classPrefixes = new HashSet<>();
-        SystemLoaderClasses byClass = testClass.getAnnotation(SystemLoaderClasses.class);
-        if (byClass != null) {
-            Stream.of(byClass.value()).map(Class::getName).forEach(classPrefixes::add);
-        }
-        SystemLoaderPackages byPackage = testClass.getAnnotation(SystemLoaderPackages.class);
-        if (byPackage != null) {
-            classPrefixes.addAll(asList(byPackage.value()));
-        }
-        return classPrefixes;
-    }
-
-    @Nonnull
-    @Override
-    protected SdkEnvironment getSandbox(FrameworkMethod method) {
-        // HACK: Calling super just to get SdkConfig via sandbox.getSdkConfig(), because
-        // RobolectricFrameworkMethod, the runtime class of method, is package-protected
-        SdkEnvironment sandbox = super.getSandbox(method);
-        return mSandboxFactory.getSdkEnvironment(
-                createClassLoaderConfig(method),
-                getJarResolver(),
-                sandbox.getSdkConfig());
-    }
-
-    private static class FrameworkClassLoader extends SandboxClassLoader {
-        private final Set<String> mSystemLoaderClassPrefixes;
-
-        private FrameworkClassLoader(
-                Set<String> systemLoaderClassPrefixes,
-                ClassLoader systemClassLoader,
-                InstrumentationConfiguration instrumentationConfig,
-                URL... urls) {
-            super(systemClassLoader, instrumentationConfig, urls);
-            mSystemLoaderClassPrefixes = systemLoaderClassPrefixes;
-        }
-
-        @Override
-        protected byte[] getByteCode(String className) throws ClassNotFoundException {
-            String classFileName = className.replace('.', '/') + ".class";
-            if (shouldLoadFromSystemLoader(className)) {
-                try (InputStream classByteStream = getResourceAsStream(classFileName)) {
-                    if (classByteStream == null) {
-                        throw new ClassNotFoundException(className);
-                    }
-                    return Util.readBytes(classByteStream);
-                } catch (IOException e) {
-                    throw new ClassNotFoundException(
-                            "Couldn't load " + className + " from system class loader", e);
-                }
-            }
-            return super.getByteCode(className);
-        }
-
-        /**
-         * HACK^2
-         * The framework Robolectric run configuration puts a prebuilt in front of us, so we try not
-         * to load the class from there, if possible.
-         */
-        @Override
-        public InputStream getResourceAsStream(String resource) {
-            try {
-                Enumeration<URL> urls = getResources(resource);
-                while (urls.hasMoreElements()) {
-                    URL url = urls.nextElement();
-                    if (!url.toString().toLowerCase().contains("prebuilt")) {
-                        return url.openStream();
-                    }
-                }
-            } catch (IOException e) {
-                // Fall through
-            }
-            return super.getResourceAsStream(resource);
-        }
-
-        /**
-         * Classes like com.package.ClassName$InnerClass should also be loaded from the system class
-         * loader, so we test if the classes in the annotation are prefixes of the class to load.
-         */
-        private boolean shouldLoadFromSystemLoader(String className) {
-            for (String classPrefix : mSystemLoaderClassPrefixes) {
-                if (className.startsWith(classPrefix)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-    }
-
-    private static class FrameworkSandboxFactory extends SandboxFactory {
-        private final Set<String> mSystemLoaderClassPrefixes;
-
-        private FrameworkSandboxFactory(Set<String> systemLoaderClassPrefixes) {
-            mSystemLoaderClassPrefixes = systemLoaderClassPrefixes;
-        }
-
-        @Nonnull
-        @Override
-        public ClassLoader createClassLoader(
-                InstrumentationConfiguration instrumentationConfig, URL... urls) {
-            return new FrameworkClassLoader(
-                    mSystemLoaderClassPrefixes,
-                    ClassLoader.getSystemClassLoader(),
-                    instrumentationConfig,
-                    urls);
-        }
-    }
-}
diff --git a/services/robotests/src/com/android/server/testing/SystemLoaderClasses.java b/services/robotests/src/com/android/server/testing/SystemLoaderClasses.java
deleted file mode 100644
index 646a413..0000000
--- a/services/robotests/src/com/android/server/testing/SystemLoaderClasses.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.testing;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation to be used in test classes that run with {@link FrameworkRobolectricTestRunner}.
- * This will make the classes specified be loaded from the system class loader, NOT from the
- * Robolectric android jar.
- *
- * @see FrameworkRobolectricTestRunner
- */
-@Target(ElementType.TYPE)
-@Retention(RetentionPolicy.RUNTIME)
-public @interface SystemLoaderClasses {
-    Class<?>[] value() default {};
-}
diff --git a/services/robotests/src/com/android/server/testing/SystemLoaderPackages.java b/services/robotests/src/com/android/server/testing/SystemLoaderPackages.java
deleted file mode 100644
index e01c0a4..0000000
--- a/services/robotests/src/com/android/server/testing/SystemLoaderPackages.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2018 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.testing;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation to be used in test classes that run with {@link FrameworkRobolectricTestRunner}.
- * This will make the classes under the specified packages be loaded from the system class loader,
- * NOT from the Robolectric android jar.
- *
- * @see FrameworkRobolectricTestRunner
- */
-@Target(ElementType.TYPE)
-@Retention(RetentionPolicy.RUNTIME)
-public @interface SystemLoaderPackages {
-    String[] value() default {};
-}
diff --git a/services/robotests/src/com/android/server/testing/shadows/FrameworkShadowContextImpl.java b/services/robotests/src/com/android/server/testing/shadows/FrameworkShadowContextImpl.java
deleted file mode 100644
index 6d22073..0000000
--- a/services/robotests/src/com/android/server/testing/shadows/FrameworkShadowContextImpl.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2018 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.testing.shadows;
-
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.UserHandle;
-
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-import org.robolectric.shadows.ShadowContextImpl;
-
-@Implements(className = ShadowContextImpl.CLASS_NAME, inheritImplementationMethods = true)
-public class FrameworkShadowContextImpl extends ShadowContextImpl {
-    @Implementation
-    public boolean bindServiceAsUser(
-            Intent service,
-            ServiceConnection connection,
-            int flags,
-            UserHandle user) {
-        return bindService(service, connection, flags);
-    }
-}
diff --git a/services/robotests/src/com/android/server/testing/shadows/FrameworkShadowLooper.java b/services/robotests/src/com/android/server/testing/shadows/FrameworkShadowLooper.java
index c0eeb38..16d16cd 100644
--- a/services/robotests/src/com/android/server/testing/shadows/FrameworkShadowLooper.java
+++ b/services/robotests/src/com/android/server/testing/shadows/FrameworkShadowLooper.java
@@ -25,7 +25,7 @@
 
 import java.util.Optional;
 
-@Implements(value = Looper.class, inheritImplementationMethods = true)
+@Implements(value = Looper.class)
 public class FrameworkShadowLooper extends ShadowLooper {
     @RealObject private Looper mLooper;
     private Optional<Boolean> mIsCurrentThread = Optional.empty();
@@ -39,7 +39,7 @@
     }
 
     @Implementation
-    public boolean isCurrentThread() {
+    protected boolean isCurrentThread() {
         if (mIsCurrentThread.isPresent()) {
             return mIsCurrentThread.get();
         }
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowAppBackupUtils.java b/services/robotests/src/com/android/server/testing/shadows/ShadowAppBackupUtils.java
index 21faa09..5fffb14 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowAppBackupUtils.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowAppBackupUtils.java
@@ -26,6 +26,7 @@
 
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.Resetter;
 
 import java.util.HashSet;
 import java.util.Set;
@@ -52,21 +53,22 @@
     }
 
     @Implementation
-    public static boolean appIsRunningAndEligibleForBackupWithTransport(
+    protected static boolean appIsRunningAndEligibleForBackupWithTransport(
             @Nullable TransportClient transportClient, String packageName, PackageManager pm) {
         return sAppsRunningAndEligibleForBackupWithTransport.contains(packageName);
     }
 
     @Implementation
-    public static boolean appIsEligibleForBackup(ApplicationInfo app, PackageManager pm) {
+    protected static boolean appIsEligibleForBackup(ApplicationInfo app, PackageManager pm) {
         return sAppsEligibleForBackup.contains(app.packageName);
     }
 
     @Implementation
-    public static boolean appGetsFullBackup(PackageInfo packageInfo) {
+    protected static boolean appGetsFullBackup(PackageInfo packageInfo) {
         return sAppsGetFullBackup.contains(packageInfo.packageName);
     }
 
+    @Resetter
     public static void reset() {
         sAppsRunningAndEligibleForBackupWithTransport.clear();
         sAppsEligibleForBackup.clear();
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataInput.java b/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataInput.java
index 4901828..e7d2a68 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataInput.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataInput.java
@@ -52,12 +52,12 @@
     private boolean mHeaderReady;
 
     @Implementation
-    public void __constructor__(FileDescriptor fd) {
+    protected void __constructor__(FileDescriptor fd) {
         mFileDescriptor = fd;
     }
 
     @Implementation
-    public boolean readNextHeader() throws IOException {
+    protected boolean readNextHeader() throws IOException {
         if (sReadNextHeaderThrow) {
             sReadNextHeaderThrow = false;
             throw new IOException("Fake exception");
@@ -75,19 +75,19 @@
     }
 
     @Implementation
-    public String getKey() {
+    protected String getKey() {
         checkHeaderReady();
         return mKey;
     }
 
     @Implementation
-    public int getDataSize() {
+    protected int getDataSize() {
         checkHeaderReady();
         return mSize;
     }
 
     @Implementation
-    public int readEntityData(byte[] data, int offset, int size) throws IOException {
+    protected int readEntityData(byte[] data, int offset, int size) throws IOException {
         checkHeaderReady();
         int result = mInput.read(data, offset, size);
         if (result < 0) {
@@ -97,7 +97,7 @@
     }
 
     @Implementation
-    public void skipEntityData() throws IOException {
+    protected void skipEntityData() throws IOException {
         checkHeaderReady();
         mInput.read(new byte[mSize], 0, mSize);
     }
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataOutput.java b/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataOutput.java
index 5812c3c..4aef28c 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataOutput.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataOutput.java
@@ -39,19 +39,19 @@
     private int mTransportFlags;
 
     @Implementation
-    public void __constructor__(FileDescriptor fd, long quota, int transportFlags) {
+    protected void __constructor__(FileDescriptor fd, long quota, int transportFlags) {
         mFileDescriptor = fd;
         mQuota = quota;
         mTransportFlags = transportFlags;
     }
 
     @Implementation
-    public long getQuota() {
+    protected long getQuota() {
         return mQuota;
     }
 
     @Implementation
-    public int getTransportFlags() {
+    protected int getTransportFlags() {
         return mTransportFlags;
     }
 
@@ -61,7 +61,7 @@
     }
 
     @Implementation
-    public int writeEntityHeader(String key, int dataSize) throws IOException {
+    protected int writeEntityHeader(String key, int dataSize) throws IOException {
         ensureOutput();
         final int size;
         try (ByteArrayOutputStream byteStream = new ByteArrayOutputStream()) {
@@ -81,7 +81,7 @@
     }
 
     @Implementation
-    public int writeEntityData(byte[] data, int size) throws IOException {
+    protected int writeEntityData(byte[] data, int size) throws IOException {
         ensureOutput();
         mOutput.write(data, 0, size);
         mOutput.flush();
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowBinder.java b/services/robotests/src/com/android/server/testing/shadows/ShadowBinder.java
index 043d44b..1ece49e 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowBinder.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowBinder.java
@@ -17,6 +17,7 @@
 package com.android.server.testing.shadows;
 
 import android.os.Binder;
+
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
 
@@ -31,14 +32,14 @@
     private static Integer originalCallingUid;
 
     @Implementation
-    public static long clearCallingIdentity() {
+    protected static long clearCallingIdentity() {
         originalCallingUid = getCallingUid();
         setCallingUid(LOCAL_UID);
         return 1L;
     }
 
     @Implementation
-    public static void restoreCallingIdentity(long token) {
+    protected static void restoreCallingIdentity(long token) {
         setCallingUid(originalCallingUid);
     }
 }
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowEventLog.java b/services/robotests/src/com/android/server/testing/shadows/ShadowEventLog.java
index 3df1723..5d9c88b 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowEventLog.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowEventLog.java
@@ -32,14 +32,14 @@
     private static final LinkedHashSet<Entry> ENTRIES = new LinkedHashSet<>();
 
     @Implementation
-    public static int writeEvent(int tag, Object... values) {
+    protected static int writeEvent(int tag, Object... values) {
         ENTRIES.add(new Entry(tag, Arrays.asList(values)));
         // Currently we don't care about the return value, if we do, estimate it correctly
         return 0;
     }
 
     @Implementation
-    public static int writeEvent(int tag, String string) {
+    protected static int writeEvent(int tag, String string) {
         return writeEvent(tag, (Object) string);
     }
 
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowFullBackup.java b/services/robotests/src/com/android/server/testing/shadows/ShadowFullBackup.java
index 3c913e3..4756476 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowFullBackup.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowFullBackup.java
@@ -31,7 +31,7 @@
      * implementation.
      */
     @Implementation
-    public static int backupToTar(
+    protected static int backupToTar(
             String packageName,
             String domain,
             String linkdomain,
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupJob.java b/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupJob.java
index 3941f17..23c44b0 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupJob.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupJob.java
@@ -18,8 +18,10 @@
 
 import android.content.Context;
 import android.os.Binder;
+
 import com.android.server.backup.BackupManagerConstants;
 import com.android.server.backup.KeyValueBackupJob;
+
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
 
@@ -32,7 +34,7 @@
     }
 
     @Implementation
-    public static void schedule(Context ctx, long delay, BackupManagerConstants constants) {
+    protected static void schedule(Context ctx, long delay, BackupManagerConstants constants) {
         callingUid = Binder.getCallingUid();
     }
 }
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupTask.java b/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupTask.java
index b7db56b..ca80664 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupTask.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupTask.java
@@ -53,7 +53,7 @@
     private List<String> mPendingFullBackups;
 
     @Implementation
-    public void __constructor__(
+    protected void __constructor__(
             BackupManagerService backupManagerService,
             TransportClient transportClient,
             String transportDirName,
@@ -71,7 +71,7 @@
     }
 
     @Implementation
-    public void execute() {
+    protected void execute() {
         mListener.onFinished("ShadowKeyValueBackupTask.execute()");
     }
 
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowPerformUnifiedRestoreTask.java b/services/robotests/src/com/android/server/testing/shadows/ShadowPerformUnifiedRestoreTask.java
index 0f93c7a..228d4eb 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowPerformUnifiedRestoreTask.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowPerformUnifiedRestoreTask.java
@@ -54,7 +54,7 @@
     private OnTaskFinishedListener mListener;
 
     @Implementation
-    public void __constructor__(
+    protected void __constructor__(
             BackupManagerService backupManagerService,
             TransportClient transportClient,
             IRestoreObserver observer,
@@ -74,7 +74,7 @@
     }
 
     @Implementation
-    public void execute() {
+    protected void execute() {
         mBackupManagerService.setRestoreInProgress(false);
         mListener.onFinished("ShadowPerformUnifiedRestoreTask.execute()");
     }
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowSlog.java b/services/robotests/src/com/android/server/testing/shadows/ShadowSlog.java
index 737b0c8..32ef1bc 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowSlog.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowSlog.java
@@ -21,92 +21,91 @@
 
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
-import org.robolectric.shadows.ShadowLog;
 
 @Implements(Slog.class)
 public class ShadowSlog {
     @Implementation
-    public static int v(String tag, String msg) {
+    protected static int v(String tag, String msg) {
         return Log.v(tag, msg);
     }
 
     @Implementation
-    public static int v(String tag, String msg, Throwable tr) {
+    protected static int v(String tag, String msg, Throwable tr) {
         return Log.v(tag, msg, tr);
     }
 
     @Implementation
-    public static int d(String tag, String msg) {
+    protected static int d(String tag, String msg) {
         return Log.d(tag, msg);
     }
 
     @Implementation
-    public static int d(String tag, String msg, Throwable tr) {
+    protected static int d(String tag, String msg, Throwable tr) {
         return Log.d(tag, msg, tr);
     }
 
     @Implementation
-    public static int i(String tag, String msg) {
+    protected static int i(String tag, String msg) {
         return Log.i(tag, msg);
     }
 
     @Implementation
-    public static int i(String tag, String msg, Throwable tr) {
+    protected static int i(String tag, String msg, Throwable tr) {
         return Log.i(tag, msg, tr);
     }
 
     @Implementation
-    public static int w(String tag, String msg) {
+    protected static int w(String tag, String msg) {
         return Log.w(tag, msg);
     }
 
     @Implementation
-    public static int w(String tag, String msg, Throwable tr) {
+    protected static int w(String tag, String msg, Throwable tr) {
         return Log.w(tag, msg, tr);
     }
 
     @Implementation
-    public static int w(String tag, Throwable tr) {
+    protected static int w(String tag, Throwable tr) {
         return Log.w(tag, tr);
     }
 
     @Implementation
-    public static int e(String tag, String msg) {
+    protected static int e(String tag, String msg) {
         return Log.e(tag, msg);
     }
 
     @Implementation
-    public static int e(String tag, String msg, Throwable tr) {
+    protected static int e(String tag, String msg, Throwable tr) {
         return Log.e(tag, msg, tr);
     }
 
     @Implementation
-    public static int wtf(String tag, String msg) {
+    protected static int wtf(String tag, String msg) {
         return Log.wtf(tag, msg);
     }
 
     @Implementation
-    public static void wtfQuiet(String tag, String msg) {
+    protected static void wtfQuiet(String tag, String msg) {
         Log.wtf(tag, msg);
     }
 
     @Implementation
-    public static int wtfStack(String tag, String msg) {
+    protected static int wtfStack(String tag, String msg) {
         return Log.wtf(tag, msg);
     }
 
     @Implementation
-    public static int wtf(String tag, Throwable tr) {
+    protected static int wtf(String tag, Throwable tr) {
         return Log.wtf(tag, tr);
     }
 
     @Implementation
-    public static int wtf(String tag, String msg, Throwable tr) {
+    protected static int wtf(String tag, String msg, Throwable tr) {
         return Log.wtf(tag, msg, tr);
     }
 
     @Implementation
-    public static int println(int priority, String tag, String msg) {
+    protected static int println(int priority, String tag, String msg) {
         return Log.println(priority, tag, msg);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java
index ee42ce8..e6b328a 100644
--- a/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java
@@ -125,7 +125,7 @@
                 "/storage/emulated/0/foo.jpg",
                 PID_GREY, UID_GREY);
         assertTranslation(
-                "/storage/emulated/0/Android/sandbox/shared:colors/foo.jpg",
+                "/storage/emulated/0/Android/sandbox/shared-colors/foo.jpg",
                 "/storage/emulated/0/foo.jpg",
                 PID_RED, UID_COLORS);
     }
@@ -137,7 +137,7 @@
                 "/storage/0000-0000/foo/bar.jpg",
                 PID_GREY, UID_GREY);
         assertTranslation(
-                "/storage/0000-0000/Android/sandbox/shared:colors/foo/bar.jpg",
+                "/storage/0000-0000/Android/sandbox/shared-colors/foo/bar.jpg",
                 "/storage/0000-0000/foo/bar.jpg",
                 PID_RED, UID_COLORS);
     }
@@ -152,7 +152,7 @@
 
         // Accessing other package paths goes into sandbox
         assertTranslation(
-                "/storage/emulated/0/Android/sandbox/shared:colors/"
+                "/storage/emulated/0/Android/sandbox/shared-colors/"
                         + "Android/data/com.grey/foo.jpg",
                 "/storage/emulated/0/Android/data/com.grey/foo.jpg",
                 PID_RED, UID_COLORS);
@@ -201,7 +201,7 @@
         // Sandboxes can't see paths in other sandboxes
         try {
             mService.translateSystemToApp(
-                    "/storage/emulated/0/Android/sandbox/shared:colors/foo.jpg",
+                    "/storage/emulated/0/Android/sandbox/shared-colors/foo.jpg",
                     PID_GREY, UID_GREY);
             fail();
         } catch (SecurityException expected) {
diff --git a/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java b/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java
index fd04970..f31ca55 100644
--- a/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java
@@ -115,7 +115,12 @@
             mTarget.setSettingsLocked(
                     mPersistedState.global.getOrDefault(Global.LOW_POWER_MODE, 0) != 0,
                     mPersistedState.global.getOrDefault(Global.LOW_POWER_MODE_STICKY, 0) != 0,
-                    mDevice.getLowPowerModeTriggerLevel());
+                    mDevice.getLowPowerModeTriggerLevel(),
+                    mPersistedState.global.getOrDefault(Global.AUTOMATIC_POWER_SAVER_MODE, 0),
+                    mPersistedState.global.getOrDefault(
+                            Global.DYNAMIC_POWER_SAVINGS_ENABLED, 0) != 0,
+                    mPersistedState.global.getOrDefault(
+                            Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, 100));
         }
 
         public void putGlobalSetting(String key, int value) {
@@ -174,6 +179,9 @@
         when(mMockResources.getBoolean(
                 com.android.internal.R.bool.config_batterySaverStickyBehaviourDisabled))
                 .thenReturn(false);
+        when(mMockResources.getInteger(
+                com.android.internal.R.integer.config_dynamicPowerSavingsDefaultDisableThreshold))
+                .thenReturn(80);
 
         mPersistedState = new DevicePersistedState();
         initDevice();
@@ -303,6 +311,7 @@
     @Test
     public void testAutoBatterySaver() {
         mDevice.putGlobalSetting(Global.LOW_POWER_MODE_TRIGGER_LEVEL, 50);
+        mDevice.putGlobalSetting(Global.AUTOMATIC_POWER_SAVER_MODE, 0);
 
         assertEquals(false, mDevice.batterySaverEnabled);
         assertEquals(100, mPersistedState.batteryLevel);
@@ -515,6 +524,7 @@
                 .thenReturn(true);
         initDevice();
         mDevice.putGlobalSetting(Global.LOW_POWER_MODE_TRIGGER_LEVEL, 50);
+        mDevice.putGlobalSetting(Global.AUTOMATIC_POWER_SAVER_MODE, 0);
 
         mTarget.setBatterySaverEnabledManually(true);
 
@@ -626,4 +636,123 @@
         assertEquals(90, mPersistedState.batteryLevel);
         assertEquals(false, mPersistedState.batteryLow);
     }
+
+    @Test
+    public void testAutoBatterySaver_smartBatterySaverEnabled() {
+        mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, 50);
+        mDevice.putGlobalSetting(Global.AUTOMATIC_POWER_SAVER_MODE, 1);
+        mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_ENABLED, 0);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(100, mPersistedState.batteryLevel);
+
+        mDevice.setBatteryLevel(90);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(90, mPersistedState.batteryLevel);
+
+        mDevice.setBatteryLevel(51);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(51, mPersistedState.batteryLevel);
+
+        // Hit the threshold. BS should be disabled since dynamic power savings still off
+        mDevice.setBatteryLevel(50);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(50, mPersistedState.batteryLevel);
+
+        // dynamic power savings comes on, battery saver should turn on
+        mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_ENABLED, 1);
+        mDevice.setBatteryLevel(40);
+
+        assertEquals(true, mDevice.batterySaverEnabled);
+        assertEquals(40, mPersistedState.batteryLevel);
+
+        mDevice.setPowered(true);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(40, mPersistedState.batteryLevel);
+
+        mDevice.setPowered(false);
+
+        assertEquals(true, mDevice.batterySaverEnabled);
+        assertEquals(40, mPersistedState.batteryLevel);
+
+        mTarget.setBatterySaverEnabledManually(false); // Manually disable -> snooze.
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(40, mPersistedState.batteryLevel);
+
+        mDevice.setBatteryLevel(30);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(30, mPersistedState.batteryLevel);
+
+        // Plug in and out, snooze will reset.
+        mDevice.setPowered(true);
+        mDevice.setPowered(false);
+
+        assertEquals(true, mDevice.batterySaverEnabled);
+        assertEquals(30, mPersistedState.batteryLevel);
+
+        mDevice.setPowered(true);
+        mDevice.setBatteryLevel(60);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(60, mPersistedState.batteryLevel);
+
+        mDevice.setPowered(false);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(60, mPersistedState.batteryLevel);
+
+        mDevice.setBatteryLevel(40);
+
+        assertEquals(true, mDevice.batterySaverEnabled);
+        assertEquals(40, mPersistedState.batteryLevel);
+
+        mDevice.setBatteryLevel(70);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(70, mPersistedState.batteryLevel);
+
+        // Bump up the threshold.
+        mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, 71);
+        mDevice.setBatteryLevel(mPersistedState.batteryLevel);
+
+        // changes are only registered if some battery level changed
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(70, mPersistedState.batteryLevel);
+
+        mDevice.setBatteryLevel(69);
+
+        assertEquals(true, mDevice.batterySaverEnabled);
+        assertEquals(69, mPersistedState.batteryLevel);
+
+        // Then down.
+        mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, 60);
+        mDevice.setBatteryLevel(mPersistedState.batteryLevel);
+
+        // changes are only registered if battery level changed
+        assertEquals(true, mDevice.batterySaverEnabled);
+        assertEquals(69, mPersistedState.batteryLevel);
+
+        mDevice.setBatteryLevel(68);
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(68, mPersistedState.batteryLevel);
+
+        // Reboot in low state -> automatically enable BS.
+        mDevice.setPowered(false);
+        mDevice.setBatteryLevel(30);
+        mTarget.setBatterySaverEnabledManually(false);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(30, mPersistedState.batteryLevel);
+
+        initDevice();
+
+        assertEquals(true, mDevice.batterySaverEnabled);
+        assertEquals(30, mPersistedState.batteryLevel);
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java b/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
index 473682d..bf7f53d 100644
--- a/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
+++ b/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
@@ -16,13 +16,12 @@
 
 package com.android.server.usage;
 
-import static junit.framework.TestCase.assertNull;
 import static junit.framework.TestCase.fail;
 
 import static org.testng.Assert.assertEquals;
 
 import android.app.usage.EventList;
-import android.app.usage.UsageEvents;
+import android.app.usage.UsageEvents.Event;
 import android.app.usage.UsageStats;
 import android.app.usage.UsageStatsManager;
 import android.content.Context;
@@ -112,6 +111,8 @@
         long time = System.currentTimeMillis() - (numberOfEvents*timeProgression);
         mIntervalStats = new IntervalStats();
 
+        mIntervalStats.majorVersion = 7;
+        mIntervalStats.minorVersion = 8;
         mIntervalStats.beginTime = time;
         mIntervalStats.interactiveTracker.count = 2;
         mIntervalStats.interactiveTracker.duration = 111111;
@@ -127,41 +128,39 @@
         }
 
         for (int i = 0; i < numberOfEvents; i++) {
-            UsageEvents.Event event = new UsageEvents.Event();
+            Event event = new Event();
             final int packageInt = ((i / 3) % 7);
             event.mPackage = "fake.package.name" + packageInt; //clusters of 3 events from 7 "apps"
             if (packageInt == 3) {
                 // Third app is an instant app
-                event.mFlags |= UsageEvents.Event.FLAG_IS_PACKAGE_INSTANT_APP;
-            } else if (packageInt == 2 || packageInt == 4) {
-                event.mClass = ".fake.class.name" + i % 11;
+                event.mFlags |= Event.FLAG_IS_PACKAGE_INSTANT_APP;
             }
 
-
+            event.mClass = ".fake.class.name" + i % 11;
             event.mTimeStamp = time;
             event.mEventType = i % 19; //"random" event type
 
             switch (event.mEventType) {
-                case UsageEvents.Event.CONFIGURATION_CHANGE:
+                case Event.CONFIGURATION_CHANGE:
                     //empty config,
                     event.mConfiguration = new Configuration();
                     break;
-                case UsageEvents.Event.SHORTCUT_INVOCATION:
+                case Event.SHORTCUT_INVOCATION:
                     //"random" shortcut
                     event.mShortcutId = "shortcut" + (i % 8);
                     break;
-                case UsageEvents.Event.STANDBY_BUCKET_CHANGED:
+                case Event.STANDBY_BUCKET_CHANGED:
                     //"random" bucket and reason
                     event.mBucketAndReason = (((i % 5 + 1) * 10) << 16) & (i % 5 + 1) << 8;
                     break;
-                case UsageEvents.Event.NOTIFICATION_INTERRUPTION:
+                case Event.NOTIFICATION_INTERRUPTION:
                     //"random" channel
                     event.mNotificationChannelId = "channel" + (i % 5);
                     break;
             }
 
             mIntervalStats.events.insert(event);
-            mIntervalStats.update(event.mPackage, event.mTimeStamp, event.mEventType);
+            mIntervalStats.update(event.mPackage, event.mClass, event.mTimeStamp, event.mEventType);
 
             time += timeProgression; // Arbitrary progression of time
         }
@@ -221,29 +220,30 @@
         // mEndTimeStamp is based on the enclosing IntervalStats, don't bother checking
         assertEquals(us1.mLastTimeUsed, us2.mLastTimeUsed);
         assertEquals(us1.mTotalTimeInForeground, us2.mTotalTimeInForeground);
+        assertEquals(us1.mLastTimeForegroundServiceUsed, us2.mLastTimeForegroundServiceUsed);
+        assertEquals(us1.mTotalTimeForegroundServiceUsed, us2.mTotalTimeForegroundServiceUsed);
         // mLaunchCount not persisted, so skipped
         assertEquals(us1.mAppLaunchCount, us2.mAppLaunchCount);
-        assertEquals(us1.mLastEvent, us2.mLastEvent);
         assertEquals(us1.mChooserCounts, us2.mChooserCounts);
     }
 
-    void compareUsageEvent(UsageEvents.Event e1, UsageEvents.Event e2, int debugId) {
+    void compareUsageEvent(Event e1, Event e2, int debugId) {
         assertEquals(e1.mPackage, e2.mPackage, "Usage event " + debugId);
         assertEquals(e1.mClass, e2.mClass, "Usage event " + debugId);
         assertEquals(e1.mTimeStamp, e2.mTimeStamp, "Usage event " + debugId);
         assertEquals(e1.mEventType, e2.mEventType, "Usage event " + debugId);
         switch (e1.mEventType) {
-            case UsageEvents.Event.CONFIGURATION_CHANGE:
+            case Event.CONFIGURATION_CHANGE:
                 assertEquals(e1.mConfiguration, e2.mConfiguration,
                         "Usage event " + debugId + e2.mConfiguration.toString());
                 break;
-            case UsageEvents.Event.SHORTCUT_INVOCATION:
+            case Event.SHORTCUT_INVOCATION:
                 assertEquals(e1.mShortcutId, e2.mShortcutId, "Usage event " + debugId);
                 break;
-            case UsageEvents.Event.STANDBY_BUCKET_CHANGED:
+            case Event.STANDBY_BUCKET_CHANGED:
                 assertEquals(e1.mBucketAndReason, e2.mBucketAndReason, "Usage event " + debugId);
                 break;
-            case UsageEvents.Event.NOTIFICATION_INTERRUPTION:
+            case Event.NOTIFICATION_INTERRUPTION:
                 assertEquals(e1.mNotificationChannelId, e2.mNotificationChannelId,
                         "Usage event " + debugId);
                 break;
@@ -252,6 +252,8 @@
     }
 
     void compareIntervalStats(IntervalStats stats1, IntervalStats stats2) {
+        assertEquals(stats1.majorVersion, stats2.majorVersion);
+        assertEquals(stats1.minorVersion, stats2.minorVersion);
         assertEquals(stats1.beginTime, stats2.beginTime);
         assertEquals(stats1.endTime, stats2.endTime);
         assertEquals(stats1.interactiveTracker.count, stats2.interactiveTracker.count);
diff --git a/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java b/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
index b6a7cfb..991981f 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
@@ -37,7 +37,7 @@
 
 /**
  * Build/Install/Run:
- *  atest FrameworksServicesTests:DimmerTests;
+ *  atest FrameworksServicesTests:DimmerTests
  */
 @Presubmit
 public class DimmerTests extends WindowTestsBase {
@@ -211,7 +211,7 @@
         mDimmer.updateDims(mTransaction, new Rect());
         verify(mSurfaceAnimatorStarter).startAnimation(any(SurfaceAnimator.class), any(
                 SurfaceControl.Transaction.class), any(AnimationAdapter.class), anyBoolean());
-        verify(dimLayer).destroy();
+        verify(mHost.getPendingTransaction()).destroy(dimLayer);
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index f4da4b3..c1655bc 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -40,6 +40,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.doNothing;
@@ -108,7 +109,7 @@
         final WindowState imeAppTarget =
                 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
 
-        mWm.mInputMethodTarget = imeAppTarget;
+        mDisplayContent.mInputMethodTarget = imeAppTarget;
 
         assertForAllWindowsOrder(Arrays.asList(
                 mWallpaperWindow,
@@ -124,8 +125,8 @@
     }
 
     @Test
-    public void testForAllWindows_WithChildWindowImeTarget() {
-        mWm.mInputMethodTarget = mChildAppWindowAbove;
+    public void testForAllWindows_WithChildWindowImeTarget() throws Exception {
+        mDisplayContent.mInputMethodTarget = mChildAppWindowAbove;
 
         assertForAllWindowsOrder(Arrays.asList(
                 mWallpaperWindow,
@@ -140,8 +141,8 @@
     }
 
     @Test
-    public void testForAllWindows_WithStatusBarImeTarget() {
-        mWm.mInputMethodTarget = mStatusBarWindow;
+    public void testForAllWindows_WithStatusBarImeTarget() throws Exception {
+        mDisplayContent.mInputMethodTarget = mStatusBarWindow;
 
         assertForAllWindowsOrder(Arrays.asList(
                 mWallpaperWindow,
@@ -568,6 +569,32 @@
         assertFalse(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
     }
 
+    @Test
+    public void testInputMethodTargetUpdateWhenSwitchingOnDisplays() {
+        final DisplayContent newDisplay = createNewDisplay();
+
+        final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
+        final WindowState appWin1 = createWindow(null, TYPE_APPLICATION, newDisplay, "appWin1");
+        appWin.setHasSurface(true);
+        appWin1.setHasSurface(true);
+
+        // Set current input method window on default display, make sure the input method target
+        // is appWin & null on the other display.
+        mDisplayContent.setInputMethodWindowLocked(mImeWindow);
+        newDisplay.setInputMethodWindowLocked(null);
+        assertTrue("appWin should be IME target window",
+                appWin.equals(mDisplayContent.mInputMethodTarget));
+        assertNull("newDisplay Ime target: ", newDisplay.mInputMethodTarget);
+
+        // Switch input method window on new display & make sure the input method target also
+        // switched as expected.
+        newDisplay.setInputMethodWindowLocked(mImeWindow);
+        mDisplayContent.setInputMethodWindowLocked(null);
+        assertTrue("appWin1 should be IME target window",
+                appWin1.equals(newDisplay.mInputMethodTarget));
+        assertNull("default display Ime target: ", mDisplayContent.mInputMethodTarget);
+    }
+
     private boolean isOptionsPanelAtRight(int displayId) {
         return (mWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT;
     }
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java b/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java
index e8d0a06..99deeb9 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java
@@ -53,7 +53,8 @@
     }
 
     @Override
-    public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) throws RemoteException {
+    public void windowFocusChanged(boolean hasFocus, boolean inTouchMode, boolean reportToClient)
+            throws RemoteException {
     }
 
     @Override
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTraversalTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTraversalTests.java
index 2b8b934..fcde08e 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTraversalTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTraversalTests.java
@@ -52,7 +52,7 @@
                 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD,
                 TYPE_BASE_APPLICATION, mDisplayContent, "splitScreenSecondaryWindow");
 
-        mWm.mInputMethodTarget = splitScreenWindow;
+        mDisplayContent.mInputMethodTarget = splitScreenWindow;
 
         Consumer<WindowState> c = mock(Consumer.class);
         mDisplayContent.forAllWindows(c, false);
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index 2abe64d..53858c7 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -192,7 +192,7 @@
                 mWm.getDefaultDisplayContentLocked().mAppTransition
                         .removeAppTransitionTimeoutCallbacks();
                 mWm.mH.removeMessages(WindowManagerService.H.WINDOW_FREEZE_TIMEOUT);
-                mWm.mInputMethodTarget = null;
+                mDisplayContent.mInputMethodTarget = null;
             }
 
             // Wait until everything is really cleaned up.
diff --git a/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
index 3c8ae3c..3dcea75 100644
--- a/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
@@ -209,7 +209,7 @@
 
     @Test
     public void testAssignWindowLayers_ForImeWithNoTarget() {
-        mWm.mInputMethodTarget = null;
+        mDisplayContent.mInputMethodTarget = null;
         mDisplayContent.assignChildLayers(mTransaction);
 
         // The Ime has an higher base layer than app windows and lower base layer than system
@@ -227,7 +227,7 @@
     @Test
     public void testAssignWindowLayers_ForImeWithAppTarget() {
         final WindowState imeAppTarget = createWindow("imeAppTarget");
-        mWm.mInputMethodTarget = imeAppTarget;
+        mDisplayContent.mInputMethodTarget = imeAppTarget;
 
         mDisplayContent.assignChildLayers(mTransaction);
 
@@ -253,7 +253,7 @@
                 TYPE_APPLICATION_MEDIA_OVERLAY, imeAppTarget.mToken,
                 "imeAppTargetChildBelowWindow");
 
-        mWm.mInputMethodTarget = imeAppTarget;
+        mDisplayContent.mInputMethodTarget = imeAppTarget;
         mDisplayContent.assignChildLayers(mTransaction);
 
         // Ime should be above all app windows except for child windows that are z-ordered above it
@@ -275,7 +275,7 @@
         final WindowState imeAppTarget = createWindow("imeAppTarget");
         final WindowState appAboveImeTarget = createWindow("appAboveImeTarget");
 
-        mWm.mInputMethodTarget = imeAppTarget;
+        mDisplayContent.mInputMethodTarget = imeAppTarget;
         mDisplayContent.assignChildLayers(mTransaction);
 
         // Ime should be above all app windows except for non-fullscreen app window above it and
@@ -298,7 +298,7 @@
                 mDisplayContent, "imeSystemOverlayTarget",
                 true /* ownerCanAddInternalSystemWindow */);
 
-        mWm.mInputMethodTarget = imeSystemOverlayTarget;
+        mDisplayContent.mInputMethodTarget = imeSystemOverlayTarget;
         mDisplayContent.assignChildLayers(mTransaction);
 
         // The IME target base layer is higher than all window except for the nav bar window, so the
@@ -321,7 +321,7 @@
 
     @Test
     public void testAssignWindowLayers_ForStatusBarImeTarget() {
-        mWm.mInputMethodTarget = mStatusBarWindow;
+        mDisplayContent.mInputMethodTarget = mStatusBarWindow;
         mDisplayContent.assignChildLayers(mTransaction);
 
         assertWindowHigher(mImeWindow, mChildAppWindowAbove);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
index f692a57..16dd92f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
@@ -25,6 +25,7 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
+import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
 import static android.view.Display.DEFAULT_DISPLAY;
 
 import static com.android.server.wm.ActivityDisplay.POSITION_TOP;
@@ -57,6 +58,7 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.graphics.Rect;
+import android.os.Build;
 import android.platform.test.annotations.Presubmit;
 
 import androidx.test.filters.MediumTest;
@@ -433,6 +435,26 @@
                 eq(activity), eq(null /* targetOptions */));
     }
 
+    /**
+     * Tests home activities that targeted sdk before Q cannot start on secondary display.
+     */
+    @Test
+    public void testStartHomeTargetSdkBeforeQ() throws Exception {
+        final TestActivityDisplay secondDisplay = spy(createNewActivityDisplay());
+        mSupervisor.addChild(secondDisplay, POSITION_TOP);
+        doReturn(true).when(secondDisplay).supportsSystemDecorations();
+
+        final ActivityInfo info = new ActivityInfo();
+        info.launchMode = LAUNCH_MULTIPLE;
+        info.applicationInfo = new ApplicationInfo();
+        info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q;
+        assertTrue(mSupervisor.canStartHomeOnDisplay(info, secondDisplay.mDisplayId,
+                false /* allowInstrumenting */));
+
+        info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.P;
+        assertFalse(mSupervisor.canStartHomeOnDisplay(info, secondDisplay.mDisplayId,
+                false /* allowInstrumenting */));
+    }
 
     /**
      * Tests that home activities can be started on the displays that supports system decorations.
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index 4f573a4..152831f 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -27,6 +27,8 @@
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_DOZE;
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_NON_DOZE;
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_EXEMPTED_SYNC_START;
+import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_FOREGROUND_SERVICE_START;
+import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_FOREGROUND_SERVICE_STOP;
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_MOVE_TO_BACKGROUND;
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_MOVE_TO_FOREGROUND;
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_NOTIFICATION_SEEN;
@@ -844,6 +846,8 @@
             // Inform listeners if necessary
             if ((event.mEventType == UsageEvents.Event.MOVE_TO_FOREGROUND
                     || event.mEventType == UsageEvents.Event.MOVE_TO_BACKGROUND
+                    || event.mEventType == UsageEvents.Event.FOREGROUND_SERVICE_START
+                    || event.mEventType == UsageEvents.Event.FOREGROUND_SERVICE_STOP
                     || event.mEventType == UsageEvents.Event.SYSTEM_INTERACTION
                     || event.mEventType == UsageEvents.Event.USER_INTERACTION
                     || event.mEventType == UsageEvents.Event.NOTIFICATION_SEEN
@@ -896,6 +900,10 @@
         switch (eventType) {
             case UsageEvents.Event.MOVE_TO_FOREGROUND: return REASON_SUB_USAGE_MOVE_TO_FOREGROUND;
             case UsageEvents.Event.MOVE_TO_BACKGROUND: return REASON_SUB_USAGE_MOVE_TO_BACKGROUND;
+            case UsageEvents.Event.FOREGROUND_SERVICE_START:
+                return REASON_SUB_USAGE_FOREGROUND_SERVICE_START;
+            case UsageEvents.Event.FOREGROUND_SERVICE_STOP:
+                return REASON_SUB_USAGE_FOREGROUND_SERVICE_STOP;
             case UsageEvents.Event.SYSTEM_INTERACTION: return REASON_SUB_USAGE_SYSTEM_INTERACTION;
             case UsageEvents.Event.USER_INTERACTION: return REASON_SUB_USAGE_USER_INTERACTION;
             case UsageEvents.Event.NOTIFICATION_SEEN: return REASON_SUB_USAGE_NOTIFICATION_SEEN;
diff --git a/services/usage/java/com/android/server/usage/IntervalStats.java b/services/usage/java/com/android/server/usage/IntervalStats.java
index db9972f..8405267 100644
--- a/services/usage/java/com/android/server/usage/IntervalStats.java
+++ b/services/usage/java/com/android/server/usage/IntervalStats.java
@@ -18,7 +18,6 @@
 import android.app.usage.ConfigurationStats;
 import android.app.usage.EventList;
 import android.app.usage.EventStats;
-import android.app.usage.TimeSparseArray;
 import android.app.usage.UsageEvents;
 import android.app.usage.UsageStats;
 import android.content.res.Configuration;
@@ -26,12 +25,16 @@
 import android.util.ArraySet;
 import android.util.proto.ProtoInputStream;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.io.IOException;
 import java.util.List;
 
-import com.android.internal.annotations.VisibleForTesting;
-
 public class IntervalStats {
+    public static final int CURRENT_MAJOR_VERSION = 1;
+    public static final int CURRENT_MINOR_VERSION = 1;
+    public int majorVersion = CURRENT_MAJOR_VERSION;
+    public int minorVersion = CURRENT_MINOR_VERSION;
     public long beginTime;
     public long endTime;
     public long lastTimeSaved;
@@ -219,8 +222,12 @@
         switch (eventType) {
             case UsageEvents.Event.MOVE_TO_FOREGROUND:
             case UsageEvents.Event.MOVE_TO_BACKGROUND:
+            case UsageEvents.Event.FOREGROUND_SERVICE_START:
+            case UsageEvents.Event.FOREGROUND_SERVICE_STOP:
             case UsageEvents.Event.END_OF_DAY:
+            case UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE:
             case UsageEvents.Event.CONTINUE_PREVIOUS_DAY:
+            case UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE:
                 return true;
         }
         return false;
@@ -239,32 +246,9 @@
      * @hide
      */
     @VisibleForTesting
-    public void update(String packageName, long timeStamp, int eventType) {
+    public void update(String packageName, String className, long timeStamp, int eventType) {
         UsageStats usageStats = getOrCreateUsageStats(packageName);
-
-        // TODO(adamlesinski): Ensure that we recover from incorrect event sequences
-        // like double MOVE_TO_BACKGROUND, etc.
-        if (eventType == UsageEvents.Event.MOVE_TO_BACKGROUND ||
-                eventType == UsageEvents.Event.END_OF_DAY) {
-            if (usageStats.mLastEvent == UsageEvents.Event.MOVE_TO_FOREGROUND ||
-                    usageStats.mLastEvent == UsageEvents.Event.CONTINUE_PREVIOUS_DAY) {
-                usageStats.mTotalTimeInForeground += timeStamp - usageStats.mLastTimeUsed;
-            }
-        }
-
-        if (isStatefulEvent(eventType)) {
-            usageStats.mLastEvent = eventType;
-        }
-
-        if (isUserVisibleEvent(eventType)) {
-            usageStats.mLastTimeUsed = timeStamp;
-        }
-        usageStats.mEndTimeStamp = timeStamp;
-
-        if (eventType == UsageEvents.Event.MOVE_TO_FOREGROUND) {
-            usageStats.mLaunchCount += 1;
-        }
-
+        usageStats.update(className, timeStamp, eventType);
         endTime = timeStamp;
     }
 
@@ -372,4 +356,19 @@
         }
         return mStringCache.valueAt(index);
     }
+
+    /**
+     * When an IntervalStats object is deserialized, if the object's version number
+     * is lower than current version number, optionally perform a upgrade.
+     */
+    void upgradeIfNeeded() {
+        // We only uprade on majorVersion change, no need to upgrade on minorVersion change.
+        if (!(majorVersion < CURRENT_MAJOR_VERSION)) {
+            return;
+        }
+        /*
+          Optional upgrade code here.
+        */
+        majorVersion = CURRENT_MAJOR_VERSION;
+    }
 }
diff --git a/services/usage/java/com/android/server/usage/UsageStatsProto.java b/services/usage/java/com/android/server/usage/UsageStatsProto.java
index 30d303f..8e1c060 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsProto.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsProto.java
@@ -21,13 +21,12 @@
 import android.app.usage.UsageStats;
 import android.content.res.Configuration;
 import android.util.ArrayMap;
-
 import android.util.Slog;
 import android.util.proto.ProtoInputStream;
 import android.util.proto.ProtoOutputStream;
 
-import java.io.InputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.ProtocolException;
 import java.util.ArrayList;
@@ -105,6 +104,7 @@
                     stats = tempPackageIndex;
                     break;
                 case (int) IntervalStatsProto.UsageStats.LAST_TIME_ACTIVE_MS:
+                    // Time attributes stored is an offset of the beginTime.
                     stats.mLastTimeUsed = statsOut.beginTime + proto.readLong(
                             IntervalStatsProto.UsageStats.LAST_TIME_ACTIVE_MS);
                     break;
@@ -113,7 +113,8 @@
                             IntervalStatsProto.UsageStats.TOTAL_TIME_ACTIVE_MS);
                     break;
                 case (int) IntervalStatsProto.UsageStats.LAST_EVENT:
-                    stats.mLastEvent = proto.readInt(IntervalStatsProto.UsageStats.LAST_EVENT);
+                    stats.mLastEvent =
+                            proto.readInt(IntervalStatsProto.UsageStats.LAST_EVENT);
                     break;
                 case (int) IntervalStatsProto.UsageStats.APP_LAUNCH_COUNT:
                     stats.mAppLaunchCount = proto.readInt(
@@ -125,6 +126,15 @@
                     loadChooserCounts(proto, stats);
                     proto.end(chooserToken);
                     break;
+                case (int) IntervalStatsProto.UsageStats.LAST_TIME_SERVICE_USED_MS:
+                    // Time attributes stored is an offset of the beginTime.
+                    stats.mLastTimeForegroundServiceUsed = statsOut.beginTime + proto.readLong(
+                            IntervalStatsProto.UsageStats.LAST_TIME_SERVICE_USED_MS);
+                    break;
+                case (int) IntervalStatsProto.UsageStats.TOTAL_TIME_SERVICE_USED_MS:
+                    stats.mTotalTimeForegroundServiceUsed = proto.readLong(
+                            IntervalStatsProto.UsageStats.TOTAL_TIME_SERVICE_USED_MS);
+                    break;
             }
         }
         if (stats.mLastTimeUsed == 0) {
@@ -315,11 +325,18 @@
                     + ") not found in IntervalStats string cache");
             proto.write(IntervalStatsProto.UsageStats.PACKAGE, usageStats.mPackageName);
         }
+        // Time attributes stored as an offset of the beginTime.
         proto.write(IntervalStatsProto.UsageStats.LAST_TIME_ACTIVE_MS,
                 usageStats.mLastTimeUsed - stats.beginTime);
         proto.write(IntervalStatsProto.UsageStats.TOTAL_TIME_ACTIVE_MS,
                 usageStats.mTotalTimeInForeground);
-        proto.write(IntervalStatsProto.UsageStats.LAST_EVENT, usageStats.mLastEvent);
+        proto.write(IntervalStatsProto.UsageStats.LAST_EVENT,
+                usageStats.mLastEvent);
+        // Time attributes stored as an offset of the beginTime.
+        proto.write(IntervalStatsProto.UsageStats.LAST_TIME_SERVICE_USED_MS,
+                usageStats.mLastTimeForegroundServiceUsed - stats.beginTime);
+        proto.write(IntervalStatsProto.UsageStats.TOTAL_TIME_SERVICE_USED_MS,
+                usageStats.mTotalTimeForegroundServiceUsed);
         proto.write(IntervalStatsProto.UsageStats.APP_LAUNCH_COUNT, usageStats.mAppLaunchCount);
         writeChooserCounts(proto, usageStats);
         proto.end(token);
@@ -471,6 +488,14 @@
                     statsOut.endTime = statsOut.beginTime + proto.readLong(
                             IntervalStatsProto.END_TIME_MS);
                     break;
+                case (int) IntervalStatsProto.MAJOR_VERSION:
+                    statsOut.majorVersion = proto.readInt(
+                            IntervalStatsProto.MAJOR_VERSION);
+                    break;
+                case (int) IntervalStatsProto.MINOR_VERSION:
+                    statsOut.minorVersion = proto.readInt(
+                            IntervalStatsProto.MINOR_VERSION);
+                    break;
                 case (int) IntervalStatsProto.INTERACTIVE:
                     loadCountAndTime(proto, IntervalStatsProto.INTERACTIVE,
                             statsOut.interactiveTracker);
@@ -505,6 +530,7 @@
                         // endTime not assigned, assume default value of 0 plus beginTime
                         statsOut.endTime = statsOut.beginTime;
                     }
+                    statsOut.upgradeIfNeeded();
                     return;
             }
         }
@@ -519,6 +545,8 @@
     public static void write(OutputStream out, IntervalStats stats) throws IOException {
         final ProtoOutputStream proto = new ProtoOutputStream(out);
         proto.write(IntervalStatsProto.END_TIME_MS, stats.endTime - stats.beginTime);
+        proto.write(IntervalStatsProto.MAJOR_VERSION, stats.majorVersion);
+        proto.write(IntervalStatsProto.MINOR_VERSION, stats.minorVersion);
         // String pool should be written before the rest of the usage stats
         writeStringPool(proto, stats);
 
diff --git a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
index a68f9d3..d940620 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
@@ -15,19 +15,18 @@
  */
 package com.android.server.usage;
 
+import android.app.usage.ConfigurationStats;
+import android.app.usage.UsageEvents;
+import android.app.usage.UsageStats;
+import android.content.res.Configuration;
+import android.util.ArrayMap;
+
 import com.android.internal.util.XmlUtils;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
-import android.app.usage.ConfigurationStats;
-import android.app.usage.EventList;
-import android.app.usage.UsageEvents;
-import android.app.usage.UsageStats;
-import android.content.res.Configuration;
-import android.util.ArrayMap;
-
 import java.io.IOException;
 import java.net.ProtocolException;
 
@@ -61,6 +60,7 @@
     private static final String FLAGS_ATTR = "flags";
     private static final String CLASS_ATTR = "class";
     private static final String TOTAL_TIME_ACTIVE_ATTR = "timeActive";
+    private static final String TOTAL_TIME_SERVICE_USED_ATTR = "timeServiceUsed";
     private static final String COUNT_ATTR = "count";
     private static final String ACTIVE_ATTR = "active";
     private static final String LAST_EVENT_ATTR = "lastEvent";
@@ -69,9 +69,12 @@
     private static final String STANDBY_BUCKET_ATTR = "standbyBucket";
     private static final String APP_LAUNCH_COUNT_ATTR = "appLaunchCount";
     private static final String NOTIFICATION_CHANNEL_ATTR = "notificationChannel";
+    private static final String MAJOR_VERSION_ATTR = "majorVersion";
+    private static final String MINOR_VERSION_ATTR = "minorVersion";
 
     // Time attributes stored as an offset of the beginTime.
     private static final String LAST_TIME_ACTIVE_ATTR = "lastTimeActive";
+    private static final String LAST_TIME_SERVICE_USED_ATTR = "lastTimeServiceUsed";
     private static final String END_TIME_ATTR = "endTime";
     private static final String TIME_ATTR = "time";
 
@@ -86,9 +89,14 @@
         // Apply the offset to the beginTime to find the absolute time.
         stats.mLastTimeUsed = statsOut.beginTime + XmlUtils.readLongAttribute(
                 parser, LAST_TIME_ACTIVE_ATTR);
+        stats.mLastTimeForegroundServiceUsed = statsOut.beginTime + XmlUtils.readLongAttribute(
+                parser, LAST_TIME_SERVICE_USED_ATTR);
         stats.mTotalTimeInForeground = XmlUtils.readLongAttribute(parser, TOTAL_TIME_ACTIVE_ATTR);
+        stats.mTotalTimeForegroundServiceUsed = XmlUtils.readLongAttribute(parser,
+                TOTAL_TIME_SERVICE_USED_ATTR);
         stats.mLastEvent = XmlUtils.readIntAttribute(parser, LAST_EVENT_ATTR);
-        stats.mAppLaunchCount = XmlUtils.readIntAttribute(parser, APP_LAUNCH_COUNT_ATTR, 0);
+        stats.mAppLaunchCount = XmlUtils.readIntAttribute(parser, APP_LAUNCH_COUNT_ATTR,
+                0);
         int eventCode;
         while ((eventCode = parser.next()) != XmlPullParser.END_DOCUMENT) {
             final String tag = parser.getName();
@@ -206,9 +214,12 @@
         // Write the time offset.
         XmlUtils.writeLongAttribute(xml, LAST_TIME_ACTIVE_ATTR,
                 usageStats.mLastTimeUsed - stats.beginTime);
-
+        XmlUtils.writeLongAttribute(xml, LAST_TIME_SERVICE_USED_ATTR,
+                usageStats.mLastTimeForegroundServiceUsed - stats.beginTime);
         XmlUtils.writeStringAttribute(xml, PACKAGE_ATTR, usageStats.mPackageName);
         XmlUtils.writeLongAttribute(xml, TOTAL_TIME_ACTIVE_ATTR, usageStats.mTotalTimeInForeground);
+        XmlUtils.writeLongAttribute(xml, TOTAL_TIME_SERVICE_USED_ATTR,
+                usageStats.mTotalTimeForegroundServiceUsed);
         XmlUtils.writeIntAttribute(xml, LAST_EVENT_ATTR, usageStats.mLastEvent);
         if (usageStats.mAppLaunchCount > 0) {
             XmlUtils.writeIntAttribute(xml, APP_LAUNCH_COUNT_ATTR, usageStats.mAppLaunchCount);
@@ -339,6 +350,8 @@
         }
 
         statsOut.endTime = statsOut.beginTime + XmlUtils.readLongAttribute(parser, END_TIME_ATTR);
+        statsOut.majorVersion = XmlUtils.readIntAttribute(parser, MAJOR_VERSION_ATTR);
+        statsOut.minorVersion = XmlUtils.readIntAttribute(parser, MINOR_VERSION_ATTR);
 
         int eventCode;
         int outerDepth = parser.getDepth();
@@ -391,6 +404,8 @@
      */
     public static void write(XmlSerializer xml, IntervalStats stats) throws IOException {
         XmlUtils.writeLongAttribute(xml, END_TIME_ATTR, stats.endTime - stats.beginTime);
+        XmlUtils.writeIntAttribute(xml, MAJOR_VERSION_ATTR, stats.majorVersion);
+        XmlUtils.writeIntAttribute(xml, MINOR_VERSION_ATTR, stats.minorVersion);
 
         writeCountAndTime(xml, INTERACTIVE_TAG, stats.interactiveTracker.count,
                 stats.interactiveTracker.duration);
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 1a8aba0..32875da 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -22,9 +22,9 @@
 import android.app.usage.UsageEvents;
 import android.app.usage.UsageStats;
 import android.app.usage.UsageStatsManager;
+import android.content.Context;
 import android.content.res.Configuration;
 import android.os.SystemClock;
-import android.content.Context;
 import android.text.format.DateUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -129,11 +129,17 @@
         for (IntervalStats stat : mCurrentStats) {
             final int pkgCount = stat.packageStats.size();
             for (int i = 0; i < pkgCount; i++) {
-                UsageStats pkgStats = stat.packageStats.valueAt(i);
-                if (pkgStats.mLastEvent == UsageEvents.Event.MOVE_TO_FOREGROUND ||
-                        pkgStats.mLastEvent == UsageEvents.Event.CONTINUE_PREVIOUS_DAY) {
-                    stat.update(pkgStats.mPackageName, stat.lastTimeSaved,
-                            UsageEvents.Event.END_OF_DAY);
+                final UsageStats pkgStats = stat.packageStats.valueAt(i);
+                if (!pkgStats.mLastForegroundActivityEventMap.isEmpty()
+                        || !pkgStats.mLastForegroundServiceEventMap.isEmpty()) {
+                    if (!pkgStats.mLastForegroundActivityEventMap.isEmpty()) {
+                        stat.update(pkgStats.mPackageName, null, stat.lastTimeSaved,
+                                UsageEvents.Event.END_OF_DAY);
+                    }
+                    if (!pkgStats.mLastForegroundServiceEventMap.isEmpty()) {
+                        stat.update(pkgStats.mPackageName, null , stat.lastTimeSaved,
+                                UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE);
+                    }
                     notifyStatsChanged();
                 }
             }
@@ -218,7 +224,8 @@
                     stats.updateKeyguardHidden(event.mTimeStamp);
                 } break;
                 default: {
-                    stats.update(event.mPackage, event.mTimeStamp, event.mEventType);
+                    stats.update(event.mPackage, event.getClassName(),
+                            event.mTimeStamp, event.mEventType);
                     if (incrementAppLaunch) {
                         stats.incrementAppLaunchCount(event.mPackage);
                     }
@@ -481,25 +488,43 @@
         final long startTime = SystemClock.elapsedRealtime();
         Slog.i(TAG, mLogPrefix + "Rolling over usage stats");
 
-        // Finish any ongoing events with an END_OF_DAY event. Make a note of which components
-        // need a new CONTINUE_PREVIOUS_DAY entry.
+        // Finish any ongoing events with an END_OF_DAY or ROLLOVER_FOREGROUND_SERVICE event.
+        // Make a note of which components need a new CONTINUE_PREVIOUS_DAY or
+        // CONTINUING_FOREGROUND_SERVICE entry.
         final Configuration previousConfig =
                 mCurrentStats[UsageStatsManager.INTERVAL_DAILY].activeConfiguration;
         ArraySet<String> continuePreviousDay = new ArraySet<>();
+        ArrayMap<String, ArrayMap<String, Integer>> continuePreviousDayForegroundActivity =
+                new ArrayMap<>();
+        ArrayMap<String, ArrayMap<String, Integer>> continuePreviousDayForegroundService =
+                new ArrayMap<>();
         for (IntervalStats stat : mCurrentStats) {
             final int pkgCount = stat.packageStats.size();
             for (int i = 0; i < pkgCount; i++) {
-                UsageStats pkgStats = stat.packageStats.valueAt(i);
-                if (pkgStats.mLastEvent == UsageEvents.Event.MOVE_TO_FOREGROUND ||
-                        pkgStats.mLastEvent == UsageEvents.Event.CONTINUE_PREVIOUS_DAY) {
+                final UsageStats pkgStats = stat.packageStats.valueAt(i);
+                if (!pkgStats.mLastForegroundActivityEventMap.isEmpty()
+                        || !pkgStats.mLastForegroundServiceEventMap.isEmpty()) {
+                    if (!pkgStats.mLastForegroundActivityEventMap.isEmpty()) {
+                        continuePreviousDayForegroundActivity.put(pkgStats.mPackageName,
+                                pkgStats.mLastForegroundActivityEventMap);
+                        stat.update(pkgStats.mPackageName, null,
+                                mDailyExpiryDate.getTimeInMillis() - 1,
+                                UsageEvents.Event.END_OF_DAY);
+                    }
+                    if (!pkgStats.mLastForegroundServiceEventMap.isEmpty()) {
+                        continuePreviousDayForegroundService.put(pkgStats.mPackageName,
+                                pkgStats.mLastForegroundServiceEventMap);
+                        stat.update(pkgStats.mPackageName, null,
+                                mDailyExpiryDate.getTimeInMillis() - 1,
+                                UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE);
+                    }
                     continuePreviousDay.add(pkgStats.mPackageName);
-                    stat.update(pkgStats.mPackageName, mDailyExpiryDate.getTimeInMillis() - 1,
-                            UsageEvents.Event.END_OF_DAY);
                     notifyStatsChanged();
                 }
             }
 
-            stat.updateConfigurationStats(null, mDailyExpiryDate.getTimeInMillis() - 1);
+            stat.updateConfigurationStats(null,
+                    mDailyExpiryDate.getTimeInMillis() - 1);
             stat.commitTime(mDailyExpiryDate.getTimeInMillis() - 1);
         }
 
@@ -509,10 +534,27 @@
 
         final int continueCount = continuePreviousDay.size();
         for (int i = 0; i < continueCount; i++) {
-            String name = continuePreviousDay.valueAt(i);
+            String pkgName = continuePreviousDay.valueAt(i);
             final long beginTime = mCurrentStats[UsageStatsManager.INTERVAL_DAILY].beginTime;
             for (IntervalStats stat : mCurrentStats) {
-                stat.update(name, beginTime, UsageEvents.Event.CONTINUE_PREVIOUS_DAY);
+                if (continuePreviousDayForegroundActivity.containsKey(pkgName)) {
+                    final ArrayMap<String, Integer> foregroundActivityEventMap =
+                            continuePreviousDayForegroundActivity.get(pkgName);
+                    final int size = foregroundActivityEventMap.size();
+                    for (int j = 0; j < size; j++) {
+                        stat.update(pkgName, foregroundActivityEventMap.keyAt(j), beginTime,
+                                UsageEvents.Event.CONTINUE_PREVIOUS_DAY);
+                    }
+                }
+                if (continuePreviousDayForegroundService.containsKey(pkgName)) {
+                    final ArrayMap<String, Integer> foregroundServiceEventMap =
+                            continuePreviousDayForegroundService.get(pkgName);
+                    final int size = foregroundServiceEventMap.size();
+                    for (int j = 0; j < size; j++) {
+                        stat.update(pkgName, foregroundServiceEventMap.keyAt(j), beginTime,
+                                UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE);
+                    }
+                }
                 stat.updateConfigurationStats(previousConfig, beginTime);
                 notifyStatsChanged();
             }
@@ -837,10 +879,18 @@
                 return "MOVE_TO_BACKGROUND";
             case UsageEvents.Event.MOVE_TO_FOREGROUND:
                 return "MOVE_TO_FOREGROUND";
+            case UsageEvents.Event.FOREGROUND_SERVICE_START:
+                return "FOREGROUND_SERVICE_START";
+            case UsageEvents.Event.FOREGROUND_SERVICE_STOP:
+                return "FOREGROUND_SERVICE_STOP";
             case UsageEvents.Event.END_OF_DAY:
                 return "END_OF_DAY";
+            case UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE:
+                return "ROLLOVER_FOREGROUND_SERVICE";
             case UsageEvents.Event.CONTINUE_PREVIOUS_DAY:
                 return "CONTINUE_PREVIOUS_DAY";
+            case UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE:
+                return "CONTINUING_FOREGROUND_SERVICE";
             case UsageEvents.Event.CONFIGURATION_CHANGE:
                 return "CONFIGURATION_CHANGE";
             case UsageEvents.Event.SYSTEM_INTERACTION:
diff --git a/startop/view_compiler/dex_builder.cc b/startop/view_compiler/dex_builder.cc
index 33df6f9..85357bb 100644
--- a/startop/view_compiler/dex_builder.cc
+++ b/startop/view_compiler/dex_builder.cc
@@ -49,6 +49,9 @@
     case Instruction::Op::kReturn:
       out << "kReturn";
       return out;
+    case Instruction::Op::kReturnObject:
+      out << "kReturnObject";
+      return out;
     case Instruction::Op::kMove:
       out << "kMove";
       return out;
@@ -137,6 +140,9 @@
     entry = Alloc<ir::String>();
     // +1 for null terminator
     entry->data = slicer::MemView{buffer.get(), header_length + string.size() + 1};
+    ::dex::u4 const new_index = dex_file_->strings_indexes.AllocateIndex();
+    dex_file_->strings_map[new_index] = entry;
+    entry->orig_index = new_index;
     string_data_.push_back(std::move(buffer));
   }
   return entry;
@@ -240,8 +246,9 @@
 
 void MethodBuilder::BuildReturn() { AddInstruction(Instruction::OpNoArgs(Op::kReturn)); }
 
-void MethodBuilder::BuildReturn(Value src) {
-  AddInstruction(Instruction::OpWithArgs(Op::kReturn, /*destination=*/{}, src));
+void MethodBuilder::BuildReturn(Value src, bool is_object) {
+  AddInstruction(Instruction::OpWithArgs(
+      is_object ? Op::kReturnObject : Op::kReturn, /*destination=*/{}, src));
 }
 
 void MethodBuilder::BuildConst4(Value target, int value) {
@@ -249,6 +256,11 @@
   AddInstruction(Instruction::OpWithArgs(Op::kMove, target, Value::Immediate(value)));
 }
 
+void MethodBuilder::BuildConstString(Value target, const std::string& value) {
+  const ir::String* const dex_string = dex_->GetOrAddString(value);
+  AddInstruction(Instruction::OpWithArgs(Op::kMove, target, Value::String(dex_string->orig_index)));
+}
+
 void MethodBuilder::EncodeInstructions() {
   buffer_.clear();
   for (const auto& instruction : instructions_) {
@@ -259,7 +271,9 @@
 void MethodBuilder::EncodeInstruction(const Instruction& instruction) {
   switch (instruction.opcode()) {
     case Instruction::Op::kReturn:
-      return EncodeReturn(instruction);
+      return EncodeReturn(instruction, ::art::Instruction::RETURN);
+    case Instruction::Op::kReturnObject:
+      return EncodeReturn(instruction, ::art::Instruction::RETURN_OBJECT);
     case Instruction::Op::kMove:
       return EncodeMove(instruction);
     case Instruction::Op::kInvokeVirtual:
@@ -271,15 +285,14 @@
   }
 }
 
-void MethodBuilder::EncodeReturn(const Instruction& instruction) {
-  DCHECK_EQ(Instruction::Op::kReturn, instruction.opcode());
+void MethodBuilder::EncodeReturn(const Instruction& instruction, ::art::Instruction::Code opcode) {
   DCHECK(!instruction.dest().has_value());
   if (instruction.args().size() == 0) {
     buffer_.push_back(art::Instruction::RETURN_VOID);
   } else {
-    DCHECK(instruction.args().size() == 1);
+    DCHECK_EQ(1, instruction.args().size());
     size_t source = RegisterValue(instruction.args()[0]);
-    buffer_.push_back(art::Instruction::RETURN | source << 8);
+    buffer_.push_back(opcode | source << 8);
   }
 }
 
@@ -297,6 +310,12 @@
     DCHECK_LT(source.value(), 16);
     buffer_.push_back(art::Instruction::CONST_4 | (source.value() << 12) |
                       (RegisterValue(*instruction.dest()) << 8));
+  } else if (source.is_string()) {
+    constexpr size_t kMaxRegisters = 256;
+    DCHECK_LT(RegisterValue(*instruction.dest()), kMaxRegisters);
+    DCHECK_LT(source.value(), 65536);  // make sure we don't need a jumbo string
+    buffer_.push_back(::art::Instruction::CONST_STRING | (RegisterValue(*instruction.dest()) << 8));
+    buffer_.push_back(source.value());
   } else {
     UNIMPLEMENTED(FATAL);
   }
diff --git a/startop/view_compiler/dex_builder.h b/startop/view_compiler/dex_builder.h
index 0744151..31414c8 100644
--- a/startop/view_compiler/dex_builder.h
+++ b/startop/view_compiler/dex_builder.h
@@ -110,18 +110,20 @@
   static constexpr Value Local(size_t id) { return Value{id, Kind::kLocalRegister}; }
   static constexpr Value Parameter(size_t id) { return Value{id, Kind::kParameter}; }
   static constexpr Value Immediate(size_t value) { return Value{value, Kind::kImmediate}; }
+  static constexpr Value String(size_t value) { return Value{value, Kind::kString}; }
   static constexpr Value Label(size_t id) { return Value{id, Kind::kLabel}; }
 
   bool is_register() const { return kind_ == Kind::kLocalRegister; }
   bool is_parameter() const { return kind_ == Kind::kParameter; }
   bool is_variable() const { return is_register() || is_parameter(); }
   bool is_immediate() const { return kind_ == Kind::kImmediate; }
+  bool is_string() const { return kind_ == Kind::kString; }
   bool is_label() const { return kind_ == Kind::kLabel; }
 
   size_t value() const { return value_; }
 
  private:
-  enum class Kind { kLocalRegister, kParameter, kImmediate, kLabel };
+  enum class Kind { kLocalRegister, kParameter, kImmediate, kString, kLabel };
 
   const size_t value_;
   const Kind kind_;
@@ -137,7 +139,7 @@
  public:
   // The operation performed by this instruction. These are virtual instructions that do not
   // correspond exactly to DEX instructions.
-  enum class Op { kReturn, kMove, kInvokeVirtual, kBindLabel, kBranchEqz };
+  enum class Op { kReturn, kReturnObject, kMove, kInvokeVirtual, kBindLabel, kBranchEqz };
 
   ////////////////////////
   // Named Constructors //
@@ -210,16 +212,22 @@
 
   // return-void
   void BuildReturn();
-  void BuildReturn(Value src);
+  void BuildReturn(Value src, bool is_object = false);
   // const/4
   void BuildConst4(Value target, int value);
+  void BuildConstString(Value target, const std::string& value);
 
   // TODO: add builders for more instructions
 
  private:
   void EncodeInstructions();
   void EncodeInstruction(const Instruction& instruction);
-  void EncodeReturn(const Instruction& instruction);
+
+  // Encodes a return instruction. For instructions with no return value, the opcode field is
+  // ignored. Otherwise, this specifies which return instruction will be used (return,
+  // return-object, etc.)
+  void EncodeReturn(const Instruction& instruction, ::art::Instruction::Code opcode);
+
   void EncodeMove(const Instruction& instruction);
   void EncodeInvokeVirtual(const Instruction& instruction);
   void EncodeBranch(art::Instruction::Code op, const Instruction& instruction);
diff --git a/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java b/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java
index 169c633..2ccdc6d5 100644
--- a/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java
+++ b/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java
@@ -82,4 +82,38 @@
     Method method = clazz.getMethod("backwardsBranch");
     Assert.assertEquals(2, method.invoke(null));
   }
+
+  @Test
+  public void returnNull() throws Exception {
+    ClassLoader loader = loadDexFile("simple.dex");
+    Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+    Method method = clazz.getMethod("returnNull");
+    Assert.assertEquals(null, method.invoke(null));
+  }
+
+  @Test
+  public void makeString() throws Exception {
+    ClassLoader loader = loadDexFile("simple.dex");
+    Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+    Method method = clazz.getMethod("makeString");
+    Assert.assertEquals("Hello, World!", method.invoke(null));
+  }
+
+  @Test
+  public void returnStringIfZeroAB() throws Exception {
+    ClassLoader loader = loadDexFile("simple.dex");
+    Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+    Method method = clazz.getMethod("returnStringIfZeroAB", int.class);
+    Assert.assertEquals("a", method.invoke(null, 0));
+    Assert.assertEquals("b", method.invoke(null, 1));
+  }
+
+  @Test
+  public void returnStringIfZeroBA() throws Exception {
+    ClassLoader loader = loadDexFile("simple.dex");
+    Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+    Method method = clazz.getMethod("returnStringIfZeroBA", int.class);
+    Assert.assertEquals("b", method.invoke(null, 0));
+    Assert.assertEquals("a", method.invoke(null, 1));
+  }
 }
diff --git a/startop/view_compiler/dex_testcase_generator.cc b/startop/view_compiler/dex_testcase_generator.cc
index c521bf2..063a0cf 100644
--- a/startop/view_compiler/dex_testcase_generator.cc
+++ b/startop/view_compiler/dex_testcase_generator.cc
@@ -138,6 +138,71 @@
   }(backwardsBranch);
   backwardsBranch.Encode();
 
+  // Test that we can make a null value. Basically:
+  //
+  // public static String returnNull() { return null; }
+  MethodBuilder returnNull{cbuilder.CreateMethod("returnNull", Prototype{string_type})};
+  [](MethodBuilder& method) {
+    Value zero = method.MakeRegister();
+    method.BuildConst4(zero, 0);
+    method.BuildReturn(zero, /*is_object=*/true);
+  }(returnNull);
+  returnNull.Encode();
+
+  // Test that we can make String literals. Basically:
+  //
+  // public static String makeString() { return "Hello, World!"; }
+  MethodBuilder makeString{cbuilder.CreateMethod("makeString", Prototype{string_type})};
+  [](MethodBuilder& method) {
+    Value string = method.MakeRegister();
+    method.BuildConstString(string, "Hello, World!");
+    method.BuildReturn(string, /*is_object=*/true);
+  }(makeString);
+  makeString.Encode();
+
+  // Make sure strings are sorted correctly.
+  //
+  // int returnStringIfZeroAB(int x) { if (x == 0) { return "a"; } else { return "b"; } }
+  MethodBuilder returnStringIfZeroAB{
+      cbuilder.CreateMethod("returnStringIfZeroAB", Prototype{string_type, TypeDescriptor::Int()})};
+  [&](MethodBuilder& method) {
+    Value resultIfZero{method.MakeRegister()};
+    Value else_target{method.MakeLabel()};
+    method.AddInstruction(Instruction::OpWithArgs(
+        Instruction::Op::kBranchEqz, /*dest=*/{}, Value::Parameter(0), else_target));
+    // else branch
+    method.BuildConstString(resultIfZero, "b");
+    method.AddInstruction(
+        Instruction::OpWithArgs(Instruction::Op::kReturnObject, /*dest=*/{}, resultIfZero));
+    // then branch
+    method.AddInstruction(
+        Instruction::OpWithArgs(Instruction::Op::kBindLabel, /*dest=*/{}, else_target));
+    method.BuildConstString(resultIfZero, "a");
+    method.AddInstruction(
+        Instruction::OpWithArgs(Instruction::Op::kReturnObject, /*dest=*/{}, resultIfZero));
+    method.Encode();
+  }(returnStringIfZeroAB);
+  // int returnStringIfZeroAB(int x) { if (x == 0) { return "b"; } else { return "a"; } }
+  MethodBuilder returnStringIfZeroBA{
+      cbuilder.CreateMethod("returnStringIfZeroBA", Prototype{string_type, TypeDescriptor::Int()})};
+  [&](MethodBuilder& method) {
+    Value resultIfZero{method.MakeRegister()};
+    Value else_target{method.MakeLabel()};
+    method.AddInstruction(Instruction::OpWithArgs(
+        Instruction::Op::kBranchEqz, /*dest=*/{}, Value::Parameter(0), else_target));
+    // else branch
+    method.BuildConstString(resultIfZero, "a");
+    method.AddInstruction(
+        Instruction::OpWithArgs(Instruction::Op::kReturnObject, /*dest=*/{}, resultIfZero));
+    // then branch
+    method.AddInstruction(
+        Instruction::OpWithArgs(Instruction::Op::kBindLabel, /*dest=*/{}, else_target));
+    method.BuildConstString(resultIfZero, "b");
+    method.AddInstruction(
+        Instruction::OpWithArgs(Instruction::Op::kReturnObject, /*dest=*/{}, resultIfZero));
+    method.Encode();
+  }(returnStringIfZeroBA);
+
   slicer::MemView image{dex_file.CreateImage()};
   std::ofstream out_file(outdir + "/simple.dex");
   out_file.write(image.ptr<const char>(), image.size());
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index b6ac91d..cef99865 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -21,6 +21,7 @@
 import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.ParcelFileDescriptor;
@@ -322,8 +323,11 @@
         /**
          * Call can be upgraded to a video call.
          * @hide
+         * @deprecated Use {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and
+         * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL} to indicate for a call
+         * whether or not video calling is supported.
          */
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 119305590)
         public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000;
 
         /**
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 34603a3..0589cd4 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -272,6 +272,9 @@
 
     /**
      * Call can be upgraded to a video call.
+     * @deprecated Use {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and
+     * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL} to indicate for a call whether or not
+     * video calling is supported.
      */
     public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000;
 
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index 9a4ea9e7..2ffad03 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -985,10 +985,10 @@
     /**
      * Generates a string representation of a capabilities bitmask.
      *
-     * @param capabilities The capabilities bitmask.
      * @return String representation of the capabilities bitmask.
+     * @hide
      */
-    private String capabilitiesToString() {
+    public String capabilitiesToString() {
         StringBuilder sb = new StringBuilder();
         if (hasCapabilities(CAPABILITY_SELF_MANAGED)) {
             sb.append("SelfManaged ");
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index fa16bfe..9f0bdd7 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -15,6 +15,7 @@
 package android.telecom;
 
 import android.Manifest;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
 import android.annotation.SuppressAutoDoc;
@@ -36,6 +37,8 @@
 
 import com.android.internal.telecom.ITelecomService;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -413,8 +416,10 @@
      * <p>
      * The phone number of the call used by Telecom to determine which call should be handed over.
      * @hide
+     * @deprecated Use the public handover APIs.  See
+     * {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} for more information.
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 119305590)
     public static final String EXTRA_IS_HANDOVER = "android.telecom.extra.IS_HANDOVER";
 
     /**
@@ -528,11 +533,19 @@
     public static final char DTMF_CHARACTER_WAIT = ';';
 
     /**
+     * @hide
+     */
+    @IntDef(prefix = { "TTY_MODE_" },
+            value = {TTY_MODE_OFF, TTY_MODE_FULL, TTY_MODE_HCO, TTY_MODE_VCO})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface TtyMode {}
+
+    /**
      * TTY (teletypewriter) mode is off.
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
     public static final int TTY_MODE_OFF = 0;
 
     /**
@@ -541,6 +554,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static final int TTY_MODE_FULL = 1;
 
     /**
@@ -550,6 +564,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static final int TTY_MODE_HCO = 2;
 
     /**
@@ -559,6 +574,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static final int TTY_MODE_VCO = 3;
 
     /**
@@ -827,8 +843,9 @@
      * @return The phone account handle of the current sim call manager.
      *
      * @hide
+     * @deprecated Use {@link #getSimCallManager()}.
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 119305590)
     public PhoneAccountHandle getSimCallManager(int userId) {
         try {
             if (isServiceConnected()) {
@@ -929,10 +946,12 @@
      * Returns a list of {@link PhoneAccountHandle}s including those which have not been enabled
      * by the user.
      *
+     * @param includeDisabledAccounts When {@code true}, disabled phone accounts will be included,
+     *                                when {@code false}, only
      * @return A list of {@code PhoneAccountHandle} objects.
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 119305590)
     public List<PhoneAccountHandle> getCallCapablePhoneAccounts(boolean includeDisabledAccounts) {
         try {
             if (isServiceConnected()) {
@@ -1155,7 +1174,7 @@
     /**
      * Used to set the default dialer package.
      *
-     * @param packageName to set the default dialer to..
+     * @param packageName to set the default dialer to.
      *
      * @result {@code true} if the default dialer was successfully changed, {@code false} if
      *         the specified package does not correspond to an installed dialer, or is already
@@ -1166,7 +1185,10 @@
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
+    @RequiresPermission(allOf = {
+            android.Manifest.permission.MODIFY_PHONE_STATE,
+            android.Manifest.permission.WRITE_SECURE_SETTINGS})
     public boolean setDefaultDialer(String packageName) {
         try {
             if (isServiceConnected()) {
@@ -1179,12 +1201,10 @@
     }
 
     /**
-     * Used to determine the dialer package that is preloaded on the system partition.
+     * Determines the package name of the system-provided default phone app.
      *
      * @return package name for the system dialer package or null if no system dialer is preloaded.
-     * @hide
      */
-    @UnsupportedAppUsage
     public String getSystemDialerPackage() {
         try {
             if (isServiceConnected()) {
@@ -1545,8 +1565,9 @@
      * - {@link TelecomManager#TTY_MODE_VCO}
      * @hide
      */
-    @UnsupportedAppUsage
-    public int getCurrentTtyMode() {
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public @TtyMode int getCurrentTtyMode() {
         try {
             if (isServiceConnected()) {
                 return getTelecomService().getCurrentTtyMode(mContext.getOpPackageName());
diff --git a/telephony/java/android/telephony/CellConfigLte.java b/telephony/java/android/telephony/CellConfigLte.java
new file mode 100644
index 0000000..35769f0
--- /dev/null
+++ b/telephony/java/android/telephony/CellConfigLte.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2018 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.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * The container of LTE cell related configs.
+ * @hide
+ */
+public class CellConfigLte implements Parcelable {
+    private final boolean mIsEndcAvailable;
+
+    /** @hide */
+    public CellConfigLte() {
+        mIsEndcAvailable = false;
+    }
+
+    /** @hide */
+    public CellConfigLte(boolean isEndcAvailable) {
+        mIsEndcAvailable = isEndcAvailable;
+    }
+
+    /** @hide */
+    public CellConfigLte(CellConfigLte config) {
+        mIsEndcAvailable = config.mIsEndcAvailable;
+    }
+
+    /**
+     * Indicates that if E-UTRA-NR Dual Connectivity (EN-DC) is supported by the LTE cell.
+     *
+     * Reference: 3GPP TS 36.331 v15.2.2 6.3.1 System information blocks.
+     *
+     * @return {@code true} if E-UTRA-NR Dual Connectivity (EN-DC) is supported by the LTE cell.
+     *
+     */
+    boolean isEndcAvailable() {
+        return mIsEndcAvailable;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mIsEndcAvailable);
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (!(other instanceof CellConfigLte)) return false;
+
+        CellConfigLte o = (CellConfigLte) other;
+        return mIsEndcAvailable == o.mIsEndcAvailable;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeBoolean(mIsEndcAvailable);
+    }
+
+    @Override
+    public String toString() {
+        return new StringBuilder().append(this.getClass().getName())
+                .append(" :{")
+                .append(" isEndcAvailable = " + mIsEndcAvailable)
+                .append(" }")
+                .toString();
+    }
+
+    private CellConfigLte(Parcel in) {
+        mIsEndcAvailable = in.readBoolean();
+    }
+
+    public static final Creator<CellConfigLte> CREATOR = new Creator<CellConfigLte>() {
+        @Override
+        public CellConfigLte createFromParcel(Parcel in) {
+            return new CellConfigLte(in);
+        }
+
+        @Override
+        public CellConfigLte[] newArray(int size) {
+            return new CellConfigLte[0];
+        }
+    };
+}
diff --git a/telephony/java/android/telephony/CellInfoLte.java b/telephony/java/android/telephony/CellInfoLte.java
index 389f643..7d5388b 100644
--- a/telephony/java/android/telephony/CellInfoLte.java
+++ b/telephony/java/android/telephony/CellInfoLte.java
@@ -19,7 +19,8 @@
 import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.telephony.Rlog;
+
+import java.util.Objects;
 
 /**
  * A {@link CellInfo} representing an LTE cell that provides identity and measurement info.
@@ -31,6 +32,7 @@
 
     private CellIdentityLte mCellIdentityLte;
     private CellSignalStrengthLte mCellSignalStrengthLte;
+    private CellConfigLte mCellConfig;
 
     /** @hide */
     @UnsupportedAppUsage
@@ -38,6 +40,7 @@
         super();
         mCellIdentityLte = new CellIdentityLte();
         mCellSignalStrengthLte = new CellSignalStrengthLte();
+        mCellConfig = new CellConfigLte();
     }
 
     /** @hide */
@@ -45,6 +48,7 @@
         super(ci);
         this.mCellIdentityLte = ci.mCellIdentityLte.copy();
         this.mCellSignalStrengthLte = ci.mCellSignalStrengthLte.copy();
+        this.mCellConfig = new CellConfigLte(ci.mCellConfig);
     }
 
     @Override
@@ -71,26 +75,37 @@
         mCellSignalStrengthLte = css;
     }
 
+    /** @hide */
+    public void setCellConfig(CellConfigLte cellConfig) {
+        if (DBG) log("setCellConfig: " + cellConfig);
+        mCellConfig = cellConfig;
+    }
+
+    /** @hide */
+    public CellConfigLte getCellConfig() {
+        if (DBG) log("getCellConfig: " + mCellConfig);
+        return mCellConfig;
+    }
+
     /**
      * @return hash code
      */
     @Override
     public int hashCode() {
-        return super.hashCode() + mCellIdentityLte.hashCode() + mCellSignalStrengthLte.hashCode();
+        return Objects.hash(
+                super.hashCode(),
+                mCellIdentityLte.hashCode(),
+                mCellSignalStrengthLte.hashCode(),
+                mCellConfig.hashCode());
     }
 
     @Override
     public boolean equals(Object other) {
-        if (!super.equals(other)) {
-            return false;
-        }
-        try {
-            CellInfoLte o = (CellInfoLte) other;
-            return mCellIdentityLte.equals(o.mCellIdentityLte)
-                    && mCellSignalStrengthLte.equals(o.mCellSignalStrengthLte);
-        } catch (ClassCastException e) {
-            return false;
-        }
+        if (!(other instanceof CellInfoLte)) return false;
+        CellInfoLte o = (CellInfoLte) other;
+        return super.equals(o) && mCellIdentityLte.equals(o.mCellIdentityLte)
+                && mCellSignalStrengthLte.equals(o.mCellSignalStrengthLte)
+                && mCellConfig.equals(o.mCellConfig);
     }
 
     @Override
@@ -101,6 +116,7 @@
         sb.append(super.toString());
         sb.append(" ").append(mCellIdentityLte);
         sb.append(" ").append(mCellSignalStrengthLte);
+        sb.append(" ").append(mCellConfig);
         sb.append("}");
 
         return sb.toString();
@@ -119,6 +135,7 @@
         super.writeToParcel(dest, flags, TYPE_LTE);
         mCellIdentityLte.writeToParcel(dest, flags);
         mCellSignalStrengthLte.writeToParcel(dest, flags);
+        mCellConfig.writeToParcel(dest, flags);
     }
 
     /**
@@ -129,6 +146,7 @@
         super(in);
         mCellIdentityLte = CellIdentityLte.CREATOR.createFromParcel(in);
         mCellSignalStrengthLte = CellSignalStrengthLte.CREATOR.createFromParcel(in);
+        mCellConfig = CellConfigLte.CREATOR.createFromParcel(in);
         if (DBG) log("CellInfoLte(Parcel): " + toString());
     }
 
diff --git a/telephony/java/android/telephony/DataSpecificRegistrationStates.java b/telephony/java/android/telephony/DataSpecificRegistrationStates.java
index 97e3037..b6e6cba 100644
--- a/telephony/java/android/telephony/DataSpecificRegistrationStates.java
+++ b/telephony/java/android/telephony/DataSpecificRegistrationStates.java
@@ -17,17 +17,40 @@
      */
     public final int maxDataCalls;
 
-    DataSpecificRegistrationStates(int maxDataCalls) {
+    /**
+     * Indicates if the use of dual connectivity with NR is restricted.
+     * Reference: 3GPP TS 24.301 v15.03 section 9.3.3.12A.
+     */
+    public final boolean isDcNrRestricted;
+
+    /**
+     * Indicates if NR is supported by the selected PLMN.
+     *
+     * {@code true} if the bit N is in the PLMN-InfoList-r15 is true and the selected PLMN is
+     * present in plmn-IdentityList at position N.
+     * Reference: 3GPP TS 36.331 v15.2.2 section 6.3.1 PLMN-InfoList-r15.
+     *            3GPP TS 36.331 v15.2.2 section 6.2.2 SystemInformationBlockType1 message.
+     */
+    public final boolean isNrAvailable;
+
+    DataSpecificRegistrationStates(
+            int maxDataCalls, boolean isDcNrRestricted, boolean isNrAvailable) {
         this.maxDataCalls = maxDataCalls;
+        this.isDcNrRestricted = isDcNrRestricted;
+        this.isNrAvailable = isNrAvailable;
     }
 
     private DataSpecificRegistrationStates(Parcel source) {
         maxDataCalls = source.readInt();
+        isDcNrRestricted = source.readBoolean();
+        isNrAvailable = source.readBoolean();
     }
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(maxDataCalls);
+        dest.writeBoolean(isDcNrRestricted);
+        dest.writeBoolean(isNrAvailable);
     }
 
     @Override
@@ -37,24 +60,30 @@
 
     @Override
     public String toString() {
-        return "DataSpecificRegistrationStates {" + " mMaxDataCalls=" + maxDataCalls + "}";
+        return new StringBuilder().append(this.getClass().getName())
+                .append(" :{")
+                .append(" maxDataCalls = " + maxDataCalls)
+                .append(" isDcNrRestricted = " + isDcNrRestricted)
+                .append(" isNrAvailable = " + isNrAvailable)
+                .append(" }")
+                .toString();
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(maxDataCalls);
+        return Objects.hash(maxDataCalls, isDcNrRestricted, isNrAvailable);
     }
 
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
 
-        if (o == null || !(o instanceof DataSpecificRegistrationStates)) {
-            return false;
-        }
+        if (!(o instanceof DataSpecificRegistrationStates)) return false;
 
         DataSpecificRegistrationStates other = (DataSpecificRegistrationStates) o;
-        return this.maxDataCalls == other.maxDataCalls;
+        return this.maxDataCalls == other.maxDataCalls
+                && this.isDcNrRestricted == other.isDcNrRestricted
+                && this.isNrAvailable == other.isNrAvailable;
     }
 
     public static final Parcelable.Creator<DataSpecificRegistrationStates> CREATOR =
diff --git a/telephony/java/android/telephony/NetworkRegistrationState.java b/telephony/java/android/telephony/NetworkRegistrationState.java
index 68e512e..75e8eda 100644
--- a/telephony/java/android/telephony/NetworkRegistrationState.java
+++ b/telephony/java/android/telephony/NetworkRegistrationState.java
@@ -161,11 +161,9 @@
      * @hide
      */
     public NetworkRegistrationState(int domain, int transportType, int regState,
-                                    int accessNetworkTechnology, int rejectCause,
-                                    boolean emergencyOnly, int[] availableServices,
-                                    @Nullable CellIdentity cellIdentity, boolean cssSupported,
-                                    int roamingIndicator, int systemIsInPrl,
-                                    int defaultRoamingIndicator) {
+            int accessNetworkTechnology, int rejectCause, boolean emergencyOnly,
+            int[] availableServices, @Nullable CellIdentity cellIdentity, boolean cssSupported,
+            int roamingIndicator, int systemIsInPrl, int defaultRoamingIndicator) {
         this(domain, transportType, regState, accessNetworkTechnology, rejectCause, emergencyOnly,
                 availableServices, cellIdentity);
 
@@ -178,13 +176,14 @@
      * @hide
      */
     public NetworkRegistrationState(int domain, int transportType, int regState,
-                                    int accessNetworkTechnology, int rejectCause,
-                                    boolean emergencyOnly, int[] availableServices,
-                                    @Nullable CellIdentity cellIdentity, int maxDataCalls) {
+            int accessNetworkTechnology, int rejectCause, boolean emergencyOnly,
+            int[] availableServices, @Nullable CellIdentity cellIdentity, int maxDataCalls,
+            boolean isDcNrRestricted, boolean isNrAvailable) {
         this(domain, transportType, regState, accessNetworkTechnology, rejectCause, emergencyOnly,
                 availableServices, cellIdentity);
 
-        mDataSpecificStates = new DataSpecificRegistrationStates(maxDataCalls);
+        mDataSpecificStates = new DataSpecificRegistrationStates(
+                maxDataCalls, isDcNrRestricted, isNrAvailable);
     }
 
     protected NetworkRegistrationState(Parcel source) {
@@ -345,7 +344,7 @@
     public boolean equals(Object o) {
         if (this == o) return true;
 
-        if (o == null || !(o instanceof NetworkRegistrationState)) {
+        if (!(o instanceof NetworkRegistrationState)) {
             return false;
         }
 
@@ -357,11 +356,10 @@
                 && mAccessNetworkTechnology == other.mAccessNetworkTechnology
                 && mRejectCause == other.mRejectCause
                 && mEmergencyOnly == other.mEmergencyOnly
-                && (mAvailableServices == other.mAvailableServices
-                    || Arrays.equals(mAvailableServices, other.mAvailableServices))
-                && equals(mCellIdentity, other.mCellIdentity)
-                && equals(mVoiceSpecificStates, other.mVoiceSpecificStates)
-                && equals(mDataSpecificStates, other.mDataSpecificStates);
+                && Arrays.equals(mAvailableServices, other.mAvailableServices)
+                && Objects.equals(mCellIdentity, other.mCellIdentity)
+                && Objects.equals(mVoiceSpecificStates, other.mVoiceSpecificStates)
+                && Objects.equals(mDataSpecificStates, other.mDataSpecificStates);
     }
 
     @Override
@@ -391,14 +389,4 @@
             return new NetworkRegistrationState[size];
         }
     };
-
-    private static boolean equals(Object o1, Object o2) {
-        if (o1 == o2) {
-            return true;
-        } else if (o1 == null) {
-            return false;
-        } else {
-            return o1.equals(o2);
-        }
-    }
 }
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index f5dff20..0c8d581 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -21,16 +21,18 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
+import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.HandlerExecutor;
 import android.os.Looper;
-import android.os.Message;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.IPhoneStateListener;
 
 import java.lang.ref.WeakReference;
 import java.util.List;
+import java.util.concurrent.Executor;
 
 /**
  * A listener class for monitoring changes in specific telephony states
@@ -320,7 +322,12 @@
     @UnsupportedAppUsage
     protected Integer mSubId;
 
-    private final Handler mHandler;
+    /**
+     * @hide
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    @UnsupportedAppUsage
+    public final IPhoneStateListener callback;
 
     /**
      * Create a PhoneStateListener for the Phone with the default subscription.
@@ -358,95 +365,27 @@
      */
     @UnsupportedAppUsage
     public PhoneStateListener(Integer subId, Looper looper) {
-        if (DBG) log("ctor: subId=" + subId + " looper=" + looper);
+        this(subId, new HandlerExecutor(new Handler(looper)));
+    }
+
+    /**
+     * Create a PhoneStateListener for the Phone using the specified Executor
+     *
+     * <p>Create a PhoneStateListener with a specified Executor for handling necessary callbacks.
+     * The Executor must not be null.
+     *
+     * @param executor a non-null Executor that will execute callbacks for the PhoneStateListener.
+     */
+    public PhoneStateListener(@NonNull Executor executor) {
+        this(null, executor);
+    }
+
+    private PhoneStateListener(Integer subId, Executor e) {
+        if (e == null) {
+            throw new IllegalArgumentException("PhoneStateListener Executor must be non-null");
+        }
         mSubId = subId;
-        mHandler = new Handler(looper) {
-            public void handleMessage(Message msg) {
-                if (DBG) {
-                    log("mSubId=" + mSubId + " what=0x" + Integer.toHexString(msg.what)
-                            + " msg=" + msg);
-                }
-                switch (msg.what) {
-                    case LISTEN_SERVICE_STATE:
-                        PhoneStateListener.this.onServiceStateChanged((ServiceState)msg.obj);
-                        break;
-                    case LISTEN_SIGNAL_STRENGTH:
-                        PhoneStateListener.this.onSignalStrengthChanged(msg.arg1);
-                        break;
-                    case LISTEN_MESSAGE_WAITING_INDICATOR:
-                        PhoneStateListener.this.onMessageWaitingIndicatorChanged(msg.arg1 != 0);
-                        break;
-                    case LISTEN_CALL_FORWARDING_INDICATOR:
-                        PhoneStateListener.this.onCallForwardingIndicatorChanged(msg.arg1 != 0);
-                        break;
-                    case LISTEN_CELL_LOCATION:
-                        PhoneStateListener.this.onCellLocationChanged((CellLocation)msg.obj);
-                        break;
-                    case LISTEN_CALL_STATE:
-                        PhoneStateListener.this.onCallStateChanged(msg.arg1, (String)msg.obj);
-                        break;
-                    case LISTEN_DATA_CONNECTION_STATE:
-                        PhoneStateListener.this.onDataConnectionStateChanged(msg.arg1, msg.arg2);
-                        PhoneStateListener.this.onDataConnectionStateChanged(msg.arg1);
-                        break;
-                    case LISTEN_DATA_ACTIVITY:
-                        PhoneStateListener.this.onDataActivity(msg.arg1);
-                        break;
-                    case LISTEN_SIGNAL_STRENGTHS:
-                        PhoneStateListener.this.onSignalStrengthsChanged((SignalStrength)msg.obj);
-                        break;
-                    case LISTEN_OTASP_CHANGED:
-                        PhoneStateListener.this.onOtaspChanged(msg.arg1);
-                        break;
-                    case LISTEN_CELL_INFO:
-                        PhoneStateListener.this.onCellInfoChanged((List<CellInfo>)msg.obj);
-                        break;
-                    case LISTEN_PRECISE_CALL_STATE:
-                        PhoneStateListener.this.onPreciseCallStateChanged((PreciseCallState)msg.obj);
-                        break;
-                    case LISTEN_PRECISE_DATA_CONNECTION_STATE:
-                        PhoneStateListener.this.onPreciseDataConnectionStateChanged(
-                                (PreciseDataConnectionState)msg.obj);
-                        break;
-                    case LISTEN_DATA_CONNECTION_REAL_TIME_INFO:
-                        PhoneStateListener.this.onDataConnectionRealTimeInfoChanged(
-                                (DataConnectionRealTimeInfo)msg.obj);
-                        break;
-                    case LISTEN_SRVCC_STATE_CHANGED:
-                        PhoneStateListener.this.onSrvccStateChanged((int) msg.obj);
-                        break;
-                    case LISTEN_VOICE_ACTIVATION_STATE:
-                        PhoneStateListener.this.onVoiceActivationStateChanged((int)msg.obj);
-                        break;
-                    case LISTEN_DATA_ACTIVATION_STATE:
-                        PhoneStateListener.this.onDataActivationStateChanged((int)msg.obj);
-                        break;
-                    case LISTEN_USER_MOBILE_DATA_STATE:
-                        PhoneStateListener.this.onUserMobileDataStateChanged((boolean)msg.obj);
-                        break;
-                    case LISTEN_OEM_HOOK_RAW_EVENT:
-                        PhoneStateListener.this.onOemHookRawEvent((byte[])msg.obj);
-                        break;
-                    case LISTEN_CARRIER_NETWORK_CHANGE:
-                        PhoneStateListener.this.onCarrierNetworkChange((boolean)msg.obj);
-                        break;
-                    case LISTEN_PHYSICAL_CHANNEL_CONFIGURATION:
-                        PhoneStateListener.this.onPhysicalChannelConfigurationChanged(
-                                (List<PhysicalChannelConfig>)msg.obj);
-                        break;
-                    case LISTEN_PHONE_CAPABILITY_CHANGE:
-                        PhoneStateListener.this.onPhoneCapabilityChanged(
-                                (PhoneCapability) msg.obj);
-                        break;
-                    case LISTEN_PREFERRED_DATA_SUBID_CHANGE:
-                        PhoneStateListener.this.onPreferredDataSubIdChanged((int) msg.obj);
-                        break;
-                    case LISTEN_RADIO_POWER_STATE_CHANGED:
-                        PhoneStateListener.this.onRadioPowerStateChanged((int) msg.obj);
-                        break;
-                }
-            }
-        };
+        callback = new IPhoneStateListenerStub(this, e);
     }
 
     /**
@@ -735,127 +674,217 @@
      */
     private static class IPhoneStateListenerStub extends IPhoneStateListener.Stub {
         private WeakReference<PhoneStateListener> mPhoneStateListenerWeakRef;
+        private Executor mExecutor;
 
-        public IPhoneStateListenerStub(PhoneStateListener phoneStateListener) {
+        IPhoneStateListenerStub(PhoneStateListener phoneStateListener, Executor executor) {
             mPhoneStateListenerWeakRef = new WeakReference<PhoneStateListener>(phoneStateListener);
-        }
-
-        private void send(int what, int arg1, int arg2, Object obj) {
-            PhoneStateListener listener = mPhoneStateListenerWeakRef.get();
-            if (listener != null) {
-                Message.obtain(listener.mHandler, what, arg1, arg2, obj).sendToTarget();
-            }
+            mExecutor = executor;
         }
 
         public void onServiceStateChanged(ServiceState serviceState) {
-            send(LISTEN_SERVICE_STATE, 0, 0, serviceState);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onServiceStateChanged(serviceState)));
         }
 
         public void onSignalStrengthChanged(int asu) {
-            send(LISTEN_SIGNAL_STRENGTH, asu, 0, null);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onSignalStrengthChanged(asu)));
         }
 
         public void onMessageWaitingIndicatorChanged(boolean mwi) {
-            send(LISTEN_MESSAGE_WAITING_INDICATOR, mwi ? 1 : 0, 0, null);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onMessageWaitingIndicatorChanged(mwi)));
         }
 
         public void onCallForwardingIndicatorChanged(boolean cfi) {
-            send(LISTEN_CALL_FORWARDING_INDICATOR, cfi ? 1 : 0, 0, null);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onCallForwardingIndicatorChanged(cfi)));
         }
 
         public void onCellLocationChanged(Bundle bundle) {
             CellLocation location = CellLocation.newFromBundle(bundle);
-            send(LISTEN_CELL_LOCATION, 0, 0, location);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onCellLocationChanged(location)));
         }
 
         public void onCallStateChanged(int state, String incomingNumber) {
-            send(LISTEN_CALL_STATE, state, 0, incomingNumber);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onCallStateChanged(state, incomingNumber)));
         }
 
         public void onDataConnectionStateChanged(int state, int networkType) {
-            send(LISTEN_DATA_CONNECTION_STATE, state, networkType, null);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(
+                            () -> psl.onDataConnectionStateChanged(state, networkType)));
         }
 
         public void onDataActivity(int direction) {
-            send(LISTEN_DATA_ACTIVITY, direction, 0, null);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onDataActivity(direction)));
         }
 
         public void onSignalStrengthsChanged(SignalStrength signalStrength) {
-            send(LISTEN_SIGNAL_STRENGTHS, 0, 0, signalStrength);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onSignalStrengthsChanged(signalStrength)));
         }
 
         public void onOtaspChanged(int otaspMode) {
-            send(LISTEN_OTASP_CHANGED, otaspMode, 0, null);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onOtaspChanged(otaspMode)));
         }
 
         public void onCellInfoChanged(List<CellInfo> cellInfo) {
-            send(LISTEN_CELL_INFO, 0, 0, cellInfo);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onCellInfoChanged(cellInfo)));
         }
 
         public void onPreciseCallStateChanged(PreciseCallState callState) {
-            send(LISTEN_PRECISE_CALL_STATE, 0, 0, callState);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onPreciseCallStateChanged(callState)));
         }
 
         public void onPreciseDataConnectionStateChanged(
                 PreciseDataConnectionState dataConnectionState) {
-            send(LISTEN_PRECISE_DATA_CONNECTION_STATE, 0, 0, dataConnectionState);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(
+                            () -> psl.onPreciseDataConnectionStateChanged(dataConnectionState)));
         }
 
-        public void onDataConnectionRealTimeInfoChanged(
-                DataConnectionRealTimeInfo dcRtInfo) {
-            send(LISTEN_DATA_CONNECTION_REAL_TIME_INFO, 0, 0, dcRtInfo);
+        public void onDataConnectionRealTimeInfoChanged(DataConnectionRealTimeInfo dcRtInfo) {
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(
+                            () -> psl.onDataConnectionRealTimeInfoChanged(dcRtInfo)));
         }
 
         public void onSrvccStateChanged(int state) {
-            send(LISTEN_SRVCC_STATE_CHANGED, 0, 0, state);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onSrvccStateChanged(state)));
         }
 
         public void onVoiceActivationStateChanged(int activationState) {
-            send(LISTEN_VOICE_ACTIVATION_STATE, 0, 0, activationState);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(
+                            () -> psl.onVoiceActivationStateChanged(activationState)));
         }
 
         public void onDataActivationStateChanged(int activationState) {
-            send(LISTEN_DATA_ACTIVATION_STATE, 0, 0, activationState);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(
+                            () -> psl.onDataActivationStateChanged(activationState)));
         }
 
         public void onUserMobileDataStateChanged(boolean enabled) {
-            send(LISTEN_USER_MOBILE_DATA_STATE, 0, 0, enabled);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(
+                            () -> psl.onUserMobileDataStateChanged(enabled)));
         }
 
         public void onOemHookRawEvent(byte[] rawData) {
-            send(LISTEN_OEM_HOOK_RAW_EVENT, 0, 0, rawData);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onOemHookRawEvent(rawData)));
         }
 
         public void onCarrierNetworkChange(boolean active) {
-            send(LISTEN_CARRIER_NETWORK_CHANGE, 0, 0, active);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onCarrierNetworkChange(active)));
         }
 
         public void onPhysicalChannelConfigurationChanged(List<PhysicalChannelConfig> configs) {
-            send(LISTEN_PHYSICAL_CHANNEL_CONFIGURATION, 0, 0, configs);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(
+                            () -> psl.onPhysicalChannelConfigurationChanged(configs)));
         }
 
         public void onPhoneCapabilityChanged(PhoneCapability capability) {
-            send(LISTEN_PHONE_CAPABILITY_CHANGE, 0, 0, capability);
-        }
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
 
-        public void onPreferredDataSubIdChanged(int subId) {
-            send(LISTEN_PREFERRED_DATA_SUBID_CHANGE, 0, 0, subId);
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onPhoneCapabilityChanged(capability)));
         }
 
         public void onRadioPowerStateChanged(@TelephonyManager.RadioPowerState int state) {
-            send(LISTEN_RADIO_POWER_STATE_CHANGED, 0, 0, state);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onRadioPowerStateChanged(state)));
         }
 
+        public void onPreferredDataSubIdChanged(int subId) {
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onPreferredDataSubIdChanged(subId)));
+        }
     }
 
-    /**
-     * @hide
-     */
-    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
-    @UnsupportedAppUsage
-    public final IPhoneStateListener callback = new IPhoneStateListenerStub(this);
 
     private void log(String s) {
         Rlog.d(LOG_TAG, s);
     }
-}
\ No newline at end of file
+}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index a188ef6..bd1a0fb 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -9361,4 +9361,55 @@
         }
         return false;
     }
+
+    /**
+     * Set preferred opportunistic data subscription id.
+     *
+     * <p>Requires that the calling app has carrier privileges on both primary and
+     * secondary subscriptions (see
+     * {@link #hasCarrierPrivileges}), or has permission
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
+     *
+     * @param subId which opportunistic subscription
+     * {@link SubscriptionManager#getOpportunisticSubscriptions} is preferred for cellular data.
+     * Pass {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID} to unset the preference
+     * @return true if request is accepted, else false.
+     *
+     */
+    public boolean setPreferredOpportunisticDataSubscription(int subId) {
+        String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+        try {
+            IAns iAlternativeNetworkService = getIAns();
+            if (iAlternativeNetworkService != null) {
+                return iAlternativeNetworkService.setPreferredData(subId, pkgForDebug);
+            }
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "setPreferredData RemoteException", ex);
+        }
+        return false;
+    }
+
+    /**
+     * Get preferred opportunistic data subscription Id
+     *
+     * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}),
+     * or has permission {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}.
+     * @return subId preferred opportunistic subscription id or
+     * {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID} if there are no preferred
+     * subscription id
+     *
+     */
+    public int getPreferredOpportunisticDataSubscription() {
+        String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+        int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+        try {
+            IAns iAlternativeNetworkService = getIAns();
+            if (iAlternativeNetworkService != null) {
+                subId = iAlternativeNetworkService.getPreferredData(pkgForDebug);
+            }
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "getPreferredData RemoteException", ex);
+        }
+        return subId;
+    }
 }
diff --git a/telephony/java/android/telephony/RcsManager.java b/telephony/java/android/telephony/rcs/RcsManager.java
similarity index 86%
rename from telephony/java/android/telephony/RcsManager.java
rename to telephony/java/android/telephony/rcs/RcsManager.java
index 00ce03a..0ef4e15 100644
--- a/telephony/java/android/telephony/RcsManager.java
+++ b/telephony/java/android/telephony/rcs/RcsManager.java
@@ -14,18 +14,22 @@
  * limitations under the License.
  */
 
-package android.telephony;
+package android.telephony.rcs;
 
+import android.annotation.SystemService;
+import android.content.Context;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.telephony.Rlog;
 
-import com.android.internal.telephony.IRcs;
+import com.android.internal.telephony.rcs.IRcs;
 
 /**
  * RcsManager is the application interface to RcsProvider and provides access methods to
  * RCS related database tables.
  * @hide - TODO make this public
  */
+@SystemService(Context.TELEPHONY_RCS_SERVICE)
 public class RcsManager {
     private static final String TAG = "RcsManager";
     private static final boolean VDBG = false;
diff --git a/telephony/java/android/telephony/rcs/RcsThread.aidl b/telephony/java/android/telephony/rcs/RcsThread.aidl
new file mode 100644
index 0000000..e2e0da5d
--- /dev/null
+++ b/telephony/java/android/telephony/rcs/RcsThread.aidl
@@ -0,0 +1,20 @@
+/*
+**
+** Copyright 2018, 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.telephony;
+
+parcelable RcsThread;
\ No newline at end of file
diff --git a/telephony/java/android/telephony/rcs/RcsThread.java b/telephony/java/android/telephony/rcs/RcsThread.java
new file mode 100644
index 0000000..83eb973
--- /dev/null
+++ b/telephony/java/android/telephony/rcs/RcsThread.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2018 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.telephony.rcs;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+
+import com.android.internal.telephony.rcs.IRcs;
+
+/**
+ * RcsThread represents a single RCS conversation thread. It holds messages that were sent and
+ * received and events that occured on that thread.
+ * @hide - TODO(sahinc) make this public
+ */
+public class RcsThread implements Parcelable {
+    public static final Creator<RcsThread> CREATOR = new Creator<RcsThread>() {
+        @Override
+        public RcsThread createFromParcel(Parcel in) {
+            return new RcsThread(in);
+        }
+
+        @Override
+        public RcsThread[] newArray(int size) {
+            return new RcsThread[size];
+        }
+    };
+
+    protected RcsThread(Parcel in) {
+    }
+
+    /**
+     * Returns the number of messages in this RCS thread.
+     *
+     * @hide
+     */
+    public int getMessageCount() {
+        try {
+            IRcs iRcs = IRcs.Stub.asInterface(ServiceManager.getService("ircs"));
+            if (iRcs != null) {
+                // TODO(sahinc): substitute to the regular thread id once we have database
+                // TODO(sahinc): connection in place
+                return iRcs.getMessageCount(/* rcsThreadId= */ 123);
+            }
+        } catch (RemoteException re) {
+            // TODO(sahinc): Log something meaningful
+        }
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/IAns.aidl b/telephony/java/com/android/internal/telephony/IAns.aidl
index 6eb8d66..e9a4649 100755
--- a/telephony/java/com/android/internal/telephony/IAns.aidl
+++ b/telephony/java/com/android/internal/telephony/IAns.aidl
@@ -49,4 +49,33 @@
     * @param callingPackage caller's package name
     */
     boolean isEnabled(String callingPackage);
+
+    /**
+     * Set preferred opportunistic data subscription id.
+     *
+     * <p>Requires that the calling app has carrier privileges on both primary and
+     * secondary subscriptions (see
+     * {@link #hasCarrierPrivileges}), or has permission
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
+     *
+     * @param subId which opportunistic subscription
+     * {@link SubscriptionManager#getOpportunisticSubscriptions} is preferred for cellular data.
+     * Pass {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID} to unset the preference
+     * @param callingPackage caller's package name
+     * @return true if request is accepted, else false.
+     *
+     */
+    boolean setPreferredData(int subId, String callingPackage);
+
+    /**
+     * Get preferred opportunistic data subscription Id
+     *
+     * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}),
+     * or has permission {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}.
+     * @return subId preferred opportunistic subscription id or
+     * {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID} if there are no preferred
+     * subscription id
+     *
+     */
+    int getPreferredData(String callingPackage);
 }
diff --git a/telephony/java/com/android/internal/telephony/IRcs.aidl b/telephony/java/com/android/internal/telephony/rcs/IRcs.aidl
similarity index 83%
rename from telephony/java/com/android/internal/telephony/IRcs.aidl
rename to telephony/java/com/android/internal/telephony/rcs/IRcs.aidl
index ede8695..4c289ac 100644
--- a/telephony/java/com/android/internal/telephony/IRcs.aidl
+++ b/telephony/java/com/android/internal/telephony/rcs/IRcs.aidl
@@ -14,8 +14,12 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony;
+package com.android.internal.telephony.rcs;
 
 interface IRcs {
+    // RcsManager APIs
     void deleteThread(int threadId);
+
+    // RcsThread APIs
+    int getMessageCount(int rcsThreadId);
 }
\ No newline at end of file
diff --git a/test-mock/api/current.txt b/test-mock/api/current.txt
index fc9b4c6..f91d74a 100644
--- a/test-mock/api/current.txt
+++ b/test-mock/api/current.txt
@@ -31,6 +31,7 @@
 
   public class MockContext extends android.content.Context {
     ctor public MockContext();
+    method public boolean bindIsolatedService(android.content.Intent, android.content.ServiceConnection, int, java.lang.String);
     method public boolean bindService(android.content.Intent, android.content.ServiceConnection, int);
     method public int checkCallingOrSelfPermission(java.lang.String);
     method public int checkCallingOrSelfUriPermission(android.net.Uri, int);
diff --git a/test-mock/src/android/test/mock/MockContext.java b/test-mock/src/android/test/mock/MockContext.java
index fa5b896..66be6d9 100644
--- a/test-mock/src/android/test/mock/MockContext.java
+++ b/test-mock/src/android/test/mock/MockContext.java
@@ -576,6 +576,13 @@
         throw new UnsupportedOperationException();
     }
 
+    @Override
+    public boolean bindIsolatedService(Intent service,
+            ServiceConnection conn, int flags,
+            String instanceName) {
+        throw new UnsupportedOperationException();
+    }
+
     /** @hide */
     @Override
     public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
diff --git a/test-runner/src/android/test/IsolatedContext.java b/test-runner/src/android/test/IsolatedContext.java
index 6e4c41e..73db451 100644
--- a/test-runner/src/android/test/IsolatedContext.java
+++ b/test-runner/src/android/test/IsolatedContext.java
@@ -75,6 +75,12 @@
     }
 
     @Override
+    public boolean bindIsolatedService(Intent service, ServiceConnection conn, int flags,
+            String instanceName) {
+        return false;
+    }
+
+    @Override
     public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
         return null;
     }
diff --git a/tests/RcsTests/Android.mk b/tests/RcsTests/Android.mk
new file mode 100644
index 0000000..adc7cab
--- /dev/null
+++ b/tests/RcsTests/Android.mk
@@ -0,0 +1,19 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := RcsTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
+
+LOCAL_CERTIFICATE := platform
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := junit android-support-test mockito-target-minus-junit4
+
+include $(BUILD_PACKAGE)
+
+# Use the following include to make our test apk.
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/RcsTests/AndroidManifest.xml b/tests/RcsTests/AndroidManifest.xml
new file mode 100644
index 0000000..a7e7d47
--- /dev/null
+++ b/tests/RcsTests/AndroidManifest.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.tests.rcs">
+    <application android:label="RCS Test">
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.tests.rcs"/>
+</manifest>
diff --git a/tests/RcsTests/src/com/android/tests/rcs/RcsManagerTest.java b/tests/RcsTests/src/com/android/tests/rcs/RcsManagerTest.java
new file mode 100644
index 0000000..7f5f03e
--- /dev/null
+++ b/tests/RcsTests/src/com/android/tests/rcs/RcsManagerTest.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2018 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.tests.rcs;
+
+import android.support.test.runner.AndroidJUnit4;
+import android.telephony.rcs.RcsManager;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class RcsManagerTest {
+    //TODO(sahinc): Add meaningful tests once we have more of the implementation in place
+    @Test
+    public void testDeleteThreadDoesntCrash() {
+        RcsManager mRcsManager = new RcsManager();
+        mRcsManager.deleteThread(0);
+    }
+}
diff --git a/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java b/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java
index 8467bee..be74a6d 100644
--- a/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java
+++ b/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java
@@ -18,10 +18,6 @@
 
 import static junit.framework.Assert.assertEquals;
 
-import com.android.server.usage.UsageStatsDatabase;
-import com.android.server.usage.UsageStatsDatabase.StatCombiner;
-import com.android.server.usage.IntervalStats;
-
 import android.app.usage.EventList;
 import android.app.usage.UsageEvents;
 import android.app.usage.UsageStatsManager;
@@ -29,10 +25,14 @@
 import android.os.SystemClock;
 import android.perftests.utils.ManualBenchmarkState;
 import android.perftests.utils.PerfManualStatusReporter;
-import android.support.test.filters.LargeTest;
 import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
 import android.support.test.runner.AndroidJUnit4;
 
+import com.android.server.usage.IntervalStats;
+import com.android.server.usage.UsageStatsDatabase;
+import com.android.server.usage.UsageStatsDatabase.StatCombiner;
+
 import org.junit.BeforeClass;
 import org.junit.Rule;
 import org.junit.Test;
@@ -90,11 +90,13 @@
         for (int pkg = 0; pkg < packageCount; pkg++) {
             UsageEvents.Event event = new UsageEvents.Event();
             event.mPackage = "fake.package.name" + pkg;
+            event.mClass = event.mPackage + ".class1";
             event.mTimeStamp = 1;
             event.mEventType = UsageEvents.Event.MOVE_TO_FOREGROUND;
             for (int evt = 0; evt < eventsPerPackage; evt++) {
                 intervalStats.events.insert(event);
-                intervalStats.update(event.mPackage, event.mTimeStamp, event.mEventType);
+                intervalStats.update(event.mPackage, event.mClass, event.mTimeStamp,
+                        event.mEventType);
             }
         }
     }
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 8fc9b97..b34ac26 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -58,7 +58,7 @@
     /**
      * Current Version of the Backup Serializer.
     */
-    private static final int BACKUP_VERSION = 2;
+    private static final int BACKUP_VERSION = 3;
     /** {@hide} */
     public static final String ssidVarName = "ssid";
     /** {@hide} */
@@ -2420,6 +2420,7 @@
         out.writeInt(apChannel);
         BackupUtils.writeString(out, preSharedKey);
         out.writeInt(getAuthType());
+        out.writeBoolean(hiddenSSID);
         return baos.toByteArray();
     }
 
@@ -2442,6 +2443,9 @@
         config.apChannel = in.readInt();
         config.preSharedKey = BackupUtils.readString(in);
         config.allowedKeyManagement.set(in.readInt());
+        if (version >= 3) {
+            config.hiddenSSID = in.readBoolean();
+        }
         return config;
     }
 }
diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
index 71d4173..26bdb18 100644
--- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
+++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
@@ -20,10 +20,10 @@
 import android.net.wifi.hotspot2.pps.HomeSp;
 import android.net.wifi.hotspot2.pps.Policy;
 import android.net.wifi.hotspot2.pps.UpdateParameter;
+import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
 import android.util.Log;
-import android.os.Parcel;
 
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
@@ -467,24 +467,54 @@
     }
 
     /**
-     * Validate the configuration data.
+     * Validate the R1 configuration data.
      *
      * @return true on success or false on failure
      * @hide
      */
     public boolean validate() {
-        if (mHomeSp == null || !mHomeSp.validate()) {
-            return false;
-        }
-        if (mCredential == null || !mCredential.validate()) {
-            return false;
-        }
-        if (mPolicy != null && !mPolicy.validate()) {
-            return false;
-        }
+        // Optional: PerProviderSubscription/<X+>/SubscriptionUpdate
         if (mSubscriptionUpdate != null && !mSubscriptionUpdate.validate()) {
             return false;
         }
+        return validateForCommonR1andR2(true);
+    }
+
+    /**
+     * Validate the R2 configuration data.
+     *
+     * @return true on success or false on failure
+     * @hide
+     */
+    public boolean validateForR2() {
+        // Required: PerProviderSubscription/UpdateIdentifier
+        if (mUpdateIdentifier == Integer.MIN_VALUE) {
+            return false;
+        }
+
+        // Required: PerProviderSubscription/<X+>/SubscriptionUpdate
+        if (mSubscriptionUpdate == null || !mSubscriptionUpdate.validate()) {
+            return false;
+        }
+        return validateForCommonR1andR2(false);
+    }
+
+    private boolean validateForCommonR1andR2(boolean isR1) {
+        // Required: PerProviderSubscription/<X+>/HomeSP
+        if (mHomeSp == null || !mHomeSp.validate()) {
+            return false;
+        }
+
+        // Required: PerProviderSubscription/<X+>/Credential
+        if (mCredential == null || !mCredential.validate(isR1)) {
+            return false;
+        }
+
+        // Optional: PerProviderSubscription/<X+>/Policy
+        if (mPolicy != null && !mPolicy.validate()) {
+            return false;
+        }
+
         if (mTrustRootCertList != null) {
             for (Map.Entry<String, byte[]> entry : mTrustRootCertList.entrySet()) {
                 String url = entry.getKey();
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
index e8fcbfd..7689fc3 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
@@ -18,8 +18,8 @@
 
 import android.net.wifi.EAPConstants;
 import android.net.wifi.ParcelUtil;
-import android.os.Parcelable;
 import android.os.Parcel;
+import android.os.Parcelable;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -1019,10 +1019,11 @@
     /**
      * Validate the configuration data.
      *
+     * @param isR1 {@code true} if the configuration is for R1
      * @return true on success or false on failure
      * @hide
      */
-    public boolean validate() {
+    public boolean validate(boolean isR1) {
         if (TextUtils.isEmpty(mRealm)) {
             Log.d(TAG, "Missing realm");
             return false;
@@ -1035,11 +1036,11 @@
 
         // Verify the credential.
         if (mUserCredential != null) {
-            if (!verifyUserCredential()) {
+            if (!verifyUserCredential(isR1)) {
                 return false;
             }
         } else if (mCertCredential != null) {
-            if (!verifyCertCredential()) {
+            if (!verifyCertCredential(isR1)) {
                 return false;
             }
         } else if (mSimCredential != null) {
@@ -1081,9 +1082,10 @@
     /**
      * Verify user credential.
      *
+     * @param isR1 {@code true} if credential is for R1
      * @return true if user credential is valid, false otherwise.
      */
-    private boolean verifyUserCredential() {
+    private boolean verifyUserCredential(boolean isR1) {
         if (mUserCredential == null) {
             Log.d(TAG, "Missing user credential");
             return false;
@@ -1095,7 +1097,10 @@
         if (!mUserCredential.validate()) {
             return false;
         }
-        if (mCaCertificate == null) {
+
+        // CA certificate is required for R1 Passpoint profile.
+        // For R2, it is downloaded using cert URL provided in PPS MO after validation completes.
+        if (isR1 && mCaCertificate == null) {
             Log.d(TAG, "Missing CA Certificate for user credential");
             return false;
         }
@@ -1106,9 +1111,10 @@
      * Verify certificate credential, which is used for EAP-TLS.  This will verify
      * that the necessary client key and certificates are provided.
      *
+     * @param isR1 {@code true} if credential is for R1
      * @return true if certificate credential is valid, false otherwise.
      */
-    private boolean verifyCertCredential() {
+    private boolean verifyCertCredential(boolean isR1) {
         if (mCertCredential == null) {
             Log.d(TAG, "Missing certificate credential");
             return false;
@@ -1123,7 +1129,9 @@
         }
 
         // Verify required key and certificates for certificate credential.
-        if (mCaCertificate == null) {
+        // CA certificate is required for R1 Passpoint profile.
+        // For R2, it is downloaded using cert URL provided in PPS MO after validation completes.
+        if (isR1 && mCaCertificate == null) {
             Log.d(TAG, "Missing CA Certificate for certificate credential");
             return false;
         }
diff --git a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
index 5f3e1b2..bf6feac 100644
--- a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
@@ -23,6 +23,7 @@
 import static org.junit.Assert.assertTrue;
 
 import android.net.MacAddress;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
 import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
 import android.os.Parcel;
 import android.support.test.filters.SmallTest;
@@ -30,6 +31,9 @@
 import org.junit.Before;
 import org.junit.Test;
 
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+
 /**
  * Unit tests for {@link android.net.wifi.WifiConfiguration}.
  */
@@ -242,4 +246,30 @@
         config.setRandomizedMacAddress(null);
         assertEquals(defaultMac, config.getRandomizedMacAddress());
     }
+
+    /**
+     * Verifies that the serialization/de-serialization for softap config works.
+     */
+    @Test
+    public void testSoftApConfigBackupAndRestore() throws Exception {
+        WifiConfiguration config = new WifiConfiguration();
+        config.SSID = "TestAP";
+        config.apBand = WifiConfiguration.AP_BAND_5GHZ;
+        config.apChannel = 40;
+        config.allowedKeyManagement.set(KeyMgmt.WPA2_PSK);
+        config.preSharedKey = "TestPsk";
+        config.hiddenSSID = true;
+
+        byte[] data = config.getBytesForBackup();
+        ByteArrayInputStream bais = new ByteArrayInputStream(data);
+        DataInputStream in = new DataInputStream(bais);
+        WifiConfiguration restoredConfig = WifiConfiguration.getWifiConfigFromBackup(in);
+
+        assertEquals(config.SSID, restoredConfig.SSID);
+        assertEquals(config.preSharedKey, restoredConfig.preSharedKey);
+        assertEquals(config.getAuthType(), restoredConfig.getAuthType());
+        assertEquals(config.apBand, restoredConfig.apBand);
+        assertEquals(config.apChannel, restoredConfig.apChannel);
+        assertEquals(config.hiddenSSID, restoredConfig.hiddenSSID);
+    }
 }
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
index 940adc8..775ce21 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
@@ -146,6 +146,7 @@
      */
     private static PasspointConfiguration createConfig() {
         PasspointConfiguration config = new PasspointConfiguration();
+        config.setUpdateIdentifier(1234);
         config.setHomeSp(createHomeSp());
         config.setCredential(createCredential());
         config.setPolicy(createPolicy());
@@ -273,18 +274,37 @@
     @Test
     public void validateDefaultConfig() throws Exception {
         PasspointConfiguration config = new PasspointConfiguration();
+
         assertFalse(config.validate());
+        assertFalse(config.validateForR2());
     }
 
     /**
-     * Verify that a configuration contained all fields is valid.
+     * Verify that a configuration containing all fields is valid for R1/R2.
      *
      * @throws Exception
      */
     @Test
     public void validateFullConfig() throws Exception {
         PasspointConfiguration config = createConfig();
+
         assertTrue(config.validate());
+        assertTrue(config.validateForR2());
+    }
+
+    /**
+     * Verify that a configuration containing all fields except for UpdateIdentifier is valid for
+     * R1, but invalid for R2.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateFullConfigWithoutUpdateIdentifier() throws Exception {
+        PasspointConfiguration config = createConfig();
+        config.setUpdateIdentifier(Integer.MIN_VALUE);
+
+        assertTrue(config.validate());
+        assertFalse(config.validateForR2());
     }
 
     /**
@@ -296,7 +316,9 @@
     public void validateConfigWithoutCredential() throws Exception {
         PasspointConfiguration config = createConfig();
         config.setCredential(null);
+
         assertFalse(config.validate());
+        assertFalse(config.validateForR2());
     }
 
     /**
@@ -308,12 +330,14 @@
     public void validateConfigWithoutHomeSp() throws Exception {
         PasspointConfiguration config = createConfig();
         config.setHomeSp(null);
+
         assertFalse(config.validate());
+        assertFalse(config.validateForR2());
     }
 
     /**
      * Verify that a configuration without Policy is valid, since Policy configurations
-     * are optional (applied for Hotspot 2.0 Release only).
+     * are optional for R1 and R2.
      *
      * @throws Exception
      */
@@ -321,12 +345,14 @@
     public void validateConfigWithoutPolicy() throws Exception {
         PasspointConfiguration config = createConfig();
         config.setPolicy(null);
+
         assertTrue(config.validate());
+        assertTrue(config.validateForR2());
     }
 
     /**
-     * Verify that a configuration without subscription update is valid, since subscription
-     * update configurations are optional (applied for Hotspot 2.0 Release only).
+     * Verify that a configuration without subscription update is valid for R1 and invalid for R2,
+     * since subscription update configuration is only applicable for R2.
      *
      * @throws Exception
      */
@@ -334,7 +360,9 @@
     public void validateConfigWithoutSubscriptionUpdate() throws Exception {
         PasspointConfiguration config = createConfig();
         config.setSubscriptionUpdate(null);
+
         assertTrue(config.validate());
+        assertFalse(config.validateForR2());
     }
 
     /**
@@ -352,12 +380,15 @@
         trustRootCertList.put(new String(rawUrlBytes, StandardCharsets.UTF_8),
                 new byte[CERTIFICATE_FINGERPRINT_BYTES]);
         config.setTrustRootCertList(trustRootCertList);
+
         assertFalse(config.validate());
 
         trustRootCertList = new HashMap<>();
         trustRootCertList.put(null, new byte[CERTIFICATE_FINGERPRINT_BYTES]);
         config.setTrustRootCertList(trustRootCertList);
+
         assertFalse(config.validate());
+        assertFalse(config.validateForR2());
     }
 
     /**
@@ -382,6 +413,7 @@
         trustRootCertList.put("test.cert.com", null);
         config.setTrustRootCertList(trustRootCertList);
         assertFalse(config.validate());
+        assertFalse(config.validateForR2());
     }
 
     /**
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
index c5ad7de..c07db6c 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
@@ -24,14 +24,13 @@
 import android.os.Parcel;
 import android.support.test.filters.SmallTest;
 
+import org.junit.Test;
+
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.PrivateKey;
 import java.security.cert.CertificateEncodingException;
 import java.security.cert.X509Certificate;
-import java.util.Arrays;
-
-import org.junit.Test;
 
 /**
  * Unit tests for {@link android.net.wifi.hotspot2.pps.CredentialTest}.
@@ -169,7 +168,12 @@
     @Test
     public void validateUserCredential() throws Exception {
         Credential cred = createCredentialWithUserCredential();
-        assertTrue(cred.validate());
+
+        // For R1 validation
+        assertTrue(cred.validate(true));
+
+        // For R2 validation
+        assertTrue(cred.validate(false));
     }
 
     /**
@@ -181,7 +185,12 @@
     public void validateUserCredentialWithoutCaCert() throws Exception {
         Credential cred = createCredentialWithUserCredential();
         cred.setCaCertificate(null);
-        assertFalse(cred.validate());
+
+        // For R1 validation
+        assertFalse(cred.validate(true));
+
+        // For R2 validation
+        assertTrue(cred.validate(false));
     }
 
     /**
@@ -193,7 +202,12 @@
     public void validateUserCredentialWithEapTls() throws Exception {
         Credential cred = createCredentialWithUserCredential();
         cred.getUserCredential().setEapType(EAPConstants.EAP_TLS);
-        assertFalse(cred.validate());
+
+        // For R1 validation
+        assertFalse(cred.validate(true));
+
+        // For R2 validation
+        assertFalse(cred.validate(false));
     }
 
 
@@ -206,7 +220,12 @@
     public void validateUserCredentialWithoutRealm() throws Exception {
         Credential cred = createCredentialWithUserCredential();
         cred.setRealm(null);
-        assertFalse(cred.validate());
+
+        // For R1 validation
+        assertFalse(cred.validate(true));
+
+        // For R2 validation
+        assertFalse(cred.validate(false));
     }
 
     /**
@@ -218,7 +237,12 @@
     public void validateUserCredentialWithoutUsername() throws Exception {
         Credential cred = createCredentialWithUserCredential();
         cred.getUserCredential().setUsername(null);
-        assertFalse(cred.validate());
+
+        // For R1 validation
+        assertFalse(cred.validate(true));
+
+        // For R2 validation
+        assertFalse(cred.validate(false));
     }
 
     /**
@@ -230,7 +254,12 @@
     public void validateUserCredentialWithoutPassword() throws Exception {
         Credential cred = createCredentialWithUserCredential();
         cred.getUserCredential().setPassword(null);
-        assertFalse(cred.validate());
+
+        // For R1 validation
+        assertFalse(cred.validate(true));
+
+        // For R2 validation
+        assertFalse(cred.validate(false));
     }
 
     /**
@@ -242,7 +271,12 @@
     public void validateUserCredentialWithoutAuthMethod() throws Exception {
         Credential cred = createCredentialWithUserCredential();
         cred.getUserCredential().setNonEapInnerMethod(null);
-        assertFalse(cred.validate());
+
+        // For R1 validation
+        assertFalse(cred.validate(true));
+
+        // For R2 validation
+        assertFalse(cred.validate(false));
     }
 
     /**
@@ -255,7 +289,12 @@
     @Test
     public void validateCertCredential() throws Exception {
         Credential cred = createCredentialWithCertificateCredential();
-        assertTrue(cred.validate());
+
+        // For R1 validation
+        assertTrue(cred.validate(true));
+
+        // For R2 validation
+        assertTrue(cred.validate(true));
     }
 
     /**
@@ -267,7 +306,12 @@
     public void validateCertCredentialWithoutCaCert() throws Exception {
         Credential cred = createCredentialWithCertificateCredential();
         cred.setCaCertificate(null);
-        assertFalse(cred.validate());
+
+        // For R1 validation
+        assertFalse(cred.validate(true));
+
+        // For R2 validation
+        assertTrue(cred.validate(false));
     }
 
     /**
@@ -279,7 +323,12 @@
     public void validateCertCredentialWithoutClientCertChain() throws Exception {
         Credential cred = createCredentialWithCertificateCredential();
         cred.setClientCertificateChain(null);
-        assertFalse(cred.validate());
+
+        // For R1 validation
+        assertFalse(cred.validate(true));
+
+        // For R2 validation
+        assertFalse(cred.validate(false));
     }
 
     /**
@@ -291,7 +340,12 @@
     public void validateCertCredentialWithoutClientPrivateKey() throws Exception {
         Credential cred = createCredentialWithCertificateCredential();
         cred.setClientPrivateKey(null);
-        assertFalse(cred.validate());
+
+        // For R1 validation
+        assertFalse(cred.validate(true));
+
+        // For R2 validation
+        assertFalse(cred.validate(false));
     }
 
     /**
@@ -304,7 +358,12 @@
     public void validateCertCredentialWithMismatchFingerprint() throws Exception {
         Credential cred = createCredentialWithCertificateCredential();
         cred.getCertCredential().setCertSha256Fingerprint(new byte[32]);
-        assertFalse(cred.validate());
+
+        // For R1 validation
+        assertFalse(cred.validate(true));
+
+        // For R2 validation
+        assertFalse(cred.validate(false));
     }
 
     /**
@@ -315,7 +374,12 @@
     @Test
     public void validateSimCredentialWithEapSim() throws Exception {
         Credential cred = createCredentialWithSimCredential();
-        assertTrue(cred.validate());
+
+        // For R1 validation
+        assertTrue(cred.validate(true));
+
+        // For R2 validation
+        assertTrue(cred.validate(false));
     }
 
     /**
@@ -327,7 +391,12 @@
     public void validateSimCredentialWithEapAka() throws Exception {
         Credential cred = createCredentialWithSimCredential();
         cred.getSimCredential().setEapType(EAPConstants.EAP_AKA);
-        assertTrue(cred.validate());
+
+        // For R1 validation
+        assertTrue(cred.validate(true));
+
+        // For R2 validation
+        assertTrue(cred.validate(false));
     }
 
     /**
@@ -339,7 +408,12 @@
     public void validateSimCredentialWithEapAkaPrime() throws Exception {
         Credential cred = createCredentialWithSimCredential();
         cred.getSimCredential().setEapType(EAPConstants.EAP_AKA_PRIME);
-        assertTrue(cred.validate());
+
+        // For R1 validation
+        assertTrue(cred.validate(true));
+
+        // For R2 validation
+        assertTrue(cred.validate(false));
     }
 
     /**
@@ -351,7 +425,12 @@
     public void validateSimCredentialWithoutIMSI() throws Exception {
         Credential cred = createCredentialWithSimCredential();
         cred.getSimCredential().setImsi(null);
-        assertFalse(cred.validate());
+
+        // For R1 validation
+        assertFalse(cred.validate(true));
+
+        // For R2 validation
+        assertFalse(cred.validate(false));
     }
 
     /**
@@ -363,7 +442,12 @@
     public void validateSimCredentialWithInvalidIMSI() throws Exception {
         Credential cred = createCredentialWithSimCredential();
         cred.getSimCredential().setImsi("dummy");
-        assertFalse(cred.validate());
+
+        // For R1 validation
+        assertFalse(cred.validate(true));
+
+        // For R2 validation
+        assertFalse(cred.validate(false));
     }
 
     /**
@@ -375,7 +459,12 @@
     public void validateSimCredentialWithEapTls() throws Exception {
         Credential cred = createCredentialWithSimCredential();
         cred.getSimCredential().setEapType(EAPConstants.EAP_TLS);
-        assertFalse(cred.validate());
+
+        // For R1 validation
+        assertFalse(cred.validate(true));
+
+        // For R2 validation
+        assertFalse(cred.validate(false));
     }
 
     /**
@@ -391,7 +480,12 @@
         simCredential.setImsi("1234*");
         simCredential.setEapType(EAPConstants.EAP_SIM);
         cred.setSimCredential(simCredential);
-        assertFalse(cred.validate());
+
+        // For R1 validation
+        assertFalse(cred.validate(true));
+
+        // For R2 validation
+        assertFalse(cred.validate(false));
     }
 
     /**