Merge "Add new values to KeyRequestType"
diff --git a/Android.bp b/Android.bp
index 9e9faf2..6cb1e5c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -147,9 +147,10 @@
         "core/java/android/hardware/display/IDisplayManager.aidl",
         "core/java/android/hardware/display/IDisplayManagerCallback.aidl",
         "core/java/android/hardware/display/IVirtualDisplayCallback.aidl",
+        "core/java/android/hardware/fingerprint/IFingerprintClientActiveCallback.aidl",
+        "core/java/android/hardware/fingerprint/IFingerprintDialogReceiver.aidl",
         "core/java/android/hardware/fingerprint/IFingerprintService.aidl",
         "core/java/android/hardware/fingerprint/IFingerprintServiceLockoutResetCallback.aidl",
-        "core/java/android/hardware/fingerprint/IFingerprintClientActiveCallback.aidl",
         "core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl",
         "core/java/android/hardware/hdmi/IHdmiControlCallback.aidl",
         "core/java/android/hardware/hdmi/IHdmiControlService.aidl",
diff --git a/api/current.txt b/api/current.txt
index 28db418..1848a8f93 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6377,6 +6377,7 @@
   public class DevicePolicyManager {
     method public void addCrossProfileIntentFilter(android.content.ComponentName, android.content.IntentFilter, int);
     method public boolean addCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String);
+    method public int addOverrideApn(android.content.ComponentName, android.telephony.data.ApnSetting);
     method public void addPersistentPreferredActivity(android.content.ComponentName, android.content.IntentFilter, android.content.ComponentName);
     method public void addUserRestriction(android.content.ComponentName, java.lang.String);
     method public boolean bindDeviceAdminServiceAsUser(android.content.ComponentName, android.content.Intent, android.content.ServiceConnection, int, android.os.UserHandle);
@@ -6420,8 +6421,10 @@
     method public android.content.ComponentName getMandatoryBackupTransport();
     method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName);
     method public long getMaximumTimeToLock(android.content.ComponentName);
+    method public java.util.List<java.lang.String> getMeteredDataDisabled(android.content.ComponentName);
     method public int getOrganizationColor(android.content.ComponentName);
     method public java.lang.CharSequence getOrganizationName(android.content.ComponentName);
+    method public java.util.List<android.telephony.data.ApnSetting> getOverrideApns(android.content.ComponentName);
     method public android.app.admin.DevicePolicyManager getParentProfileInstance(android.content.ComponentName);
     method public java.lang.String getPasswordBlacklistName(android.content.ComponentName);
     method public long getPasswordExpiration(android.content.ComponentName);
@@ -6473,6 +6476,7 @@
     method public boolean isManagedProfile(android.content.ComponentName);
     method public boolean isMasterVolumeMuted(android.content.ComponentName);
     method public boolean isNetworkLoggingEnabled(android.content.ComponentName);
+    method public boolean isOverrideApnEnabled(android.content.ComponentName);
     method public boolean isPackageSuspended(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
     method public boolean isPrintingEnabled();
     method public boolean isProfileOwnerApp(java.lang.String);
@@ -6488,6 +6492,7 @@
     method public void removeActiveAdmin(android.content.ComponentName);
     method public boolean removeCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String);
     method public boolean removeKeyPair(android.content.ComponentName, java.lang.String);
+    method public boolean removeOverrideApn(android.content.ComponentName, int);
     method public boolean removeUser(android.content.ComponentName, android.os.UserHandle);
     method public boolean requestBugreport(android.content.ComponentName);
     method public boolean resetPassword(java.lang.String, int);
@@ -6524,9 +6529,11 @@
     method public void setMasterVolumeMuted(android.content.ComponentName, boolean);
     method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
     method public void setMaximumTimeToLock(android.content.ComponentName, long);
+    method public java.util.List<java.lang.String> setMeteredDataDisabled(android.content.ComponentName, java.util.List<java.lang.String>);
     method public void setNetworkLoggingEnabled(android.content.ComponentName, boolean);
     method public void setOrganizationColor(android.content.ComponentName, int);
     method public void setOrganizationName(android.content.ComponentName, java.lang.CharSequence);
+    method public void setOverrideApnsEnabled(android.content.ComponentName, boolean);
     method public java.lang.String[] setPackagesSuspended(android.content.ComponentName, java.lang.String[], boolean);
     method public boolean setPasswordBlacklist(android.content.ComponentName, java.lang.String, java.util.List<java.lang.String>);
     method public void setPasswordExpirationTimeout(android.content.ComponentName, long);
@@ -6571,6 +6578,7 @@
     method public void transferOwnership(android.content.ComponentName, android.content.ComponentName, android.os.PersistableBundle);
     method public void uninstallAllUserCaCerts(android.content.ComponentName);
     method public void uninstallCaCert(android.content.ComponentName, byte[]);
+    method public boolean updateOverrideApn(android.content.ComponentName, int, android.telephony.data.ApnSetting);
     method public void wipeData(int);
     method public void wipeDataWithReason(int, java.lang.CharSequence);
     field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
@@ -7100,6 +7108,7 @@
     field public static final android.os.Parcelable.Creator<android.app.slice.Slice> CREATOR;
     field public static final java.lang.String EXTRA_TOGGLE_STATE = "android.app.slice.extra.TOGGLE_STATE";
     field public static final java.lang.String HINT_ACTIONS = "actions";
+    field public static final java.lang.String HINT_CALLER_NEEDED = "caller_needed";
     field public static final java.lang.String HINT_HORIZONTAL = "horizontal";
     field public static final java.lang.String HINT_LARGE = "large";
     field public static final java.lang.String HINT_LIST = "list";
@@ -7128,8 +7137,6 @@
     method public android.app.slice.Slice.Builder addAction(android.app.PendingIntent, android.app.slice.Slice, java.lang.String);
     method public android.app.slice.Slice.Builder addBundle(android.os.Bundle, java.lang.String, java.lang.String...);
     method public android.app.slice.Slice.Builder addBundle(android.os.Bundle, java.lang.String, java.util.List<java.lang.String>);
-    method public deprecated android.app.slice.Slice.Builder addColor(int, java.lang.String, java.lang.String...);
-    method public deprecated android.app.slice.Slice.Builder addColor(int, java.lang.String, java.util.List<java.lang.String>);
     method public android.app.slice.Slice.Builder addHints(java.lang.String...);
     method public android.app.slice.Slice.Builder addHints(java.util.List<java.lang.String>);
     method public android.app.slice.Slice.Builder addIcon(android.graphics.drawable.Icon, java.lang.String, java.lang.String...);
@@ -7152,7 +7159,6 @@
     method public int describeContents();
     method public android.app.PendingIntent getAction();
     method public android.os.Bundle getBundle();
-    method public deprecated int getColor();
     method public java.lang.String getFormat();
     method public java.util.List<java.lang.String> getHints();
     method public android.graphics.drawable.Icon getIcon();
@@ -7167,7 +7173,6 @@
     field public static final android.os.Parcelable.Creator<android.app.slice.SliceItem> CREATOR;
     field public static final java.lang.String FORMAT_ACTION = "action";
     field public static final java.lang.String FORMAT_BUNDLE = "bundle";
-    field public static final deprecated java.lang.String FORMAT_COLOR = "color";
     field public static final java.lang.String FORMAT_IMAGE = "image";
     field public static final java.lang.String FORMAT_INT = "int";
     field public static final java.lang.String FORMAT_REMOTE_INPUT = "input";
@@ -7197,6 +7202,7 @@
   public abstract class SliceProvider extends android.content.ContentProvider {
     ctor public SliceProvider();
     method public final int delete(android.net.Uri, java.lang.String, java.lang.String[]);
+    method public final java.lang.String getBindingPackage();
     method public final java.lang.String getType(android.net.Uri);
     method public final android.net.Uri insert(android.net.Uri, android.content.ContentValues);
     method public android.app.slice.Slice onBindSlice(android.net.Uri, java.util.List<android.app.slice.SliceSpec>);
@@ -10873,7 +10879,8 @@
     field public android.content.pm.ServiceInfo[] services;
     field public java.lang.String sharedUserId;
     field public int sharedUserLabel;
-    field public android.content.pm.Signature[] signatures;
+    field public deprecated android.content.pm.Signature[] signatures;
+    field public android.content.pm.Signature[][] signingCertificateHistory;
     field public java.lang.String[] splitNames;
     field public int[] splitRevisionCodes;
     field public deprecated int versionCode;
@@ -11076,6 +11083,8 @@
     method public abstract android.graphics.drawable.Drawable getUserBadgedIcon(android.graphics.drawable.Drawable, android.os.UserHandle);
     method public abstract java.lang.CharSequence getUserBadgedLabel(java.lang.CharSequence, android.os.UserHandle);
     method public abstract android.content.res.XmlResourceParser getXml(java.lang.String, int, android.content.pm.ApplicationInfo);
+    method public boolean hasSigningCertificate(java.lang.String, byte[], int);
+    method public boolean hasSigningCertificate(int, byte[], int);
     method public abstract boolean hasSystemFeature(java.lang.String);
     method public abstract boolean hasSystemFeature(java.lang.String, int);
     method public abstract boolean isInstantApp();
@@ -11101,6 +11110,8 @@
     method public abstract void setInstallerPackageName(java.lang.String, java.lang.String);
     method public abstract void updateInstantAppCookie(byte[]);
     method public abstract void verifyPendingInstall(int, int);
+    field public static final int CERT_INPUT_RAW_X509 = 0; // 0x0
+    field public static final int CERT_INPUT_SHA256 = 1; // 0x1
     field public static final int COMPONENT_ENABLED_STATE_DEFAULT = 0; // 0x0
     field public static final int COMPONENT_ENABLED_STATE_DISABLED = 2; // 0x2
     field public static final int COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED = 4; // 0x4
@@ -11219,7 +11230,8 @@
     field public static final int GET_RESOLVED_FILTER = 64; // 0x40
     field public static final int GET_SERVICES = 4; // 0x4
     field public static final int GET_SHARED_LIBRARY_FILES = 1024; // 0x400
-    field public static final int GET_SIGNATURES = 64; // 0x40
+    field public static final deprecated int GET_SIGNATURES = 64; // 0x40
+    field public static final int GET_SIGNING_CERTIFICATES = 134217728; // 0x8000000
     field public static final deprecated int GET_UNINSTALLED_PACKAGES = 8192; // 0x2000
     field public static final int GET_URI_PERMISSION_PATTERNS = 2048; // 0x800
     field public static final int INSTALL_REASON_DEVICE_RESTORE = 2; // 0x2
@@ -16396,6 +16408,20 @@
 
 package android.hardware.fingerprint {
 
+  public class FingerprintDialog {
+    method public void authenticate(android.hardware.fingerprint.FingerprintManager.CryptoObject, android.os.CancellationSignal, java.util.concurrent.Executor, android.hardware.fingerprint.FingerprintManager.AuthenticationCallback);
+    method public void authenticate(android.os.CancellationSignal, java.util.concurrent.Executor, android.hardware.fingerprint.FingerprintManager.AuthenticationCallback);
+  }
+
+  public static class FingerprintDialog.Builder {
+    ctor public FingerprintDialog.Builder();
+    method public android.hardware.fingerprint.FingerprintDialog build(android.content.Context);
+    method public android.hardware.fingerprint.FingerprintDialog.Builder setDescription(java.lang.CharSequence);
+    method public android.hardware.fingerprint.FingerprintDialog.Builder setNegativeButton(java.lang.CharSequence, java.util.concurrent.Executor, android.content.DialogInterface.OnClickListener);
+    method public android.hardware.fingerprint.FingerprintDialog.Builder setSubtitle(java.lang.CharSequence);
+    method public android.hardware.fingerprint.FingerprintDialog.Builder setTitle(java.lang.CharSequence);
+  }
+
   public class FingerprintManager {
     method public void authenticate(android.hardware.fingerprint.FingerprintManager.CryptoObject, android.os.CancellationSignal, int, android.hardware.fingerprint.FingerprintManager.AuthenticationCallback, android.os.Handler);
     method public boolean hasEnrolledFingerprints();
@@ -21587,6 +21613,7 @@
     method public android.location.LocationProvider getProvider(java.lang.String);
     method public java.util.List<java.lang.String> getProviders(boolean);
     method public java.util.List<java.lang.String> getProviders(android.location.Criteria, boolean);
+    method public boolean isLocationEnabled();
     method public boolean isProviderEnabled(java.lang.String);
     method public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
     method public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
@@ -35865,7 +35892,6 @@
     field public static final java.lang.String ACTION_BLUETOOTH_SETTINGS = "android.settings.BLUETOOTH_SETTINGS";
     field public static final java.lang.String ACTION_CAPTIONING_SETTINGS = "android.settings.CAPTIONING_SETTINGS";
     field public static final java.lang.String ACTION_CAST_SETTINGS = "android.settings.CAST_SETTINGS";
-    field public static final java.lang.String ACTION_CHANNEL_GROUP_NOTIFICATION_SETTINGS = "android.settings.CHANNEL_GROUP_NOTIFICATION_SETTINGS";
     field public static final java.lang.String ACTION_CHANNEL_NOTIFICATION_SETTINGS = "android.settings.CHANNEL_NOTIFICATION_SETTINGS";
     field public static final java.lang.String ACTION_DATA_ROAMING_SETTINGS = "android.settings.DATA_ROAMING_SETTINGS";
     field public static final java.lang.String ACTION_DATE_SETTINGS = "android.settings.DATE_SETTINGS";
@@ -35906,6 +35932,7 @@
     field public static final java.lang.String ACTION_SETTINGS = "android.settings.SETTINGS";
     field public static final java.lang.String ACTION_SHOW_REGULATORY_INFO = "android.settings.SHOW_REGULATORY_INFO";
     field public static final java.lang.String ACTION_SOUND_SETTINGS = "android.settings.SOUND_SETTINGS";
+    field public static final java.lang.String ACTION_STORAGE_VOLUME_ACCESS_SETTINGS = "android.settings.STORAGE_VOLUME_ACCESS_SETTINGS";
     field public static final java.lang.String ACTION_SYNC_SETTINGS = "android.settings.SYNC_SETTINGS";
     field public static final java.lang.String ACTION_USAGE_ACCESS_SETTINGS = "android.settings.USAGE_ACCESS_SETTINGS";
     field public static final java.lang.String ACTION_USER_DICTIONARY_SETTINGS = "android.settings.USER_DICTIONARY_SETTINGS";
@@ -35926,7 +35953,6 @@
     field public static final java.lang.String EXTRA_APP_PACKAGE = "android.provider.extra.APP_PACKAGE";
     field public static final java.lang.String EXTRA_AUTHORITIES = "authorities";
     field public static final java.lang.String EXTRA_BATTERY_SAVER_MODE_ENABLED = "android.settings.extra.battery_saver_mode_enabled";
-    field public static final java.lang.String EXTRA_CHANNEL_GROUP_ID = "android.provider.extra.CHANNEL_GROUP_ID";
     field public static final java.lang.String EXTRA_CHANNEL_ID = "android.provider.extra.CHANNEL_ID";
     field public static final java.lang.String EXTRA_DO_NOT_DISTURB_MODE_ENABLED = "android.settings.extra.do_not_disturb_mode_enabled";
     field public static final java.lang.String EXTRA_DO_NOT_DISTURB_MODE_MINUTES = "android.settings.extra.do_not_disturb_mode_minutes";
@@ -36038,11 +36064,11 @@
     field public static final deprecated java.lang.String HTTP_PROXY = "http_proxy";
     field public static final java.lang.String INPUT_METHOD_SELECTOR_VISIBILITY = "input_method_selector_visibility";
     field public static final deprecated java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
-    field public static final java.lang.String LOCATION_MODE = "location_mode";
-    field public static final int LOCATION_MODE_BATTERY_SAVING = 2; // 0x2
-    field public static final int LOCATION_MODE_HIGH_ACCURACY = 3; // 0x3
-    field public static final int LOCATION_MODE_OFF = 0; // 0x0
-    field public static final int LOCATION_MODE_SENSORS_ONLY = 1; // 0x1
+    field public static final deprecated java.lang.String LOCATION_MODE = "location_mode";
+    field public static final deprecated int LOCATION_MODE_BATTERY_SAVING = 2; // 0x2
+    field public static final deprecated int LOCATION_MODE_HIGH_ACCURACY = 3; // 0x3
+    field public static final deprecated int LOCATION_MODE_OFF = 0; // 0x0
+    field public static final deprecated int LOCATION_MODE_SENSORS_ONLY = 1; // 0x1
     field public static final deprecated java.lang.String LOCATION_PROVIDERS_ALLOWED = "location_providers_allowed";
     field public static final deprecated java.lang.String LOCK_PATTERN_ENABLED = "lock_pattern_autolock";
     field public static final deprecated java.lang.String LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED = "lock_pattern_tactile_feedback_enabled";
@@ -37860,6 +37886,7 @@
     method public boolean isDigestsSpecified();
     method public boolean isInvalidatedByBiometricEnrollment();
     method public boolean isRandomizedEncryptionRequired();
+    method public boolean isStrongBoxBacked();
     method public boolean isUserAuthenticationRequired();
     method public boolean isUserAuthenticationValidWhileOnBody();
   }
@@ -37877,6 +37904,7 @@
     method public android.security.keystore.KeyGenParameterSpec.Builder setDigests(java.lang.String...);
     method public android.security.keystore.KeyGenParameterSpec.Builder setEncryptionPaddings(java.lang.String...);
     method public android.security.keystore.KeyGenParameterSpec.Builder setInvalidatedByBiometricEnrollment(boolean);
+    method public android.security.keystore.KeyGenParameterSpec.Builder setIsStrongBoxBacked(boolean);
     method public android.security.keystore.KeyGenParameterSpec.Builder setKeySize(int);
     method public android.security.keystore.KeyGenParameterSpec.Builder setKeyValidityEnd(java.util.Date);
     method public android.security.keystore.KeyGenParameterSpec.Builder setKeyValidityForConsumptionEnd(java.util.Date);
@@ -37937,6 +37965,7 @@
     field public static final java.lang.String ENCRYPTION_PADDING_PKCS7 = "PKCS7Padding";
     field public static final java.lang.String ENCRYPTION_PADDING_RSA_OAEP = "OAEPPadding";
     field public static final java.lang.String ENCRYPTION_PADDING_RSA_PKCS1 = "PKCS1Padding";
+    field public static final deprecated java.lang.String KEY_ALGORITHM_3DES = "DESede";
     field public static final java.lang.String KEY_ALGORITHM_AES = "AES";
     field public static final java.lang.String KEY_ALGORITHM_EC = "EC";
     field public static final java.lang.String KEY_ALGORITHM_HMAC_SHA1 = "HmacSHA1";
@@ -37947,11 +37976,13 @@
     field public static final java.lang.String KEY_ALGORITHM_RSA = "RSA";
     field public static final int ORIGIN_GENERATED = 1; // 0x1
     field public static final int ORIGIN_IMPORTED = 2; // 0x2
+    field public static final int ORIGIN_SECURELY_IMPORTED = 8; // 0x8
     field public static final int ORIGIN_UNKNOWN = 4; // 0x4
     field public static final int PURPOSE_DECRYPT = 2; // 0x2
     field public static final int PURPOSE_ENCRYPT = 1; // 0x1
     field public static final int PURPOSE_SIGN = 4; // 0x4
     field public static final int PURPOSE_VERIFY = 8; // 0x8
+    field public static final int PURPOSE_WRAP_KEY = 32; // 0x20
     field public static final java.lang.String SIGNATURE_PADDING_RSA_PKCS1 = "PKCS1";
     field public static final java.lang.String SIGNATURE_PADDING_RSA_PSS = "PSS";
   }
@@ -37991,12 +38022,24 @@
     method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidityDurationSeconds(int);
   }
 
+  public class StrongBoxUnavailableException extends java.security.ProviderException {
+    ctor public StrongBoxUnavailableException();
+  }
+
   public class UserNotAuthenticatedException extends java.security.InvalidKeyException {
     ctor public UserNotAuthenticatedException();
     ctor public UserNotAuthenticatedException(java.lang.String);
     ctor public UserNotAuthenticatedException(java.lang.String, java.lang.Throwable);
   }
 
+  public class WrappedKeyEntry implements java.security.KeyStore.Entry {
+    ctor public WrappedKeyEntry(byte[], java.lang.String, java.lang.String, java.security.spec.AlgorithmParameterSpec);
+    method public java.security.spec.AlgorithmParameterSpec getAlgorithmParameterSpec();
+    method public java.lang.String getTransformation();
+    method public byte[] getWrappedKeyBytes();
+    method public java.lang.String getWrappingKeyAlias();
+  }
+
 }
 
 package android.service.autofill {
@@ -40888,6 +40931,7 @@
     field public static final java.lang.String KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_VAL_STRING = "ci_action_on_sys_update_extra_val_string";
     field public static final java.lang.String KEY_CI_ACTION_ON_SYS_UPDATE_INTENT_STRING = "ci_action_on_sys_update_intent_string";
     field public static final java.lang.String KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING = "config_ims_package_override_string";
+    field public static final java.lang.String KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING = "config_plans_package_override_string";
     field public static final java.lang.String KEY_CONFIG_TELEPHONY_USE_OWN_NUMBER_FOR_VOICEMAIL_BOOL = "config_telephony_use_own_number_for_voicemail_bool";
     field public static final java.lang.String KEY_CSP_ENABLED_BOOL = "csp_enabled_bool";
     field public static final java.lang.String KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG = "data_limit_threshold_bytes_long";
@@ -41581,10 +41625,16 @@
     method public static int getDefaultSmsSubscriptionId();
     method public static int getDefaultSubscriptionId();
     method public static int getDefaultVoiceSubscriptionId();
+    method public java.util.List<android.telephony.SubscriptionPlan> getSubscriptionPlans(int);
     method public boolean isNetworkRoaming(int);
     method public void removeOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
+    method public void setSubscriptionOverrideCongested(int, boolean, long);
+    method public void setSubscriptionOverrideUnmetered(int, boolean, long);
+    method public void setSubscriptionPlans(int, java.util.List<android.telephony.SubscriptionPlan>);
     field public static final java.lang.String ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED = "android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED";
     field public static final java.lang.String ACTION_DEFAULT_SUBSCRIPTION_CHANGED = "android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED";
+    field public static final java.lang.String ACTION_MANAGE_SUBSCRIPTION_PLANS = "android.telephony.action.MANAGE_SUBSCRIPTION_PLANS";
+    field public static final java.lang.String ACTION_REFRESH_SUBSCRIPTION_PLANS = "android.telephony.action.REFRESH_SUBSCRIPTION_PLANS";
     field public static final int DATA_ROAMING_DISABLE = 0; // 0x0
     field public static final int DATA_ROAMING_ENABLE = 1; // 0x1
     field public static final java.lang.String EXTRA_SUBSCRIPTION_INDEX = "android.telephony.extra.SUBSCRIPTION_INDEX";
@@ -41596,6 +41646,38 @@
     method public void onSubscriptionsChanged();
   }
 
+  public final class SubscriptionPlan implements android.os.Parcelable {
+    method public java.util.Iterator<android.util.Pair<java.time.ZonedDateTime, java.time.ZonedDateTime>> cycleIterator();
+    method public int describeContents();
+    method public int getDataLimitBehavior();
+    method public long getDataLimitBytes();
+    method public long getDataUsageBytes();
+    method public long getDataUsageTime();
+    method public java.lang.CharSequence getSummary();
+    method public java.lang.CharSequence getTitle();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final long BYTES_UNKNOWN = -1L; // 0xffffffffffffffffL
+    field public static final long BYTES_UNLIMITED = 9223372036854775807L; // 0x7fffffffffffffffL
+    field public static final android.os.Parcelable.Creator<android.telephony.SubscriptionPlan> CREATOR;
+    field public static final int LIMIT_BEHAVIOR_BILLED = 1; // 0x1
+    field public static final int LIMIT_BEHAVIOR_DISABLED = 0; // 0x0
+    field public static final int LIMIT_BEHAVIOR_THROTTLED = 2; // 0x2
+    field public static final int LIMIT_BEHAVIOR_UNKNOWN = -1; // 0xffffffff
+    field public static final long TIME_UNKNOWN = -1L; // 0xffffffffffffffffL
+  }
+
+  public static class SubscriptionPlan.Builder {
+    method public android.telephony.SubscriptionPlan build();
+    method public static android.telephony.SubscriptionPlan.Builder createNonrecurring(java.time.ZonedDateTime, java.time.ZonedDateTime);
+    method public static android.telephony.SubscriptionPlan.Builder createRecurringDaily(java.time.ZonedDateTime);
+    method public static android.telephony.SubscriptionPlan.Builder createRecurringMonthly(java.time.ZonedDateTime);
+    method public static android.telephony.SubscriptionPlan.Builder createRecurringWeekly(java.time.ZonedDateTime);
+    method public android.telephony.SubscriptionPlan.Builder setDataLimit(long, int);
+    method public android.telephony.SubscriptionPlan.Builder setDataUsage(long, long);
+    method public android.telephony.SubscriptionPlan.Builder setSummary(java.lang.CharSequence);
+    method public android.telephony.SubscriptionPlan.Builder setTitle(java.lang.CharSequence);
+  }
+
   public class TelephonyManager {
     method public boolean canChangeDtmfToneLength();
     method public android.telephony.TelephonyManager createForPhoneAccountHandle(android.telecom.PhoneAccountHandle);
@@ -45691,6 +45773,7 @@
     field public static final int KEYCODE_PROG_YELLOW = 185; // 0xb9
     field public static final int KEYCODE_Q = 45; // 0x2d
     field public static final int KEYCODE_R = 46; // 0x2e
+    field public static final int KEYCODE_REFRESH = 285; // 0x11d
     field public static final int KEYCODE_RIGHT_BRACKET = 72; // 0x48
     field public static final int KEYCODE_RO = 217; // 0xd9
     field public static final int KEYCODE_S = 47; // 0x2f
@@ -47859,6 +47942,7 @@
     method protected final int getLocalFeatures();
     method public android.media.session.MediaController getMediaController();
     method public abstract int getNavigationBarColor();
+    method public int getNavigationBarDividerColor();
     method public android.transition.Transition getReenterTransition();
     method public android.transition.Transition getReturnTransition();
     method public android.transition.Transition getSharedElementEnterTransition();
@@ -47927,6 +48011,7 @@
     method public void setLogo(int);
     method public void setMediaController(android.media.session.MediaController);
     method public abstract void setNavigationBarColor(int);
+    method public void setNavigationBarDividerColor(int);
     method public void setReenterTransition(android.transition.Transition);
     method public abstract void setResizingCaptionDrawable(android.graphics.drawable.Drawable);
     method public final void setRestrictedCaptionAreaListener(android.view.Window.OnRestrictedCaptionAreaChangedListener);
diff --git a/api/system-current.txt b/api/system-current.txt
index 97f82e9..14320c4 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -2333,11 +2333,15 @@
     method public deprecated boolean addGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener);
     method public void flushGnssBatch();
     method public int getGnssBatchSize();
+    method public boolean isLocationEnabledForUser(android.os.UserHandle);
+    method public boolean isProviderEnabledForUser(java.lang.String, android.os.UserHandle);
     method public boolean registerGnssBatchedLocationCallback(long, boolean, android.location.BatchedLocationCallback, android.os.Handler);
     method public deprecated void removeGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener);
     method public deprecated void removeGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener);
     method public void requestLocationUpdates(android.location.LocationRequest, android.location.LocationListener, android.os.Looper);
     method public void requestLocationUpdates(android.location.LocationRequest, android.app.PendingIntent);
+    method public void setLocationEnabledForUser(boolean, android.os.UserHandle);
+    method public boolean setProviderEnabledForUser(java.lang.String, boolean, android.os.UserHandle);
     method public boolean unregisterGnssBatchedLocationCallback(android.location.BatchedLocationCallback);
   }
 
@@ -2867,6 +2871,7 @@
   }
 
   public final class IpSecManager {
+    method public void applyTunnelModeTransform(android.net.IpSecManager.IpSecTunnelInterface, int, android.net.IpSecTransform) throws java.io.IOException;
     method public android.net.IpSecManager.IpSecTunnelInterface createIpSecTunnelInterface(java.net.InetAddress, java.net.InetAddress, android.net.Network) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
   }
 
@@ -3898,6 +3903,120 @@
 
 }
 
+package android.security.keystore.recovery {
+
+  public class DecryptionFailedException extends java.security.GeneralSecurityException {
+    ctor public DecryptionFailedException(java.lang.String);
+  }
+
+  public class InternalRecoveryServiceException extends java.security.GeneralSecurityException {
+    ctor public InternalRecoveryServiceException(java.lang.String);
+    ctor public InternalRecoveryServiceException(java.lang.String, java.lang.Throwable);
+  }
+
+  public final class KeyChainProtectionParams implements android.os.Parcelable {
+    method public void clearSecret();
+    method public int describeContents();
+    method public android.security.keystore.recovery.KeyDerivationParams getKeyDerivationParams();
+    method public int getLockScreenUiFormat();
+    method public byte[] getSecret();
+    method public int getUserSecretType();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.security.keystore.recovery.KeyChainProtectionParams> CREATOR;
+    field public static final int TYPE_CUSTOM_PASSWORD = 101; // 0x65
+    field public static final int TYPE_LOCKSCREEN = 100; // 0x64
+    field public static final int UI_FORMAT_PASSWORD = 2; // 0x2
+    field public static final int UI_FORMAT_PATTERN = 3; // 0x3
+    field public static final int UI_FORMAT_PIN = 1; // 0x1
+  }
+
+  public static class KeyChainProtectionParams.Builder {
+    ctor public KeyChainProtectionParams.Builder();
+    method public android.security.keystore.recovery.KeyChainProtectionParams build();
+    method public android.security.keystore.recovery.KeyChainProtectionParams.Builder setKeyDerivationParams(android.security.keystore.recovery.KeyDerivationParams);
+    method public android.security.keystore.recovery.KeyChainProtectionParams.Builder setLockScreenUiFormat(int);
+    method public android.security.keystore.recovery.KeyChainProtectionParams.Builder setSecret(byte[]);
+    method public android.security.keystore.recovery.KeyChainProtectionParams.Builder setUserSecretType(int);
+  }
+
+  public final class KeyChainSnapshot implements android.os.Parcelable {
+    method public int describeContents();
+    method public long getCounterId();
+    method public byte[] getEncryptedRecoveryKeyBlob();
+    method public java.util.List<android.security.keystore.recovery.KeyChainProtectionParams> getKeyChainProtectionParams();
+    method public int getMaxAttempts();
+    method public byte[] getServerParams();
+    method public int getSnapshotVersion();
+    method public byte[] getTrustedHardwarePublicKey();
+    method public java.util.List<android.security.keystore.recovery.WrappedApplicationKey> getWrappedApplicationKeys();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.security.keystore.recovery.KeyChainSnapshot> CREATOR;
+  }
+
+  public final class KeyDerivationParams implements android.os.Parcelable {
+    method public static android.security.keystore.recovery.KeyDerivationParams createSha256Params(byte[]);
+    method public int describeContents();
+    method public int getAlgorithm();
+    method public byte[] getSalt();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int ALGORITHM_SHA256 = 1; // 0x1
+    field public static final android.os.Parcelable.Creator<android.security.keystore.recovery.KeyDerivationParams> CREATOR;
+  }
+
+  public class LockScreenRequiredException extends java.security.GeneralSecurityException {
+    ctor public LockScreenRequiredException(java.lang.String);
+  }
+
+  public class RecoveryController {
+    method public byte[] generateAndStoreKey(java.lang.String, byte[]) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException;
+    method public java.util.List<java.lang.String> getAliases(java.lang.String) throws android.security.keystore.recovery.InternalRecoveryServiceException;
+    method public static android.security.keystore.recovery.RecoveryController getInstance(android.content.Context);
+    method public int[] getPendingRecoverySecretTypes() throws android.security.keystore.recovery.InternalRecoveryServiceException;
+    method public android.security.keystore.recovery.KeyChainSnapshot getRecoveryData() throws android.security.keystore.recovery.InternalRecoveryServiceException;
+    method public int[] getRecoverySecretTypes() throws android.security.keystore.recovery.InternalRecoveryServiceException;
+    method public int getRecoveryStatus(java.lang.String, java.lang.String) throws android.security.keystore.recovery.InternalRecoveryServiceException;
+    method public void initRecoveryService(java.lang.String, byte[]) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException;
+    method public void recoverySecretAvailable(android.security.keystore.recovery.KeyChainProtectionParams) throws android.security.keystore.recovery.InternalRecoveryServiceException;
+    method public void removeKey(java.lang.String) throws android.security.keystore.recovery.InternalRecoveryServiceException;
+    method public void setRecoverySecretTypes(int[]) throws android.security.keystore.recovery.InternalRecoveryServiceException;
+    method public void setRecoveryStatus(java.lang.String, java.lang.String, int) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.content.pm.PackageManager.NameNotFoundException;
+    method public void setServerParams(byte[]) throws android.security.keystore.recovery.InternalRecoveryServiceException;
+    method public void setSnapshotCreatedPendingIntent(android.app.PendingIntent) throws android.security.keystore.recovery.InternalRecoveryServiceException;
+    field public static final int RECOVERY_STATUS_MISSING_ACCOUNT = 2; // 0x2
+    field public static final int RECOVERY_STATUS_PERMANENT_FAILURE = 3; // 0x3
+    field public static final int RECOVERY_STATUS_SYNCED = 0; // 0x0
+    field public static final int RECOVERY_STATUS_SYNC_IN_PROGRESS = 1; // 0x1
+  }
+
+  public class RecoverySession implements java.lang.AutoCloseable {
+    method public void close();
+    method public java.util.Map<java.lang.String, byte[]> recoverKeys(byte[], java.util.List<android.security.keystore.recovery.WrappedApplicationKey>) throws android.security.keystore.recovery.DecryptionFailedException, android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.SessionExpiredException;
+    method public byte[] start(byte[], byte[], byte[], java.util.List<android.security.keystore.recovery.KeyChainProtectionParams>) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException;
+  }
+
+  public class SessionExpiredException extends java.security.GeneralSecurityException {
+    ctor public SessionExpiredException(java.lang.String);
+  }
+
+  public final class WrappedApplicationKey implements android.os.Parcelable {
+    method public int describeContents();
+    method public byte[] getAccount();
+    method public java.lang.String getAlias();
+    method public byte[] getEncryptedKeyMaterial();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.security.keystore.recovery.WrappedApplicationKey> CREATOR;
+  }
+
+  public static class WrappedApplicationKey.Builder {
+    ctor public WrappedApplicationKey.Builder();
+    method public android.security.keystore.recovery.WrappedApplicationKey build();
+    method public android.security.keystore.recovery.WrappedApplicationKey.Builder setAccount(byte[]);
+    method public android.security.keystore.recovery.WrappedApplicationKey.Builder setAlias(java.lang.String);
+    method public android.security.keystore.recovery.WrappedApplicationKey.Builder setEncryptedKeyMaterial(byte[]);
+  }
+
+}
+
 package android.service.autofill {
 
   public abstract class AutofillFieldClassificationService extends android.app.Service {
@@ -4390,6 +4509,12 @@
 
 package android.telephony {
 
+  public static final class AccessNetworkConstants.TransportType {
+    ctor public AccessNetworkConstants.TransportType();
+    field public static final int WLAN = 2; // 0x2
+    field public static final int WWAN = 1; // 0x1
+  }
+
   public class CarrierConfigManager {
     method public static android.os.PersistableBundle getDefaultConfig();
     method public void updateConfigForPhoneId(int, java.lang.String);
@@ -4605,18 +4730,21 @@
     method public abstract android.telephony.data.DataService.DataServiceProvider createDataServiceProvider(int);
     field public static final java.lang.String DATA_SERVICE_EXTRA_SLOT_ID = "android.telephony.data.extra.SLOT_ID";
     field public static final java.lang.String DATA_SERVICE_INTERFACE = "android.telephony.data.DataService";
+    field public static final int REQUEST_REASON_HANDOVER = 3; // 0x3
+    field public static final int REQUEST_REASON_NORMAL = 1; // 0x1
+    field public static final int REQUEST_REASON_SHUTDOWN = 2; // 0x2
   }
 
   public class DataService.DataServiceProvider {
     ctor public DataService.DataServiceProvider(int);
-    method public void deactivateDataCall(int, boolean, boolean, android.telephony.data.DataServiceCallback);
+    method public void deactivateDataCall(int, int, android.telephony.data.DataServiceCallback);
     method public void getDataCallList(android.telephony.data.DataServiceCallback);
     method public final int getSlotId();
     method public final void notifyDataCallListChanged(java.util.List<android.telephony.data.DataCallResponse>);
     method protected void onDestroy();
     method public void setDataProfile(java.util.List<android.telephony.data.DataProfile>, boolean, android.telephony.data.DataServiceCallback);
     method public void setInitialAttachApn(android.telephony.data.DataProfile, boolean, android.telephony.data.DataServiceCallback);
-    method public void setupDataCall(int, android.telephony.data.DataProfile, boolean, boolean, boolean, android.net.LinkProperties, android.telephony.data.DataServiceCallback);
+    method public void setupDataCall(int, android.telephony.data.DataProfile, boolean, boolean, int, android.net.LinkProperties, android.telephony.data.DataServiceCallback);
   }
 
   public class DataServiceCallback {
diff --git a/api/test-current.txt b/api/test-current.txt
index acc819e..254fc15 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -521,6 +521,7 @@
   }
 
   public static final class Settings.Global extends android.provider.Settings.NameValueTable {
+    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";
     field public static final java.lang.String USE_OPEN_WIFI_PACKAGE = "use_open_wifi_package";
   }
diff --git a/cmds/incidentd/Android.mk b/cmds/incidentd/Android.mk
index 368a70b..2b00d9e 100644
--- a/cmds/incidentd/Android.mk
+++ b/cmds/incidentd/Android.mk
@@ -91,9 +91,7 @@
 
 gen_src_dir:=
 
-ifeq ($(BUILD_WITH_INCIDENTD_RC), true)
 LOCAL_INIT_RC := incidentd.rc
-endif
 
 include $(BUILD_EXECUTABLE)
 
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index ca097d0..ba628b8 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -725,7 +725,7 @@
     if (checkCallingPermission(String16(kPermissionDump))) {
         ConfigKey configKey(ipc->getCallingUid(), key);
         StatsdConfig cfg;
-        if (!cfg.ParseFromArray(&config[0], config.size())) {
+        if (config.empty() || !cfg.ParseFromArray(&config[0], config.size())) {
             *success = false;
             return Status::ok();
         }
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 49d5224..cc68c05 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -699,6 +699,26 @@
     }
 
     @Override
+    public boolean hasSigningCertificate(
+            String packageName, byte[] certificate, @PackageManager.CertificateInputType int type) {
+        try {
+            return mPM.hasSigningCertificate(packageName, certificate, type);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @Override
+    public boolean hasSigningCertificate(
+            int uid, byte[] certificate, @PackageManager.CertificateInputType int type) {
+        try {
+            return mPM.hasUidSigningCertificate(uid, certificate, type);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @Override
     public String[] getPackagesForUid(int uid) {
         try {
             return mPM.getPackagesForUid(uid);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 2e3b8af..d6fddfc 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -4130,7 +4130,7 @@
             final Bundle ex = mN.extras;
             updateBackgroundColor(contentView);
             bindNotificationHeader(contentView, p.ambient, p.headerTextSecondary);
-            bindLargeIcon(contentView, p.hideLargeIcon, p.alwaysShowReply);
+            bindLargeIcon(contentView, p.hideLargeIcon || p.ambient, p.alwaysShowReply);
             boolean showProgress = handleProgressBar(p.hasProgress, contentView, ex);
             if (p.title != null) {
                 contentView.setViewVisibility(R.id.title, View.VISIBLE);
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index c06ad3f..30f2697 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -32,8 +32,6 @@
 
 import com.android.internal.util.Preconditions;
 
-import com.android.internal.util.Preconditions;
-
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.xmlpull.v1.XmlPullParser;
@@ -936,7 +934,9 @@
     }
 
     /** @hide */
-    public void toProto(ProtoOutputStream proto) {
+    public void writeToProto(ProtoOutputStream proto, long fieldId) {
+        final long token = proto.start(fieldId);
+
         proto.write(NotificationChannelProto.ID, mId);
         proto.write(NotificationChannelProto.NAME, mName);
         proto.write(NotificationChannelProto.DESCRIPTION, mDesc);
@@ -959,10 +959,10 @@
         proto.write(NotificationChannelProto.IS_DELETED, mDeleted);
         proto.write(NotificationChannelProto.GROUP, mGroup);
         if (mAudioAttributes != null) {
-            long aToken = proto.start(NotificationChannelProto.AUDIO_ATTRIBUTES);
-            mAudioAttributes.toProto(proto);
-            proto.end(aToken);
+            mAudioAttributes.writeToProto(proto, NotificationChannelProto.AUDIO_ATTRIBUTES);
         }
         proto.write(NotificationChannelProto.IS_BLOCKABLE_SYSTEM, mBlockableSystem);
+
+        proto.end(token);
     }
 }
diff --git a/core/java/android/app/NotificationChannelGroup.java b/core/java/android/app/NotificationChannelGroup.java
index 5cb7fb7..16166f7 100644
--- a/core/java/android/app/NotificationChannelGroup.java
+++ b/core/java/android/app/NotificationChannelGroup.java
@@ -298,13 +298,17 @@
     }
 
     /** @hide */
-    public void toProto(ProtoOutputStream proto) {
+    public void writeToProto(ProtoOutputStream proto, long fieldId) {
+        final long token = proto.start(fieldId);
+
         proto.write(NotificationChannelGroupProto.ID, mId);
         proto.write(NotificationChannelGroupProto.NAME, mName.toString());
         proto.write(NotificationChannelGroupProto.DESCRIPTION, mDescription);
         proto.write(NotificationChannelGroupProto.IS_BLOCKED, mBlocked);
         for (NotificationChannel channel : mChannels) {
-            channel.toProto(proto);
+            channel.writeToProto(proto, NotificationChannelGroupProto.CHANNELS);
         }
+
+        proto.end(token);
     }
 }
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 659cf16..45bed5d 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -1133,7 +1133,7 @@
         }
 
         /** @hide */
-        public void toProto(ProtoOutputStream proto, long fieldId) {
+        public void writeToProto(ProtoOutputStream proto, long fieldId) {
             final long pToken = proto.start(fieldId);
 
             bitwiseToProtoEnum(proto, PolicyProto.PRIORITY_CATEGORIES, priorityCategories);
diff --git a/core/java/android/app/ProfilerInfo.java b/core/java/android/app/ProfilerInfo.java
index a295c4c..0ed1b08 100644
--- a/core/java/android/app/ProfilerInfo.java
+++ b/core/java/android/app/ProfilerInfo.java
@@ -20,6 +20,7 @@
 import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
 import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
 
 import java.io.IOException;
 import java.util.Objects;
@@ -124,6 +125,20 @@
         out.writeBoolean(attachAgentDuringBind);
     }
 
+    /** @hide */
+    public void writeToProto(ProtoOutputStream proto, long fieldId) {
+        final long token = proto.start(fieldId);
+        proto.write(ProfilerInfoProto.PROFILE_FILE, profileFile);
+        if (profileFd != null) {
+            proto.write(ProfilerInfoProto.PROFILE_FD, profileFd.getFd());
+        }
+        proto.write(ProfilerInfoProto.SAMPLING_INTERVAL, samplingInterval);
+        proto.write(ProfilerInfoProto.AUTO_STOP_PROFILER, autoStopProfiler);
+        proto.write(ProfilerInfoProto.STREAMING_OUTPUT, streamingOutput);
+        proto.write(ProfilerInfoProto.AGENT, agent);
+        proto.end(token);
+    }
+
     public static final Parcelable.Creator<ProfilerInfo> CREATOR =
             new Parcelable.Creator<ProfilerInfo>() {
                 @Override
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 7fccda8..52870b3 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -68,6 +68,7 @@
 import android.security.keystore.ParcelableKeyGenParameterSpec;
 import android.service.restrictions.RestrictionsReceiver;
 import android.telephony.TelephonyManager;
+import android.telephony.data.ApnSetting;
 import android.util.ArraySet;
 import android.util.Log;
 
@@ -8228,6 +8229,47 @@
     }
 
     /**
+     * Called by a device or profile owner to restrict packages from accessing metered data.
+     *
+     * @param admin which {@link DeviceAdminReceiver} this request is associated with.
+     * @param packageNames the list of package names to be restricted.
+     * @return a list of package names which could not be restricted.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
+     */
+    public @NonNull List<String> setMeteredDataDisabled(@NonNull ComponentName admin,
+            @NonNull List<String> packageNames) {
+        throwIfParentInstance("setMeteredDataDisabled");
+        if (mService != null) {
+            try {
+                return mService.setMeteredDataDisabled(admin, packageNames);
+            } catch (RemoteException re) {
+                throw re.rethrowFromSystemServer();
+            }
+        }
+        return packageNames;
+    }
+
+    /**
+     * Called by a device or profile owner to retrieve the list of packages which are restricted
+     * by the admin from accessing metered data.
+     *
+     * @param admin which {@link DeviceAdminReceiver} this request is associated with.
+     * @return the list of restricted package names.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
+     */
+    public @NonNull List<String> getMeteredDataDisabled(@NonNull ComponentName admin) {
+        throwIfParentInstance("getMeteredDataDisabled");
+        if (mService != null) {
+            try {
+                return mService.getMeteredDataDisabled(admin);
+            } catch (RemoteException re) {
+                throw re.rethrowFromSystemServer();
+            }
+        }
+        return new ArrayList<>();
+    }
+
+    /**
      * Called by device owners to retrieve device logs from before the device's last reboot.
      * <p>
      * <strong> This API is not supported on all devices. Calling this API on unsupported devices
@@ -9257,4 +9299,138 @@
             throw re.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * Called by device owner to add an override APN.
+     *
+     * @param admin which {@link DeviceAdminReceiver} this request is associated with
+     * @param apnSetting the override APN to insert
+     * @return The {@code id} of inserted override APN. Or {@code -1} when failed to insert into
+     *         the database.
+     * @throws SecurityException if {@code admin} is not a device owner.
+     *
+     * @see #setOverrideApnsEnabled(ComponentName, boolean)
+     */
+    public int addOverrideApn(@NonNull ComponentName admin, @NonNull ApnSetting apnSetting) {
+        throwIfParentInstance("addOverrideApn");
+        if (mService != null) {
+            try {
+                return mService.addOverrideApn(admin, apnSetting);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Called by device owner to update an override APN.
+     *
+     * @param admin which {@link DeviceAdminReceiver} this request is associated with
+     * @param apnId the {@code id} of the override APN to update
+     * @param apnSetting the override APN to update
+     * @return {@code true} if the required override APN is successfully updated,
+     *         {@code false} otherwise.
+     * @throws SecurityException if {@code admin} is not a device owner.
+     *
+     * @see #setOverrideApnsEnabled(ComponentName, boolean)
+     */
+    public boolean updateOverrideApn(@NonNull ComponentName admin, int apnId,
+            @NonNull ApnSetting apnSetting) {
+        throwIfParentInstance("updateOverrideApn");
+        if (mService != null) {
+            try {
+                return mService.updateOverrideApn(admin, apnId, apnSetting);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Called by device owner to remove an override APN.
+     *
+     * @param admin which {@link DeviceAdminReceiver} this request is associated with
+     * @param apnId the {@code id} of the override APN to remove
+     * @return {@code true} if the required override APN is successfully removed, {@code false}
+     *         otherwise.
+     * @throws SecurityException if {@code admin} is not a device owner.
+     *
+     * @see #setOverrideApnsEnabled(ComponentName, boolean)
+     */
+    public boolean removeOverrideApn(@NonNull ComponentName admin, int apnId) {
+        throwIfParentInstance("removeOverrideApn");
+        if (mService != null) {
+            try {
+                return mService.removeOverrideApn(admin, apnId);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Called by device owner to get all override APNs inserted by device owner.
+     *
+     * @param admin which {@link DeviceAdminReceiver} this request is associated with
+     * @return A list of override APNs inserted by device owner.
+     * @throws SecurityException if {@code admin} is not a device owner.
+     *
+     * @see #setOverrideApnsEnabled(ComponentName, boolean)
+     */
+    public List<ApnSetting> getOverrideApns(@NonNull ComponentName admin) {
+        throwIfParentInstance("getOverrideApns");
+        if (mService != null) {
+            try {
+                return mService.getOverrideApns(admin);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+        return Collections.emptyList();
+    }
+
+    /**
+     * Called by device owner to set if override APNs should be enabled.
+     * <p> Override APNs are separated from other APNs on the device, and can only be inserted or
+     * modified by the device owner. When enabled, only override APNs are in use, any other APNs
+     * are ignored.
+     *
+     * @param admin which {@link DeviceAdminReceiver} this request is associated with
+     * @param enabled {@code true} if override APNs should be enabled, {@code false} otherwise
+     * @throws SecurityException if {@code admin} is not a device owner.
+     */
+    public void setOverrideApnsEnabled(@NonNull ComponentName admin, boolean enabled) {
+        throwIfParentInstance("setOverrideApnEnabled");
+        if (mService != null) {
+            try {
+                mService.setOverrideApnsEnabled(admin, enabled);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    /**
+     * Called by device owner to check if override APNs are currently enabled.
+     *
+     * @param admin which {@link DeviceAdminReceiver} this request is associated with
+     * @return {@code true} if override APNs are currently enabled, {@code false} otherwise.
+     * @throws SecurityException if {@code admin} is not a device owner.
+     *
+     * @see #setOverrideApnsEnabled(ComponentName, boolean)
+     */
+    public boolean isOverrideApnEnabled(@NonNull ComponentName admin) {
+        throwIfParentInstance("isOverrideApnEnabled");
+        if (mService != null) {
+            try {
+                return mService.isOverrideApnEnabled(admin);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+        return false;
+    }
 }
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index d2a2be7..a5ca4cf 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -38,6 +38,7 @@
 import android.os.UserHandle;
 import android.security.keymaster.KeymasterCertificateChain;
 import android.security.keystore.ParcelableKeyGenParameterSpec;
+import android.telephony.data.ApnSetting;
 
 import java.util.List;
 
@@ -400,4 +401,14 @@
     void setPrintingEnabled(in ComponentName admin, boolean enabled);
     boolean isPrintingEnabled();
     CharSequence getPrintingDisabledReason();
+
+    List<String> setMeteredDataDisabled(in ComponentName admin, in List<String> packageNames);
+    List<String> getMeteredDataDisabled(in ComponentName admin);
+
+    int addOverrideApn(in ComponentName admin, in ApnSetting apnSetting);
+    boolean updateOverrideApn(in ComponentName admin, int apnId, in ApnSetting apnSetting);
+    boolean removeOverrideApn(in ComponentName admin, int apnId);
+    List<ApnSetting> getOverrideApns(in ComponentName admin);
+    void setOverrideApnsEnabled(in ComponentName admin, boolean enabled);
+    boolean isOverrideApnEnabled(in ComponentName admin);
 }
diff --git a/core/java/android/app/slice/Slice.java b/core/java/android/app/slice/Slice.java
index 5bd3440..5808f8b 100644
--- a/core/java/android/app/slice/Slice.java
+++ b/core/java/android/app/slice/Slice.java
@@ -156,10 +156,11 @@
      */
     public static final String HINT_SEE_MORE = "see_more";
     /**
-     * A hint to tell the system that this slice cares about the return value of
-     * {@link SliceProvider#getBindingPackage} and should not cache the result
-     * for multiple apps.
-     * @hide
+     * A hint used when implementing app-specific slice permissions.
+     * Tells the system that for this slice the return value of
+     * {@link SliceProvider#onBindSlice(Uri, List)} may be different depending on
+     * {@link SliceProvider#getBindingPackage} and should not be cached for multiple
+     * apps.
      */
     public static final String HINT_CALLER_NEEDED = "caller_needed";
     /**
@@ -429,28 +430,6 @@
          * Add a color to the slice being constructed
          * @param subType Optional template-specific type information
          * @see {@link SliceItem#getSubType()}
-         * @deprecated will be removed once supportlib updates
-         */
-        public Builder addColor(int color, @Nullable String subType, @SliceHint String... hints) {
-            mItems.add(new SliceItem(color, SliceItem.FORMAT_INT, subType, hints));
-            return this;
-        }
-
-        /**
-         * Add a color to the slice being constructed
-         * @param subType Optional template-specific type information
-         * @see {@link SliceItem#getSubType()}
-         * @deprecated will be removed once supportlib updates
-         */
-        public Builder addColor(int color, @Nullable String subType,
-                @SliceHint List<String> hints) {
-            return addColor(color, subType, hints.toArray(new String[hints.size()]));
-        }
-
-        /**
-         * Add a color to the slice being constructed
-         * @param subType Optional template-specific type information
-         * @see {@link SliceItem#getSubType()}
          */
         public Builder addInt(int value, @Nullable String subType, @SliceHint String... hints) {
             mItems.add(new SliceItem(value, SliceItem.FORMAT_INT, subType, hints));
diff --git a/core/java/android/app/slice/SliceItem.java b/core/java/android/app/slice/SliceItem.java
index bcfd413..9eb2bb8 100644
--- a/core/java/android/app/slice/SliceItem.java
+++ b/core/java/android/app/slice/SliceItem.java
@@ -98,11 +98,6 @@
      */
     public static final String FORMAT_INT = "int";
     /**
-     * A {@link SliceItem} that contains an int.
-     * @deprecated to be removed
-     */
-    public static final String FORMAT_COLOR = "color";
-    /**
      * A {@link SliceItem} that contains a timestamp.
      */
     public static final String FORMAT_TIMESTAMP = "timestamp";
@@ -231,13 +226,6 @@
     }
 
     /**
-     * @deprecated to be removed.
-     */
-    public int getColor() {
-        return (Integer) mObj;
-    }
-
-    /**
      * @return The slice held by this {@link #FORMAT_ACTION} or {@link #FORMAT_SLICE} SliceItem
      */
     public Slice getSlice() {
diff --git a/core/java/android/app/slice/SliceProvider.java b/core/java/android/app/slice/SliceProvider.java
index bd4103f..00e8cca 100644
--- a/core/java/android/app/slice/SliceProvider.java
+++ b/core/java/android/app/slice/SliceProvider.java
@@ -158,7 +158,6 @@
      * currently happening. The returned package will have been
      * verified to belong to the calling UID. Returns {@code null} if not
      * currently performing an {@link #onBindSlice(Uri, List)}.
-     * @hide
      */
     public final @Nullable String getBindingPackage() {
         return mBindingPkg;
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index f04e907..edb992b 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -106,6 +106,12 @@
          */
         public static final int NOTIFICATION_SEEN = 10;
 
+        /**
+         * An event type denoting a change in App Standby Bucket.
+         * @hide
+         */
+        public static final int STANDBY_BUCKET_CHANGED = 11;
+
         /** @hide */
         public static final int FLAG_IS_PACKAGE_INSTANT_APP = 1 << 0;
 
@@ -170,6 +176,13 @@
          */
         public String[] mContentAnnotations;
 
+        /**
+         * The app standby bucket assigned.
+         * Only present for {@link #STANDBY_BUCKET_CHANGED} event types
+         * {@hide}
+         */
+        public int mBucket;
+
         /** @hide */
         @EventFlags
         public int mFlags;
@@ -189,6 +202,7 @@
             mContentType = orig.mContentType;
             mContentAnnotations = orig.mContentAnnotations;
             mFlags = orig.mFlags;
+            mBucket = orig.mBucket;
         }
 
         /**
@@ -399,6 +413,9 @@
                 p.writeString(event.mContentType);
                 p.writeStringArray(event.mContentAnnotations);
                 break;
+            case Event.STANDBY_BUCKET_CHANGED:
+                p.writeInt(event.mBucket);
+                break;
         }
     }
 
@@ -442,6 +459,9 @@
                 eventOut.mContentType = p.readString();
                 eventOut.mContentAnnotations = p.createStringArray();
                 break;
+            case Event.STANDBY_BUCKET_CHANGED:
+                eventOut.mBucket = p.readInt();
+                break;
         }
     }
 
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 84cbdb4..7bdf72f 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -34,6 +34,7 @@
 import android.text.TextUtils;
 import android.util.Printer;
 import android.util.SparseArray;
+import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.util.ArrayUtils;
 
@@ -1183,6 +1184,105 @@
         super.dumpBack(pw, prefix);
     }
 
+    /** {@hide} */
+    public void writeToProto(ProtoOutputStream proto, long fieldId, int dumpFlags) {
+        long token = proto.start(fieldId);
+        super.writeToProto(proto, ApplicationInfoProto.PACKAGE);
+        proto.write(ApplicationInfoProto.PERMISSION, permission);
+        proto.write(ApplicationInfoProto.PROCESS_NAME, processName);
+        proto.write(ApplicationInfoProto.UID, uid);
+        proto.write(ApplicationInfoProto.FLAGS, flags);
+        proto.write(ApplicationInfoProto.PRIVATE_FLAGS, privateFlags);
+        proto.write(ApplicationInfoProto.THEME, theme);
+        proto.write(ApplicationInfoProto.SOURCE_DIR, sourceDir);
+        if (!Objects.equals(sourceDir, publicSourceDir)) {
+            proto.write(ApplicationInfoProto.PUBLIC_SOURCE_DIR, publicSourceDir);
+        }
+        if (!ArrayUtils.isEmpty(splitSourceDirs)) {
+            for (String dir : splitSourceDirs) {
+                proto.write(ApplicationInfoProto.SPLIT_SOURCE_DIRS, dir);
+            }
+        }
+        if (!ArrayUtils.isEmpty(splitPublicSourceDirs)
+                && !Arrays.equals(splitSourceDirs, splitPublicSourceDirs)) {
+            for (String dir : splitPublicSourceDirs) {
+                proto.write(ApplicationInfoProto.SPLIT_PUBLIC_SOURCE_DIRS, dir);
+            }
+        }
+        if (resourceDirs != null) {
+            for (String dir : resourceDirs) {
+                proto.write(ApplicationInfoProto.RESOURCE_DIRS, dir);
+            }
+        }
+        proto.write(ApplicationInfoProto.DATA_DIR, dataDir);
+        proto.write(ApplicationInfoProto.CLASS_LOADER_NAME, classLoaderName);
+        if (!ArrayUtils.isEmpty(splitClassLoaderNames)) {
+            for (String name : splitClassLoaderNames) {
+                proto.write(ApplicationInfoProto.SPLIT_CLASS_LOADER_NAMES, name);
+            }
+        }
+
+        long versionToken = proto.start(ApplicationInfoProto.VERSION);
+        proto.write(ApplicationInfoProto.Version.ENABLED, enabled);
+        proto.write(ApplicationInfoProto.Version.MIN_SDK_VERSION, minSdkVersion);
+        proto.write(ApplicationInfoProto.Version.TARGET_SDK_VERSION, targetSdkVersion);
+        proto.write(ApplicationInfoProto.Version.VERSION_CODE, versionCode);
+        proto.write(ApplicationInfoProto.Version.TARGET_SANDBOX_VERSION, targetSandboxVersion);
+        proto.end(versionToken);
+
+        if ((dumpFlags & DUMP_FLAG_DETAILS) != 0) {
+            long detailToken = proto.start(ApplicationInfoProto.DETAIL);
+            if (className != null) {
+                proto.write(ApplicationInfoProto.Detail.CLASS_NAME, className);
+            }
+            proto.write(ApplicationInfoProto.Detail.TASK_AFFINITY, taskAffinity);
+            proto.write(ApplicationInfoProto.Detail.REQUIRES_SMALLEST_WIDTH_DP,
+                    requiresSmallestWidthDp);
+            proto.write(ApplicationInfoProto.Detail.COMPATIBLE_WIDTH_LIMIT_DP,
+                    compatibleWidthLimitDp);
+            proto.write(ApplicationInfoProto.Detail.LARGEST_WIDTH_LIMIT_DP,
+                    largestWidthLimitDp);
+            if (seInfo != null) {
+                proto.write(ApplicationInfoProto.Detail.SEINFO, seInfo);
+                proto.write(ApplicationInfoProto.Detail.SEINFO_USER, seInfoUser);
+            }
+            proto.write(ApplicationInfoProto.Detail.DEVICE_PROTECTED_DATA_DIR,
+                    deviceProtectedDataDir);
+            proto.write(ApplicationInfoProto.Detail.CREDENTIAL_PROTECTED_DATA_DIR,
+                    credentialProtectedDataDir);
+            if (sharedLibraryFiles != null) {
+                for (String f : sharedLibraryFiles) {
+                    proto.write(ApplicationInfoProto.Detail.SHARED_LIBRARY_FILES, f);
+                }
+            }
+            if (manageSpaceActivityName != null) {
+                proto.write(ApplicationInfoProto.Detail.MANAGE_SPACE_ACTIVITY_NAME,
+                        manageSpaceActivityName);
+            }
+            if (descriptionRes != 0) {
+                proto.write(ApplicationInfoProto.Detail.DESCRIPTION_RES, descriptionRes);
+            }
+            if (uiOptions != 0) {
+                proto.write(ApplicationInfoProto.Detail.UI_OPTIONS, uiOptions);
+            }
+            proto.write(ApplicationInfoProto.Detail.SUPPORTS_RTL, hasRtlSupport());
+            if (fullBackupContent > 0) {
+                proto.write(ApplicationInfoProto.Detail.CONTENT, "@xml/" + fullBackupContent);
+            } else {
+                proto.write(ApplicationInfoProto.Detail.IS_FULL_BACKUP, fullBackupContent == 0);
+            }
+            if (networkSecurityConfigRes != 0) {
+                proto.write(ApplicationInfoProto.Detail.NETWORK_SECURITY_CONFIG_RES,
+                        networkSecurityConfigRes);
+            }
+            if (category != CATEGORY_UNDEFINED) {
+                proto.write(ApplicationInfoProto.Detail.CATEGORY, category);
+            }
+            proto.end(detailToken);
+        }
+        proto.end(token);
+    }
+
     /**
      * @return true if "supportsRtl" has been set to true in the AndroidManifest
      * @hide
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index cce6b84..379bff4 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -656,4 +656,8 @@
     void setHarmfulAppWarning(String packageName, CharSequence warning, int userId);
 
     CharSequence getHarmfulAppWarning(String packageName, int userId);
+
+    boolean hasSigningCertificate(String packageName, in byte[] signingCertificate, int flags);
+
+    boolean hasUidSigningCertificate(int uid, in byte[] signingCertificate, int flags);
 }
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index 5a91e94..13ec4fd 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -246,9 +246,44 @@
      * equivalent to being signed with certificates B and A. This means that
      * in case multiple signatures are reported you cannot assume the one at
      * the first position to be the same across updates.
+     *
+     * <strong>Deprecated</strong> This has been replaced by the
+     * {@link PackageInfo#signingCertificateHistory} field, which takes into
+     * account signing certificate rotation.  For backwards compatibility in
+     * the event of signing certificate rotation, this will return the oldest
+     * reported signing certificate, so that an application will appear to
+     * callers as though no rotation occurred.
+     *
+     * @deprecated use {@code signingCertificateHistory} instead
      */
+    @Deprecated
     public Signature[] signatures;
-    
+
+    /**
+     * Array of all signatures arrays read from the package file, potentially
+     * including past signing certificates no longer used after signing
+     * certificate rotation.  Though signing certificate rotation is only
+     * available for apps with a single signing certificate, this provides an
+     * array of arrays so that packages signed with multiple signing
+     * certificates can still return all signers.  This is only filled in if
+     * the flag {@link PackageManager#GET_SIGNING_CERTIFICATES} was set.
+     *
+     * A package must be singed with at least one certificate, which is at
+     * position zero in the array.  An application may be signed by multiple
+     * certificates, which would be in the array at position zero in an
+     * indeterminate order.  A package may also have a history of certificates
+     * due to signing certificate rotation.  In this case, the array will be
+     * populated by a series of single-entry arrays corresponding to a signing
+     * certificate of the package.
+     *
+     * <strong>Note:</strong> Signature ordering is not guaranteed to be
+     * stable which means that a package signed with certificates A and B is
+     * equivalent to being signed with certificates B and A. This means that
+     * in case multiple signatures are reported you cannot assume the one at
+     * the first position will be the same across updates.
+     */
+    public Signature[][] signingCertificateHistory;
+
     /**
      * Application specified preferred configuration
      * {@link android.R.styleable#AndroidManifestUsesConfiguration
diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java
index 11830c2..2c0c6ad0 100644
--- a/core/java/android/content/pm/PackageItemInfo.java
+++ b/core/java/android/content/pm/PackageItemInfo.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.content.res.XmlResourceParser;
-
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.Parcel;
@@ -28,6 +27,8 @@
 import android.text.TextPaint;
 import android.text.TextUtils;
 import android.util.Printer;
+import android.util.proto.ProtoOutputStream;
+
 import java.text.Collator;
 import java.util.Comparator;
 
@@ -386,6 +387,24 @@
         dest.writeInt(showUserIcon);
     }
 
+    /**
+     * @hide
+     */
+    public void writeToProto(ProtoOutputStream proto, long fieldId) {
+        long token = proto.start(fieldId);
+        if (name != null) {
+            proto.write(PackageItemInfoProto.NAME, name);
+        }
+        proto.write(PackageItemInfoProto.PACKAGE_NAME, packageName);
+        if (labelRes != 0 || nonLocalizedLabel != null || icon != 0 || banner != 0) {
+            proto.write(PackageItemInfoProto.LABEL_RES, labelRes);
+            proto.write(PackageItemInfoProto.NON_LOCALIZED_LABEL, nonLocalizedLabel.toString());
+            proto.write(PackageItemInfoProto.ICON, icon);
+            proto.write(PackageItemInfoProto.BANNER, banner);
+        }
+        proto.end(token);
+    }
+
     protected PackageItemInfo(Parcel source) {
         name = source.readString();
         packageName = source.readString();
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index b81267a..67c9584 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -133,6 +133,7 @@
             GET_SERVICES,
             GET_SHARED_LIBRARY_FILES,
             GET_SIGNATURES,
+            GET_SIGNING_CERTIFICATES,
             GET_URI_PERMISSION_PATTERNS,
             MATCH_UNINSTALLED_PACKAGES,
             MATCH_DISABLED_COMPONENTS,
@@ -272,7 +273,10 @@
     /**
      * {@link PackageInfo} flag: return information about the
      * signatures included in the package.
+     *
+     * @deprecated use {@code GET_SIGNING_CERTIFICATES} instead
      */
+    @Deprecated
     public static final int GET_SIGNATURES          = 0x00000040;
 
     /**
@@ -488,6 +492,14 @@
     public static final int MATCH_STATIC_SHARED_LIBRARIES = 0x04000000;
 
     /**
+     * {@link PackageInfo} flag: return the signing certificates associated with
+     * this package.  Each entry is a signing certificate that the package
+     * has proven it is authorized to use, usually a past signing certificate from
+     * which it has rotated.
+     */
+    public static final int GET_SIGNING_CERTIFICATES = 0x08000000;
+
+    /**
      * Internal flag used to indicate that a system component has done their
      * homework and verified that they correctly handle packages and components
      * that come and go over time. In particular:
@@ -3781,7 +3793,7 @@
     public abstract int getInstantAppCookieMaxBytes();
 
     /**
-     * @deprecated
+     * deprecated
      * @hide
      */
     public abstract int getInstantAppCookieMaxSize();
@@ -5914,4 +5926,60 @@
     public CharSequence getHarmfulAppWarning(@NonNull String packageName) {
         throw new UnsupportedOperationException("getHarmfulAppWarning not implemented in subclass");
     }
+
+    /** @hide */
+    @IntDef(prefix = { "CERT_INPUT_" }, value = {
+            CERT_INPUT_RAW_X509,
+            CERT_INPUT_SHA256
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface CertificateInputType {}
+
+    /**
+     * Certificate input bytes: the input bytes represent an encoded X.509 Certificate which could
+     * be generated using an {@code CertificateFactory}
+     */
+    public static final int CERT_INPUT_RAW_X509 = 0;
+
+    /**
+     * Certificate input bytes: the input bytes represent the SHA256 output of an encoded X.509
+     * Certificate.
+     */
+    public static final int CERT_INPUT_SHA256 = 1;
+
+    /**
+     * Searches the set of signing certificates by which the given package has proven to have been
+     * signed.  This should be used instead of {@code getPackageInfo} with {@code GET_SIGNATURES}
+     * since it takes into account the possibility of signing certificate rotation, except in the
+     * case of packages that are signed by multiple certificates, for which signing certificate
+     * rotation is not supported.
+     *
+     * @param packageName package whose signing certificates to check
+     * @param certificate signing certificate for which to search
+     * @param type representation of the {@code certificate}
+     * @return true if this package was or is signed by exactly the certificate {@code certificate}
+     */
+    public boolean hasSigningCertificate(
+            String packageName, byte[] certificate, @CertificateInputType int type) {
+        throw new UnsupportedOperationException(
+                "hasSigningCertificate not implemented in subclass");
+    }
+
+    /**
+     * Searches the set of signing certificates by which the given uid has proven to have been
+     * signed.  This should be used instead of {@code getPackageInfo} with {@code GET_SIGNATURES}
+     * since it takes into account the possibility of signing certificate rotation, except in the
+     * case of packages that are signed by multiple certificates, for which signing certificate
+     * rotation is not supported.
+     *
+     * @param uid package whose signing certificates to check
+     * @param certificate signing certificate for which to search
+     * @param type representation of the {@code certificate}
+     * @return true if this package was or is signed by exactly the certificate {@code certificate}
+     */
+    public boolean hasSigningCertificate(
+            int uid, byte[] certificate, @CertificateInputType int type) {
+        throw new UnsupportedOperationException(
+                "hasSigningCertificate not implemented in subclass");
+    }
 }
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 4a71467..5b5ccf5 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -801,13 +801,40 @@
                 }
             }
         }
+        // deprecated method of getting signing certificates
         if ((flags&PackageManager.GET_SIGNATURES) != 0) {
-            if (p.mSigningDetails.hasSignatures()) {
+            if (p.mSigningDetails.hasPastSigningCertificates()) {
+                // Package has included signing certificate rotation information.  Return the oldest
+                // cert so that programmatic checks keep working even if unaware of key rotation.
+                pi.signatures = new Signature[1];
+                pi.signatures[0] = p.mSigningDetails.pastSigningCertificates[0];
+            } else if (p.mSigningDetails.hasSignatures()) {
+                // otherwise keep old behavior
                 int numberOfSigs = p.mSigningDetails.signatures.length;
                 pi.signatures = new Signature[numberOfSigs];
                 System.arraycopy(p.mSigningDetails.signatures, 0, pi.signatures, 0, numberOfSigs);
             }
         }
+
+        // replacement for GET_SIGNATURES
+        if ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) {
+            if (p.mSigningDetails.hasPastSigningCertificates()) {
+                // Package has included signing certificate rotation information.  Convert each
+                // entry to an array
+                int numberOfSigs = p.mSigningDetails.pastSigningCertificates.length;
+                pi.signingCertificateHistory = new Signature[numberOfSigs][];
+                for (int i = 0; i < numberOfSigs; i++) {
+                    pi.signingCertificateHistory[i] =
+                            new Signature[] { p.mSigningDetails.pastSigningCertificates[i] };
+                }
+            } else if (p.mSigningDetails.hasSignatures()) {
+                // otherwise keep old behavior
+                int numberOfSigs = p.mSigningDetails.signatures.length;
+                pi.signingCertificateHistory = new Signature[1][numberOfSigs];
+                System.arraycopy(p.mSigningDetails.signatures, 0,
+                        pi.signingCertificateHistory[0], 0, numberOfSigs);
+            }
+        }
         return pi;
     }
 
@@ -5684,23 +5711,74 @@
         @Nullable
         public final ArraySet<PublicKey> publicKeys;
 
+        /**
+         * Collection of {@code Signature} objects, each of which is formed from a former signing
+         * certificate of this APK before it was changed by signing certificate rotation.
+         */
+        @Nullable
+        public final Signature[] pastSigningCertificates;
+
+        /**
+         * Flags for the {@code pastSigningCertificates} collection, which indicate the capabilities
+         * the including APK wishes to grant to its past signing certificates.
+         */
+        @Nullable
+        public final int[] pastSigningCertificatesFlags;
+
         /** A representation of unknown signing details. Use instead of null. */
         public static final SigningDetails UNKNOWN =
-                new SigningDetails(null, SignatureSchemeVersion.UNKNOWN, null);
+                new SigningDetails(null, SignatureSchemeVersion.UNKNOWN, null, null, null);
 
         @VisibleForTesting
         public SigningDetails(Signature[] signatures,
                 @SignatureSchemeVersion int signatureSchemeVersion,
-                ArraySet<PublicKey> keys) {
+                ArraySet<PublicKey> keys, Signature[] pastSigningCertificates,
+                int[] pastSigningCertificatesFlags) {
             this.signatures = signatures;
             this.signatureSchemeVersion = signatureSchemeVersion;
             this.publicKeys = keys;
+            this.pastSigningCertificates = pastSigningCertificates;
+            this.pastSigningCertificatesFlags = pastSigningCertificatesFlags;
+        }
+
+        public SigningDetails(Signature[] signatures,
+                @SignatureSchemeVersion int signatureSchemeVersion,
+                Signature[] pastSigningCertificates, int[] pastSigningCertificatesFlags)
+                throws CertificateException {
+            this(signatures, signatureSchemeVersion, toSigningKeys(signatures),
+                    pastSigningCertificates, pastSigningCertificatesFlags);
         }
 
         public SigningDetails(Signature[] signatures,
                 @SignatureSchemeVersion int signatureSchemeVersion)
                 throws CertificateException {
-            this(signatures, signatureSchemeVersion, toSigningKeys(signatures));
+            this(signatures, signatureSchemeVersion,
+                    null, null);
+        }
+
+        public SigningDetails(SigningDetails orig) {
+            if (orig != null) {
+                if (orig.signatures != null) {
+                    this.signatures = orig.signatures.clone();
+                } else {
+                    this.signatures = null;
+                }
+                this.signatureSchemeVersion = orig.signatureSchemeVersion;
+                this.publicKeys = new ArraySet<>(orig.publicKeys);
+                if (orig.pastSigningCertificates != null) {
+                    this.pastSigningCertificates = orig.pastSigningCertificates.clone();
+                    this.pastSigningCertificatesFlags = orig.pastSigningCertificatesFlags.clone();
+                } else {
+                    this.pastSigningCertificates = null;
+                    this.pastSigningCertificatesFlags = null;
+                }
+            } else {
+                this.signatures = null;
+                this.signatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
+                this.publicKeys = null;
+                this.pastSigningCertificates = null;
+                this.pastSigningCertificatesFlags = null;
+            }
         }
 
         /** Returns true if the signing details have one or more signatures. */
@@ -5708,6 +5786,11 @@
             return signatures != null && signatures.length > 0;
         }
 
+        /** Returns true if the signing details have past signing certificates. */
+        public boolean hasPastSigningCertificates() {
+            return pastSigningCertificates != null && pastSigningCertificates.length > 0;
+        }
+
         /** Returns true if the signatures in this and other match exactly. */
         public boolean signaturesMatchExactly(SigningDetails other) {
             return Signature.areExactMatch(this.signatures, other.signatures);
@@ -5728,6 +5811,8 @@
             dest.writeTypedArray(this.signatures, flags);
             dest.writeInt(this.signatureSchemeVersion);
             dest.writeArraySet(this.publicKeys);
+            dest.writeTypedArray(this.pastSigningCertificates, flags);
+            dest.writeIntArray(this.pastSigningCertificatesFlags);
         }
 
         protected SigningDetails(Parcel in) {
@@ -5735,6 +5820,8 @@
             this.signatures = in.createTypedArray(Signature.CREATOR);
             this.signatureSchemeVersion = in.readInt();
             this.publicKeys = (ArraySet<PublicKey>) in.readArraySet(boot);
+            this.pastSigningCertificates = in.createTypedArray(Signature.CREATOR);
+            this.pastSigningCertificatesFlags = in.createIntArray();
         }
 
         public static final Creator<SigningDetails> CREATOR = new Creator<SigningDetails>() {
@@ -5761,8 +5848,23 @@
 
             if (signatureSchemeVersion != that.signatureSchemeVersion) return false;
             if (!Signature.areExactMatch(signatures, that.signatures)) return false;
-            return publicKeys != null ? publicKeys.equals(that.publicKeys)
-                    : that.publicKeys == null;
+            if (publicKeys != null) {
+                if (!publicKeys.equals((that.publicKeys))) {
+                    return false;
+                }
+            } else if (that.publicKeys != null) {
+                return false;
+            }
+
+            // can't use Signature.areExactMatch() because order matters with the past signing certs
+            if (!Arrays.equals(pastSigningCertificates, that.pastSigningCertificates)) {
+                return false;
+            }
+            if (!Arrays.equals(pastSigningCertificatesFlags, that.pastSigningCertificatesFlags)) {
+                return false;
+            }
+
+            return true;
         }
 
         @Override
@@ -5770,8 +5872,77 @@
             int result = +Arrays.hashCode(signatures);
             result = 31 * result + signatureSchemeVersion;
             result = 31 * result + (publicKeys != null ? publicKeys.hashCode() : 0);
+            result = 31 * result + Arrays.hashCode(pastSigningCertificates);
+            result = 31 * result + Arrays.hashCode(pastSigningCertificatesFlags);
             return result;
         }
+
+        /**
+         * Builder of {@code SigningDetails} instances.
+         */
+        public static class Builder {
+            private Signature[] mSignatures;
+            private int mSignatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
+            private Signature[] mPastSigningCertificates;
+            private int[] mPastSigningCertificatesFlags;
+
+            public Builder() {
+            }
+
+            /** get signing certificates used to sign the current APK */
+            public Builder setSignatures(Signature[] signatures) {
+                mSignatures = signatures;
+                return this;
+            }
+
+            /** set the signature scheme version used to sign the APK */
+            public Builder setSignatureSchemeVersion(int signatureSchemeVersion) {
+                mSignatureSchemeVersion = signatureSchemeVersion;
+                return this;
+            }
+
+            /** set the signing certificates by which the APK proved it can be authenticated */
+            public Builder setPastSigningCertificates(Signature[] pastSigningCertificates) {
+                mPastSigningCertificates = pastSigningCertificates;
+                return this;
+            }
+
+            /** set the flags for the {@code pastSigningCertificates} */
+            public Builder setPastSigningCertificatesFlags(int[] pastSigningCertificatesFlags) {
+                mPastSigningCertificatesFlags = pastSigningCertificatesFlags;
+                return this;
+            }
+
+            private void checkInvariants() {
+                // must have signatures and scheme version set
+                if (mSignatures == null) {
+                    throw new IllegalStateException("SigningDetails requires the current signing"
+                            + " certificates.");
+                }
+
+                // pastSigningCerts and flags must match up
+                boolean pastMismatch = false;
+                if (mPastSigningCertificates != null && mPastSigningCertificatesFlags != null) {
+                    if (mPastSigningCertificates.length != mPastSigningCertificatesFlags.length) {
+                        pastMismatch = true;
+                    }
+                } else if (!(mPastSigningCertificates == null
+                        && mPastSigningCertificatesFlags == null)) {
+                    pastMismatch = true;
+                }
+                if (pastMismatch) {
+                    throw new IllegalStateException("SigningDetails must have a one to one mapping "
+                            + "between pastSigningCertificates and pastSigningCertificatesFlags");
+                }
+            }
+            /** build a {@code SigningDetails} object */
+            public SigningDetails build()
+                    throws CertificateException {
+                checkInvariants();
+                return new SigningDetails(mSignatures, mSignatureSchemeVersion,
+                        mPastSigningCertificates, mPastSigningCertificatesFlags);
+            }
+        }
     }
 
     /**
diff --git a/core/java/android/hardware/fingerprint/FingerprintDialog.java b/core/java/android/hardware/fingerprint/FingerprintDialog.java
new file mode 100644
index 0000000..6b7fab7
--- /dev/null
+++ b/core/java/android/hardware/fingerprint/FingerprintDialog.java
@@ -0,0 +1,293 @@
+/*
+ * 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.fingerprint;
+
+import static android.Manifest.permission.USE_FINGERPRINT;
+
+import android.annotation.CallbackExecutor;
+import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
+import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
+import android.hardware.fingerprint.IFingerprintDialogReceiver;
+import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.text.TextUtils;
+
+import java.util.concurrent.Executor;
+
+/**
+ * A class that manages a system-provided fingerprint dialog.
+ */
+public class FingerprintDialog {
+
+    /**
+     * @hide
+     */
+    public static final String KEY_TITLE = "title";
+    /**
+     * @hide
+     */
+    public static final String KEY_SUBTITLE = "subtitle";
+    /**
+     * @hide
+     */
+    public static final String KEY_DESCRIPTION = "description";
+    /**
+     * @hide
+     */
+    public static final String KEY_POSITIVE_TEXT = "positive_text";
+    /**
+     * @hide
+     */
+    public static final String KEY_NEGATIVE_TEXT = "negative_text";
+
+    /**
+     * Error/help message will show for this amount of time.
+     * For error messages, the dialog will also be dismissed after this amount of time.
+     * Error messages will be propagated back to the application via AuthenticationCallback
+     * after this amount of time.
+     * @hide
+     */
+    public static final int HIDE_DIALOG_DELAY = 3000; // ms
+    /**
+     * @hide
+     */
+    public static final int DISMISSED_REASON_POSITIVE = 1;
+
+    /**
+     * @hide
+     */
+    public static final int DISMISSED_REASON_NEGATIVE = 2;
+
+    /**
+     * @hide
+     */
+    public static final int DISMISSED_REASON_USER_CANCEL = 3;
+
+    private static class ButtonInfo {
+        Executor executor;
+        DialogInterface.OnClickListener listener;
+        ButtonInfo(Executor ex, DialogInterface.OnClickListener l) {
+            executor = ex;
+            listener = l;
+        }
+    }
+
+    /**
+     * A builder that collects arguments, to be shown on the system-provided fingerprint dialog.
+     **/
+    public static class Builder {
+        private final Bundle bundle;
+        private ButtonInfo positiveButtonInfo;
+        private ButtonInfo negativeButtonInfo;
+
+        /**
+         * Creates a builder for a fingerprint dialog.
+         */
+        public Builder() {
+            bundle = new Bundle();
+        }
+
+        /**
+         * Required: Set the title to display.
+         * @param title
+         * @return
+         */
+        public Builder setTitle(@NonNull CharSequence title) {
+            bundle.putCharSequence(KEY_TITLE, title);
+            return this;
+        }
+
+        /**
+         * Optional: Set the subtitle to display.
+         * @param subtitle
+         * @return
+         */
+        public Builder setSubtitle(@NonNull CharSequence subtitle) {
+            bundle.putCharSequence(KEY_SUBTITLE, subtitle);
+            return this;
+        }
+
+        /**
+         * Optional: Set the description to display.
+         * @param description
+         * @return
+         */
+        public Builder setDescription(@NonNull CharSequence description) {
+            bundle.putCharSequence(KEY_DESCRIPTION, description);
+            return this;
+        }
+
+        /**
+         * Optional: Set the text for the positive button. If not set, the positive button
+         * will not show.
+         * @param text
+         * @return
+         * @hide
+         */
+        public Builder setPositiveButton(@NonNull CharSequence text,
+                @NonNull @CallbackExecutor Executor executor,
+                @NonNull DialogInterface.OnClickListener listener) {
+            if (TextUtils.isEmpty(text)) {
+                throw new IllegalArgumentException("Text must be set and non-empty");
+            }
+            if (executor == null) {
+                throw new IllegalArgumentException("Executor must not be null");
+            }
+            if (listener == null) {
+                throw new IllegalArgumentException("Listener must not be null");
+            }
+            bundle.putCharSequence(KEY_POSITIVE_TEXT, text);
+            positiveButtonInfo = new ButtonInfo(executor, listener);
+            return this;
+        }
+
+        /**
+         * Required: Set the text for the negative button.
+         * @param text
+         * @return
+         */
+        public Builder setNegativeButton(@NonNull CharSequence text,
+                @NonNull @CallbackExecutor Executor executor,
+                @NonNull DialogInterface.OnClickListener listener) {
+            if (TextUtils.isEmpty(text)) {
+                throw new IllegalArgumentException("Text must be set and non-empty");
+            }
+            if (executor == null) {
+                throw new IllegalArgumentException("Executor must not be null");
+            }
+            if (listener == null) {
+                throw new IllegalArgumentException("Listener must not be null");
+            }
+            bundle.putCharSequence(KEY_NEGATIVE_TEXT, text);
+            negativeButtonInfo = new ButtonInfo(executor, listener);
+            return this;
+        }
+
+        /**
+         * Creates a {@link FingerprintDialog} with the arguments supplied to this builder.
+         * @param context
+         * @return a {@link FingerprintDialog}
+         * @throws IllegalArgumentException if any of the required fields are not set.
+         */
+        public FingerprintDialog build(Context context) {
+            final CharSequence title = bundle.getCharSequence(KEY_TITLE);
+            final CharSequence negative = bundle.getCharSequence(KEY_NEGATIVE_TEXT);
+
+            if (TextUtils.isEmpty(title)) {
+                throw new IllegalArgumentException("Title must be set and non-empty");
+            } else if (TextUtils.isEmpty(negative)) {
+                throw new IllegalArgumentException("Negative text must be set and non-empty");
+            }
+            return new FingerprintDialog(context, bundle, positiveButtonInfo, negativeButtonInfo);
+        }
+    }
+
+    private FingerprintManager mFingerprintManager;
+    private Bundle mBundle;
+    private ButtonInfo mPositiveButtonInfo;
+    private ButtonInfo mNegativeButtonInfo;
+
+    IFingerprintDialogReceiver mDialogReceiver = new IFingerprintDialogReceiver.Stub() {
+        @Override
+        public void onDialogDismissed(int reason) {
+            // Check the reason and invoke OnClickListener(s) if necessary
+            if (reason == DISMISSED_REASON_POSITIVE) {
+                mPositiveButtonInfo.executor.execute(() -> {
+                    mPositiveButtonInfo.listener.onClick(null, DialogInterface.BUTTON_POSITIVE);
+                });
+            } else if (reason == DISMISSED_REASON_NEGATIVE) {
+                mNegativeButtonInfo.executor.execute(() -> {
+                    mNegativeButtonInfo.listener.onClick(null, DialogInterface.BUTTON_NEGATIVE);
+                });
+            }
+        }
+    };
+
+    private FingerprintDialog(Context context, Bundle bundle,
+            ButtonInfo positiveButtonInfo, ButtonInfo negativeButtonInfo) {
+        mBundle = bundle;
+        mPositiveButtonInfo = positiveButtonInfo;
+        mNegativeButtonInfo = negativeButtonInfo;
+        mFingerprintManager = context.getSystemService(FingerprintManager.class);
+    }
+
+    /**
+     * This call warms up the fingerprint hardware, displays a system-provided dialog,
+     * and starts scanning for a fingerprint. It terminates when
+     * {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} is called, when
+     * {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult)} is called,
+     * when {@link AuthenticationCallback#onAuthenticationFailed()} is called or when the user
+     * dismisses the system-provided dialog, at which point the crypto object becomes invalid.
+     * This operation can be canceled by using the provided cancel object. The application will
+     * receive authentication errors through {@link AuthenticationCallback}, and button events
+     * through the corresponding callback set in
+     * {@link Builder#setNegativeButton(CharSequence, Executor, DialogInterface.OnClickListener)}.
+     * It is safe to reuse the {@link FingerprintDialog} object, and calling
+     * {@link FingerprintDialog#authenticate(CancellationSignal, Executor, AuthenticationCallback)}
+     * while an existing authentication attempt is occurring will stop the previous client and
+     * start a new authentication. The interrupted client will receive a cancelled notification
+     * through {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)}.
+     *
+     * @throws IllegalArgumentException if any of the arguments are null
+     *
+     * @param crypto object associated with the call
+     * @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
+     */
+    @RequiresPermission(USE_FINGERPRINT)
+    public void authenticate(@NonNull FingerprintManager.CryptoObject crypto,
+            @NonNull CancellationSignal cancel,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull FingerprintManager.AuthenticationCallback callback) {
+        mFingerprintManager.authenticate(crypto, cancel, mBundle, executor, mDialogReceiver,
+                callback);
+    }
+
+    /**
+     * This call warms up the fingerprint hardware, displays a system-provided dialog,
+     * and starts scanning for a fingerprint. It terminates when
+     * {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} is called, when
+     * {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult)} is called,
+     * when {@link AuthenticationCallback#onAuthenticationFailed()} is called or when the user
+     * dismisses the system-provided dialog. This operation can be canceled by using the provided
+     * cancel object. The application will receive authentication errors through
+     * {@link AuthenticationCallback}, and button events through the corresponding callback set in
+     * {@link Builder#setNegativeButton(CharSequence, Executor, DialogInterface.OnClickListener)}.
+     * It is safe to reuse the {@link FingerprintDialog} object, and calling
+     * {@link FingerprintDialog#authenticate(CancellationSignal, Executor, AuthenticationCallback)}
+     * while an existing authentication attempt is occurring will stop the previous client and
+     * start a new authentication. The interrupted client will receive a cancelled notification
+     * through {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)}.
+     *
+     * @throws IllegalArgumentException if any of the arguments are null
+     *
+     * @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
+     */
+    @RequiresPermission(USE_FINGERPRINT)
+    public void authenticate(@NonNull CancellationSignal cancel,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull FingerprintManager.AuthenticationCallback callback) {
+        mFingerprintManager.authenticate(cancel, mBundle, executor, mDialogReceiver, callback);
+    }
+}
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 987718a..62d92c4 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -16,6 +16,11 @@
 
 package android.hardware.fingerprint;
 
+import static android.Manifest.permission.INTERACT_ACROSS_USERS;
+import static android.Manifest.permission.MANAGE_FINGERPRINT;
+import static android.Manifest.permission.USE_FINGERPRINT;
+
+import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -23,6 +28,7 @@
 import android.app.ActivityManager;
 import android.content.Context;
 import android.os.Binder;
+import android.os.Bundle;
 import android.os.CancellationSignal;
 import android.os.CancellationSignal.OnCancelListener;
 import android.os.Handler;
@@ -38,14 +44,11 @@
 
 import java.security.Signature;
 import java.util.List;
+import java.util.concurrent.Executor;
 
 import javax.crypto.Cipher;
 import javax.crypto.Mac;
 
-import static android.Manifest.permission.INTERACT_ACROSS_USERS;
-import static android.Manifest.permission.MANAGE_FINGERPRINT;
-import static android.Manifest.permission.USE_FINGERPRINT;
-
 /**
  * A class that coordinates access to the fingerprint hardware.
  */
@@ -204,6 +207,7 @@
     private CryptoObject mCryptoObject;
     private Fingerprint mRemovalFingerprint;
     private Handler mHandler;
+    private Executor mExecutor;
 
     private class OnEnrollCancelListener implements OnCancelListener {
         @Override
@@ -505,7 +509,9 @@
     }
 
     /**
-     * Per-user version
+     * Per-user version, see {@link FingerprintManager#authenticate(CryptoObject,
+     * CancellationSignal, int, AuthenticationCallback, Handler)}
+     * @param userId the user ID that the fingerprint hardware will authenticate for.
      * @hide
      */
     @RequiresPermission(USE_FINGERPRINT)
@@ -530,7 +536,7 @@
             mCryptoObject = crypto;
             long sessionId = crypto != null ? crypto.getOpId() : 0;
             mService.authenticate(mToken, sessionId, userId, mServiceReceiver, flags,
-                    mContext.getOpPackageName());
+                    mContext.getOpPackageName(), null /* bundle */, null /* receiver */);
         } catch (RemoteException e) {
             Log.w(TAG, "Remote exception while authenticating: ", e);
             if (callback != null) {
@@ -543,6 +549,111 @@
     }
 
     /**
+     * Per-user version, see {@link FingerprintManager#authenticate(CryptoObject,
+     * CancellationSignal, Bundle, Executor, IFingerprintDialogReceiver, AuthenticationCallback)}
+     * @param userId the user ID that the fingerprint hardware will authenticate for.
+     */
+    private void authenticate(int userId,
+            @Nullable CryptoObject crypto,
+            @NonNull CancellationSignal cancel,
+            @NonNull Bundle bundle,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull IFingerprintDialogReceiver receiver,
+            @NonNull AuthenticationCallback callback) {
+        mCryptoObject = crypto;
+        if (cancel.isCanceled()) {
+            Log.w(TAG, "authentication already canceled");
+            return;
+        } else {
+            cancel.setOnCancelListener(new OnAuthenticationCancelListener(crypto));
+        }
+
+        if (mService != null) {
+            try {
+                mExecutor = executor;
+                mAuthenticationCallback = callback;
+                final long sessionId = crypto != null ? crypto.getOpId() : 0;
+                mService.authenticate(mToken, sessionId, userId, mServiceReceiver,
+                        0 /* flags */, mContext.getOpPackageName(), bundle, receiver);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Remote exception while authenticating", e);
+                mExecutor.execute(() -> {
+                    callback.onAuthenticationError(FINGERPRINT_ERROR_HW_UNAVAILABLE,
+                            getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */));
+                });
+            }
+        }
+    }
+
+    /**
+     * Private method, see {@link FingerprintDialog#authenticate(CancellationSignal, Executor,
+     * AuthenticationCallback)}
+     * @param cancel
+     * @param executor
+     * @param callback
+     * @hide
+     */
+    public void authenticate(
+            @NonNull CancellationSignal cancel,
+            @NonNull Bundle bundle,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull IFingerprintDialogReceiver receiver,
+            @NonNull AuthenticationCallback callback) {
+        if (cancel == null) {
+            throw new IllegalArgumentException("Must supply a cancellation signal");
+        }
+        if (bundle == null) {
+            throw new IllegalArgumentException("Must supply a bundle");
+        }
+        if (executor == null) {
+            throw new IllegalArgumentException("Must supply an executor");
+        }
+        if (receiver == null) {
+            throw new IllegalArgumentException("Must supply a receiver");
+        }
+        if (callback == null) {
+            throw new IllegalArgumentException("Must supply a calback");
+        }
+        authenticate(UserHandle.myUserId(), null, cancel, bundle, executor, receiver, callback);
+    }
+
+    /**
+     * Private method, see {@link FingerprintDialog#authenticate(CryptoObject, CancellationSignal,
+     * Executor, AuthenticationCallback)}
+     * @param crypto
+     * @param cancel
+     * @param executor
+     * @param callback
+     * @hide
+     */
+    public void authenticate(@NonNull CryptoObject crypto,
+            @NonNull CancellationSignal cancel,
+            @NonNull Bundle bundle,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull IFingerprintDialogReceiver receiver,
+            @NonNull AuthenticationCallback callback) {
+        if (crypto == null) {
+            throw new IllegalArgumentException("Must supply a crypto object");
+        }
+        if (cancel == null) {
+            throw new IllegalArgumentException("Must supply a cancellation signal");
+        }
+        if (bundle == null) {
+            throw new IllegalArgumentException("Must supply a bundle");
+        }
+        if (executor == null) {
+            throw new IllegalArgumentException("Must supply an executor");
+        }
+        if (receiver == null) {
+            throw new IllegalArgumentException("Must supply a receiver");
+        }
+        if (callback == null) {
+            throw new IllegalArgumentException("Must supply a calback");
+        }
+        authenticate(UserHandle.myUserId(), crypto, cancel, bundle, executor, receiver, callback);
+    }
+
+    /**
      * Request fingerprint enrollment. This call warms up the fingerprint hardware
      * and starts scanning for fingerprints. Progress will be indicated by callbacks to the
      * {@link EnrollmentCallback} object. It terminates when
@@ -929,64 +1040,64 @@
             }
         }
 
-        private void sendErrorResult(long deviceId, int errMsgId, int vendorCode) {
-            // emulate HAL 2.1 behavior and send real errMsgId
-            final int clientErrMsgId = errMsgId == FINGERPRINT_ERROR_VENDOR
-                    ? (vendorCode + FINGERPRINT_ERROR_VENDOR_BASE) : errMsgId;
-            if (mEnrollmentCallback != null) {
-                mEnrollmentCallback.onEnrollmentError(clientErrMsgId,
-                        getErrorString(errMsgId, vendorCode));
-            } else if (mAuthenticationCallback != null) {
-                mAuthenticationCallback.onAuthenticationError(clientErrMsgId,
-                        getErrorString(errMsgId, vendorCode));
-            } else if (mRemovalCallback != null) {
-                mRemovalCallback.onRemovalError(mRemovalFingerprint, clientErrMsgId,
-                        getErrorString(errMsgId, vendorCode));
-            } else if (mEnumerateCallback != null) {
-                mEnumerateCallback.onEnumerateError(clientErrMsgId,
-                        getErrorString(errMsgId, vendorCode));
-            }
-        }
-
         private void sendEnrollResult(Fingerprint fp, int remaining) {
             if (mEnrollmentCallback != null) {
                 mEnrollmentCallback.onEnrollmentProgress(remaining);
             }
         }
-
-        private void sendAuthenticatedSucceeded(Fingerprint fp, int userId) {
-            if (mAuthenticationCallback != null) {
-                final AuthenticationResult result =
-                        new AuthenticationResult(mCryptoObject, fp, userId);
-                mAuthenticationCallback.onAuthenticationSucceeded(result);
-            }
-        }
-
-        private void sendAuthenticatedFailed() {
-            if (mAuthenticationCallback != null) {
-                mAuthenticationCallback.onAuthenticationFailed();
-            }
-        }
-
-        private void sendAcquiredResult(long deviceId, int acquireInfo, int vendorCode) {
-            if (mAuthenticationCallback != null) {
-                mAuthenticationCallback.onAuthenticationAcquired(acquireInfo);
-            }
-            final String msg = getAcquiredString(acquireInfo, vendorCode);
-            if (msg == null) {
-                return;
-            }
-            // emulate HAL 2.1 behavior and send real acquiredInfo
-            final int clientInfo = acquireInfo == FINGERPRINT_ACQUIRED_VENDOR
-                    ? (vendorCode + FINGERPRINT_ACQUIRED_VENDOR_BASE) : acquireInfo;
-            if (mEnrollmentCallback != null) {
-                mEnrollmentCallback.onEnrollmentHelp(clientInfo, msg);
-            } else if (mAuthenticationCallback != null) {
-                mAuthenticationCallback.onAuthenticationHelp(clientInfo, msg);
-            }
-        }
     };
 
+    private void sendAuthenticatedSucceeded(Fingerprint fp, int userId) {
+        if (mAuthenticationCallback != null) {
+            final AuthenticationResult result =
+                    new AuthenticationResult(mCryptoObject, fp, userId);
+            mAuthenticationCallback.onAuthenticationSucceeded(result);
+        }
+    }
+
+    private void sendAuthenticatedFailed() {
+        if (mAuthenticationCallback != null) {
+            mAuthenticationCallback.onAuthenticationFailed();
+        }
+    }
+
+    private void sendAcquiredResult(long deviceId, int acquireInfo, int vendorCode) {
+        if (mAuthenticationCallback != null) {
+            mAuthenticationCallback.onAuthenticationAcquired(acquireInfo);
+        }
+        final String msg = getAcquiredString(acquireInfo, vendorCode);
+        if (msg == null) {
+            return;
+        }
+        // emulate HAL 2.1 behavior and send real acquiredInfo
+        final int clientInfo = acquireInfo == FINGERPRINT_ACQUIRED_VENDOR
+                ? (vendorCode + FINGERPRINT_ACQUIRED_VENDOR_BASE) : acquireInfo;
+        if (mEnrollmentCallback != null) {
+            mEnrollmentCallback.onEnrollmentHelp(clientInfo, msg);
+        } else if (mAuthenticationCallback != null) {
+            mAuthenticationCallback.onAuthenticationHelp(clientInfo, msg);
+        }
+    }
+
+    private void sendErrorResult(long deviceId, int errMsgId, int vendorCode) {
+        // emulate HAL 2.1 behavior and send real errMsgId
+        final int clientErrMsgId = errMsgId == FINGERPRINT_ERROR_VENDOR
+                ? (vendorCode + FINGERPRINT_ERROR_VENDOR_BASE) : errMsgId;
+        if (mEnrollmentCallback != null) {
+            mEnrollmentCallback.onEnrollmentError(clientErrMsgId,
+                    getErrorString(errMsgId, vendorCode));
+        } else if (mAuthenticationCallback != null) {
+            mAuthenticationCallback.onAuthenticationError(clientErrMsgId,
+                    getErrorString(errMsgId, vendorCode));
+        } else if (mRemovalCallback != null) {
+            mRemovalCallback.onRemovalError(mRemovalFingerprint, clientErrMsgId,
+                    getErrorString(errMsgId, vendorCode));
+        } else if (mEnumerateCallback != null) {
+            mEnumerateCallback.onEnumerateError(clientErrMsgId,
+                    getErrorString(errMsgId, vendorCode));
+        }
+    }
+
     /**
      * @hide
      */
@@ -1023,7 +1134,10 @@
         }
     }
 
-    private String getErrorString(int errMsg, int vendorCode) {
+    /**
+     * @hide
+     */
+    public String getErrorString(int errMsg, int vendorCode) {
         switch (errMsg) {
             case FINGERPRINT_ERROR_UNABLE_TO_PROCESS:
                 return mContext.getString(
@@ -1043,6 +1157,9 @@
             case FINGERPRINT_ERROR_LOCKOUT_PERMANENT:
                 return mContext.getString(
                         com.android.internal.R.string.fingerprint_error_lockout_permanent);
+            case FINGERPRINT_ERROR_USER_CANCELED:
+                return mContext.getString(
+                        com.android.internal.R.string.fingerprint_error_user_canceled);
             case FINGERPRINT_ERROR_VENDOR: {
                     String[] msgArray = mContext.getResources().getStringArray(
                             com.android.internal.R.array.fingerprint_error_vendor);
@@ -1055,7 +1172,10 @@
         return null;
     }
 
-    private String getAcquiredString(int acquireInfo, int vendorCode) {
+    /**
+     * @hide
+     */
+    public String getAcquiredString(int acquireInfo, int vendorCode) {
         switch (acquireInfo) {
             case FINGERPRINT_ACQUIRED_GOOD:
                 return null;
@@ -1096,22 +1216,47 @@
 
         @Override // binder call
         public void onAcquired(long deviceId, int acquireInfo, int vendorCode) {
-            mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, vendorCode, deviceId).sendToTarget();
+            if (mExecutor != null) {
+                mExecutor.execute(() -> {
+                    sendAcquiredResult(deviceId, acquireInfo, vendorCode);
+                });
+            } else {
+                mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, vendorCode,
+                        deviceId).sendToTarget();
+            }
         }
 
         @Override // binder call
         public void onAuthenticationSucceeded(long deviceId, Fingerprint fp, int userId) {
-            mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, userId, 0, fp).sendToTarget();
+            if (mExecutor != null) {
+                mExecutor.execute(() -> {
+                    sendAuthenticatedSucceeded(fp, userId);
+                });
+            } else {
+                mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, userId, 0, fp).sendToTarget();
+            }
         }
 
         @Override // binder call
         public void onAuthenticationFailed(long deviceId) {
-            mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget();
+            if (mExecutor != null) {
+                mExecutor.execute(() -> {
+                    sendAuthenticatedFailed();
+                });
+            } else {
+                mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget();
+            }
         }
 
         @Override // binder call
         public void onError(long deviceId, int error, int vendorCode) {
-            mHandler.obtainMessage(MSG_ERROR, error, vendorCode, deviceId).sendToTarget();
+            if (mExecutor != null) {
+                mExecutor.execute(() -> {
+                    sendErrorResult(deviceId, error, vendorCode);
+                });
+            } else {
+                mHandler.obtainMessage(MSG_ERROR, error, vendorCode, deviceId).sendToTarget();
+            }
         }
 
         @Override // binder call
diff --git a/core/java/android/hardware/fingerprint/IFingerprintDialogReceiver.aidl b/core/java/android/hardware/fingerprint/IFingerprintDialogReceiver.aidl
new file mode 100644
index 0000000..13e7974
--- /dev/null
+++ b/core/java/android/hardware/fingerprint/IFingerprintDialogReceiver.aidl
@@ -0,0 +1,28 @@
+/*
+ * 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.fingerprint;
+
+import android.hardware.fingerprint.Fingerprint;
+import android.os.Bundle;
+import android.os.UserHandle;
+
+/**
+ * Communication channel from the FingerprintDialog (SysUI) back to AuthenticationClient.
+ * @hide
+ */
+oneway interface IFingerprintDialogReceiver {
+    void onDialogDismissed(int reason);
+}
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index 4879d54..f1502e4 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -17,6 +17,7 @@
 
 import android.os.Bundle;
 import android.hardware.fingerprint.IFingerprintClientActiveCallback;
+import android.hardware.fingerprint.IFingerprintDialogReceiver;
 import android.hardware.fingerprint.IFingerprintServiceReceiver;
 import android.hardware.fingerprint.IFingerprintServiceLockoutResetCallback;
 import android.hardware.fingerprint.Fingerprint;
@@ -29,7 +30,8 @@
 interface IFingerprintService {
     // Authenticate the given sessionId with a fingerprint
     void authenticate(IBinder token, long sessionId, int userId,
-            IFingerprintServiceReceiver receiver, int flags, String opPackageName);
+            IFingerprintServiceReceiver receiver, int flags, String opPackageName,
+            in Bundle bundle, IFingerprintDialogReceiver dialogReceiver);
 
     // Cancel authentication for the given sessionId
     void cancelAuthentication(IBinder token, String opPackageName);
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index f04f03f6..6125394 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -748,7 +748,7 @@
      * @hide
      */
     @SystemApi
-    void applyTunnelModeTransform(IpSecTunnelInterface tunnel, int direction,
+    public void applyTunnelModeTransform(IpSecTunnelInterface tunnel, int direction,
             IpSecTransform transform) throws IOException {
         // TODO: call IpSecService
     }
diff --git a/core/java/android/os/Handler.java b/core/java/android/os/Handler.java
index 5c5e351..fc88e90 100644
--- a/core/java/android/os/Handler.java
+++ b/core/java/android/os/Handler.java
@@ -202,7 +202,8 @@
         mLooper = Looper.myLooper();
         if (mLooper == null) {
             throw new RuntimeException(
-                "Can't create handler inside thread that has not called Looper.prepare()");
+                "Can't create handler inside thread " + Thread.currentThread()
+                        + " that has not called Looper.prepare()");
         }
         mQueue = mLooper.mQueue;
         mCallback = callback;
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 3798a5e..61172e1 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -23,6 +23,7 @@
 import android.annotation.SystemService;
 import android.content.Context;
 import android.util.Log;
+import android.util.proto.ProtoOutputStream;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -1652,6 +1653,21 @@
             }
         }
 
+        /** @hide */
+        public void writeToProto(ProtoOutputStream proto, long fieldId) {
+            synchronized (mToken) {
+                final long token = proto.start(fieldId);
+                proto.write(PowerManagerProto.WakeLockProto.HEX_STRING,
+                        Integer.toHexString(System.identityHashCode(this)));
+                proto.write(PowerManagerProto.WakeLockProto.HELD, mHeld);
+                proto.write(PowerManagerProto.WakeLockProto.INTERNAL_COUNT, mInternalCount);
+                if (mWorkSource != null) {
+                    mWorkSource.writeToProto(proto, PowerManagerProto.WakeLockProto.WORK_SOURCE);
+                }
+                proto.end(token);
+            }
+        }
+
         /**
          * Wraps a Runnable such that this method immediately acquires the wake lock and then
          * once the Runnable is done the wake lock is released.
diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java
index 3ef0961..c7d89b0 100644
--- a/core/java/android/os/PowerManagerInternal.java
+++ b/core/java/android/os/PowerManagerInternal.java
@@ -71,6 +71,24 @@
     }
 
     /**
+     * Converts platform constants to proto enums.
+     */
+    public static int wakefulnessToProtoEnum(int wakefulness) {
+        switch (wakefulness) {
+            case WAKEFULNESS_ASLEEP:
+                return PowerManagerInternalProto.WAKEFULNESS_ASLEEP;
+            case WAKEFULNESS_AWAKE:
+                return PowerManagerInternalProto.WAKEFULNESS_AWAKE;
+            case WAKEFULNESS_DREAMING:
+                return PowerManagerInternalProto.WAKEFULNESS_DREAMING;
+            case WAKEFULNESS_DOZING:
+                return PowerManagerInternalProto.WAKEFULNESS_DOZING;
+            default:
+                return wakefulness;
+        }
+    }
+
+    /**
      * Returns true if the wakefulness state represents an interactive state
      * as defined by {@link android.os.PowerManager#isInteractive}.
      */
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 7654e9b..6833908 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -143,7 +143,7 @@
      * Defines the UID/GID for the WebView zygote process.
      * @hide
      */
-    public static final int WEBVIEW_ZYGOTE_UID = 1051;
+    public static final int WEBVIEW_ZYGOTE_UID = 1053;
 
     /**
      * Defines the UID used for resource tracking for OTA updates.
@@ -574,6 +574,14 @@
     }
 
     /**
+     * Returns whether the given uid belongs to a system core component or not.
+     * @hide
+     */
+    public static boolean isCoreUid(int uid) {
+        return UserHandle.isCore(uid);
+    }
+
+    /**
      * Returns whether the given uid belongs to an application.
      * @param uid A kernel uid.
      * @return Whether the uid corresponds to an application sandbox running in
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index 6381b56..5be72bc 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -126,7 +126,10 @@
         return getAppId(uid1) == getAppId(uid2);
     }
 
-    /** @hide */
+    /**
+     * Whether a UID is an "isolated" UID.
+     * @hide
+     */
     public static boolean isIsolated(int uid) {
         if (uid > 0) {
             final int appId = getAppId(uid);
@@ -136,7 +139,11 @@
         }
     }
 
-    /** @hide */
+    /**
+     * Whether a UID belongs to a regular app. *Note* "Not a regular app" does not mean
+     * "it's system", because of isolated UIDs. Use {@link #isCore} for that.
+     * @hide
+     */
     public static boolean isApp(int uid) {
         if (uid > 0) {
             final int appId = getAppId(uid);
@@ -147,6 +154,19 @@
     }
 
     /**
+     * Whether a UID belongs to a system core component or not.
+     * @hide
+     */
+    public static boolean isCore(int uid) {
+        if (uid > 0) {
+            final int appId = getAppId(uid);
+            return appId < Process.FIRST_APPLICATION_UID;
+        } else {
+            return false;
+        }
+    }
+
+    /**
      * Returns the user for a given uid.
      * @param uid A uid for an application running in a particular user.
      * @return A {@link UserHandle} for that user.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 0e323f8..b5f23be 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -41,7 +41,6 @@
 import android.app.AppOpsManager;
 import android.app.Application;
 import android.app.NotificationChannel;
-import android.app.NotificationChannelGroup;
 import android.app.NotificationManager;
 import android.app.SearchManager;
 import android.app.WallpaperManager;
@@ -75,7 +74,6 @@
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
 import android.os.UserHandle;
-import android.provider.SettingsValidators;
 import android.provider.SettingsValidators.Validator;
 import android.speech.tts.TextToSpeech;
 import android.telephony.SubscriptionManager;
@@ -1345,18 +1343,6 @@
             = "android.settings.CHANNEL_NOTIFICATION_SETTINGS";
 
     /**
-     * Activity Action: Show notification settings for a single {@link NotificationChannelGroup}.
-     * <p>
-     *     Input: {@link #EXTRA_APP_PACKAGE}, the package containing the channel group to display.
-     *     Input: {@link #EXTRA_CHANNEL_GROUP_ID}, the id of the channel group to display.
-     * <p>
-     * Output: Nothing.
-     */
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String ACTION_CHANNEL_GROUP_NOTIFICATION_SETTINGS =
-            "android.settings.CHANNEL_GROUP_NOTIFICATION_SETTINGS";
-
-    /**
      * Activity Extra: The package owner of the notification channel settings to display.
      * <p>
      * This must be passed as an extra field to the {@link #ACTION_CHANNEL_NOTIFICATION_SETTINGS}.
@@ -1372,15 +1358,6 @@
     public static final String EXTRA_CHANNEL_ID = "android.provider.extra.CHANNEL_ID";
 
     /**
-     * Activity Extra: The {@link NotificationChannelGroup#getId()} of the notification channel
-     * group settings to display.
-     * <p>
-     * This must be passed as an extra field to the
-     * {@link #ACTION_CHANNEL_GROUP_NOTIFICATION_SETTINGS}.
-     */
-    public static final String EXTRA_CHANNEL_GROUP_ID = "android.provider.extra.CHANNEL_GROUP_ID";
-
-    /**
      * Activity Action: Show notification redaction settings.
      *
      * @hide
@@ -1502,6 +1479,21 @@
     public static final String ACTION_REQUEST_SET_AUTOFILL_SERVICE =
             "android.settings.REQUEST_SET_AUTOFILL_SERVICE";
 
+    /**
+     * Activity Action: Show screen for controlling which apps have access on volume directories.
+     * <p>
+     * Input: Nothing.
+     * <p>
+     * Output: Nothing.
+     * <p>
+     * Applications typically use this action to ask the user to revert the "Do not ask again"
+     * status of directory access requests made by
+     * {@link android.os.storage.StorageVolume#createAccessIntent(String)}.
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_STORAGE_VOLUME_ACCESS_SETTINGS =
+            "android.settings.STORAGE_VOLUME_ACCESS_SETTINGS";
+
     // End of Intent actions for Settings
 
     /**
@@ -5509,37 +5501,54 @@
          * Note: do not rely on this value being present in settings.db or on ContentObserver
          * notifications for the corresponding Uri. Use {@link LocationManager#MODE_CHANGED_ACTION}
          * to receive changes in this value.
+         *
+         * @deprecated To check location status, use {@link LocationManager#isLocationEnabled()}. To
+         *             get the status of a location provider, use
+         *             {@link LocationManager#isProviderEnabled(String)}.
          */
+        @Deprecated
         public static final String LOCATION_MODE = "location_mode";
-        /**
-         * Stores the previous location mode when {@link #LOCATION_MODE} is set to
-         * {@link #LOCATION_MODE_OFF}
-         * @hide
-         */
-        public static final String LOCATION_PREVIOUS_MODE = "location_previous_mode";
 
         /**
-         * Sets all location providers to the previous states before location was turned off.
-         * @hide
-         */
-        public static final int LOCATION_MODE_PREVIOUS = -1;
-        /**
          * Location access disabled.
+         *
+         * @deprecated To check location status, use {@link LocationManager#isLocationEnabled()}. To
+         *             get the status of a location provider, use
+         *             {@link LocationManager#isProviderEnabled(String)}.
          */
+        @Deprecated
         public static final int LOCATION_MODE_OFF = 0;
+
         /**
          * Network Location Provider disabled, but GPS and other sensors enabled.
+         *
+         * @deprecated To check location status, use {@link LocationManager#isLocationEnabled()}. To
+         *             get the status of a location provider, use
+         *             {@link LocationManager#isProviderEnabled(String)}.
          */
+        @Deprecated
         public static final int LOCATION_MODE_SENSORS_ONLY = 1;
+
         /**
          * Reduced power usage, such as limiting the number of GPS updates per hour. Requests
          * with {@link android.location.Criteria#POWER_HIGH} may be downgraded to
          * {@link android.location.Criteria#POWER_MEDIUM}.
+         *
+         * @deprecated To check location status, use {@link LocationManager#isLocationEnabled()}. To
+         *             get the status of a location provider, use
+         *             {@link LocationManager#isProviderEnabled(String)}.
          */
+        @Deprecated
         public static final int LOCATION_MODE_BATTERY_SAVING = 2;
+
         /**
          * Best-effort location computation allowed.
+         *
+         * @deprecated To check location status, use {@link LocationManager#isLocationEnabled()}. To
+         *             get the status of a location provider, use
+         *             {@link LocationManager#isProviderEnabled(String)}.
          */
+        @Deprecated
         public static final int LOCATION_MODE_HIGH_ACCURACY = 3;
 
         /**
@@ -7866,7 +7875,6 @@
             CLONE_TO_MANAGED_PROFILE.add(ENABLED_ACCESSIBILITY_SERVICES);
             CLONE_TO_MANAGED_PROFILE.add(ENABLED_INPUT_METHODS);
             CLONE_TO_MANAGED_PROFILE.add(LOCATION_MODE);
-            CLONE_TO_MANAGED_PROFILE.add(LOCATION_PREVIOUS_MODE);
             CLONE_TO_MANAGED_PROFILE.add(LOCATION_PROVIDERS_ALLOWED);
             CLONE_TO_MANAGED_PROFILE.add(SELECTED_INPUT_METHOD_SUBTYPE);
         }
@@ -7917,8 +7925,7 @@
          * @param provider the location provider to query
          * @return true if the provider is enabled
          *
-         * @deprecated use {@link #LOCATION_MODE} or
-         *             {@link LocationManager#isProviderEnabled(String)}
+         * @deprecated use {@link LocationManager#isProviderEnabled(String)}
          */
         @Deprecated
         public static final boolean isLocationProviderEnabled(ContentResolver cr, String provider) {
@@ -7931,12 +7938,13 @@
          * @param provider the location provider to query
          * @param userId the userId to query
          * @return true if the provider is enabled
-         * @deprecated use {@link #LOCATION_MODE} or
-         *             {@link LocationManager#isProviderEnabled(String)}
+         *
+         * @deprecated use {@link LocationManager#isProviderEnabled(String)}
          * @hide
          */
         @Deprecated
-        public static final boolean isLocationProviderEnabledForUser(ContentResolver cr, String provider, int userId) {
+        public static final boolean isLocationProviderEnabledForUser(
+                ContentResolver cr, String provider, int userId) {
             String allowedProviders = Settings.Secure.getStringForUser(cr,
                     LOCATION_PROVIDERS_ALLOWED, userId);
             return TextUtils.delimitedStringContains(allowedProviders, ',', provider);
@@ -7947,7 +7955,8 @@
          * @param cr the content resolver to use
          * @param provider the location provider to enable or disable
          * @param enabled true if the provider should be enabled
-         * @deprecated use {@link #putInt(ContentResolver, String, int)} and {@link #LOCATION_MODE}
+         * @deprecated This API is deprecated. It requires WRITE_SECURE_SETTINGS permission to
+         *             change location settings.
          */
         @Deprecated
         public static final void setLocationProviderEnabled(ContentResolver cr,
@@ -7963,8 +7972,8 @@
          * @param enabled true if the provider should be enabled
          * @param userId the userId for which to enable/disable providers
          * @return true if the value was set, false on database errors
-         * @deprecated use {@link #putIntForUser(ContentResolver, String, int, int)} and
-         *             {@link #LOCATION_MODE}
+         *
+         * @deprecated use {@link LocationManager#setProviderEnabledForUser(String, boolean, int)}
          * @hide
          */
         @Deprecated
@@ -7985,28 +7994,6 @@
         }
 
         /**
-         * Saves the current location mode into {@link #LOCATION_PREVIOUS_MODE}.
-         */
-        private static final boolean saveLocationModeForUser(ContentResolver cr, int userId) {
-            final int mode = getLocationModeForUser(cr, userId);
-            return putIntForUser(cr, Settings.Secure.LOCATION_PREVIOUS_MODE, mode, userId);
-        }
-
-        /**
-         * Restores the current location mode from {@link #LOCATION_PREVIOUS_MODE}.
-         */
-        private static final boolean restoreLocationModeForUser(ContentResolver cr, int userId) {
-            int mode = getIntForUser(cr, Settings.Secure.LOCATION_PREVIOUS_MODE,
-                    LOCATION_MODE_HIGH_ACCURACY, userId);
-            // Make sure that the previous mode is never "off". Otherwise the user won't be able to
-            // turn on location any longer.
-            if (mode == LOCATION_MODE_OFF) {
-                mode = LOCATION_MODE_HIGH_ACCURACY;
-            }
-            return setLocationModeForUser(cr, mode, userId);
-        }
-
-        /**
          * Thread-safe method for setting the location mode to one of
          * {@link #LOCATION_MODE_HIGH_ACCURACY}, {@link #LOCATION_MODE_SENSORS_ONLY},
          * {@link #LOCATION_MODE_BATTERY_SAVING}, or {@link #LOCATION_MODE_OFF}.
@@ -8019,18 +8006,20 @@
          * @return true if the value was set, false on database errors
          *
          * @throws IllegalArgumentException if mode is not one of the supported values
+         *
+         * @deprecated To enable/disable location, use
+         *             {@link LocationManager#setLocationEnabledForUser(boolean, int)}.
+         *             To enable/disable a specific location provider, use
+         *             {@link LocationManager#setProviderEnabledForUser(String, boolean, int)}.
          */
-        private static final boolean setLocationModeForUser(ContentResolver cr, int mode,
-                int userId) {
+        @Deprecated
+        private static boolean setLocationModeForUser(
+                ContentResolver cr, int mode, int userId) {
             synchronized (mLocationSettingsLock) {
                 boolean gps = false;
                 boolean network = false;
                 switch (mode) {
-                    case LOCATION_MODE_PREVIOUS:
-                        // Retrieve the actual mode and set to that mode.
-                        return restoreLocationModeForUser(cr, userId);
                     case LOCATION_MODE_OFF:
-                        saveLocationModeForUser(cr, userId);
                         break;
                     case LOCATION_MODE_SENSORS_ONLY:
                         gps = true;
@@ -8045,15 +8034,7 @@
                     default:
                         throw new IllegalArgumentException("Invalid location mode: " + mode);
                 }
-                // Note it's important that we set the NLP mode first. The Google implementation
-                // of NLP clears its NLP consent setting any time it receives a
-                // LocationManager.PROVIDERS_CHANGED_ACTION broadcast and NLP is disabled. Also,
-                // it shows an NLP consent dialog any time it receives the broadcast, NLP is
-                // enabled, and the NLP consent is not set. If 1) we were to enable GPS first,
-                // 2) a setup wizard has its own NLP consent UI that sets the NLP consent setting,
-                // and 3) the receiver happened to complete before we enabled NLP, then the Google
-                // NLP would detect the attempt to enable NLP and show a redundant NLP consent
-                // dialog. Then the people who wrote the setup wizard would be sad.
+
                 boolean nlpSuccess = Settings.Secure.setLocationProviderEnabledForUser(
                         cr, LocationManager.NETWORK_PROVIDER, network, userId);
                 boolean gpsSuccess = Settings.Secure.setLocationProviderEnabledForUser(
@@ -11193,6 +11174,7 @@
          *
          * @hide
          */
+        @TestApi
         public static final String LOCATION_GLOBAL_KILL_SWITCH =
                 "location_global_kill_switch";
 
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index 72afbb8..3464370 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -102,6 +102,7 @@
     public static final int KM_ALGORITHM_RSA = 1;
     public static final int KM_ALGORITHM_EC = 3;
     public static final int KM_ALGORITHM_AES = 32;
+    public static final int KM_ALGORITHM_3DES = 33;
     public static final int KM_ALGORITHM_HMAC = 128;
 
     // Block modes.
@@ -131,6 +132,7 @@
     public static final int KM_ORIGIN_GENERATED = 0;
     public static final int KM_ORIGIN_IMPORTED = 2;
     public static final int KM_ORIGIN_UNKNOWN = 3;
+    public static final int KM_ORIGIN_SECURELY_IMPORTED = 4;
 
     // Key usability requirements.
     public static final int KM_BLOB_STANDALONE = 0;
@@ -141,6 +143,7 @@
     public static final int KM_PURPOSE_DECRYPT = 1;
     public static final int KM_PURPOSE_SIGN = 2;
     public static final int KM_PURPOSE_VERIFY = 3;
+    public static final int KM_PURPOSE_WRAP = 5;
 
     // Key formats.
     public static final int KM_KEY_FORMAT_X509 = 0;
diff --git a/core/java/android/security/keystore/BackwardsCompat.java b/core/java/android/security/keystore/BackwardsCompat.java
new file mode 100644
index 0000000..69558c4
--- /dev/null
+++ b/core/java/android/security/keystore/BackwardsCompat.java
@@ -0,0 +1,127 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.List;
+import java.util.function.Function;
+
+/**
+ * Helpers for converting classes between old and new API, so we can preserve backwards
+ * compatibility while teamfooding. This will be removed soon.
+ *
+ * @hide
+ */
+class BackwardsCompat {
+
+
+    static KeychainProtectionParams toLegacyKeychainProtectionParams(
+            android.security.keystore.recovery.KeyChainProtectionParams keychainProtectionParams
+    ) {
+        return new KeychainProtectionParams.Builder()
+                .setUserSecretType(keychainProtectionParams.getUserSecretType())
+                .setSecret(keychainProtectionParams.getSecret())
+                .setLockScreenUiFormat(keychainProtectionParams.getLockScreenUiFormat())
+                .setKeyDerivationParams(
+                        toLegacyKeyDerivationParams(
+                                keychainProtectionParams.getKeyDerivationParams()))
+                .build();
+    }
+
+    static KeyDerivationParams toLegacyKeyDerivationParams(
+            android.security.keystore.recovery.KeyDerivationParams keyDerivationParams
+    ) {
+        return new KeyDerivationParams(
+                keyDerivationParams.getAlgorithm(), keyDerivationParams.getSalt());
+    }
+
+    static WrappedApplicationKey toLegacyWrappedApplicationKey(
+            android.security.keystore.recovery.WrappedApplicationKey wrappedApplicationKey
+    ) {
+        return new WrappedApplicationKey.Builder()
+                .setAlias(wrappedApplicationKey.getAlias())
+                .setEncryptedKeyMaterial(wrappedApplicationKey.getEncryptedKeyMaterial())
+                .build();
+    }
+
+    static android.security.keystore.recovery.KeyDerivationParams fromLegacyKeyDerivationParams(
+            KeyDerivationParams keyDerivationParams
+    ) {
+        return new android.security.keystore.recovery.KeyDerivationParams(
+                keyDerivationParams.getAlgorithm(), keyDerivationParams.getSalt());
+    }
+
+    static android.security.keystore.recovery.WrappedApplicationKey fromLegacyWrappedApplicationKey(
+            WrappedApplicationKey wrappedApplicationKey
+    ) {
+        return new android.security.keystore.recovery.WrappedApplicationKey.Builder()
+                .setAlias(wrappedApplicationKey.getAlias())
+                .setEncryptedKeyMaterial(wrappedApplicationKey.getEncryptedKeyMaterial())
+                .build();
+    }
+
+    static List<android.security.keystore.recovery.WrappedApplicationKey>
+            fromLegacyWrappedApplicationKeys(List<WrappedApplicationKey> wrappedApplicationKeys
+    ) {
+        return map(wrappedApplicationKeys, BackwardsCompat::fromLegacyWrappedApplicationKey);
+    }
+
+    static List<android.security.keystore.recovery.KeyChainProtectionParams>
+            fromLegacyKeychainProtectionParams(
+                    List<KeychainProtectionParams> keychainProtectionParams) {
+        return map(keychainProtectionParams, BackwardsCompat::fromLegacyKeychainProtectionParam);
+    }
+
+    static android.security.keystore.recovery.KeyChainProtectionParams
+            fromLegacyKeychainProtectionParam(KeychainProtectionParams keychainProtectionParams) {
+        return new android.security.keystore.recovery.KeyChainProtectionParams.Builder()
+                .setUserSecretType(keychainProtectionParams.getUserSecretType())
+                .setSecret(keychainProtectionParams.getSecret())
+                .setLockScreenUiFormat(keychainProtectionParams.getLockScreenUiFormat())
+                .setKeyDerivationParams(
+                        fromLegacyKeyDerivationParams(
+                                keychainProtectionParams.getKeyDerivationParams()))
+                .build();
+    }
+
+    static KeychainSnapshot toLegacyKeychainSnapshot(
+            android.security.keystore.recovery.KeyChainSnapshot keychainSnapshot
+    ) {
+        return new KeychainSnapshot.Builder()
+                .setCounterId(keychainSnapshot.getCounterId())
+                .setEncryptedRecoveryKeyBlob(keychainSnapshot.getEncryptedRecoveryKeyBlob())
+                .setTrustedHardwarePublicKey(keychainSnapshot.getTrustedHardwarePublicKey())
+                .setSnapshotVersion(keychainSnapshot.getSnapshotVersion())
+                .setMaxAttempts(keychainSnapshot.getMaxAttempts())
+                .setServerParams(keychainSnapshot.getServerParams())
+                .setKeychainProtectionParams(
+                        map(keychainSnapshot.getKeyChainProtectionParams(),
+                                BackwardsCompat::toLegacyKeychainProtectionParams))
+                .setWrappedApplicationKeys(
+                        map(keychainSnapshot.getWrappedApplicationKeys(),
+                                BackwardsCompat::toLegacyWrappedApplicationKey))
+                .build();
+    }
+
+    static <A, B> List<B> map(List<A> as, Function<A, B> f) {
+        ArrayList<B> bs = new ArrayList<>(as.size());
+        for (A a : as) {
+            bs.add(f.apply(a));
+        }
+        return bs;
+    }
+}
diff --git a/core/java/android/security/keystore/KeyDerivationParams.java b/core/java/android/security/keystore/KeyDerivationParams.java
index b702acc..b19cee2 100644
--- a/core/java/android/security/keystore/KeyDerivationParams.java
+++ b/core/java/android/security/keystore/KeyDerivationParams.java
@@ -61,7 +61,7 @@
         return new KeyDerivationParams(ALGORITHM_SHA256, salt);
     }
 
-    private KeyDerivationParams(@KeyDerivationAlgorithm int algorithm, @NonNull byte[] salt) {
+    KeyDerivationParams(@KeyDerivationAlgorithm int algorithm, @NonNull byte[] salt) {
         mAlgorithm = algorithm;
         mSalt = Preconditions.checkNotNull(salt);
     }
diff --git a/core/java/android/security/keystore/KeychainProtectionParams.aidl b/core/java/android/security/keystore/KeychainProtectionParams.aidl
deleted file mode 100644
index 0341223..0000000
--- a/core/java/android/security/keystore/KeychainProtectionParams.aidl
+++ /dev/null
@@ -1,20 +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 android.security.keystore;
-
-/* @hide */
-parcelable KeychainProtectionParams;
diff --git a/core/java/android/security/keystore/KeychainProtectionParams.java b/core/java/android/security/keystore/KeychainProtectionParams.java
index a3cd431..a940fdc 100644
--- a/core/java/android/security/keystore/KeychainProtectionParams.java
+++ b/core/java/android/security/keystore/KeychainProtectionParams.java
@@ -260,9 +260,6 @@
         }
     };
 
-    /**
-     * @hide
-     */
     @Override
     public void writeToParcel(Parcel out, int flags) {
         out.writeInt(mUserSecretType);
diff --git a/core/java/android/security/keystore/KeychainSnapshot.java b/core/java/android/security/keystore/KeychainSnapshot.java
index e03dd4a..23aec25 100644
--- a/core/java/android/security/keystore/KeychainSnapshot.java
+++ b/core/java/android/security/keystore/KeychainSnapshot.java
@@ -151,6 +151,8 @@
 
     /**
      * Builder for creating {@link KeychainSnapshot}.
+     *
+     * @hide
      */
     public static class Builder {
         private KeychainSnapshot mInstance = new KeychainSnapshot();
@@ -263,9 +265,6 @@
         }
     }
 
-    /**
-     * @hide
-     */
     @Override
     public void writeToParcel(Parcel out, int flags) {
         out.writeInt(mSnapshotVersion);
diff --git a/core/java/android/security/keystore/RecoveryController.java b/core/java/android/security/keystore/RecoveryController.java
index 87283cb..8be6d52 100644
--- a/core/java/android/security/keystore/RecoveryController.java
+++ b/core/java/android/security/keystore/RecoveryController.java
@@ -167,7 +167,7 @@
     public @NonNull KeychainSnapshot getRecoveryData(@NonNull byte[] account)
             throws InternalRecoveryServiceException {
         try {
-            return mBinder.getRecoveryData(account);
+            return BackwardsCompat.toLegacyKeychainSnapshot(mBinder.getRecoveryData(account));
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         } catch (ServiceSpecificException e) {
@@ -360,28 +360,6 @@
     }
 
     /**
-     * Method notifies KeyStore that a user-generated secret is available. This method generates a
-     * symmetric session key which a trusted remote device can use to return a recovery key. Caller
-     * should use {@link KeychainProtectionParams#clearSecret} to override the secret value in
-     * memory.
-     *
-     * @param recoverySecret user generated secret together with parameters necessary to regenerate
-     *     it on a new device.
-     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
-     *     service.
-     */
-    public void recoverySecretAvailable(@NonNull KeychainProtectionParams recoverySecret)
-            throws InternalRecoveryServiceException {
-        try {
-            mBinder.recoverySecretAvailable(recoverySecret);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        } catch (ServiceSpecificException e) {
-            throw wrapUnexpectedServiceSpecificException(e);
-        }
-    }
-
-    /**
      * Initializes recovery session and returns a blob with proof of recovery secrets possession.
      * The method generates symmetric key for a session, which trusted remote device can use to
      * return recovery key.
@@ -417,7 +395,7 @@
                             verifierPublicKey,
                             vaultParams,
                             vaultChallenge,
-                            secrets);
+                            BackwardsCompat.fromLegacyKeychainProtectionParams(secrets));
             return new RecoveryClaim(recoverySession, recoveryClaim);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -451,7 +429,9 @@
             InternalRecoveryServiceException {
         try {
             return (Map<String, byte[]>) mBinder.recoverKeys(
-                    session.getSessionId(), recoveryKeyBlob, applicationKeys);
+                    session.getSessionId(),
+                    recoveryKeyBlob,
+                    BackwardsCompat.fromLegacyWrappedApplicationKeys(applicationKeys));
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         } catch (ServiceSpecificException e) {
diff --git a/core/java/android/security/keystore/recovery/BadCertificateFormatException.java b/core/java/android/security/keystore/recovery/BadCertificateFormatException.java
new file mode 100644
index 0000000..e0781a5
--- /dev/null
+++ b/core/java/android/security/keystore/recovery/BadCertificateFormatException.java
@@ -0,0 +1,29 @@
+/*
+ * 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.recovery;
+
+/**
+ * Error thrown when the recovery agent supplies an invalid X509 certificate.
+ *
+ * @hide
+ * Deprecated
+ */
+public class BadCertificateFormatException extends RecoveryControllerException {
+    public BadCertificateFormatException(String msg) {
+        super(msg);
+    }
+}
diff --git a/core/java/android/security/keystore/recovery/DecryptionFailedException.java b/core/java/android/security/keystore/recovery/DecryptionFailedException.java
new file mode 100644
index 0000000..af00e05
--- /dev/null
+++ b/core/java/android/security/keystore/recovery/DecryptionFailedException.java
@@ -0,0 +1,34 @@
+/*
+ * 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.recovery;
+
+import android.annotation.SystemApi;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * Error thrown when decryption failed, due to an agent error. i.e., using the incorrect key,
+ * trying to decrypt garbage data, trying to decrypt data that has somehow been corrupted, etc.
+ *
+ * @hide
+ */
+@SystemApi
+public class DecryptionFailedException extends GeneralSecurityException {
+    public DecryptionFailedException(String msg) {
+        super(msg);
+    }
+}
diff --git a/core/java/android/security/keystore/recovery/InternalRecoveryServiceException.java b/core/java/android/security/keystore/recovery/InternalRecoveryServiceException.java
new file mode 100644
index 0000000..218d26e
--- /dev/null
+++ b/core/java/android/security/keystore/recovery/InternalRecoveryServiceException.java
@@ -0,0 +1,39 @@
+/*
+ * 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.recovery;
+
+import android.annotation.SystemApi;
+
+import java.security.GeneralSecurityException;
+/**
+ * An error thrown when something went wrong internally in the recovery service.
+ *
+ * <p>This is an unexpected error, and indicates a problem with the service itself, rather than the
+ * caller having performed some kind of illegal action.
+ *
+ * @hide
+ */
+@SystemApi
+public class InternalRecoveryServiceException extends GeneralSecurityException {
+    public InternalRecoveryServiceException(String msg) {
+        super(msg);
+    }
+
+    public InternalRecoveryServiceException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/core/java/android/security/keystore/KeychainSnapshot.aidl b/core/java/android/security/keystore/recovery/KeyChainProtectionParams.aidl
similarity index 88%
copy from core/java/android/security/keystore/KeychainSnapshot.aidl
copy to core/java/android/security/keystore/recovery/KeyChainProtectionParams.aidl
index b35713f..58edc84 100644
--- a/core/java/android/security/keystore/KeychainSnapshot.aidl
+++ b/core/java/android/security/keystore/recovery/KeyChainProtectionParams.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.security.keystore;
+package android.security.keystore.recovery;
 
 /* @hide */
-parcelable KeychainSnapshot;
+parcelable KeyChainProtectionParams;
diff --git a/core/java/android/security/keystore/recovery/KeyChainProtectionParams.java b/core/java/android/security/keystore/recovery/KeyChainProtectionParams.java
new file mode 100644
index 0000000..a43952a
--- /dev/null
+++ b/core/java/android/security/keystore/recovery/KeyChainProtectionParams.java
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keystore.recovery;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+
+/**
+ * A {@link KeyChainSnapshot} is protected with a key derived from the user's lock screen. This
+ * class wraps all the data necessary to derive the same key on a recovering device:
+ *
+ * <ul>
+ *     <li>UI parameters for the user's lock screen - so that if e.g., the user was using a pattern,
+ *         the recovering device can display the pattern UI to the user when asking them to enter
+ *         the lock screen from their previous device.
+ *     <li>The algorithm used to derive a key from the user's lock screen, e.g. SHA-256 with a salt.
+ * </ul>
+ *
+ * <p>As such, this data is sent along with the {@link KeyChainSnapshot} when syncing the current
+ * version of the keychain.
+ *
+ * <p>For now, the recoverable keychain only supports a single layer of protection, which is the
+ * user's lock screen. In the future, the keychain will support multiple layers of protection
+ * (e.g. an additional keychain password, along with the lock screen).
+ *
+ * @hide
+ */
+@SystemApi
+public final class KeyChainProtectionParams implements Parcelable {
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"TYPE_"}, value = {TYPE_LOCKSCREEN, TYPE_CUSTOM_PASSWORD})
+    public @interface UserSecretType {
+    }
+
+    /**
+     * Lockscreen secret is required to recover KeyStore.
+     */
+    public static final int TYPE_LOCKSCREEN = 100;
+
+    /**
+     * Custom passphrase, unrelated to lock screen, is required to recover KeyStore.
+     */
+    public static final int TYPE_CUSTOM_PASSWORD = 101;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"UI_FORMAT_"}, value = {UI_FORMAT_PIN, UI_FORMAT_PASSWORD, UI_FORMAT_PATTERN})
+    public @interface LockScreenUiFormat {
+    }
+
+    /**
+     * Pin with digits only.
+     */
+    public static final int UI_FORMAT_PIN = 1;
+
+    /**
+     * Password. String with latin-1 characters only.
+     */
+    public static final int UI_FORMAT_PASSWORD = 2;
+
+    /**
+     * Pattern with 3 by 3 grid.
+     */
+    public static final int UI_FORMAT_PATTERN = 3;
+
+    @UserSecretType
+    private Integer mUserSecretType;
+
+    @LockScreenUiFormat
+    private Integer mLockScreenUiFormat;
+
+    /**
+     * Parameters of the key derivation function, including algorithm, difficulty, salt.
+     */
+    private KeyDerivationParams mKeyDerivationParams;
+    private byte[] mSecret; // Derived from user secret. The field must have limited visibility.
+
+    /**
+     * @param secret Constructor creates a reference to the secret. Caller must use
+     * @link {#clearSecret} to overwrite its value in memory.
+     * @hide
+     */
+    public KeyChainProtectionParams(@UserSecretType int userSecretType,
+            @LockScreenUiFormat int lockScreenUiFormat,
+            @NonNull KeyDerivationParams keyDerivationParams,
+            @NonNull byte[] secret) {
+        mUserSecretType = userSecretType;
+        mLockScreenUiFormat = lockScreenUiFormat;
+        mKeyDerivationParams = Preconditions.checkNotNull(keyDerivationParams);
+        mSecret = Preconditions.checkNotNull(secret);
+    }
+
+    private KeyChainProtectionParams() {
+
+    }
+
+    /**
+     * @see TYPE_LOCKSCREEN
+     * @see TYPE_CUSTOM_PASSWORD
+     */
+    public @UserSecretType int getUserSecretType() {
+        return mUserSecretType;
+    }
+
+    /**
+     * Specifies UX shown to user during recovery.
+     * Default value is {@code UI_FORMAT_LOCKSCREEN}
+     *
+     * @see UI_FORMAT_PIN
+     * @see UI_FORMAT_PASSWORD
+     * @see UI_FORMAT_PATTERN
+     */
+    public @LockScreenUiFormat int getLockScreenUiFormat() {
+        return mLockScreenUiFormat;
+    }
+
+    /**
+     * Specifies function used to derive symmetric key from user input
+     * Format is defined in separate util class.
+     */
+    public @NonNull KeyDerivationParams getKeyDerivationParams() {
+        return mKeyDerivationParams;
+    }
+
+    /**
+     * Secret derived from user input.
+     * Default value is empty array
+     *
+     * @return secret or empty array
+     */
+    public @NonNull byte[] getSecret() {
+        return mSecret;
+    }
+
+    /**
+     * Builder for creating {@link KeyChainProtectionParams}.
+     */
+    public static class Builder {
+        private KeyChainProtectionParams mInstance = new KeyChainProtectionParams();
+
+        /**
+         * Sets user secret type.
+         *
+         * @see TYPE_LOCKSCREEN
+         * @see TYPE_CUSTOM_PASSWORD
+         * @param userSecretType The secret type
+         * @return This builder.
+         */
+        public Builder setUserSecretType(@UserSecretType int userSecretType) {
+            mInstance.mUserSecretType = userSecretType;
+            return this;
+        }
+
+        /**
+         * Sets UI format.
+         *
+         * @see UI_FORMAT_PIN
+         * @see UI_FORMAT_PASSWORD
+         * @see UI_FORMAT_PATTERN
+         * @param lockScreenUiFormat The UI format
+         * @return This builder.
+         */
+        public Builder setLockScreenUiFormat(@LockScreenUiFormat int lockScreenUiFormat) {
+            mInstance.mLockScreenUiFormat = lockScreenUiFormat;
+            return this;
+        }
+
+        /**
+         * Sets parameters of the key derivation function.
+         *
+         * @param keyDerivationParams Key derivation Params
+         * @return This builder.
+         */
+        public Builder setKeyDerivationParams(@NonNull KeyDerivationParams
+                keyDerivationParams) {
+            mInstance.mKeyDerivationParams = keyDerivationParams;
+            return this;
+        }
+
+        /**
+         * Secret derived from user input, or empty array.
+         *
+         * @param secret The secret.
+         * @return This builder.
+         */
+        public Builder setSecret(@NonNull byte[] secret) {
+            mInstance.mSecret = secret;
+            return this;
+        }
+
+
+        /**
+         * Creates a new {@link KeyChainProtectionParams} instance.
+         * The instance will include default values, if {@link setSecret}
+         * or {@link setUserSecretType} were not called.
+         *
+         * @return new instance
+         * @throws NullPointerException if some required fields were not set.
+         */
+        @NonNull public KeyChainProtectionParams build() {
+            if (mInstance.mUserSecretType == null) {
+                mInstance.mUserSecretType = TYPE_LOCKSCREEN;
+            }
+            Preconditions.checkNotNull(mInstance.mLockScreenUiFormat);
+            Preconditions.checkNotNull(mInstance.mKeyDerivationParams);
+            if (mInstance.mSecret == null) {
+                mInstance.mSecret = new byte[]{};
+            }
+            return mInstance;
+        }
+    }
+
+    /**
+     * Removes secret from memory than object is no longer used.
+     * Since finalizer call is not reliable, please use @link {#clearSecret} directly.
+     */
+    @Override
+    protected void finalize() throws Throwable {
+        clearSecret();
+        super.finalize();
+    }
+
+    /**
+     * Fills mSecret with zeroes.
+     */
+    public void clearSecret() {
+        Arrays.fill(mSecret, (byte) 0);
+    }
+
+    public static final Parcelable.Creator<KeyChainProtectionParams> CREATOR =
+            new Parcelable.Creator<KeyChainProtectionParams>() {
+        public KeyChainProtectionParams createFromParcel(Parcel in) {
+            return new KeyChainProtectionParams(in);
+        }
+
+        public KeyChainProtectionParams[] newArray(int length) {
+            return new KeyChainProtectionParams[length];
+        }
+    };
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(mUserSecretType);
+        out.writeInt(mLockScreenUiFormat);
+        out.writeTypedObject(mKeyDerivationParams, flags);
+        out.writeByteArray(mSecret);
+    }
+
+    /**
+     * @hide
+     */
+    protected KeyChainProtectionParams(Parcel in) {
+        mUserSecretType = in.readInt();
+        mLockScreenUiFormat = in.readInt();
+        mKeyDerivationParams = in.readTypedObject(KeyDerivationParams.CREATOR);
+        mSecret = in.createByteArray();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+}
diff --git a/core/java/android/security/keystore/KeychainSnapshot.aidl b/core/java/android/security/keystore/recovery/KeyChainSnapshot.aidl
similarity index 89%
rename from core/java/android/security/keystore/KeychainSnapshot.aidl
rename to core/java/android/security/keystore/recovery/KeyChainSnapshot.aidl
index b35713f..d02a2ea 100644
--- a/core/java/android/security/keystore/KeychainSnapshot.aidl
+++ b/core/java/android/security/keystore/recovery/KeyChainSnapshot.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.security.keystore;
+package android.security.keystore.recovery;
 
 /* @hide */
-parcelable KeychainSnapshot;
+parcelable KeyChainSnapshot;
diff --git a/core/java/android/security/keystore/recovery/KeyChainSnapshot.java b/core/java/android/security/keystore/recovery/KeyChainSnapshot.java
new file mode 100644
index 0000000..df535ed
--- /dev/null
+++ b/core/java/android/security/keystore/recovery/KeyChainSnapshot.java
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keystore.recovery;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.List;
+
+/**
+ * A snapshot of a version of the keystore. Two events can trigger the generation of a new snapshot:
+ *
+ * <ul>
+ *     <li>The user's lock screen changes. (A key derived from the user's lock screen is used to
+ *         protected the keychain, which is why this forces a new snapshot.)
+ *     <li>A key is added to or removed from the recoverable keychain.
+ * </ul>
+ *
+ * <p>The snapshot data is also encrypted with the remote trusted hardware's public key, so even
+ * the recovery agent itself should not be able to decipher the data. The recovery agent sends an
+ * instance of this to the remote trusted hardware whenever a new snapshot is generated. During a
+ * recovery flow, the recovery agent retrieves a snapshot from the remote trusted hardware. It then
+ * sends it to the framework, where it is decrypted using the user's lock screen from their previous
+ * device.
+ *
+ * @hide
+ */
+@SystemApi
+public final class KeyChainSnapshot implements Parcelable {
+    private static final int DEFAULT_MAX_ATTEMPTS = 10;
+    private static final long DEFAULT_COUNTER_ID = 1L;
+
+    private int mSnapshotVersion;
+    private int mMaxAttempts = DEFAULT_MAX_ATTEMPTS;
+    private long mCounterId = DEFAULT_COUNTER_ID;
+    private byte[] mServerParams;
+    private byte[] mPublicKey;
+    private List<KeyChainProtectionParams> mKeyChainProtectionParams;
+    private List<WrappedApplicationKey> mEntryRecoveryData;
+    private byte[] mEncryptedRecoveryKeyBlob;
+
+    /**
+     * @hide
+     * Deprecated, consider using builder.
+     */
+    public KeyChainSnapshot(
+            int snapshotVersion,
+            @NonNull List<KeyChainProtectionParams> keyChainProtectionParams,
+            @NonNull List<WrappedApplicationKey> wrappedApplicationKeys,
+            @NonNull byte[] encryptedRecoveryKeyBlob) {
+        mSnapshotVersion = snapshotVersion;
+        mKeyChainProtectionParams =
+                Preconditions.checkCollectionElementsNotNull(keyChainProtectionParams,
+                        "KeyChainProtectionParams");
+        mEntryRecoveryData = Preconditions.checkCollectionElementsNotNull(wrappedApplicationKeys,
+                "wrappedApplicationKeys");
+        mEncryptedRecoveryKeyBlob = Preconditions.checkNotNull(encryptedRecoveryKeyBlob);
+    }
+
+    private KeyChainSnapshot() {
+
+    }
+
+    /**
+     * Snapshot version for given account. It is incremented when user secret or list of application
+     * keys changes.
+     */
+    public int getSnapshotVersion() {
+        return mSnapshotVersion;
+    }
+
+    /**
+     * Number of user secret guesses allowed during Keychain recovery.
+     */
+    public int getMaxAttempts() {
+        return mMaxAttempts;
+    }
+
+    /**
+     * CounterId which is rotated together with user secret.
+     */
+    public long getCounterId() {
+        return mCounterId;
+    }
+
+    /**
+     * Server parameters.
+     */
+    public @NonNull byte[] getServerParams() {
+        return mServerParams;
+    }
+
+    /**
+     * Public key used to encrypt {@code encryptedRecoveryKeyBlob}.
+     *
+     * See implementation for binary key format
+     */
+    // TODO: document key format.
+    public @NonNull byte[] getTrustedHardwarePublicKey() {
+        return mPublicKey;
+    }
+
+    /**
+     * UI and key derivation parameters. Note that combination of secrets may be used.
+     */
+    public @NonNull List<KeyChainProtectionParams> getKeyChainProtectionParams() {
+        return mKeyChainProtectionParams;
+    }
+
+    /**
+     * List of application keys, with key material encrypted by
+     * the recovery key ({@link #getEncryptedRecoveryKeyBlob}).
+     */
+    public @NonNull List<WrappedApplicationKey> getWrappedApplicationKeys() {
+        return mEntryRecoveryData;
+    }
+
+    /**
+     * Recovery key blob, encrypted by user secret and recovery service public key.
+     */
+    public @NonNull byte[] getEncryptedRecoveryKeyBlob() {
+        return mEncryptedRecoveryKeyBlob;
+    }
+
+    public static final Creator<KeyChainSnapshot> CREATOR =
+            new Creator<KeyChainSnapshot>() {
+        public KeyChainSnapshot createFromParcel(Parcel in) {
+            return new KeyChainSnapshot(in);
+        }
+
+        public KeyChainSnapshot[] newArray(int length) {
+            return new KeyChainSnapshot[length];
+        }
+    };
+
+    /**
+     * Builder for creating {@link KeyChainSnapshot}.
+     * @hide
+     */
+    public static class Builder {
+        private KeyChainSnapshot mInstance = new KeyChainSnapshot();
+
+        /**
+         * Snapshot version for given account.
+         *
+         * @param snapshotVersion The snapshot version
+         * @return This builder.
+         */
+        public Builder setSnapshotVersion(int snapshotVersion) {
+            mInstance.mSnapshotVersion = snapshotVersion;
+            return this;
+        }
+
+        /**
+         * Sets the number of user secret guesses allowed during Keychain recovery.
+         *
+         * @param maxAttempts The maximum number of guesses.
+         * @return This builder.
+         */
+        public Builder setMaxAttempts(int maxAttempts) {
+            mInstance.mMaxAttempts = maxAttempts;
+            return this;
+        }
+
+        /**
+         * Sets counter id.
+         *
+         * @param counterId The counter id.
+         * @return This builder.
+         */
+        public Builder setCounterId(long counterId) {
+            mInstance.mCounterId = counterId;
+            return this;
+        }
+
+        /**
+         * Sets server parameters.
+         *
+         * @param serverParams The server parameters
+         * @return This builder.
+         */
+        public Builder setServerParams(byte[] serverParams) {
+            mInstance.mServerParams = serverParams;
+            return this;
+        }
+
+        /**
+         * Sets public key used to encrypt recovery blob.
+         *
+         * @param publicKey The public key
+         * @return This builder.
+         */
+        public Builder setTrustedHardwarePublicKey(byte[] publicKey) {
+            mInstance.mPublicKey = publicKey;
+            return this;
+        }
+
+        /**
+         * Sets UI and key derivation parameters
+         *
+         * @param recoveryMetadata The UI and key derivation parameters
+         * @return This builder.
+         */
+        public Builder setKeyChainProtectionParams(
+                @NonNull List<KeyChainProtectionParams> recoveryMetadata) {
+            mInstance.mKeyChainProtectionParams = recoveryMetadata;
+            return this;
+        }
+
+        /**
+         * List of application keys.
+         *
+         * @param entryRecoveryData List of application keys
+         * @return This builder.
+         */
+        public Builder setWrappedApplicationKeys(List<WrappedApplicationKey> entryRecoveryData) {
+            mInstance.mEntryRecoveryData = entryRecoveryData;
+            return this;
+        }
+
+        /**
+         * Sets recovery key blob
+         *
+         * @param encryptedRecoveryKeyBlob The recovery key blob.
+         * @return This builder.
+         */
+        public Builder setEncryptedRecoveryKeyBlob(@NonNull byte[] encryptedRecoveryKeyBlob) {
+            mInstance.mEncryptedRecoveryKeyBlob = encryptedRecoveryKeyBlob;
+            return this;
+        }
+
+
+        /**
+         * Creates a new {@link KeyChainSnapshot} instance.
+         *
+         * @return new instance
+         * @throws NullPointerException if some required fields were not set.
+         */
+        @NonNull public KeyChainSnapshot build() {
+            Preconditions.checkCollectionElementsNotNull(mInstance.mKeyChainProtectionParams,
+                    "recoveryMetadata");
+            Preconditions.checkCollectionElementsNotNull(mInstance.mEntryRecoveryData,
+                    "entryRecoveryData");
+            Preconditions.checkNotNull(mInstance.mEncryptedRecoveryKeyBlob);
+            Preconditions.checkNotNull(mInstance.mServerParams);
+            Preconditions.checkNotNull(mInstance.mPublicKey);
+            return mInstance;
+        }
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(mSnapshotVersion);
+        out.writeTypedList(mKeyChainProtectionParams);
+        out.writeByteArray(mEncryptedRecoveryKeyBlob);
+        out.writeTypedList(mEntryRecoveryData);
+        out.writeInt(mMaxAttempts);
+        out.writeLong(mCounterId);
+        out.writeByteArray(mServerParams);
+        out.writeByteArray(mPublicKey);
+    }
+
+    /**
+     * @hide
+     */
+    protected KeyChainSnapshot(Parcel in) {
+        mSnapshotVersion = in.readInt();
+        mKeyChainProtectionParams = in.createTypedArrayList(KeyChainProtectionParams.CREATOR);
+        mEncryptedRecoveryKeyBlob = in.createByteArray();
+        mEntryRecoveryData = in.createTypedArrayList(WrappedApplicationKey.CREATOR);
+        mMaxAttempts = in.readInt();
+        mCounterId = in.readLong();
+        mServerParams = in.createByteArray();
+        mPublicKey = in.createByteArray();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+}
diff --git a/core/java/android/security/keystore/KeyDerivationParams.aidl b/core/java/android/security/keystore/recovery/KeyDerivationParams.aidl
similarity index 93%
rename from core/java/android/security/keystore/KeyDerivationParams.aidl
rename to core/java/android/security/keystore/recovery/KeyDerivationParams.aidl
index f39aa04..2b1bbbe 100644
--- a/core/java/android/security/keystore/KeyDerivationParams.aidl
+++ b/core/java/android/security/keystore/recovery/KeyDerivationParams.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.security.keystore;
+package android.security.keystore.recovery;
 
 /* @hide */
 parcelable KeyDerivationParams;
diff --git a/core/java/android/security/keystore/recovery/KeyDerivationParams.java b/core/java/android/security/keystore/recovery/KeyDerivationParams.java
new file mode 100644
index 0000000..fc909a0
--- /dev/null
+++ b/core/java/android/security/keystore/recovery/KeyDerivationParams.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keystore.recovery;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Collection of parameters which define a key derivation function.
+ * Currently only supports salted SHA-256
+ *
+ * @hide
+ */
+@SystemApi
+public final class KeyDerivationParams implements Parcelable {
+    private final int mAlgorithm;
+    private byte[] mSalt;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"ALGORITHM_"}, value = {ALGORITHM_SHA256, ALGORITHM_ARGON2ID})
+    public @interface KeyDerivationAlgorithm {
+    }
+
+    /**
+     * Salted SHA256
+     */
+    public static final int ALGORITHM_SHA256 = 1;
+
+    /**
+     * Argon2ID
+     * @hide
+     */
+    // TODO: add Argon2ID support.
+    public static final int ALGORITHM_ARGON2ID = 2;
+
+    /**
+     * Creates instance of the class to to derive key using salted SHA256 hash.
+     */
+    public static KeyDerivationParams createSha256Params(@NonNull byte[] salt) {
+        return new KeyDerivationParams(ALGORITHM_SHA256, salt);
+    }
+
+    /**
+     * @hide
+     */
+    // TODO: Make private once legacy API is removed
+    public KeyDerivationParams(@KeyDerivationAlgorithm int algorithm, @NonNull byte[] salt) {
+        mAlgorithm = algorithm;
+        mSalt = Preconditions.checkNotNull(salt);
+    }
+
+    /**
+     * Gets algorithm.
+     */
+    public @KeyDerivationAlgorithm int getAlgorithm() {
+        return mAlgorithm;
+    }
+
+    /**
+     * Gets salt.
+     */
+    public @NonNull byte[] getSalt() {
+        return mSalt;
+    }
+
+    public static final Parcelable.Creator<KeyDerivationParams> CREATOR =
+            new Parcelable.Creator<KeyDerivationParams>() {
+        public KeyDerivationParams createFromParcel(Parcel in) {
+                return new KeyDerivationParams(in);
+        }
+
+        public KeyDerivationParams[] newArray(int length) {
+            return new KeyDerivationParams[length];
+        }
+    };
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(mAlgorithm);
+        out.writeByteArray(mSalt);
+    }
+
+    /**
+     * @hide
+     */
+    protected KeyDerivationParams(Parcel in) {
+        mAlgorithm = in.readInt();
+        mSalt = in.createByteArray();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+}
diff --git a/core/java/android/security/keystore/recovery/LockScreenRequiredException.java b/core/java/android/security/keystore/recovery/LockScreenRequiredException.java
new file mode 100644
index 0000000..0062d29
--- /dev/null
+++ b/core/java/android/security/keystore/recovery/LockScreenRequiredException.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.security.keystore.recovery;
+
+import android.annotation.SystemApi;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * Error thrown when trying to generate keys for a profile that has no lock screen set.
+ *
+ * <p>A lock screen must be set, as the lock screen is used to encrypt the snapshot.
+ *
+ * @hide
+ */
+@SystemApi
+public class LockScreenRequiredException extends GeneralSecurityException {
+    public LockScreenRequiredException(String msg) {
+        super(msg);
+    }
+}
diff --git a/core/java/android/security/keystore/recovery/RecoveryClaim.java b/core/java/android/security/keystore/recovery/RecoveryClaim.java
new file mode 100644
index 0000000..45c6b4ff
--- /dev/null
+++ b/core/java/android/security/keystore/recovery/RecoveryClaim.java
@@ -0,0 +1,55 @@
+/*
+ * 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.recovery;
+
+/**
+ * An attempt to recover a keychain protected by remote secure hardware.
+ *
+ * @hide
+ * Deprecated
+ */
+public class RecoveryClaim {
+
+    private final RecoverySession mRecoverySession;
+    private final byte[] mClaimBytes;
+
+    RecoveryClaim(RecoverySession recoverySession, byte[] claimBytes) {
+        mRecoverySession = recoverySession;
+        mClaimBytes = claimBytes;
+    }
+
+    /**
+     * Returns the session associated with the recovery attempt. This is used to match the symmetric
+     * key, which remains internal to the framework, for decrypting the claim response.
+     *
+     * @return The session data.
+     */
+    public RecoverySession getRecoverySession() {
+        return mRecoverySession;
+    }
+
+    /**
+     * Returns the encrypted claim's bytes.
+     *
+     * <p>This should be sent by the recovery agent to the remote secure hardware, which will use
+     * it to decrypt the keychain, before sending it re-encrypted with the session's symmetric key
+     * to the device.
+     */
+    public byte[] getClaimBytes() {
+        return mClaimBytes;
+    }
+}
diff --git a/core/java/android/security/keystore/recovery/RecoveryController.java b/core/java/android/security/keystore/recovery/RecoveryController.java
new file mode 100644
index 0000000..71a36f1
--- /dev/null
+++ b/core/java/android/security/keystore/recovery/RecoveryController.java
@@ -0,0 +1,460 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keystore.recovery;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
+
+import com.android.internal.widget.ILockSettings;
+
+import java.security.cert.CertificateException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * An assistant for generating {@link javax.crypto.SecretKey} instances that can be recovered by
+ * other Android devices belonging to the user. The exported keychain is protected by the user's
+ * lock screen.
+ *
+ * <p>The RecoveryController must be paired with a recovery agent. The recovery agent is responsible
+ * for transporting the keychain to remote trusted hardware. This hardware must prevent brute force
+ * attempts against the user's lock screen by limiting the number of allowed guesses (to, e.g., 10).
+ * After  that number of incorrect guesses, the trusted hardware no longer allows access to the
+ * key chain.
+ *
+ * <p>For now only the recovery agent itself is able to create keys, so it is expected that the
+ * recovery agent is itself the system app.
+ *
+ * <p>A recovery agent requires the privileged permission
+ * {@code android.Manifest.permission#RECOVER_KEYSTORE}.
+ *
+ * @hide
+ */
+@SystemApi
+public class RecoveryController {
+    private static final String TAG = "RecoveryController";
+
+    /** Key has been successfully synced. */
+    public static final int RECOVERY_STATUS_SYNCED = 0;
+    /** Waiting for recovery agent to sync the key. */
+    public static final int RECOVERY_STATUS_SYNC_IN_PROGRESS = 1;
+    /** Recovery account is not available. */
+    public static final int RECOVERY_STATUS_MISSING_ACCOUNT = 2;
+    /** Key cannot be synced. */
+    public static final int RECOVERY_STATUS_PERMANENT_FAILURE = 3;
+
+    /**
+     * Failed because no snapshot is yet pending to be synced for the user.
+     *
+     * @hide
+     */
+    public static final int ERROR_NO_SNAPSHOT_PENDING = 21;
+
+    /**
+     * Failed due to an error internal to the recovery service. This is unexpected and indicates
+     * either a problem with the logic in the service, or a problem with a dependency of the
+     * service (such as AndroidKeyStore).
+     *
+     * @hide
+     */
+    public static final int ERROR_SERVICE_INTERNAL_ERROR = 22;
+
+    /**
+     * Failed because the user does not have a lock screen set.
+     *
+     * @hide
+     */
+    public static final int ERROR_INSECURE_USER = 23;
+
+    /**
+     * Error thrown when attempting to use a recovery session that has since been closed.
+     *
+     * @hide
+     */
+    public static final int ERROR_SESSION_EXPIRED = 24;
+
+    /**
+     * Failed because the provided certificate was not a valid X509 certificate.
+     *
+     * @hide
+     */
+    public static final int ERROR_BAD_CERTIFICATE_FORMAT = 25;
+
+    /**
+     * Error thrown if decryption failed. This might be because the tag is wrong, the key is wrong,
+     * the data has become corrupted, the data has been tampered with, etc.
+     *
+     * @hide
+     */
+    public static final int ERROR_DECRYPTION_FAILED = 26;
+
+
+    private final ILockSettings mBinder;
+
+    private RecoveryController(ILockSettings binder) {
+        mBinder = binder;
+    }
+
+    /**
+     * Internal method used by {@code RecoverySession}.
+     *
+     * @hide
+     */
+    ILockSettings getBinder() {
+        return mBinder;
+    }
+
+    /**
+     * Gets a new instance of the class.
+     */
+    public static RecoveryController getInstance(Context context) {
+        ILockSettings lockSettings =
+                ILockSettings.Stub.asInterface(ServiceManager.getService("lock_settings"));
+        return new RecoveryController(lockSettings);
+    }
+
+    /**
+     * Initializes key recovery service for the calling application. RecoveryController
+     * randomly chooses one of the keys from the list and keeps it to use for future key export
+     * operations. Collection of all keys in the list must be signed by the provided {@code
+     * rootCertificateAlias}, which must also be present in the list of root certificates
+     * preinstalled on the device. The random selection allows RecoveryController to select
+     * which of a set of remote recovery service devices will be used.
+     *
+     * <p>In addition, RecoveryController enforces a delay of three months between
+     * consecutive initialization attempts, to limit the ability of an attacker to often switch
+     * remote recovery devices and significantly increase number of recovery attempts.
+     *
+     * @param rootCertificateAlias alias of a root certificate preinstalled on the device
+     * @param signedPublicKeyList binary blob a list of X509 certificates and signature
+     * @throws CertificateException if the {@code signedPublicKeyList} is in a bad format.
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
+     */
+    @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE)
+    public void initRecoveryService(
+            @NonNull String rootCertificateAlias, @NonNull byte[] signedPublicKeyList)
+            throws CertificateException, InternalRecoveryServiceException {
+        try {
+            mBinder.initRecoveryService(rootCertificateAlias, signedPublicKeyList);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            if (e.errorCode == ERROR_BAD_CERTIFICATE_FORMAT) {
+                throw new CertificateException(e.getMessage());
+            }
+            throw wrapUnexpectedServiceSpecificException(e);
+        }
+    }
+
+    /**
+     * Returns data necessary to store all recoverable keys. Key material is
+     * encrypted with user secret and recovery public key.
+     *
+     * @return Data necessary to recover keystore.
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
+     */
+    @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE)
+    public @NonNull KeyChainSnapshot getRecoveryData()
+            throws InternalRecoveryServiceException {
+        try {
+            return mBinder.getRecoveryData(/*account=*/ new byte[]{});
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            if (e.errorCode == ERROR_NO_SNAPSHOT_PENDING) {
+                return null;
+            }
+            throw wrapUnexpectedServiceSpecificException(e);
+        }
+    }
+
+    /**
+     * Sets a listener which notifies recovery agent that new recovery snapshot is available. {@link
+     * #getRecoveryData} can be used to get the snapshot. Note that every recovery agent can have at
+     * most one registered listener at any time.
+     *
+     * @param intent triggered when new snapshot is available. Unregisters listener if the value is
+     *     {@code null}.
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
+     */
+    @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE)
+    public void setSnapshotCreatedPendingIntent(@Nullable PendingIntent intent)
+            throws InternalRecoveryServiceException {
+        try {
+            mBinder.setSnapshotCreatedPendingIntent(intent);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            throw wrapUnexpectedServiceSpecificException(e);
+        }
+    }
+
+    /**
+     * Server parameters used to generate new recovery key blobs. This value will be included in
+     * {@code KeyChainSnapshot.getEncryptedRecoveryKeyBlob()}. The same value must be included
+     * in vaultParams {@link #startRecoverySession}
+     *
+     * @param serverParams included in recovery key blob.
+     * @see #getRecoveryData
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
+     */
+    @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE)
+    public void setServerParams(byte[] serverParams) throws InternalRecoveryServiceException {
+        try {
+            mBinder.setServerParams(serverParams);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            throw wrapUnexpectedServiceSpecificException(e);
+        }
+    }
+
+    /**
+     * Gets aliases of recoverable keys for the application.
+     *
+     * @param packageName which recoverable keys' aliases will be returned.
+     *
+     * @return {@code List} of all aliases.
+     */
+    public List<String> getAliases(@Nullable String packageName)
+            throws InternalRecoveryServiceException {
+        try {
+            // TODO: update aidl
+            Map<String, Integer> allStatuses = mBinder.getRecoveryStatus(packageName);
+            return new ArrayList<>(allStatuses.keySet());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            throw wrapUnexpectedServiceSpecificException(e);
+        }
+    }
+
+    /**
+     * Updates recovery status for given key. It is used to notify keystore that key was
+     * successfully stored on the server or there were an error. Application can check this value
+     * using {@code getRecoveyStatus}.
+     *
+     * @param packageName Application whose recoverable key's status are to be updated.
+     * @param alias Application-specific key alias.
+     * @param status Status specific to recovery agent.
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
+     */
+    @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE)
+    public void setRecoveryStatus(
+            @NonNull String packageName, String alias, int status)
+            throws NameNotFoundException, InternalRecoveryServiceException {
+        try {
+            // TODO: update aidl
+            String[] aliases = alias == null ? null : new String[]{alias};
+            mBinder.setRecoveryStatus(packageName, aliases, status);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            throw wrapUnexpectedServiceSpecificException(e);
+        }
+    }
+
+    /**
+     * Returns recovery status for Application's KeyStore key.
+     * Negative status values are reserved for recovery agent specific codes. List of common codes:
+     *
+     * <ul>
+     *   <li>{@link #RECOVERY_STATUS_SYNCED}
+     *   <li>{@link #RECOVERY_STATUS_SYNC_IN_PROGRESS}
+     *   <li>{@link #RECOVERY_STATUS_MISSING_ACCOUNT}
+     *   <li>{@link #RECOVERY_STATUS_PERMANENT_FAILURE}
+     * </ul>
+     *
+     * @param packageName Application whose recoverable key status is returned.
+     * @param alias Application-specific key alias.
+     * @return Recovery status.
+     * @see #setRecoveryStatus
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
+     */
+    public int getRecoveryStatus(String packageName, String alias)
+            throws InternalRecoveryServiceException {
+        try {
+            // TODO: update aidl
+            Map<String, Integer> allStatuses = mBinder.getRecoveryStatus(packageName);
+            Integer status = allStatuses.get(alias);
+            if (status == null) {
+                return RecoveryController.RECOVERY_STATUS_PERMANENT_FAILURE;
+            } else {
+                return status;
+            }
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            throw wrapUnexpectedServiceSpecificException(e);
+        }
+    }
+
+    /**
+     * Specifies a set of secret types used for end-to-end keystore encryption. Knowing all of them
+     * is necessary to recover data.
+     *
+     * @param secretTypes {@link KeyChainProtectionParams#TYPE_LOCKSCREEN} or {@link
+     *     KeyChainProtectionParams#TYPE_CUSTOM_PASSWORD}
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
+     */
+    public void setRecoverySecretTypes(
+            @NonNull @KeyChainProtectionParams.UserSecretType int[] secretTypes)
+            throws InternalRecoveryServiceException {
+        try {
+            mBinder.setRecoverySecretTypes(secretTypes);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            throw wrapUnexpectedServiceSpecificException(e);
+        }
+    }
+
+    /**
+     * Defines a set of secret types used for end-to-end keystore encryption. Knowing all of them is
+     * necessary to generate KeyChainSnapshot.
+     *
+     * @return list of recovery secret types
+     * @see KeyChainSnapshot
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
+     */
+    public @NonNull @KeyChainProtectionParams.UserSecretType int[] getRecoverySecretTypes()
+            throws InternalRecoveryServiceException {
+        try {
+            return mBinder.getRecoverySecretTypes();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            throw wrapUnexpectedServiceSpecificException(e);
+        }
+    }
+
+    /**
+     * Returns a list of recovery secret types, necessary to create a pending recovery snapshot.
+     * When user enters a secret of a pending type {@link #recoverySecretAvailable} should be
+     * called.
+     *
+     * @return list of recovery secret types
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
+     */
+    @NonNull
+    public @KeyChainProtectionParams.UserSecretType int[] getPendingRecoverySecretTypes()
+            throws InternalRecoveryServiceException {
+        try {
+            return mBinder.getPendingRecoverySecretTypes();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            throw wrapUnexpectedServiceSpecificException(e);
+        }
+    }
+
+    /**
+     * Method notifies KeyStore that a user-generated secret is available. This method generates a
+     * symmetric session key which a trusted remote device can use to return a recovery key. Caller
+     * should use {@link KeyChainProtectionParams#clearSecret} to override the secret value in
+     * memory.
+     *
+     * @param recoverySecret user generated secret together with parameters necessary to regenerate
+     *     it on a new device.
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
+     */
+    public void recoverySecretAvailable(@NonNull KeyChainProtectionParams recoverySecret)
+            throws InternalRecoveryServiceException {
+        try {
+            mBinder.recoverySecretAvailable(recoverySecret);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            throw wrapUnexpectedServiceSpecificException(e);
+        }
+    }
+
+    /**
+     * Generates a AES256/GCM/NoPADDING key called {@code alias} and loads it into the recoverable
+     * key store. Returns the raw material of the key.
+     *
+     * @param alias The key alias.
+     * @param account The account associated with the key
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
+     * @throws LockScreenRequiredException if the user has not set a lock screen. This is required
+     *     to generate recoverable keys, as the snapshots are encrypted using a key derived from the
+     *     lock screen.
+     */
+    public byte[] generateAndStoreKey(@NonNull String alias, byte[] account)
+            throws InternalRecoveryServiceException, LockScreenRequiredException {
+        try {
+            // TODO: add account
+            return mBinder.generateAndStoreKey(alias);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            if (e.errorCode == ERROR_INSECURE_USER) {
+                throw new LockScreenRequiredException(e.getMessage());
+            }
+            throw wrapUnexpectedServiceSpecificException(e);
+        }
+    }
+
+    /**
+     * Removes a key called {@code alias} from the recoverable key store.
+     *
+     * @param alias The key alias.
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
+     */
+    public void removeKey(@NonNull String alias) throws InternalRecoveryServiceException {
+        try {
+            mBinder.removeKey(alias);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            throw wrapUnexpectedServiceSpecificException(e);
+        }
+    }
+
+    InternalRecoveryServiceException wrapUnexpectedServiceSpecificException(
+            ServiceSpecificException e) {
+        if (e.errorCode == ERROR_SERVICE_INTERNAL_ERROR) {
+            return new InternalRecoveryServiceException(e.getMessage());
+        }
+
+        // Should never happen. If it does, it's a bug, and we need to update how the method that
+        // called this throws its exceptions.
+        return new InternalRecoveryServiceException("Unexpected error code for method: "
+                + e.errorCode, e);
+    }
+}
diff --git a/core/java/android/security/keystore/recovery/RecoveryControllerException.java b/core/java/android/security/keystore/recovery/RecoveryControllerException.java
new file mode 100644
index 0000000..2733aca
--- /dev/null
+++ b/core/java/android/security/keystore/recovery/RecoveryControllerException.java
@@ -0,0 +1,37 @@
+/*
+ * 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.recovery;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * Base exception for errors thrown by {@link RecoveryController}.
+ *
+ * @hide
+ * Deprecated
+ */
+public abstract class RecoveryControllerException extends GeneralSecurityException {
+    RecoveryControllerException() { }
+
+    RecoveryControllerException(String msg) {
+        super(msg);
+    }
+
+    public RecoveryControllerException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/core/java/android/security/keystore/recovery/RecoverySession.java b/core/java/android/security/keystore/recovery/RecoverySession.java
new file mode 100644
index 0000000..4db5d6e
--- /dev/null
+++ b/core/java/android/security/keystore/recovery/RecoverySession.java
@@ -0,0 +1,177 @@
+/*
+ * 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.recovery;
+
+import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.os.RemoteException;
+import android.os.ServiceSpecificException;
+import android.util.Log;
+
+import java.security.SecureRandom;
+import java.security.cert.CertificateException;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Session to recover a {@link KeyChainSnapshot} from the remote trusted hardware, initiated by a
+ * recovery agent.
+ *
+ * @hide
+ */
+@SystemApi
+public class RecoverySession implements AutoCloseable {
+    private static final String TAG = "RecoverySession";
+
+    private static final int SESSION_ID_LENGTH_BYTES = 16;
+
+    private final String mSessionId;
+    private final RecoveryController mRecoveryController;
+
+    private RecoverySession(RecoveryController recoveryController, String sessionId) {
+        mRecoveryController = recoveryController;
+        mSessionId = sessionId;
+    }
+
+    /**
+     * A new session, started by {@code recoveryManager}.
+     */
+    @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE)
+    static RecoverySession newInstance(RecoveryController recoveryController) {
+        return new RecoverySession(recoveryController, newSessionId());
+    }
+
+    /**
+     * Returns a new random session ID.
+     */
+    private static String newSessionId() {
+        SecureRandom secureRandom = new SecureRandom();
+        byte[] sessionId = new byte[SESSION_ID_LENGTH_BYTES];
+        secureRandom.nextBytes(sessionId);
+        StringBuilder sb = new StringBuilder();
+        for (byte b : sessionId) {
+            sb.append(Byte.toHexString(b, /*upperCase=*/ false));
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Starts a recovery session and returns a blob with proof of recovery secret possession.
+     * The method generates a symmetric key for a session, which trusted remote device can use to
+     * return recovery key.
+     *
+     * @param verifierPublicKey Encoded {@code java.security.cert.X509Certificate} with Public key
+     *     used to create the recovery blob on the source device.
+     *     Keystore will verify the certificate using root of trust.
+     * @param vaultParams Must match the parameters in the corresponding field in the recovery blob.
+     *     Used to limit number of guesses.
+     * @param vaultChallenge Data passed from server for this recovery session and used to prevent
+     *     replay attacks
+     * @param secrets Secrets provided by user, the method only uses type and secret fields.
+     * @return The recovery claim. Claim provides a b binary blob with recovery claim. It is
+     *     encrypted with verifierPublicKey and contains a proof of user secrets, session symmetric
+     *     key and parameters necessary to identify the counter with the number of failed recovery
+     *     attempts.
+     * @throws CertificateException if the {@code verifierPublicKey} is in an incorrect
+     *     format.
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
+     */
+    @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE)
+    @NonNull public byte[] start(
+            @NonNull byte[] verifierPublicKey,
+            @NonNull byte[] vaultParams,
+            @NonNull byte[] vaultChallenge,
+            @NonNull List<KeyChainProtectionParams> secrets)
+            throws CertificateException, InternalRecoveryServiceException {
+        try {
+            byte[] recoveryClaim =
+                    mRecoveryController.getBinder().startRecoverySession(
+                            mSessionId,
+                            verifierPublicKey,
+                            vaultParams,
+                            vaultChallenge,
+                            secrets);
+            return recoveryClaim;
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            if (e.errorCode == RecoveryController.ERROR_BAD_CERTIFICATE_FORMAT) {
+                throw new CertificateException(e.getMessage());
+            }
+            throw mRecoveryController.wrapUnexpectedServiceSpecificException(e);
+        }
+    }
+
+    /**
+     * Imports keys.
+     *
+     * @param recoveryKeyBlob Recovery blob encrypted by symmetric key generated for this session.
+     * @param applicationKeys Application keys. Key material can be decrypted using recoveryKeyBlob
+     *     and session. KeyStore only uses package names from the application info in {@link
+     *     WrappedApplicationKey}. Caller is responsibility to perform certificates check.
+     * @return Map from alias to raw key material.
+     * @throws SessionExpiredException if {@code session} has since been closed.
+     * @throws DecryptionFailedException if unable to decrypt the snapshot.
+     * @throws InternalRecoveryServiceException if an error occurs internal to the recovery service.
+     */
+    @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE)
+    public Map<String, byte[]> recoverKeys(
+            @NonNull byte[] recoveryKeyBlob,
+            @NonNull List<WrappedApplicationKey> applicationKeys)
+            throws SessionExpiredException, DecryptionFailedException,
+            InternalRecoveryServiceException {
+        try {
+            return (Map<String, byte[]>) mRecoveryController.getBinder().recoverKeys(
+                    mSessionId, recoveryKeyBlob, applicationKeys);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            if (e.errorCode == RecoveryController.ERROR_DECRYPTION_FAILED) {
+                throw new DecryptionFailedException(e.getMessage());
+            }
+            if (e.errorCode == RecoveryController.ERROR_SESSION_EXPIRED) {
+                throw new SessionExpiredException(e.getMessage());
+            }
+            throw mRecoveryController.wrapUnexpectedServiceSpecificException(e);
+        }
+    }
+
+    /**
+     * An internal session ID, used by the framework to match recovery claims to snapshot responses.
+     *
+     * @hide
+     */
+    String getSessionId() {
+        return mSessionId;
+    }
+
+    /**
+     * Deletes all data associated with {@code session}. Should not be invoked directly but via
+     * {@link RecoverySession#close()}.
+     */
+    @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE)
+    @Override
+    public void close() {
+        try {
+            mRecoveryController.getBinder().closeSession(mSessionId);
+        } catch (RemoteException | ServiceSpecificException e) {
+            Log.e(TAG, "Unexpected error trying to close session", e);
+        }
+    }
+}
diff --git a/core/java/android/security/keystore/recovery/SessionExpiredException.java b/core/java/android/security/keystore/recovery/SessionExpiredException.java
new file mode 100644
index 0000000..8c18e41
--- /dev/null
+++ b/core/java/android/security/keystore/recovery/SessionExpiredException.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 android.security.keystore.recovery;
+
+import android.annotation.SystemApi;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * Error thrown when attempting to use a {@link RecoverySession} that has since expired.
+ *
+ * @hide
+ */
+@SystemApi
+public class SessionExpiredException extends GeneralSecurityException {
+    public SessionExpiredException(String msg) {
+        super(msg);
+    }
+}
diff --git a/core/java/android/security/keystore/WrappedApplicationKey.aidl b/core/java/android/security/keystore/recovery/WrappedApplicationKey.aidl
similarity index 93%
rename from core/java/android/security/keystore/WrappedApplicationKey.aidl
rename to core/java/android/security/keystore/recovery/WrappedApplicationKey.aidl
index a6294fe..b2d1ae4 100644
--- a/core/java/android/security/keystore/WrappedApplicationKey.aidl
+++ b/core/java/android/security/keystore/recovery/WrappedApplicationKey.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.security.keystore;
+package android.security.keystore.recovery;
 
 /* @hide */
 parcelable WrappedApplicationKey;
diff --git a/core/java/android/security/keystore/recovery/WrappedApplicationKey.java b/core/java/android/security/keystore/recovery/WrappedApplicationKey.java
new file mode 100644
index 0000000..f360bbe9
--- /dev/null
+++ b/core/java/android/security/keystore/recovery/WrappedApplicationKey.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keystore.recovery;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+/**
+ * Helper class with data necessary recover a single application key, given a recovery key.
+ *
+ * <ul>
+ *   <li>Alias - Keystore alias of the key.
+ *   <li>Account Recovery Agent specific account associated with the key.
+ *   <li>Encrypted key material.
+ * </ul>
+ *
+ * Note that Application info is not included. Recovery Agent can only make its own keys
+ * recoverable.
+ *
+ * @hide
+ */
+@SystemApi
+public final class WrappedApplicationKey implements Parcelable {
+    private String mAlias;
+    // The only supported format is AES-256 symmetric key.
+    private byte[] mEncryptedKeyMaterial;
+    private byte[] mAccount;
+
+    /**
+     * Builder for creating {@link WrappedApplicationKey}.
+     */
+    public static class Builder {
+        private WrappedApplicationKey mInstance = new WrappedApplicationKey();
+
+        /**
+         * Sets Application-specific alias of the key.
+         *
+         * @param alias The alias.
+         * @return This builder.
+         */
+        public Builder setAlias(@NonNull String alias) {
+            mInstance.mAlias = alias;
+            return this;
+        }
+
+        /**
+         * Sets Recovery agent specific account.
+         *
+         * @param account The account.
+         * @return This builder.
+         */
+        public Builder setAccount(@NonNull byte[] account) {
+            mInstance.mAccount = account;
+            return this;
+        }
+
+        /**
+         * Sets key material encrypted by recovery key.
+         *
+         * @param encryptedKeyMaterial The key material
+         * @return This builder
+         */
+
+        public Builder setEncryptedKeyMaterial(@NonNull byte[] encryptedKeyMaterial) {
+            mInstance.mEncryptedKeyMaterial = encryptedKeyMaterial;
+            return this;
+        }
+
+        /**
+         * Creates a new {@link WrappedApplicationKey} instance.
+         *
+         * @return new instance
+         * @throws NullPointerException if some required fields were not set.
+         */
+        @NonNull public WrappedApplicationKey build() {
+            Preconditions.checkNotNull(mInstance.mAlias);
+            Preconditions.checkNotNull(mInstance.mEncryptedKeyMaterial);
+            if (mInstance.mAccount == null) {
+                mInstance.mAccount = new byte[]{};
+            }
+            return mInstance;
+        }
+    }
+
+    private WrappedApplicationKey() {
+    }
+
+    /**
+     * Deprecated - consider using Builder.
+     * @hide
+     */
+    public WrappedApplicationKey(@NonNull String alias, @NonNull byte[] encryptedKeyMaterial) {
+        mAlias = Preconditions.checkNotNull(alias);
+        mEncryptedKeyMaterial = Preconditions.checkNotNull(encryptedKeyMaterial);
+    }
+
+    /**
+     * Application-specific alias of the key.
+     *
+     * @see java.security.KeyStore.aliases
+     */
+    public @NonNull String getAlias() {
+        return mAlias;
+    }
+
+    /** Key material encrypted by recovery key. */
+    public @NonNull byte[] getEncryptedKeyMaterial() {
+        return mEncryptedKeyMaterial;
+    }
+
+    /** Account, default value is empty array */
+    public @NonNull byte[] getAccount() {
+        if (mAccount == null) {
+            return new byte[]{};
+        }
+        return mAccount;
+    }
+
+    public static final Parcelable.Creator<WrappedApplicationKey> CREATOR =
+            new Parcelable.Creator<WrappedApplicationKey>() {
+                public WrappedApplicationKey createFromParcel(Parcel in) {
+                    return new WrappedApplicationKey(in);
+                }
+
+                public WrappedApplicationKey[] newArray(int length) {
+                    return new WrappedApplicationKey[length];
+                }
+            };
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeString(mAlias);
+        out.writeByteArray(mEncryptedKeyMaterial);
+        out.writeByteArray(mAccount);
+    }
+
+    /**
+     * @hide
+     */
+    protected WrappedApplicationKey(Parcel in) {
+        mAlias = in.readString();
+        mEncryptedKeyMaterial = in.createByteArray();
+        mAccount = in.createByteArray();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+}
diff --git a/core/java/android/service/autofill/AutofillFieldClassificationService.java b/core/java/android/service/autofill/AutofillFieldClassificationService.java
index df63a91..1ef6100 100644
--- a/core/java/android/service/autofill/AutofillFieldClassificationService.java
+++ b/core/java/android/service/autofill/AutofillFieldClassificationService.java
@@ -172,6 +172,7 @@
      * {@hide}
      */
     public static final class Scores implements Parcelable {
+        @NonNull
         public final float[][] scores;
 
         private Scores(Parcel parcel) {
@@ -185,11 +186,23 @@
             }
         }
 
-        private Scores(float[][] scores) {
+        private Scores(@NonNull float[][] scores) {
             this.scores = scores;
         }
 
         @Override
+        public String toString() {
+            final int size1 = scores.length;
+            final int size2 = size1 > 0 ? scores[0].length : 0;
+            final StringBuilder builder = new StringBuilder("Scores [")
+                    .append(size1).append("x").append(size2).append("] ");
+            for (int i = 0; i < size1; i++) {
+                builder.append(i).append(": ").append(Arrays.toString(scores[i])).append(' ');
+            }
+            return builder.toString();
+        }
+
+        @Override
         public int describeContents() {
             return 0;
         }
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 9f9033c..b313514 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -40,7 +40,7 @@
         DEFAULT_FLAGS.put("device_info_v2", "true");
         DEFAULT_FLAGS.put("settings_app_info_v2", "true");
         DEFAULT_FLAGS.put("settings_connected_device_v2", "true");
-        DEFAULT_FLAGS.put("settings_battery_v2", "false");
+        DEFAULT_FLAGS.put("settings_battery_v2", "true");
         DEFAULT_FLAGS.put("settings_battery_display_app_list", "false");
         DEFAULT_FLAGS.put("settings_security_settings_v2", "true");
         DEFAULT_FLAGS.put("settings_zone_picker_v2", "true");
diff --git a/core/java/android/util/PackageUtils.java b/core/java/android/util/PackageUtils.java
index e2e9d53..a5e3818 100644
--- a/core/java/android/util/PackageUtils.java
+++ b/core/java/android/util/PackageUtils.java
@@ -105,7 +105,7 @@
      * @param data The data.
      * @return The digest or null if an error occurs.
      */
-    public static @Nullable String computeSha256Digest(@NonNull byte[] data) {
+    public static @Nullable byte[] computeSha256DigestBytes(@NonNull byte[] data) {
         MessageDigest messageDigest;
         try {
             messageDigest = MessageDigest.getInstance("SHA256");
@@ -116,6 +116,15 @@
 
         messageDigest.update(data);
 
-        return ByteStringUtils.toHexString(messageDigest.digest());
+        return messageDigest.digest();
+    }
+
+    /**
+     * Computes the SHA256 digest of some data.
+     * @param data The data.
+     * @return The digest or null if an error occurs.
+     */
+    public static @Nullable String computeSha256Digest(@NonNull byte[] data) {
+        return ByteStringUtils.toHexString(computeSha256DigestBytes(data));
     }
 }
diff --git a/core/java/android/util/apk/ApkSignatureVerifier.java b/core/java/android/util/apk/ApkSignatureVerifier.java
index a2a7616..8794372 100644
--- a/core/java/android/util/apk/ApkSignatureVerifier.java
+++ b/core/java/android/util/apk/ApkSignatureVerifier.java
@@ -80,10 +80,22 @@
                     ApkSignatureSchemeV3Verifier.verify(apkPath);
             Certificate[][] signerCerts = new Certificate[][] { vSigner.certs };
             Signature[] signerSigs = convertToSignatures(signerCerts);
-            return new PackageParser.SigningDetails(signerSigs,
-                    SignatureSchemeVersion.SIGNING_BLOCK_V3);
+            Signature[] pastSignerSigs = null;
+            int[] pastSignerSigsFlags = null;
+            if (vSigner.por != null) {
+                // populate proof-of-rotation information
+                pastSignerSigs = new Signature[vSigner.por.certs.size()];
+                pastSignerSigsFlags = new int[vSigner.por.flagsList.size()];
+                for (int i = 0; i < pastSignerSigs.length; i++) {
+                    pastSignerSigs[i] = new Signature(vSigner.por.certs.get(i).getEncoded());
+                    pastSignerSigsFlags[i] = vSigner.por.flagsList.get(i);
+                }
+            }
+            return new PackageParser.SigningDetails(
+                    signerSigs, SignatureSchemeVersion.SIGNING_BLOCK_V3,
+                    pastSignerSigs, pastSignerSigsFlags);
         } catch (SignatureNotFoundException e) {
-            // not signed with v2, try older if allowed
+            // not signed with v3, try older if allowed
             if (minSignatureSchemeVersion >= SignatureSchemeVersion.SIGNING_BLOCK_V3) {
                 throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
                         "No APK Signature Scheme v3 signature in package " + apkPath, e);
@@ -92,7 +104,7 @@
             // APK Signature Scheme v2 signature found but did not verify
             throw new  PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
                     "Failed to collect certificates from " + apkPath
-                            + " using APK Signature Scheme v2", e);
+                            + " using APK Signature Scheme v3", e);
         } finally {
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
         }
@@ -304,25 +316,37 @@
         }
 
         // first try v3
-        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyV3");
+        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "certsOnlyV3");
         try {
             ApkSignatureSchemeV3Verifier.VerifiedSigner vSigner =
                     ApkSignatureSchemeV3Verifier.plsCertsNoVerifyOnlyCerts(apkPath);
             Certificate[][] signerCerts = new Certificate[][] { vSigner.certs };
             Signature[] signerSigs = convertToSignatures(signerCerts);
-            return new PackageParser.SigningDetails(signerSigs,
-                    SignatureSchemeVersion.SIGNING_BLOCK_V3);
+            Signature[] pastSignerSigs = null;
+            int[] pastSignerSigsFlags = null;
+            if (vSigner.por != null) {
+                // populate proof-of-rotation information
+                pastSignerSigs = new Signature[vSigner.por.certs.size()];
+                pastSignerSigsFlags = new int[vSigner.por.flagsList.size()];
+                for (int i = 0; i < pastSignerSigs.length; i++) {
+                    pastSignerSigs[i] = new Signature(vSigner.por.certs.get(i).getEncoded());
+                    pastSignerSigsFlags[i] = vSigner.por.flagsList.get(i);
+                }
+            }
+            return new PackageParser.SigningDetails(
+                    signerSigs, SignatureSchemeVersion.SIGNING_BLOCK_V3,
+                    pastSignerSigs, pastSignerSigsFlags);
         } catch (SignatureNotFoundException e) {
-            // not signed with v2, try older if allowed
+            // not signed with v3, try older if allowed
             if (minSignatureSchemeVersion >= SignatureSchemeVersion.SIGNING_BLOCK_V3) {
                 throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
                         "No APK Signature Scheme v3 signature in package " + apkPath, e);
             }
         } catch (Exception e) {
-            // APK Signature Scheme v2 signature found but did not verify
+            // APK Signature Scheme v3 signature found but did not verify
             throw new  PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
                     "Failed to collect certificates from " + apkPath
-                            + " using APK Signature Scheme v2", e);
+                            + " using APK Signature Scheme v3", e);
         } finally {
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
         }
diff --git a/core/java/android/util/proto/ProtoUtils.java b/core/java/android/util/proto/ProtoUtils.java
index 85b7ec8..c7bbb9f 100644
--- a/core/java/android/util/proto/ProtoUtils.java
+++ b/core/java/android/util/proto/ProtoUtils.java
@@ -48,4 +48,26 @@
         proto.write(Duration.END_MS, endMs);
         proto.end(token);
     }
+
+    /**
+     * Helper function to write bit-wise flags to proto as repeated enums
+     * @hide
+     */
+    public static void writeBitWiseFlagsToProtoEnum(ProtoOutputStream proto, long fieldId,
+            int flags, int[] origEnums, int[] protoEnums) {
+        if (protoEnums.length != origEnums.length) {
+            throw new IllegalArgumentException("The length of origEnums must match protoEnums");
+        }
+        int len = origEnums.length;
+        for (int i = 0; i < len; i++) {
+            // handle zero flag case.
+            if (origEnums[i] == 0 && flags == 0) {
+                proto.write(fieldId, protoEnums[i]);
+                return;
+            }
+            if ((flags & origEnums[i]) != 0) {
+                proto.write(fieldId, protoEnums[i]);
+            }
+        }
+    }
 }
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index ed2b8b6..a597405 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -806,8 +806,10 @@
     public static final int KEYCODE_SYSTEM_NAVIGATION_RIGHT = 283;
     /** Key code constant: Show all apps */
     public static final int KEYCODE_ALL_APPS = 284;
+    /** Key code constant: Refresh key. */
+    public static final int KEYCODE_REFRESH = 285;
 
-    private static final int LAST_KEYCODE = KEYCODE_ALL_APPS;
+    private static final int LAST_KEYCODE = KEYCODE_REFRESH;
 
     // NOTE: If you add a new keycode here you must also add it to:
     //  isSystem()
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index e0864bd..4631261 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -57,6 +57,7 @@
 import android.view.animation.AnimationUtils;
 import android.view.animation.LayoutAnimationController;
 import android.view.animation.Transformation;
+import android.view.autofill.Helper;
 
 import com.android.internal.R;
 
@@ -3474,8 +3475,10 @@
         }
 
         if (!isLaidOut()) {
-            Log.v(VIEW_LOG_TAG, "dispatchProvideStructure(): not laid out, ignoring "
-                    + childrenCount + " children of " + getAccessibilityViewId());
+            if (Helper.sVerbose) {
+                Log.v(VIEW_LOG_TAG, "dispatchProvideStructure(): not laid out, ignoring "
+                        + childrenCount + " children of " + getAccessibilityViewId());
+            }
             return;
         }
 
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 176927f..95abea1 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -2244,9 +2244,36 @@
      * <p>
      * The transitionName for the view background will be "android:navigation:background".
      * </p>
+     * @attr ref android.R.styleable#Window_navigationBarColor
      */
     public abstract void setNavigationBarColor(@ColorInt int color);
 
+    /**
+     * Shows a thin line of the specified color between the navigation bar and the app
+     * content.
+     * <p>
+     * For this to take effect,
+     * the window must be drawing the system bar backgrounds with
+     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} and
+     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION} must not be set.
+     *
+     * @param dividerColor The color of the thin line.
+     * @attr ref android.R.styleable#Window_navigationBarDividerColor
+     */
+    public void setNavigationBarDividerColor(@ColorInt int dividerColor) {
+    }
+
+    /**
+     * Retrieves the color of the navigation bar divider.
+     *
+     * @return The color of the navigation bar divider color.
+     * @see #setNavigationBarColor(int)
+     * @attr ref android.R.styleable#Window_navigationBarDividerColor
+     */
+    public @ColorInt int getNavigationBarDividerColor() {
+        return 0;
+    }
+
     /** @hide */
     public void setTheme(int resId) {
     }
diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java
index f5c3613..990fbdb 100644
--- a/core/java/android/view/animation/AnimationUtils.java
+++ b/core/java/android/view/animation/AnimationUtils.java
@@ -156,6 +156,8 @@
                 anim = new RotateAnimation(c, attrs);
             }  else if (name.equals("translate")) {
                 anim = new TranslateAnimation(c, attrs);
+            } else if (name.equals("cliprect")) {
+                anim = new ClipRectAnimation(c, attrs);
             } else {
                 throw new RuntimeException("Unknown animation name: " + parser.getName());
             }
diff --git a/core/java/android/view/animation/ClipRectAnimation.java b/core/java/android/view/animation/ClipRectAnimation.java
index e194927..21509d3 100644
--- a/core/java/android/view/animation/ClipRectAnimation.java
+++ b/core/java/android/view/animation/ClipRectAnimation.java
@@ -16,7 +16,11 @@
 
 package android.view.animation;
 
+import android.content.Context;
+import android.content.res.TypedArray;
 import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
 
 /**
  * An animation that controls the clip of an object. See the
@@ -26,8 +30,84 @@
  * @hide
  */
 public class ClipRectAnimation extends Animation {
-    protected Rect mFromRect = new Rect();
-    protected Rect mToRect = new Rect();
+    protected final Rect mFromRect = new Rect();
+    protected final Rect mToRect = new Rect();
+
+    private int mFromLeftType = ABSOLUTE;
+    private int mFromTopType = ABSOLUTE;
+    private int mFromRightType = ABSOLUTE;
+    private int mFromBottomType = ABSOLUTE;
+
+    private int mToLeftType = ABSOLUTE;
+    private int mToTopType = ABSOLUTE;
+    private int mToRightType = ABSOLUTE;
+    private int mToBottomType = ABSOLUTE;
+
+    private float mFromLeftValue;
+    private float mFromTopValue;
+    private float mFromRightValue;
+    private float mFromBottomValue;
+
+    private float mToLeftValue;
+    private float mToTopValue;
+    private float mToRightValue;
+    private float mToBottomValue;
+
+    /**
+     * Constructor used when a ClipRectAnimation is loaded from a resource.
+     *
+     * @param context Application context to use
+     * @param attrs Attribute set from which to read values
+     */
+    public ClipRectAnimation(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        TypedArray a = context.obtainStyledAttributes(attrs,
+                com.android.internal.R.styleable.ClipRectAnimation);
+
+        Description d = Description.parseValue(a.peekValue(
+                com.android.internal.R.styleable.ClipRectAnimation_fromLeft));
+        mFromLeftType = d.type;
+        mFromLeftValue = d.value;
+
+        d = Description.parseValue(a.peekValue(
+                com.android.internal.R.styleable.ClipRectAnimation_fromTop));
+        mFromTopType = d.type;
+        mFromTopValue = d.value;
+
+        d = Description.parseValue(a.peekValue(
+                com.android.internal.R.styleable.ClipRectAnimation_fromRight));
+        mFromRightType = d.type;
+        mFromRightValue = d.value;
+
+        d = Description.parseValue(a.peekValue(
+                com.android.internal.R.styleable.ClipRectAnimation_fromBottom));
+        mFromBottomType = d.type;
+        mFromBottomValue = d.value;
+
+
+        d = Description.parseValue(a.peekValue(
+                com.android.internal.R.styleable.ClipRectAnimation_toLeft));
+        mToLeftType = d.type;
+        mToLeftValue = d.value;
+
+        d = Description.parseValue(a.peekValue(
+                com.android.internal.R.styleable.ClipRectAnimation_toTop));
+        mToTopType = d.type;
+        mToTopValue = d.value;
+
+        d = Description.parseValue(a.peekValue(
+                com.android.internal.R.styleable.ClipRectAnimation_toRight));
+        mToRightType = d.type;
+        mToRightValue = d.value;
+
+        d = Description.parseValue(a.peekValue(
+                com.android.internal.R.styleable.ClipRectAnimation_toBottom));
+        mToBottomType = d.type;
+        mToBottomValue = d.value;
+
+        a.recycle();
+    }
 
     /**
      * Constructor to use when building a ClipRectAnimation from code
@@ -39,8 +119,15 @@
         if (fromClip == null || toClip == null) {
             throw new RuntimeException("Expected non-null animation clip rects");
         }
-        mFromRect.set(fromClip);
-        mToRect.set(toClip);
+        mFromLeftValue = fromClip.left;
+        mFromTopValue = fromClip.top;
+        mFromRightValue= fromClip.right;
+        mFromBottomValue = fromClip.bottom;
+
+        mToLeftValue = toClip.left;
+        mToTopValue = toClip.top;
+        mToRightValue= toClip.right;
+        mToBottomValue = toClip.bottom;
     }
 
     /**
@@ -48,8 +135,7 @@
      */
     public ClipRectAnimation(int fromL, int fromT, int fromR, int fromB,
             int toL, int toT, int toR, int toB) {
-        mFromRect.set(fromL, fromT, fromR, fromB);
-        mToRect.set(toL, toT, toR, toB);
+        this(new Rect(fromL, fromT, fromR, fromB), new Rect(toL, toT, toR, toB));
     }
 
     @Override
@@ -65,4 +151,17 @@
     public boolean willChangeTransformationMatrix() {
         return false;
     }
+
+    @Override
+    public void initialize(int width, int height, int parentWidth, int parentHeight) {
+        super.initialize(width, height, parentWidth, parentHeight);
+        mFromRect.set((int) resolveSize(mFromLeftType, mFromLeftValue, width, parentWidth),
+                (int) resolveSize(mFromTopType, mFromTopValue, height, parentHeight),
+                (int) resolveSize(mFromRightType, mFromRightValue, width, parentWidth),
+                (int) resolveSize(mFromBottomType, mFromBottomValue, height, parentHeight));
+        mToRect.set((int) resolveSize(mToLeftType, mToLeftValue, width, parentWidth),
+                (int) resolveSize(mToTopType, mToTopValue, height, parentHeight),
+                (int) resolveSize(mToRightType, mToRightValue, width, parentWidth),
+                (int) resolveSize(mToBottomType, mToBottomValue, height, parentHeight));
+    }
 }
diff --git a/core/java/android/widget/MediaControlView2.java b/core/java/android/widget/MediaControlView2.java
index 0aa2b64..42ba61b 100644
--- a/core/java/android/widget/MediaControlView2.java
+++ b/core/java/android/widget/MediaControlView2.java
@@ -28,6 +28,21 @@
 import android.view.MotionEvent;
 
 /**
+ * A View that contains the controls for MediaPlayer2.
+ * It provides a wide range of UI including buttons such as "Play/Pause", "Rewind", "Fast Forward",
+ * "Subtitle", "Full Screen", and it is also possible to add multiple custom buttons.
+ *
+ * <p>
+ * <em> MediaControlView2 can be initialized in two different ways: </em>
+ * 1) When VideoView2 is initialized, it automatically initializes a MediaControlView2 instance and
+ * adds it to the view.
+ * 2) Initialize MediaControlView2 programmatically and add it to a ViewGroup instance.
+ *
+ * In the first option, VideoView2 automatically connects MediaControlView2 to MediaController2,
+ * which is necessary to communicate with MediaSession2. In the second option, however, the
+ * developer needs to manually retrieve a MediaController2 instance and set it to MediaControlView2
+ * by calling setController(MediaController2 controller).
+ *
  * TODO PUBLIC API
  * @hide
  */
@@ -55,103 +70,103 @@
                 .createMediaControlView2(this, new SuperProvider());
     }
 
+    /**
+     * @hide
+     */
     public MediaControlView2Provider getProvider() {
         return mProvider;
     }
 
     /**
-     * TODO: add docs
+     * Sets MediaController2 instance to control corresponding MediaSession2.
      */
     public void setController(MediaController controller) {
         mProvider.setController_impl(controller);
     }
 
     /**
-     * TODO: add docs
+     * Shows the control view on screen. It will disappear automatically after 3 seconds of
+     * inactivity.
      */
     public void show() {
         mProvider.show_impl();
     }
 
     /**
-     * TODO: add docs
+     * Shows the control view on screen. It will disappear automatically after {@code timeout}
+     * milliseconds of inactivity.
      */
     public void show(int timeout) {
         mProvider.show_impl(timeout);
     }
 
     /**
-     * TODO: add docs
+     * Returns whether the control view is currently shown or hidden.
      */
     public boolean isShowing() {
         return mProvider.isShowing_impl();
     }
 
     /**
-     * TODO: add docs
+     * Hide the control view from the screen.
      */
     public void hide() {
         mProvider.hide_impl();
     }
 
     /**
-     * TODO: add docs
-     */
-    public void showCCButton() {
-        mProvider.showCCButton_impl();
-    }
-
-    /**
-     * TODO: add docs
+     * Returns whether the media is currently playing or not.
      */
     public boolean isPlaying() {
         return mProvider.isPlaying_impl();
     }
 
     /**
-     * TODO: add docs
+     * Returns the current position of the media in milliseconds.
      */
     public int getCurrentPosition() {
         return mProvider.getCurrentPosition_impl();
     }
 
     /**
-     * TODO: add docs
+     * Returns the percentage of how much of the media is currently buffered in storage.
      */
     public int getBufferPercentage() {
         return mProvider.getBufferPercentage_impl();
     }
 
     /**
-     * TODO: add docs
+     * Returns whether the media can be paused or not.
      */
     public boolean canPause() {
         return mProvider.canPause_impl();
     }
 
     /**
-     * TODO: add docs
+     * Returns whether the media can be rewound or not.
      */
     public boolean canSeekBackward() {
         return mProvider.canSeekBackward_impl();
     }
 
     /**
-     * TODO: add docs
+     * Returns whether the media can be fast-forwarded or not.
      */
     public boolean canSeekForward() {
         return mProvider.canSeekForward_impl();
     }
 
     /**
-     * TODO: add docs
+     * If the media selected has a subtitle track, calling this method will display the subtitle at
+     * the bottom of the view. If a media has multiple subtitle tracks, this method will select the
+     * first one of them.
      */
     public void showSubtitle() {
         mProvider.showSubtitle_impl();
     }
 
     /**
-     * TODO: add docs
+     * Hides the currently displayed subtitle.
      */
     public void hideSubtitle() {
         mProvider.hideSubtitle_impl();
diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java
index 02cd09f..43abade 100644
--- a/core/java/com/android/internal/net/NetworkStatsFactory.java
+++ b/core/java/com/android/internal/net/NetworkStatsFactory.java
@@ -31,13 +31,17 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.ProcFileReader;
+import com.google.android.collect.Lists;
 
 import libcore.io.IoUtils;
 
+import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.FileReader;
 import java.io.IOException;
 import java.net.ProtocolException;
+import java.util.ArrayList;
 import java.util.Objects;
 
 /**
@@ -57,6 +61,8 @@
     // Used for correct stats accounting on clatd interfaces.
     private static final int IPV4V6_HEADER_DELTA = 20;
 
+    /** Path to {@code /proc/net/dev}. */
+    private final File mStatsIfaceDev;
     /** Path to {@code /proc/net/xt_qtaguid/iface_stat_all}. */
     private final File mStatsXtIfaceAll;
     /** Path to {@code /proc/net/xt_qtaguid/iface_stat_fmt}. */
@@ -64,6 +70,8 @@
     /** Path to {@code /proc/net/xt_qtaguid/stats}. */
     private final File mStatsXtUid;
 
+    private boolean mUseBpfStats;
+
     // TODO: to improve testability and avoid global state, do not use a static variable.
     @GuardedBy("sStackedIfaces")
     private static final ArrayMap<String, String> sStackedIfaces = new ArrayMap<>();
@@ -79,14 +87,54 @@
     }
 
     public NetworkStatsFactory() {
-        this(new File("/proc/"));
+        this(new File("/proc/"), new File("/sys/fs/bpf/traffic_uid_stats_map").exists());
     }
 
     @VisibleForTesting
-    public NetworkStatsFactory(File procRoot) {
+    public NetworkStatsFactory(File procRoot, boolean useBpfStats) {
+        mStatsIfaceDev = new File(procRoot, "net/dev");
         mStatsXtIfaceAll = new File(procRoot, "net/xt_qtaguid/iface_stat_all");
         mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt");
         mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats");
+        mUseBpfStats = useBpfStats;
+    }
+
+    @VisibleForTesting
+    public NetworkStats readNetworkStatsIfaceDev() throws IOException {
+        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
+
+        final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
+        final NetworkStats.Entry entry = new NetworkStats.Entry();
+
+        BufferedReader reader = null;
+        try {
+            reader = new BufferedReader(new FileReader(mStatsIfaceDev));
+
+            // skip first two header lines
+            reader.readLine();
+            reader.readLine();
+
+            // parse remaining lines
+            String line;
+            while ((line = reader.readLine()) != null) {
+                String[] values = line.trim().split("\\:?\\s+");
+                entry.iface = values[0];
+                entry.uid = UID_ALL;
+                entry.set = SET_ALL;
+                entry.tag = TAG_NONE;
+                entry.rxBytes = Long.parseLong(values[1]);
+                entry.rxPackets = Long.parseLong(values[2]);
+                entry.txBytes = Long.parseLong(values[9]);
+                entry.txPackets = Long.parseLong(values[10]);
+                stats.addValues(entry);
+            }
+        } catch (NullPointerException|NumberFormatException e) {
+            throw new ProtocolException("problem parsing stats", e);
+        } finally {
+            IoUtils.closeQuietly(reader);
+            StrictMode.setThreadPolicy(savedPolicy);
+        }
+        return stats;
     }
 
     /**
@@ -98,6 +146,11 @@
      * @throws IllegalStateException when problem parsing stats.
      */
     public NetworkStats readNetworkStatsSummaryDev() throws IOException {
+
+        // Return the stats get from /proc/net/dev if switched to bpf module.
+        if (mUseBpfStats)
+            return readNetworkStatsIfaceDev();
+
         final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
 
         final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
@@ -149,6 +202,11 @@
      * @throws IllegalStateException when problem parsing stats.
      */
     public NetworkStats readNetworkStatsSummaryXt() throws IOException {
+
+        // Return the stats get from /proc/net/dev if qtaguid  module is replaced.
+        if (mUseBpfStats)
+            return readNetworkStatsIfaceDev();
+
         final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
 
         // return null when kernel doesn't support
@@ -254,7 +312,7 @@
                 stats = new NetworkStats(SystemClock.elapsedRealtime(), -1);
             }
             if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), limitUid,
-                    limitIfaces, limitTag) != 0) {
+                    limitIfaces, limitTag, mUseBpfStats) != 0) {
                 throw new IOException("Failed to parse network stats");
             }
             if (SANITY_CHECK_NATIVE) {
@@ -348,6 +406,6 @@
      * are expected to monotonically increase since device boot.
      */
     @VisibleForTesting
-    public static native int nativeReadNetworkStatsDetail(
-            NetworkStats stats, String path, int limitUid, String[] limitIfaces, int limitTag);
+    public static native int nativeReadNetworkStatsDetail(NetworkStats stats, String path,
+        int limitUid, String[] limitIfaces, int limitTag, boolean useBpfStats);
 }
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index e8ee29d..34b5ec8 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -3810,6 +3810,19 @@
         }
     }
 
+    @Override
+    public void setNavigationBarDividerColor(int navigationBarDividerColor) {
+        mNavigationBarDividerColor = navigationBarDividerColor;
+        if (mDecor != null) {
+            mDecor.updateColorViews(null, false /* animate */);
+        }
+    }
+
+    @Override
+    public int getNavigationBarDividerColor() {
+        return mNavigationBarDividerColor;
+    }
+
     public void setIsStartingWindow(boolean isStartingWindow) {
         mIsStartingWindow = isStartingWindow;
     }
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index e097362a..f5af80a 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -18,6 +18,7 @@
 
 import android.content.ComponentName;
 import android.graphics.Rect;
+import android.hardware.fingerprint.IFingerprintDialogReceiver;
 import android.os.Bundle;
 import android.service.notification.StatusBarNotification;
 
@@ -130,4 +131,15 @@
     void handleSystemKey(in int key);
 
     void showShutdownUi(boolean isReboot, String reason);
+
+    // Used to show the dialog when FingerprintService starts authentication
+    void showFingerprintDialog(in Bundle bundle, IFingerprintDialogReceiver receiver);
+    // Used to hide the dialog when a finger is authenticated
+    void onFingerprintAuthenticated();
+    // Used to set a temporary message, e.g. fingerprint not recognized, finger moved too fast, etc
+    void onFingerprintHelp(String message);
+    // Used to set a message - the dialog will dismiss after a certain amount of time
+    void onFingerprintError(String error);
+    // Used to hide the fingerprint dialog when the authenticationclient is stopped
+    void hideFingerprintDialog();
 }
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 03603e4..cb0b53c 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -20,6 +20,7 @@
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.service.notification.StatusBarNotification;
+import android.hardware.fingerprint.IFingerprintDialogReceiver;
 
 import com.android.internal.statusbar.IStatusBar;
 import com.android.internal.statusbar.StatusBarIcon;
@@ -79,4 +80,15 @@
     void remTile(in ComponentName tile);
     void clickTile(in ComponentName tile);
     void handleSystemKey(in int key);
+
+    // Used to show the dialog when FingerprintService starts authentication
+    void showFingerprintDialog(in Bundle bundle, IFingerprintDialogReceiver receiver);
+    // Used to hide the dialog when a finger is authenticated
+    void onFingerprintAuthenticated();
+    // Used to set a temporary message, e.g. fingerprint not recognized, finger moved too fast, etc
+    void onFingerprintHelp(String message);
+    // Used to set a message - the dialog will dismiss after a certain amount of time
+    void onFingerprintError(String error);
+    // Used to hide the fingerprint dialog when the authenticationclient is stopped
+    void hideFingerprintDialog();
 }
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index e3f1f47..927d757 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -19,9 +19,9 @@
 import android.app.PendingIntent;
 import android.app.trust.IStrongAuthTracker;
 import android.os.Bundle;
-import android.security.keystore.WrappedApplicationKey;
-import android.security.keystore.KeychainSnapshot;
-import android.security.keystore.KeychainProtectionParams;
+import android.security.keystore.recovery.WrappedApplicationKey;
+import android.security.keystore.recovery.KeyChainSnapshot;
+import android.security.keystore.recovery.KeyChainProtectionParams;
 import com.android.internal.widget.ICheckCredentialProgressCallback;
 import com.android.internal.widget.VerifyCredentialResponse;
 
@@ -64,7 +64,7 @@
     // {@code ServiceSpecificException} may be thrown to signal an error, which caller can
     // convert to  {@code RecoveryManagerException}.
     void initRecoveryService(in String rootCertificateAlias, in byte[] signedPublicKeyList);
-    KeychainSnapshot getRecoveryData(in byte[] account);
+    KeyChainSnapshot getRecoveryData(in byte[] account);
     byte[] generateAndStoreKey(String alias);
     void removeKey(String alias);
     void setSnapshotCreatedPendingIntent(in PendingIntent intent);
@@ -75,10 +75,10 @@
     void setRecoverySecretTypes(in int[] secretTypes);
     int[] getRecoverySecretTypes();
     int[] getPendingRecoverySecretTypes();
-    void recoverySecretAvailable(in KeychainProtectionParams recoverySecret);
+    void recoverySecretAvailable(in KeyChainProtectionParams recoverySecret);
     byte[] startRecoverySession(in String sessionId,
             in byte[] verifierPublicKey, in byte[] vaultParams, in byte[] vaultChallenge,
-            in List<KeychainProtectionParams> secrets);
+            in List<KeyChainProtectionParams> secrets);
     Map/*<String, byte[]>*/ recoverKeys(in String sessionId, in byte[] recoveryKeyBlob,
             in List<WrappedApplicationKey> applicationKeys);
     void closeSession(in String sessionId);
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 543acc7..47765d9 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -228,6 +228,8 @@
     ],
 
     shared_libs: [
+        "libbpf",
+        "libnetdutils",
         "libmemtrack",
         "libandroidfw",
         "libappfuse",
diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
index d254de6..99d9839 100644
--- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
+++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
@@ -30,7 +30,14 @@
 
 #include <utils/Log.h>
 #include <utils/misc.h>
-#include <utils/Vector.h>
+
+#include "android-base/unique_fd.h"
+#include "bpf/BpfNetworkStats.h"
+#include "bpf/BpfUtils.h"
+
+using android::bpf::hasBpfSupport;
+using android::bpf::parseBpfNetworkStatsDetail;
+using android::bpf::stats_line;
 
 namespace android {
 
@@ -53,17 +60,6 @@
     jfieldID operations;
 } gNetworkStatsClassInfo;
 
-struct stats_line {
-    char iface[32];
-    int32_t uid;
-    int32_t set;
-    int32_t tag;
-    int64_t rxBytes;
-    int64_t rxPackets;
-    int64_t txBytes;
-    int64_t txPackets;
-};
-
 static jobjectArray get_string_array(JNIEnv* env, jobject obj, jfieldID field, int size, bool grow)
 {
     if (!grow) {
@@ -97,33 +93,14 @@
     return env->NewLongArray(size);
 }
 
-static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats,
-        jstring path, jint limitUid, jobjectArray limitIfacesObj, jint limitTag) {
-    ScopedUtfChars path8(env, path);
-    if (path8.c_str() == NULL) {
-        return -1;
-    }
-
-    FILE *fp = fopen(path8.c_str(), "r");
+static int legacyReadNetworkStatsDetail(std::vector<stats_line>* lines,
+                                        const std::vector<std::string>& limitIfaces,
+                                        int limitTag, int limitUid, const char* path) {
+    FILE* fp = fopen(path, "r");
     if (fp == NULL) {
         return -1;
     }
 
-    Vector<String8> limitIfaces;
-    if (limitIfacesObj != NULL && env->GetArrayLength(limitIfacesObj) > 0) {
-        int num = env->GetArrayLength(limitIfacesObj);
-        limitIfaces.setCapacity(num);
-        for (int i=0; i<num; i++) {
-            jstring string = (jstring)env->GetObjectArrayElement(limitIfacesObj, i);
-            ScopedUtfChars string8(env, string);
-            if (string8.c_str() != NULL) {
-                limitIfaces.add(String8(string8.c_str()));
-            }
-        }
-    }
-
-    Vector<stats_line> lines;
-
     int lastIdx = 1;
     int idx;
     char buffer[384];
@@ -215,7 +192,7 @@
                 //ALOGI("skipping due to uid: %s", buffer);
                 continue;
             }
-            lines.push_back(s);
+            lines->push_back(s);
         } else {
             //ALOGI("skipping due to bad remaining fields: %s", pos);
         }
@@ -225,8 +202,42 @@
         ALOGE("Failed to close netstats file");
         return -1;
     }
+    return 0;
+}
+
+static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, jstring path,
+                                  jint limitUid, jobjectArray limitIfacesObj, jint limitTag,
+                                  jboolean useBpfStats) {
+    ScopedUtfChars path8(env, path);
+    if (path8.c_str() == NULL) {
+        return -1;
+    }
+
+    std::vector<std::string> limitIfaces;
+    if (limitIfacesObj != NULL && env->GetArrayLength(limitIfacesObj) > 0) {
+        int num = env->GetArrayLength(limitIfacesObj);
+        for (int i = 0; i < num; i++) {
+            jstring string = (jstring)env->GetObjectArrayElement(limitIfacesObj, i);
+            ScopedUtfChars string8(env, string);
+            if (string8.c_str() != NULL) {
+                limitIfaces.push_back(std::string(string8.c_str()));
+            }
+        }
+    }
+    std::vector<stats_line> lines;
+
+
+    if (useBpfStats) {
+        if (parseBpfNetworkStatsDetail(&lines, limitIfaces, limitTag, limitUid) < 0)
+            return -1;
+    } else {
+        if (legacyReadNetworkStatsDetail(&lines, limitIfaces, limitTag,
+                                         limitUid, path8.c_str()) < 0)
+            return -1;
+    }
 
     int size = lines.size();
+
     bool grow = size > env->GetIntField(stats, gNetworkStatsClassInfo.capacity);
 
     ScopedLocalRef<jobjectArray> iface(env, get_string_array(env, stats,
@@ -303,7 +314,7 @@
 
 static const JNINativeMethod gMethods[] = {
         { "nativeReadNetworkStatsDetail",
-                "(Landroid/net/NetworkStats;Ljava/lang/String;I[Ljava/lang/String;I)I",
+                "(Landroid/net/NetworkStats;Ljava/lang/String;I[Ljava/lang/String;IZ)I",
                 (void*) readNetworkStatsDetail }
 };
 
diff --git a/core/proto/android/app/activitymanager.proto b/core/proto/android/app/activitymanager.proto
index 3412a32..03f8204 100644
--- a/core/proto/android/app/activitymanager.proto
+++ b/core/proto/android/app/activitymanager.proto
@@ -19,6 +19,7 @@
 package android.app;
 
 option java_multiple_files = true;
+option java_outer_classname = "ActivityManagerProto";
 
 // ActivityManager.java PROCESS_STATEs
 enum ProcessState {
@@ -79,3 +80,16 @@
   PROCESS_STATE_NONEXISTENT = 1900;
 }
 
+// ActivityManager.java UID_OBSERVERs flags
+enum UidObserverFlag {
+  // report changes in process state, original value is 1 << 0
+  UID_OBSERVER_FLAG_PROCSTATE = 1;
+  // report uid gone, original value is 1 << 1
+  UID_OBSERVER_FLAG_GONE = 2;
+  // report uid has become idle, original value is 1 << 2
+  UID_OBSERVER_FLAG_IDLE = 3;
+  // report uid has become active, original value is 1 << 3
+  UID_OBSERVER_FLAG_ACTIVE = 4;
+  // report uid cached state has changed, original value is 1 << 4
+  UID_OBSERVER_FLAG_CACHED = 5;
+}
diff --git a/core/proto/android/app/profilerinfo.proto b/core/proto/android/app/profilerinfo.proto
new file mode 100644
index 0000000..ca1b935
--- /dev/null
+++ b/core/proto/android/app/profilerinfo.proto
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+option java_package = "android.app";
+option java_multiple_files = true;
+
+package android.app;
+
+/**
+ * An android.app.ProfilerInfo object.
+ */
+message ProfilerInfoProto {
+    optional string profile_file = 1;
+    optional int32 profile_fd = 2;
+    optional int32 sampling_interval = 3;
+    optional bool auto_stop_profiler = 4;
+    optional bool streaming_output = 5;
+    optional string agent = 6;
+}
diff --git a/core/proto/android/content/package_item_info.proto b/core/proto/android/content/package_item_info.proto
new file mode 100644
index 0000000..8470159
--- /dev/null
+++ b/core/proto/android/content/package_item_info.proto
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+option java_package = "android.content.pm";
+option java_multiple_files = true;
+
+package android.content.pm;
+
+message PackageItemInfoProto {
+    optional string name = 1;
+    optional string package_name = 2;
+    optional int32 label_res = 3;
+    optional string non_localized_label = 4;
+    optional int32 icon = 5;
+    optional int32 banner = 6;
+}
+
+// Proto of android.content.pm.ApplicationInfo which extends PackageItemInfo
+message ApplicationInfoProto {
+    optional PackageItemInfoProto package = 1;
+    optional string permission = 2;
+    optional string process_name = 3;
+    optional int32 uid = 4;
+    optional int32 flags = 5;
+    optional int32 private_flags = 6;
+    optional int32 theme = 7;
+    optional string source_dir = 8;
+    optional string public_source_dir = 9;
+    repeated string split_source_dirs = 10;
+    repeated string split_public_source_dirs = 11;
+    repeated string resource_dirs = 12;
+    optional string data_dir = 13;
+    optional string class_loader_name = 14;
+    repeated string split_class_loader_names = 15;
+
+    message Version {
+        optional bool enabled = 1;
+        optional int32 min_sdk_version = 2;
+        optional int32 target_sdk_version = 3;
+        optional int32 version_code = 4;
+        optional int32 target_sandbox_version = 5;
+    }
+    optional Version version = 16;
+
+    message Detail {
+        optional string class_name = 1;
+        optional string task_affinity = 2;
+        optional int32 requires_smallest_width_dp = 3;
+        optional int32 compatible_width_limit_dp = 4;
+        optional int32 largest_width_limit_dp = 5;
+        optional string seinfo = 6;
+        optional string seinfo_user = 7;
+        optional string device_protected_data_dir = 8;
+        optional string credential_protected_data_dir = 9;
+        repeated string shared_library_files = 10;
+        optional string manage_space_activity_name = 11;
+        optional int32 description_res = 12;
+        optional int32 ui_options = 13;
+        optional bool supports_rtl = 14;
+        oneof full_backup_content {
+            string content = 15;
+            bool is_full_backup = 16;
+        }
+        optional int32 networkSecurity_config_res = 17;
+        optional int32 category = 18;
+    }
+    optional Detail detail = 17;
+}
diff --git a/core/proto/android/os/batterystats.proto b/core/proto/android/os/batterystats.proto
index 331f80f..ce1d5c9 100644
--- a/core/proto/android/os/batterystats.proto
+++ b/core/proto/android/os/batterystats.proto
@@ -22,8 +22,11 @@
 import "frameworks/base/core/proto/android/app/jobparameters.proto";
 import "frameworks/base/core/proto/android/os/powermanager.proto";
 import "frameworks/base/core/proto/android/telephony/signalstrength.proto";
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
 
 message BatteryStatsProto {
+  option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
   optional int32 report_version = 1;
   optional int64 parcel_version = 2;
   optional string start_platform_version = 3;
@@ -33,6 +36,8 @@
 }
 
 message ControllerActivityProto {
+  option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
   // Time (milliseconds) spent in the idle state.
   optional int64 idle_duration_ms = 1;
   // Time (milliseconds) spent in the receive state.
@@ -45,6 +50,8 @@
   // of power. The levels themselves are controller-specific (and may possibly
   // be device specific...yet to be confirmed).
   message TxLevel {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Transmit level. Higher levels draw more power.
     optional int32 level = 1;
     // Time spent in this specific transmit level state.
@@ -54,7 +61,11 @@
 }
 
 message SystemProto {
+  option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
   message Battery {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Wall clock time when the data collection started.
     // In case of device time manually reset by users:
     //   start_clock_time_ms keeps the same value in the current collection
@@ -92,6 +103,8 @@
   optional Battery battery = 1;
 
   message BatteryDischarge {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Discharged battery percentage points since the stats were last reset
     // after charging (lower bound approximation).
     optional int32 lower_bound_since_charge = 1;
@@ -142,6 +155,8 @@
   // the entire duration. Field for which the conditions were not consistent
   // for the entire duration should be marked MIXED.
   message BatteryLevelStep {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // How long the battery was at the current level.
     optional int64 duration_ms = 1;
     // Battery level
@@ -192,6 +207,8 @@
   repeated int64 cpu_frequency = 7;
 
   message DataConnection {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     enum Name {
       NONE = 0;
       GPRS = 1;
@@ -221,6 +238,8 @@
   optional ControllerActivityProto global_wifi_controller = 11;
 
   message GlobalNetwork {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Total Bytes received on mobile connections.
     optional int64 mobile_bytes_rx = 1;
     // Total Bytes transmitted on mobile connections.
@@ -245,6 +264,8 @@
   optional GlobalNetwork global_network = 12;
 
   message GlobalWifi {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // The amount of time that wifi has been on while the device was running on
     // battery.
     optional int64 on_duration_ms = 1;
@@ -257,6 +278,8 @@
   // Kernel wakelock metrics are only recorded when the device is unplugged
   // *and* the screen is off.
   message KernelWakelock {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     optional string name = 1;
     // Kernel wakelock stats aren't apportioned across all kernel wakelocks (as
     // app wakelocks stats are).
@@ -267,6 +290,8 @@
   repeated KernelWakelock kernel_wakelock = 14;
 
   message Misc {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     optional int64 screen_on_duration_ms = 1;
     optional int64 phone_on_duration_ms = 2;
     optional int64 full_wakelock_total_duration_ms = 3;
@@ -312,12 +337,16 @@
   optional Misc misc = 15;
 
   message PhoneSignalStrength {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     optional android.telephony.SignalStrengthProto.StrengthName name = 1;
     optional TimerProto total = 2;
   };
   repeated PhoneSignalStrength phone_signal_strength = 16;
 
   message PowerUseItem {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     enum Sipper {
       UNKNOWN_SIPPER = 0;
       IDLE = 1;
@@ -352,6 +381,8 @@
   repeated PowerUseItem power_use_item = 17;
 
   message PowerUseSummary {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     optional double battery_capacity_mah = 1;
     optional double computed_power_mah = 2;
     // Lower bound of actual power drained.
@@ -362,6 +393,8 @@
   optional PowerUseSummary power_use_summary = 18;
 
   message ResourcePowerManager {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Either StateName or StateName.VoterName.
     optional string name = 1;
     optional TimerProto total = 2;
@@ -370,6 +403,8 @@
   repeated ResourcePowerManager resource_power_manager = 19;
 
   message ScreenBrightness {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     enum Name {
       DARK = 0; // Not screen-off.
       DIM = 1;
@@ -386,18 +421,24 @@
   optional TimerProto signal_scanning = 21;
 
   message WakeupReason {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     optional string name = 1;
     optional TimerProto total = 2;
   };
   repeated WakeupReason wakeup_reason = 22;
 
   message WifiMulticastWakelockTotal {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     optional int64 duration_ms = 1;
     optional int32 count = 2;
   }
   optional WifiMulticastWakelockTotal wifi_multicast_wakelock_total = 23;
 
   message WifiSignalStrength {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     enum Name {
       NONE = 0;
       POOR = 1;
@@ -411,6 +452,8 @@
   repeated WifiSignalStrength wifi_signal_strength = 24;
 
   message WifiState {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     enum Name {
       OFF = 0;
       OFF_SCANNING = 1;
@@ -427,6 +470,8 @@
   repeated WifiState wifi_state = 25;
 
   message WifiSupplicantState {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     enum Name {
       INVALID = 0;
       DISCONNECTED = 1;
@@ -449,6 +494,8 @@
 }
 
 message TimerProto {
+  option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
   // This may be an apportioned time.
   optional int64 duration_ms = 1;
   optional int64 count = 2;
@@ -468,14 +515,20 @@
 }
 
 message UidProto {
+  option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
   // Combination of app ID and user ID.
   optional int32 uid = 1;
 
   // The statistics associated with a particular package.
   message Package {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     optional string name = 1;
 
     message Service {
+      option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
       optional string name = 1;
       // Time spent started.
       optional int64 start_duration_ms = 2;
@@ -492,6 +545,8 @@
 
   // Bluetooth misc data.
   message BluetoothMisc {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Duration spent BLE scanning blamed on this App (i.e. apportioned to this
     // app amongst all apps doing BLE scanning; see explanation of 'apportioned'
     // in App's comment).
@@ -515,6 +570,8 @@
   optional BluetoothMisc bluetooth_misc = 6;
 
   message Cpu {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Total CPU time with processes executing in userspace. Summed up across
     // multiple cores.
     optional int64 user_duration_ms = 1;
@@ -529,6 +586,8 @@
     // system_duration_millis, which are just approximations. Data is not
     // tracked when device is charging.
     message ByFrequency {
+      option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
       // Index of the frequency in system.cpu_frequency. It starts from 1, to
       // make it easier to analyze.
       optional int32 frequency_index = 1;
@@ -551,6 +610,8 @@
     }
     // CPU times at different process states.
     message ByProcessState {
+      option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
       optional ProcessState process_state = 1;
       repeated ByFrequency by_frequency = 2;
     }
@@ -574,7 +635,11 @@
   optional TimerProto video = 14;
 
   message Job {
-    optional string name = 1;
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional string name = 1 [
+        (android.privacy).dest = DEST_EXPLICIT
+    ];
     // Job times aren't apportioned.
     optional TimerProto total = 2;
     optional TimerProto background = 3;
@@ -582,10 +647,16 @@
   repeated Job jobs = 15;
 
   message JobCompletion {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Job name.
-    optional string name = 1;
+    optional string name = 1 [
+        (android.privacy).dest = DEST_EXPLICIT
+    ];
 
     message ReasonCount {
+      option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
       optional android.app.JobParametersProto.CancelReason name = 1;
       optional int32 count = 2;
     }
@@ -594,6 +665,8 @@
   repeated JobCompletion job_completion = 16;
 
   message Network {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Mobile data traffic (total, background + foreground).
     optional int64 mobile_bytes_rx = 1;
     optional int64 mobile_bytes_tx = 2;
@@ -631,6 +704,8 @@
 
   // TODO: combine System and App messages?
   message PowerUseItem {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Estimated power use in mAh.
     optional double computed_power_mah = 1;
     // Starting in Oreo, Battery Settings has two modes to display the battery
@@ -648,6 +723,8 @@
 
   // Durations are not pooled/apportioned.
   message Process {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     optional string name = 1;
     // Time spent executing in user code.
     optional int64 user_duration_ms = 2;
@@ -665,6 +742,8 @@
   repeated Process process = 19;
 
   message StateTime {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // All of these (non-deprecated) states are mutually exclusive and can be
     // added together to find the total time a uid has had any processes running
     // at all.
@@ -706,6 +785,8 @@
   repeated StateTime states = 20;
 
   message Sensor {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     optional int32 id = 1;
     optional TimerProto apportioned = 2;
     // Background times aren't apportioned.
@@ -714,7 +795,11 @@
   repeated Sensor sensors = 21;
 
   message Sync {
-    optional string name = 1;
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional string name = 1 [
+        (android.privacy).dest = DEST_EXPLICIT
+    ];
     // Sync times aren't apportioned.
     optional TimerProto total = 2;
     optional TimerProto background = 3;
@@ -722,6 +807,8 @@
   repeated Sync syncs = 22;
 
   message UserActivity {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     optional android.os.PowerManagerProto.UserActivityEvent name = 1;
     optional int32 count = 2;
   };
@@ -736,6 +823,8 @@
   // wakelocks. AggregatedWakelock, on the other hand, holds overall per-app
   // wakelock data.
   message AggregatedWakelock {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // The total duration that the app spent holding partial wakelocks.
     // It includes both foreground + background use.
     optional int64 partial_duration_ms = 1;
@@ -747,7 +836,11 @@
   optional AggregatedWakelock aggregated_wakelock = 24;
 
   message Wakelock {
-    optional string name = 1;
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional string name = 1 [
+        (android.privacy).dest = DEST_EXPLICIT
+    ];
 
     // Full wakelocks keep the screen on. Based on
     // PowerManager.SCREEN_BRIGHT_WAKE_LOCK (deprecated in API 13) and
@@ -776,14 +869,20 @@
   repeated Wakelock wakelocks = 25;
 
   message WakeupAlarm {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Wakeup alarm name.
-    optional string name = 1;
+    optional string name = 1 [
+        (android.privacy).dest = DEST_EXPLICIT
+    ];
     // Only includes counts when screen-off (& on battery).
     optional int32 count = 2;
   }
   repeated WakeupAlarm wakeup_alarm = 26;
 
   message Wifi {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Duration holding Wifi-lock. This time is apportioned.
     optional int64 full_wifi_lock_duration_ms = 1;
     // Duration running Wifi. This time is apportioned.
diff --git a/core/proto/android/os/batterytype.proto b/core/proto/android/os/batterytype.proto
index 75d0dd3..2388c1e 100644
--- a/core/proto/android/os/batterytype.proto
+++ b/core/proto/android/os/batterytype.proto
@@ -20,6 +20,10 @@
 
 option java_multiple_files = true;
 
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
 message BatteryTypeProto {
-   optional string type = 1;
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional string type = 1;
 }
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index e5efb90..828a55f 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -226,7 +226,10 @@
         (section).args = "activity --proto service"
     ];
 
-    optional com.android.server.am.proto.ProcessProto amprocesses = 3015;
+    optional com.android.server.am.proto.ProcessesProto amprocesses = 3015 [
+        (section).type = SECTION_DUMPSYS,
+        (section).args = "activity --proto processes"
+    ];
 
     optional com.android.server.AlarmManagerServiceProto alarm = 3016 [
         (section).type = SECTION_DUMPSYS,
diff --git a/core/proto/android/os/powermanager.proto b/core/proto/android/os/powermanager.proto
index e9f409d..8e0a607 100644
--- a/core/proto/android/os/powermanager.proto
+++ b/core/proto/android/os/powermanager.proto
@@ -19,6 +19,8 @@
 
 option java_multiple_files = true;
 
+import "frameworks/base/core/proto/android/os/worksource.proto";
+
 message PowerManagerProto {
     /* User activity events in PowerManager.java. */
     enum UserActivityEvent {
@@ -85,6 +87,14 @@
         // the dozing state.
         DRAW_WAKE_LOCK = 128;
     }
+
+    // WakeLock class in android.os.PowerManager, it is the one used by sdk
+    message WakeLockProto {
+        optional string hex_string = 1;
+        optional bool held = 2;
+        optional int32 internal_count = 3;
+        optional WorkSourceProto work_source = 4;
+    }
 }
 
 message PowerManagerInternalProto {
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index d3ca496..1434d82 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -18,11 +18,17 @@
 
 package com.android.server.am.proto;
 
+import "frameworks/base/core/proto/android/app/activitymanager.proto";
 import "frameworks/base/core/proto/android/app/notification.proto";
+import "frameworks/base/core/proto/android/app/profilerinfo.proto";
+import "frameworks/base/core/proto/android/content/component_name.proto";
+import "frameworks/base/core/proto/android/content/configuration.proto";
 import "frameworks/base/core/proto/android/content/intent.proto";
+import "frameworks/base/core/proto/android/content/package_item_info.proto";
 import "frameworks/base/core/proto/android/graphics/rect.proto";
 import "frameworks/base/core/proto/android/internal/processstats.proto";
 import "frameworks/base/core/proto/android/os/looper.proto";
+import "frameworks/base/core/proto/android/os/powermanager.proto";
 import "frameworks/base/core/proto/android/server/intentresolver.proto";
 import "frameworks/base/core/proto/android/server/windowmanagerservice.proto";
 import "frameworks/base/core/proto/android/util/common.proto";
@@ -36,7 +42,7 @@
 
   optional ActiveServicesProto services = 3;
 
-  optional ProcessProto processes = 4;
+  optional ProcessesProto processes = 4;
 }
 
 // "dumpsys activity --proto activities"
@@ -130,6 +136,7 @@
   optional int32 user_id = 4;
   optional int32 app_id = 5;
   optional int32 isolated_app_id = 6;
+  optional bool persistent = 7;
 }
 
 message BroadcastRecordProto {
@@ -459,7 +466,7 @@
     WAIVE_PRIORITY = 6;
     IMPORTANT = 7;
     ADJUST_WITH_ACTIVITY = 8;
-    FG_SERVICE_WHILE_WAKE = 9;
+    FG_SERVICE_WHILE_AWAKE = 9;
     FG_SERVICE = 10;
     TREAT_LIKE_ACTIVITY = 11;
     VISIBLE = 12;
@@ -492,5 +499,362 @@
 }
 
 // TODO: "dumpsys activity --proto processes"
-message ProcessProto {
+message ProcessesProto {
+  repeated ProcessRecordProto procs = 1;
+  repeated ProcessRecordProto isolated_procs = 2;
+  repeated ActiveInstrumentationProto active_instrumentations = 3;
+  repeated UidRecordProto active_uids = 4;
+  repeated UidRecordProto validate_uids = 5;
+
+  // Process LRU list (sorted by oom_adj)
+  message LruProcesses {
+    optional int32 size = 1;
+    optional int32 non_act_at = 2;
+    optional int32 non_svc_at = 3;
+    repeated ProcessOomProto list = 4;
+  }
+  optional LruProcesses lru_procs = 6;
+  repeated ProcessRecordProto pids_self_locked = 7;
+  // Foreground Processes
+  repeated ImportanceTokenProto important_procs = 8;
+  // Persisent processes that are starting
+  repeated ProcessRecordProto persistent_starting_procs = 9;
+  // Processes that are being removed
+  repeated ProcessRecordProto removed_procs = 10;
+  // Processes that are on old until the system is ready
+  repeated ProcessRecordProto on_hold_procs = 11;
+  // Processes that are waiting to GC
+  repeated ProcessToGcProto gc_procs = 12;
+  optional AppErrorsProto app_errors = 13;
+  optional UserControllerProto user_controller = 14;
+  optional ProcessRecordProto home_proc = 15;
+  optional ProcessRecordProto previous_proc = 16;
+  optional int64 previous_proc_visible_time_ms = 17;
+  optional ProcessRecordProto heavy_weight_proc = 18;
+  optional .android.content.ConfigurationProto global_configuration = 19;
+  // ActivityStackSupervisorProto dumps these values as well, still here?
+  // repeated ActivityDisplayProto displays = 20;
+
+  optional bool config_will_change = 21;
+
+  message ScreenCompatPackage {
+    optional string package = 1;
+    optional int32 mode = 2;
+  }
+  repeated ScreenCompatPackage screen_compat_packages = 22;
+
+  message UidObserverRegistrationProto {
+    optional int32 uid = 1;
+    optional string package = 2;
+    repeated .android.app.UidObserverFlag flags = 3;
+    optional int32 cut_point = 4; // only available when UID_OBSERVER_PROCSTATE is on
+
+    message ProcState {
+      optional int32 uid = 1;
+      optional int32 state = 2;
+    }
+    repeated ProcState last_proc_states = 5;
+  }
+  repeated UidObserverRegistrationProto uid_observers = 23;
+  repeated int32 device_idle_whitelist = 24;
+  repeated int32 device_idle_temp_whitelist = 25;
+
+  message PendingTempWhitelist {
+    optional int32 target_uid = 1;
+    optional int64 duration_ms = 2;
+    optional string tag = 3;
+  }
+  repeated PendingTempWhitelist pending_temp_whitelist = 26;
+
+  message SleepStatus {
+    optional .android.os.PowerManagerInternalProto.Wakefulness wakefulness = 1;
+    repeated string sleep_tokens = 2;
+    optional bool sleeping = 3;
+    optional bool shutting_down = 4;
+    optional bool test_pss_mode = 5;
+  }
+  optional SleepStatus sleep_status = 27;
+
+  message VoiceProto {
+    optional string session = 1;
+    optional .android.os.PowerManagerProto.WakeLockProto wakelock = 2;
+  }
+  optional VoiceProto running_voice = 28;
+
+  message VrControllerProto {
+    enum VrMode {
+      FLAG_NON_VR_MODE = 0;
+      FLAG_VR_MODE = 1;
+      FLAG_PERSISTENT_VR_MODE = 2;
+    }
+    repeated VrMode vr_mode = 1;
+    optional int32 render_thread_id = 2;
+  }
+  optional VrControllerProto vr_controller = 29;
+
+  message DebugApp {
+    optional string debug_app = 1;
+    optional string orig_debug_app = 2;
+    optional bool debug_transient = 3;
+    optional bool orig_wait_for_debugger = 4;
+  }
+  optional DebugApp debug = 30;
+  optional AppTimeTrackerProto current_tracker = 31;
+
+  message MemWatchProcess {
+    message Process {
+      optional string name = 1;
+
+      message MemStats {
+        optional int32 uid = 1;
+        optional string size = 2;
+        optional string report_to = 3;
+      }
+      repeated MemStats mem_stats = 2;
+    }
+    repeated Process procs = 1;
+
+    message Dump {
+      optional string proc_name = 1;
+      optional string file = 2;
+      optional int32 pid = 3;
+      optional int32 uid = 4;
+    }
+    optional Dump dump = 2;
+  }
+  optional MemWatchProcess mem_watch_processes = 32;
+  optional string track_allocation_app = 33;
+
+  message Profile {
+    optional string app_name = 1;
+    optional ProcessRecordProto proc = 2;
+    optional .android.app.ProfilerInfoProto info = 3;
+    optional int32 type = 4;
+  }
+  optional Profile profile = 34;
+  optional string native_debugging_app = 35;
+  optional bool always_finish_activities = 36;
+
+  message Controller {
+    optional string controller = 1;
+    optional bool is_a_monkey = 2;
+  }
+  optional Controller controller = 37;
+
+  optional int32 total_persistent_procs = 38;
+  optional bool processes_ready = 39;
+  optional bool system_ready = 40;
+  optional bool booted = 41;
+  optional int32 factory_test = 42;
+  optional bool booting = 43;
+  optional bool call_finish_booting = 44;
+  optional bool boot_animation_complete = 45;
+  optional int64 last_power_check_uptime_ms = 46;
+  optional .android.os.PowerManagerProto.WakeLockProto going_to_sleep = 47;
+  optional .android.os.PowerManagerProto.WakeLockProto launching_activity = 48;
+  optional int32 adj_seq = 49;
+  optional int32 lru_seq = 50;
+  optional int32 num_non_cached_procs = 51;
+  optional int32 num_cached_hidden_procs = 52;
+  optional int32 num_service_procs = 53;
+  optional int32 new_num_service_procs = 54;
+  optional bool allow_lower_mem_level = 55;
+  optional int32 last_memory_level = 56;
+  optional int32 last_num_processes = 57;
+  optional .android.util.Duration last_idle_time = 58;
+  optional int64 low_ram_since_last_idle_ms = 59;
+}
+
+message ActiveInstrumentationProto {
+  optional .android.content.ComponentNameProto class = 1;
+  optional bool finished = 2;
+  repeated ProcessRecordProto running_processes = 3;
+  repeated string target_processes = 4;
+  optional .android.content.pm.ApplicationInfoProto target_info = 5;
+  optional string profile_file = 6;
+  optional string watcher = 7;
+  optional string ui_automation_connection = 8;
+  optional string arguments = 9;
+}
+
+// Proto definition of com.android.server.am.UidRecord.java
+message UidRecordProto {
+  optional string hex_hash = 1;
+  optional int32 uid = 2;
+  optional .android.app.ProcessState current = 3;
+  optional bool ephemeral = 4;
+  optional bool fg_services = 5;
+  optional bool whilelist = 6;
+  optional .android.util.Duration last_background_time = 7;
+  optional bool idle = 8;
+
+  enum Change {
+    CHANGE_GONE = 0;
+    CHANGE_IDLE = 1;
+    CHANGE_ACTIVE = 2;
+    CHANGE_CACHED = 3;
+    CHANGE_UNCACHED = 4;
+  }
+  repeated Change last_reported_changes = 9;
+  optional int32 num_procs = 10;
+
+  message ProcStateSequence {
+    optional int64 cururent = 1;
+    optional int64 last_network_updated = 2;
+    optional int64 last_dispatched = 3;
+  }
+  optional ProcStateSequence network_state_update = 11;
+}
+
+// proto of class ImportanceToken in ActivityManagerService
+message ImportanceTokenProto {
+  optional int32 pid = 1;
+  optional string token = 2;
+  optional string reason = 3;
+}
+
+message ProcessOomProto {
+  optional bool persistent = 1;
+  optional int32 num = 2;
+  optional string oom_adj = 3;
+
+  // Activity manager's version of Process enum, see ProcessList.java
+  enum SchedGroup {
+    SCHED_GROUP_UNKNOWN = -1;
+    SCHED_GROUP_BACKGROUND = 0;
+    SCHED_GROUP_DEFAULT = 1;
+    SCHED_GROUP_TOP_APP = 2;
+    SCHED_GROUP_TOP_APP_BOUND = 3;
+  }
+  optional SchedGroup sched_group = 4 [ default = SCHED_GROUP_UNKNOWN];
+
+  oneof Foreground {
+    bool activities = 5;
+    bool services = 6;
+  }
+
+  optional .android.app.ProcessState state = 7;
+  optional int32 trim_memory_level = 8;
+  optional ProcessRecordProto proc = 9;
+  optional string adj_type = 10;
+
+  oneof AdjTarget {
+    .android.content.ComponentNameProto adj_target_component_name = 11;
+    string adj_target_object = 12;
+  }
+
+  oneof AdjSource {
+    ProcessRecordProto adj_source_proc = 13;
+    string adj_source_object = 14;
+  }
+
+  message Detail {
+    optional int32 max_adj = 1;
+    optional int32 cur_raw_adj = 2;
+    optional int32 set_raw_adj = 3;
+    optional int32 cur_adj = 4;
+    optional int32 set_adj = 5;
+    optional .android.app.ProcessState current_state = 7;
+    optional .android.app.ProcessState set_state = 8;
+    optional string last_pss = 9;
+    optional string last_swap_pss = 10;
+    optional string last_cached_pss = 11;
+    optional bool cached = 12;
+    optional bool empty = 13;
+    optional bool has_above_client = 14;
+
+    // only make sense if process is a service
+    message CpuRunTime {
+      optional int64 over_ms = 1;
+      optional int64 used_ms = 2;
+      optional float ultilization = 3; // ratio of cpu time usage
+    }
+    optional CpuRunTime service_run_time = 15;
+  }
+  optional Detail detail = 15;
+}
+
+message ProcessToGcProto {
+  optional ProcessRecordProto proc = 1;
+  optional bool report_low_memory = 2;
+  optional int64 now_uptime_ms = 3;
+  optional int64 last_gced_ms = 4;
+  optional int64 last_low_memory_ms = 5;
+}
+
+// sync with com.android.server.am.AppErrors.java
+message AppErrorsProto {
+
+  optional int64 now_uptime_ms = 1;
+
+  message ProcessCrashTime {
+    optional string process_name = 1;
+
+    message Entry {
+      optional int32 uid = 1;
+      optional int64 last_crashed_at_ms = 2;
+    }
+    repeated Entry entries = 2;
+  }
+  repeated ProcessCrashTime process_crash_times = 2;
+
+  message BadProcess {
+    optional string process_name = 1;
+
+    message Entry {
+      optional int32 uid = 1;
+      optional int64 crashed_at_ms = 2;
+      optional string short_msg = 3;
+      optional string long_msg = 4;
+      optional string stack = 5;
+    }
+    repeated Entry entries = 2;
+  }
+  repeated BadProcess bad_processes = 3;
+}
+
+// sync with com.android.server.am.UserState.java
+message UserStateProto {
+  enum State {
+    STATE_BOOTING = 0;
+    STATE_RUNNING_LOCKED = 1;
+    STATE_RUNNING_UNLOCKING = 2;
+    STATE_RUNNING_UNLOCKED = 3;
+    STATE_STOPPING = 4;
+    STATE_SHUTDOWN = 5;
+  }
+  optional State state = 1;
+  optional bool switching = 2;
+}
+
+// sync with com.android.server.am.UserController.java
+message UserControllerProto {
+  message User {
+    optional int32 id = 1;
+    optional UserStateProto state = 2;
+  }
+  repeated User started_users = 1;
+  repeated int32 started_user_array = 2;
+  repeated int32 user_lru = 3;
+
+  message UserProfile {
+    optional int32 user = 1;
+    optional int32 profile = 2;
+  }
+  repeated UserProfile user_profile_group_ids = 4;
+}
+
+// sync with com.android.server.am.AppTimeTracker.java
+message AppTimeTrackerProto {
+  optional string receiver = 1;
+  optional int64 total_duration_ms = 2;
+
+  message PackageTime {
+    optional string package = 1;
+    optional int64 duration_ms = 2;
+  }
+  repeated PackageTime package_times = 3;
+
+  optional .android.util.Duration started_time = 4;
+  optional string started_package = 5;
 }
diff --git a/core/proto/android/server/jobscheduler.proto b/core/proto/android/server/jobscheduler.proto
index f72ca62..739fca3 100644
--- a/core/proto/android/server/jobscheduler.proto
+++ b/core/proto/android/server/jobscheduler.proto
@@ -558,4 +558,6 @@
 
     optional int64 last_successful_run_time = 22;
     optional int64 last_failed_run_time = 23;
+
+    optional int64 internal_flags = 24;
 }
diff --git a/core/proto/android/service/battery.proto b/core/proto/android/service/battery.proto
index 4cb7fd3..42fa72c 100644
--- a/core/proto/android/service/battery.proto
+++ b/core/proto/android/service/battery.proto
@@ -21,8 +21,11 @@
 option java_outer_classname = "BatteryServiceProto";
 
 import "frameworks/base/core/proto/android/os/batterymanager.proto";
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
 
 message BatteryServiceDumpProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     enum BatteryStatus {
         BATTERY_STATUS_INVALID = 0;
         BATTERY_STATUS_UNKNOWN = 1;
diff --git a/core/proto/android/service/batterystats.proto b/core/proto/android/service/batterystats.proto
index 54d3f40..e31e7f3 100644
--- a/core/proto/android/service/batterystats.proto
+++ b/core/proto/android/service/batterystats.proto
@@ -21,7 +21,10 @@
 option java_outer_classname = "BatteryStatsServiceProto";
 
 import "frameworks/base/core/proto/android/os/batterystats.proto";
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
 
 message BatteryStatsServiceDumpProto {
+  option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
   optional android.os.BatteryStatsProto batterystats = 1;
 }
diff --git a/core/proto/android/service/notification.proto b/core/proto/android/service/notification.proto
index 7a0e152..65df89a 100644
--- a/core/proto/android/service/notification.proto
+++ b/core/proto/android/service/notification.proto
@@ -24,6 +24,7 @@
 import "frameworks/base/core/proto/android/app/notification_channel_group.proto";
 import "frameworks/base/core/proto/android/app/notificationmanager.proto";
 import "frameworks/base/core/proto/android/content/component_name.proto";
+import "frameworks/base/core/proto/android/media/audioattributes.proto";
 
 message NotificationServiceDumpProto {
     repeated NotificationRecordProto records = 1;
@@ -55,7 +56,7 @@
     optional int32 flags = 3;
     optional string channelId = 4;
     optional string sound = 5;
-    optional int32 sound_usage = 6;
+    optional .android.media.AudioAttributesProto audio_attributes = 6;
     optional bool can_vibrate = 7;
     optional bool can_show_light = 8;
     optional string group_key = 9;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 93d852c..081c92c 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -327,6 +327,10 @@
     <protected-broadcast android:name="com.android.server.wifi.ConnectToNetworkNotification.CONNECT_TO_NETWORK" />
     <protected-broadcast android:name="com.android.server.wifi.ConnectToNetworkNotification.PICK_WIFI_NETWORK" />
     <protected-broadcast android:name="com.android.server.wifi.ConnectToNetworkNotification.PICK_NETWORK_AFTER_FAILURE" />
+    <protected-broadcast android:name="com.android.server.wifi.wakeup.DISMISS_NOTIFICATION" />
+    <protected-broadcast android:name="com.android.server.wifi.wakeup.OPEN_WIFI_PREFERENCES" />
+    <protected-broadcast android:name="com.android.server.wifi.wakeup.OPEN_WIFI_SETTINGS" />
+    <protected-broadcast android:name="com.android.server.wifi.wakeup.TURN_OFF_WIFI_WAKE" />
     <protected-broadcast android:name="android.net.wifi.WIFI_STATE_CHANGED" />
     <protected-broadcast android:name="android.net.wifi.WIFI_AP_STATE_CHANGED" />
     <protected-broadcast android:name="android.net.wifi.WIFI_CREDENTIAL_CHANGED" />
diff --git a/core/res/res/anim/activity_close_enter.xml b/core/res/res/anim/activity_close_enter.xml
index a67b0ca..371bcfe 100644
--- a/core/res/res/anim/activity_close_enter.xml
+++ b/core/res/res/anim/activity_close_enter.xml
@@ -17,9 +17,17 @@
 */
 -->
 
-<set xmlns:android="http://schemas.android.com/apk/res/android" android:zAdjustment="normal">
-    <alpha android:fromAlpha="0.7" android:toAlpha="1.0"
-            android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
-            android:interpolator="@interpolator/linear_out_slow_in"
-            android:duration="250"/>
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shareInterpolator="false">
+    <translate
+        android:fromYDelta="-2%"
+        android:toYDelta="0"
+        android:interpolator="@interpolator/fast_out_slow_in"
+        android:duration="425"/>
+    <alpha
+        android:fromAlpha="0.9"
+        android:toAlpha="1.0"
+        android:interpolator="@interpolator/activity_close_dim"
+        android:startOffset="0"
+        android:duration="425"/>
 </set>
\ No newline at end of file
diff --git a/core/res/res/anim/activity_close_exit.xml b/core/res/res/anim/activity_close_exit.xml
index d8c42ed..143bedb 100644
--- a/core/res/res/anim/activity_close_exit.xml
+++ b/core/res/res/anim/activity_close_exit.xml
@@ -18,15 +18,27 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:shareInterpolator="false" android:zAdjustment="top">
-    <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
-            android:interpolator="@interpolator/linear"
-            android:fillEnabled="true"
-            android:fillBefore="false" android:fillAfter="true"
-            android:startOffset="100"
-            android:duration="150"/>
-    <translate android:fromYDelta="0%" android:toYDelta="8%"
-            android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
-            android:interpolator="@interpolator/accelerate_quart"
-            android:duration="250"/>
+    android:shareInterpolator="false"
+    android:zAdjustment="top">
+    <translate
+        android:fromYDelta="0"
+        android:toYDelta="4.1%"
+        android:interpolator="@interpolator/fast_out_slow_in"
+        android:duration="425"/>
+    <cliprect
+        android:fromLeft="0%"
+        android:fromTop="0%"
+        android:fromRight="100%"
+        android:fromBottom="100%"
+        android:toLeft="0%"
+        android:toTop="95.9%"
+        android:toRight="100%"
+        android:toBottom="100%"
+        android:interpolator="@interpolator/exaggerated_ease"
+        android:duration="425"/>
+    <alpha
+        android:fromAlpha="1.0"
+        android:toAlpha="1.0"
+        android:interpolator="@interpolator/fast_out_linear_in"
+        android:duration="425"/>
 </set>
\ No newline at end of file
diff --git a/core/res/res/anim/activity_open_enter.xml b/core/res/res/anim/activity_open_enter.xml
index 1d949d2..f9381b4 100644
--- a/core/res/res/anim/activity_open_enter.xml
+++ b/core/res/res/anim/activity_open_enter.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
 /*
 ** Copyright 2009, The Android Open Source Project
 **
@@ -18,15 +17,21 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:shareInterpolator="false"
-        android:zAdjustment="top">
-    <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
-            android:interpolator="@interpolator/decelerate_quart"
-            android:fillEnabled="true"
-            android:fillBefore="false" android:fillAfter="true"
-            android:duration="200"/>
-    <translate android:fromYDelta="8%" android:toYDelta="0"
-            android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
-            android:interpolator="@interpolator/decelerate_quint"
-            android:duration="350"/>
+    android:shareInterpolator="false">
+    <translate
+        android:fromYDelta="4.1%"
+        android:toYDelta="0"
+        android:interpolator="@interpolator/fast_out_slow_in"
+        android:duration="425"/>
+    <cliprect
+        android:fromLeft="0%"
+        android:fromTop="95.9%"
+        android:fromRight="100%"
+        android:fromBottom="100%"
+        android:toLeft="0%"
+        android:toTop="0%"
+        android:toRight="100%"
+        android:toBottom="100%"
+        android:interpolator="@interpolator/exaggerated_ease"
+        android:duration="425"/>
 </set>
\ No newline at end of file
diff --git a/core/res/res/anim/activity_open_exit.xml b/core/res/res/anim/activity_open_exit.xml
index 3a84197..d52b150 100644
--- a/core/res/res/anim/activity_open_exit.xml
+++ b/core/res/res/anim/activity_open_exit.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
 /*
 ** Copyright 2009, The Android Open Source Project
 **
@@ -18,9 +17,15 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:background="#ff000000" android:zAdjustment="normal">
-    <alpha android:fromAlpha="1.0" android:toAlpha="0.7"
-            android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true"
-            android:interpolator="@interpolator/fast_out_slow_in"
-            android:duration="217"/>
+    android:shareInterpolator="false">
+    <translate
+        android:fromYDelta="0"
+        android:toYDelta="-2%"
+        android:interpolator="@interpolator/fast_out_slow_in"
+        android:duration="425"/>
+    <alpha
+        android:fromAlpha="1.0"
+        android:toAlpha="0.9"
+        android:interpolator="@interpolator/linear"
+        android:duration="117"/>
 </set>
\ No newline at end of file
diff --git a/core/res/res/anim/task_close_enter.xml b/core/res/res/anim/task_close_enter.xml
index bea0ee5..81d1300 100644
--- a/core/res/res/anim/task_close_enter.xml
+++ b/core/res/res/anim/task_close_enter.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
 /*
 ** Copyright 2009, The Android Open Source Project
 **
@@ -16,27 +15,54 @@
 ** limitations under the License.
 */
 -->
-
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:shareInterpolator="false" android:zAdjustment="normal">
+    android:shareInterpolator="false"
+    android:zAdjustment="top">
 
-    <alpha android:fromAlpha="0.6" android:toAlpha="1.0"
-            android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
-            android:interpolator="@interpolator/decelerate_cubic"
-            android:startOffset="600"
-            android:duration="133"/>
+    <alpha
+        android:fromAlpha="1"
+        android:toAlpha="1.0"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
+        android:interpolator="@interpolator/linear"
+        android:startOffset="67"
+        android:duration="217"/>
 
-    <translate android:fromYDelta="10%" android:toYDelta="0"
-            android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
-            android:interpolator="@interpolator/decelerate_cubic"
-            android:startOffset="300"
-            android:duration="433" />
+    <translate
+        android:fromXDelta="105%"
+        android:toXDelta="0"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
+        android:interpolator="@interpolator/aggressive_ease"
+        android:startOffset="50"
+        android:duration="383"/>
 
-    <scale android:fromXScale=".9" android:toXScale="1.0"
-            android:fromYScale=".9" android:toYScale="1.0"
-            android:pivotX="50%p" android:pivotY="0%p"
-            android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
-            android:interpolator="@interpolator/fast_out_slow_in"
-            android:startOffset="300"
-            android:duration="433" />
+    <scale
+        android:fromXScale="1.0526"
+        android:toXScale="1"
+        android:fromYScale="1.0526"
+        android:toYScale="1"
+        android:pivotX="50%"
+        android:pivotY="50%"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
+        android:interpolator="@interpolator/fast_out_slow_in"
+        android:duration="283"/>
+
+    <scale
+        android:fromXScale="0.95"
+        android:toXScale="1"
+        android:fromYScale="0.95"
+        android:toYScale="1"
+        android:pivotX="50%"
+        android:pivotY="50%"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
+        android:interpolator="@interpolator/fast_out_slow_in"
+        android:startOffset="283"
+        android:duration="317"/>
 </set>
\ No newline at end of file
diff --git a/core/res/res/anim/task_close_exit.xml b/core/res/res/anim/task_close_exit.xml
index b6a0807..ab8b89c 100644
--- a/core/res/res/anim/task_close_exit.xml
+++ b/core/res/res/anim/task_close_exit.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
 /*
 ** Copyright 2009, The Android Open Source Project
 **
@@ -18,20 +17,44 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:shareInterpolator="false" android:zAdjustment="top">
+    android:shareInterpolator="false">
 
-    <alpha android:fromAlpha="1.0" android:toAlpha="0"
-            android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
-            android:interpolator="@interpolator/accelerate_quad"
-            android:startOffset="250"
-            android:duration="167"/>
+    <alpha
+        android:fromAlpha="1.0"
+        android:toAlpha="1"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
+        android:interpolator="@interpolator/linear"
+        android:startOffset="67"
+        android:duration="283"/>
 
-    <translate android:fromYDelta="0" android:toYDelta="110%"
-            android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
-            android:interpolator="@interpolator/accelerate_quint"
-            android:duration="417"/>
+    <translate
+        android:fromXDelta="0"
+        android:toXDelta="-105%"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
+        android:interpolator="@interpolator/aggressive_ease"
+        android:startOffset="50"
+        android:duration="383"/>
+
+    <scale
+        android:fromXScale="1.0"
+        android:toXScale="0.95"
+        android:fromYScale="1.0"
+        android:toYScale="0.95"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
+        android:pivotX="50%"
+        android:pivotY="50%"
+        android:interpolator="@interpolator/fast_out_slow_in"
+        android:duration="283"/>
 
     <!-- This is needed to keep the animation running while task_open_enter completes -->
-    <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
-            android:duration="700" />
+    <alpha
+        android:fromAlpha="1.0"
+        android:toAlpha="1.0"
+        android:duration="600"/>
 </set>
\ No newline at end of file
diff --git a/core/res/res/anim/task_open_enter.xml b/core/res/res/anim/task_open_enter.xml
index b73e14f..2ee7cd8 100644
--- a/core/res/res/anim/task_open_enter.xml
+++ b/core/res/res/anim/task_open_enter.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
 /*
 ** Copyright 2009, The Android Open Source Project
 **
@@ -15,20 +14,55 @@
 ** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
--->
-<!-- This should in sync with task_open_enter_cross_profile_apps.xml -->
+--><!-- This should in sync with task_open_enter_cross_profile_apps.xml -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:shareInterpolator="false" android:zAdjustment="top">
+    android:shareInterpolator="false"
+    android:zAdjustment="top">
 
-    <alpha android:fromAlpha="0" android:toAlpha="1.0"
-            android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
-            android:interpolator="@interpolator/decelerate_quart"
-            android:startOffset="300"
-            android:duration="167"/>
+    <alpha
+        android:fromAlpha="1"
+        android:toAlpha="1.0"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
+        android:interpolator="@interpolator/linear"
+        android:startOffset="67"
+        android:duration="217"/>
 
-    <translate android:fromYDelta="110%" android:toYDelta="0"
-            android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
-            android:interpolator="@interpolator/decelerate_quint"
-            android:startOffset="300"
-            android:duration="417" />
+    <translate
+        android:fromXDelta="-105%"
+        android:toXDelta="0"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
+        android:interpolator="@interpolator/aggressive_ease"
+        android:startOffset="50"
+        android:duration="383"/>
+
+    <scale
+        android:fromXScale="1.0526"
+        android:toXScale="1"
+        android:fromYScale="1.0526"
+        android:toYScale="1"
+        android:pivotX="50%"
+        android:pivotY="50%"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
+        android:interpolator="@interpolator/fast_out_slow_in"
+        android:duration="283"/>
+
+    <scale
+        android:fromXScale="0.95"
+        android:toXScale="1"
+        android:fromYScale="0.95"
+        android:toYScale="1"
+        android:pivotX="50%"
+        android:pivotY="50%"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
+        android:interpolator="@interpolator/fast_out_slow_in"
+        android:startOffset="283"
+        android:duration="317"/>
 </set>
\ No newline at end of file
diff --git a/core/res/res/anim/task_open_enter_cross_profile_apps.xml b/core/res/res/anim/task_open_enter_cross_profile_apps.xml
index ad89fde..a92425e 100644
--- a/core/res/res/anim/task_open_enter_cross_profile_apps.xml
+++ b/core/res/res/anim/task_open_enter_cross_profile_apps.xml
@@ -18,24 +18,61 @@
 -->
 <!-- This should in sync with task_open_enter.xml -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-     android:shareInterpolator="false" android:zAdjustment="top">
+    android:shareInterpolator="false"
+    android:zAdjustment="top">
 
-    <alpha android:fromAlpha="0" android:toAlpha="1.0"
-           android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
-           android:interpolator="@interpolator/decelerate_quart"
-           android:startOffset="300"
-           android:duration="167"/>
+    <alpha
+        android:fromAlpha="1"
+        android:toAlpha="1.0"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
+        android:interpolator="@interpolator/linear"
+        android:startOffset="67"
+        android:duration="217"/>
 
-    <translate android:fromYDelta="110%" android:toYDelta="0"
-               android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
-               android:interpolator="@interpolator/decelerate_quint"
-               android:startOffset="300"
-               android:duration="417"/>
+    <translate
+        android:fromXDelta="-105%"
+        android:toXDelta="0"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
+        android:interpolator="@interpolator/aggressive_ease"
+        android:startOffset="50"
+        android:duration="383"/>
+
+    <scale
+        android:fromXScale="1.0526"
+        android:toXScale="1"
+        android:fromYScale="1.0526"
+        android:toYScale="1"
+        android:pivotX="50%"
+        android:pivotY="50%"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
+        android:interpolator="@interpolator/fast_out_slow_in"
+        android:duration="283"/>
+
+    <scale
+        android:fromXScale="0.95"
+        android:toXScale="1"
+        android:fromYScale="0.95"
+        android:toYScale="1"
+        android:pivotX="50%"
+        android:pivotY="50%"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
+        android:interpolator="@interpolator/fast_out_slow_in"
+        android:startOffset="283"
+        android:duration="317"/>
 
     <!-- To keep the transition around longer for the thumbnail, should be kept in sync with
          cross_profile_apps_thumbmail.xml -->
-    <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
-           android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
-           android:startOffset="717"
-           android:duration="200"/>
+    <alpha
+        android:fromAlpha="1.0"
+        android:toAlpha="1.0"
+        android:startOffset="717"
+        android:duration="200"/>
 </set>
\ No newline at end of file
diff --git a/core/res/res/anim/task_open_exit.xml b/core/res/res/anim/task_open_exit.xml
index 78d0fb0..ecb98ce 100644
--- a/core/res/res/anim/task_open_exit.xml
+++ b/core/res/res/anim/task_open_exit.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
 /*
 ** Copyright 2009, The Android Open Source Project
 **
@@ -18,26 +17,44 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:background="#ff000000" android:shareInterpolator="false" android:zAdjustment="normal">
+    android:shareInterpolator="false">
 
-    <alpha android:fromAlpha="1.0" android:toAlpha="0.6"
-            android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
-            android:interpolator="@interpolator/accelerate_cubic"
-            android:duration="133"/>
+    <alpha
+        android:fromAlpha="1.0"
+        android:toAlpha="1"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
+        android:interpolator="@interpolator/linear"
+        android:startOffset="67"
+        android:duration="283"/>
 
-    <translate android:fromYDelta="0" android:toYDelta="10%"
-            android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
-            android:interpolator="@interpolator/accelerate_cubic"
-            android:duration="433"/>
+    <translate
+        android:fromXDelta="0"
+        android:toXDelta="105%"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
+        android:interpolator="@interpolator/aggressive_ease"
+        android:startOffset="50"
+        android:duration="383"/>
 
-    <scale android:fromXScale="1.0" android:toXScale="0.9"
-            android:fromYScale="1.0" android:toYScale="0.9"
-            android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
-            android:pivotX="50%p" android:pivotY="50%p"
-            android:interpolator="@interpolator/fast_out_slow_in"
-            android:duration="433" />
+    <scale
+        android:fromXScale="1.0"
+        android:toXScale="0.95"
+        android:fromYScale="1.0"
+        android:toYScale="0.95"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
+        android:pivotX="50%"
+        android:pivotY="50%"
+        android:interpolator="@interpolator/fast_out_slow_in"
+        android:duration="283"/>
 
     <!-- This is needed to keep the animation running while task_open_enter completes -->
-    <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
-            android:duration="700" />
+    <alpha
+        android:fromAlpha="1.0"
+        android:toAlpha="1.0"
+        android:duration="600"/>
 </set>
\ No newline at end of file
diff --git a/core/res/res/interpolator/activity_close_dim.xml b/core/res/res/interpolator/activity_close_dim.xml
new file mode 100644
index 0000000..faad139
--- /dev/null
+++ b/core/res/res/interpolator/activity_close_dim.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:controlX1="0.33"
+    android:controlY1="0"
+    android:controlX2="1"
+    android:controlY2="1"/>
diff --git a/core/res/res/layout/notification_template_material_ambient.xml b/core/res/res/layout/notification_template_material_ambient.xml
index 435289d..19c4d23 100644
--- a/core/res/res/layout/notification_template_material_ambient.xml
+++ b/core/res/res/layout/notification_template_material_ambient.xml
@@ -57,7 +57,7 @@
                 android:singleLine="true"
                 android:ellipsize="marquee"
                 android:fadingEdge="horizontal"
-                android:textSize="20sp"
+                android:textSize="24sp"
                 android:textColor="#ffffffff"
             />
             <TextView android:id="@+id/text"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 4eaf93d..354d658 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1897,6 +1897,7 @@
         <enum name="KEYCODE_SYSTEM_NAVIGATION_LEFT" value="282" />
         <enum name="KEYCODE_SYSTEM_NAVIGATION_RIGHT" value="283" />
         <enum name="KEYCODE_ALL_APPS" value="284" />
+        <enum name="KEYCODE_REFRESH" value="285" />
     </attr>
 
     <!-- ***************************************************************** -->
@@ -2066,7 +2067,8 @@
              <p>For this to take effect, the window must be drawing the system bar backgrounds with
              {@link android.R.attr#windowDrawsSystemBarBackgrounds} and the navigation bar must not
              have been requested to be translucent with
-             {@link android.R.attr#windowTranslucentNavigation}. -->
+             {@link android.R.attr#windowTranslucentNavigation}.
+             Corresponds to {@link android.view.Window#setNavigationBarDividerColor(int)}. -->
         <attr name="navigationBarDividerColor" format="color" />
 
         <!-- The duration, in milliseconds, of the window background fade duration
@@ -6336,6 +6338,17 @@
         <attr name="toAlpha" format="float" />
     </declare-styleable>
 
+    <declare-styleable name="ClipRectAnimation">
+        <attr name="fromLeft" format="fraction" />
+        <attr name="fromTop" format="fraction" />
+        <attr name="fromRight" format="fraction" />
+        <attr name="fromBottom" format="fraction" />
+        <attr name="toLeft" format="fraction" />
+        <attr name="toTop" format="fraction" />
+        <attr name="toRight" format="fraction" />
+        <attr name="toBottom" format="fraction" />
+    </declare-styleable>
+
     <declare-styleable name="LayoutAnimation">
         <!-- Fraction of the animation duration used to delay the beginning of
          the animation of each child. -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 170ba42..88549b5 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1321,6 +1321,9 @@
     <string-array name="fingerprint_acquired_vendor">
     </string-array>
 
+    <!-- Message shown by the fingerprint dialog when fingerprint is not recognized -->
+    <string name="fingerprint_not_recognized">Not recognized</string>
+
     <!-- Error message shown when the fingerprint hardware can't be accessed -->
     <string name="fingerprint_error_hw_not_available">Fingerprint hardware not available.</string>
     <!-- Error message shown when the fingerprint hardware has run out of room for storing fingerprints -->
@@ -1329,6 +1332,8 @@
     <string name="fingerprint_error_timeout">Fingerprint time out reached. Try again.</string>
     <!-- Generic error message shown when the fingerprint operation (e.g. enrollment or authentication) is canceled. Generally not shown to the user-->
     <string name="fingerprint_error_canceled">Fingerprint operation canceled.</string>
+    <!-- Generic error message shown when the fingerprint authentication operation is canceled due to user input. Generally not shown to the user -->
+    <string name="fingerprint_error_user_canceled">Fingerprint operation canceled by user.</string>
     <!-- Generic error message shown when the fingerprint operation fails because too many attempts have been made. -->
     <string name="fingerprint_error_lockout">Too many attempts. Try again later.</string>
     <!-- Generic error message shown when the fingerprint operation fails because strong authentication is required -->
@@ -4480,7 +4485,7 @@
     <string name="zen_mode_alarm">Until <xliff:g id="formattedTime" example="10:00 PM">%1$s</xliff:g> (next alarm)</string>
 
     <!-- Zen mode condition: no exit criteria. [CHAR LIMIT=NONE] -->
-    <string name="zen_mode_forever">Until you turn off Do Not Disturb</string>
+    <string name="zen_mode_forever">Until you turn off</string>
 
     <!-- Zen mode condition: no exit criteria, includes the name of the feature for emphasis. [CHAR LIMIT=NONE] -->
     <string name="zen_mode_forever_dnd">Until you turn off Do Not Disturb</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 4ef0a6c..1711ec9 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2341,9 +2341,11 @@
   <java-symbol type="string" name="fingerprint_acquired_too_fast" />
   <java-symbol type="array" name="fingerprint_acquired_vendor" />
   <java-symbol type="string" name="fingerprint_error_canceled" />
+  <java-symbol type="string" name="fingerprint_error_user_canceled" />
   <java-symbol type="string" name="fingerprint_error_lockout" />
   <java-symbol type="string" name="fingerprint_error_lockout_permanent" />
   <java-symbol type="string" name="fingerprint_name_template" />
+  <java-symbol type="string" name="fingerprint_not_recognized" />
 
   <!-- Fingerprint config -->
   <java-symbol type="integer" name="config_fingerprintMaxTemplatesPerUser"/>
diff --git a/core/tests/benchmarks/src/com/android/internal/net/NetworkStatsFactoryBenchmark.java b/core/tests/benchmarks/src/com/android/internal/net/NetworkStatsFactoryBenchmark.java
index e62fbd6..c213464 100644
--- a/core/tests/benchmarks/src/com/android/internal/net/NetworkStatsFactoryBenchmark.java
+++ b/core/tests/benchmarks/src/com/android/internal/net/NetworkStatsFactoryBenchmark.java
@@ -53,7 +53,7 @@
                     stats, mStats.getAbsolutePath(), NetworkStats.UID_ALL,
                     // Looks like this was broken by change d0c5b9abed60b7bc056d026bf0f2b2235410fb70
                     // Fixed compilation problem but needs addressing properly.
-                    new String[0], 999);
+                    new String[0], 999, false);
         }
     }
 }
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 7403c26..bc2d099 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -481,7 +481,6 @@
                  Settings.Secure.INSTALL_NON_MARKET_APPS,
                  Settings.Secure.LAST_SETUP_SHOWN,
                  Settings.Secure.LOCATION_MODE,
-                 Settings.Secure.LOCATION_PREVIOUS_MODE,
                  Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, // Candidate?
                  Settings.Secure.LOCK_SCREEN_ALLOW_REMOTE_INPUT, // Candidate?
                  Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT,
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 4be6408..09192f4 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -172,6 +172,8 @@
     <assign-permission name="android.permission.ACCESS_LOWPAN_STATE" uid="lowpan" />
     <assign-permission name="android.permission.MANAGE_LOWPAN_INTERFACES" uid="lowpan" />
 
+    <assign-permission name="android.permission.DUMP" uid="statsd" />
+    <assign-permission name="android.permission.PACKAGE_USAGE_STATS" uid="statsd" />
     <assign-permission name="android.permission.STATSCOMPANION" uid="statsd" />
 
     <!-- This is a list of all the libraries available for application
diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl
index 74f8c71..8699cb4 100644
--- a/data/keyboards/Generic.kl
+++ b/data/keyboards/Generic.kl
@@ -192,7 +192,7 @@
 # key 170 "KEY_ISO"
 key 171   MUSIC
 key 172   HOME
-# key 173 "KEY_REFRESH"
+key 173   REFRESH
 # key 174 "KEY_EXIT"
 # key 175 "KEY_MOVE"
 # key 176 "KEY_EDIT"
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 1690e8c..e25386b 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -510,6 +510,19 @@
         return importKey(alias, args, format, keyData, UID_SELF, flags, outCharacteristics);
     }
 
+    public int importWrappedKey(String wrappedKeyAlias, byte[] wrappedKey,
+            String wrappingKeyAlias,
+            byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid, int uid,
+            KeyCharacteristics outCharacteristics) {
+        try {
+            return mBinder.importWrappedKey(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
+                    maskingKey, args, rootSid, fingerprintSid, outCharacteristics);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Cannot connect to keystore", e);
+            return SYSTEM_ERROR;
+        }
+    }
+
     public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
             KeymasterBlob appId, int uid) {
         try {
diff --git a/keystore/java/android/security/keystore/AndroidKeyStore3DESCipherSpi.java b/keystore/java/android/security/keystore/AndroidKeyStore3DESCipherSpi.java
new file mode 100644
index 0000000..01fd062
--- /dev/null
+++ b/keystore/java/android/security/keystore/AndroidKeyStore3DESCipherSpi.java
@@ -0,0 +1,298 @@
+/*
+ * 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.security.keymaster.KeymasterArguments;
+import android.security.keymaster.KeymasterDefs;
+
+import java.security.AlgorithmParameters;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.security.ProviderException;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+import java.util.Arrays;
+
+import javax.crypto.CipherSpi;
+import javax.crypto.spec.IvParameterSpec;
+
+/**
+ * Base class for Android Keystore 3DES {@link CipherSpi} implementations.
+ *
+ * @hide
+ */
+public class AndroidKeyStore3DESCipherSpi extends AndroidKeyStoreCipherSpiBase {
+
+    private static final int BLOCK_SIZE_BYTES = 8;
+
+    private final int mKeymasterBlockMode;
+    private final int mKeymasterPadding;
+    /** Whether this transformation requires an IV. */
+    private final boolean mIvRequired;
+
+    private byte[] mIv;
+
+    /** Whether the current {@code #mIv} has been used by the underlying crypto operation. */
+    private boolean mIvHasBeenUsed;
+
+    AndroidKeyStore3DESCipherSpi(
+            int keymasterBlockMode,
+            int keymasterPadding,
+            boolean ivRequired) {
+        mKeymasterBlockMode = keymasterBlockMode;
+        mKeymasterPadding = keymasterPadding;
+        mIvRequired = ivRequired;
+    }
+
+    abstract static class ECB extends AndroidKeyStore3DESCipherSpi {
+        protected ECB(int keymasterPadding) {
+            super(KeymasterDefs.KM_MODE_ECB, keymasterPadding, false);
+        }
+
+        public static class NoPadding extends ECB {
+            public NoPadding() {
+                super(KeymasterDefs.KM_PAD_NONE);
+            }
+        }
+
+        public static class PKCS7Padding extends ECB {
+            public PKCS7Padding() {
+                super(KeymasterDefs.KM_PAD_PKCS7);
+            }
+        }
+    }
+
+    abstract static class CBC extends AndroidKeyStore3DESCipherSpi {
+        protected CBC(int keymasterPadding) {
+            super(KeymasterDefs.KM_MODE_CBC, keymasterPadding, true);
+        }
+
+        public static class NoPadding extends CBC {
+            public NoPadding() {
+                super(KeymasterDefs.KM_PAD_NONE);
+            }
+        }
+
+        public static class PKCS7Padding extends CBC {
+            public PKCS7Padding() {
+                super(KeymasterDefs.KM_PAD_PKCS7);
+            }
+        }
+    }
+
+    @Override
+    protected void initKey(int i, Key key) throws InvalidKeyException {
+        if (!(key instanceof AndroidKeyStoreSecretKey)) {
+            throw new InvalidKeyException(
+                    "Unsupported key: " + ((key != null) ? key.getClass().getName() : "null"));
+        }
+        if (!KeyProperties.KEY_ALGORITHM_3DES.equalsIgnoreCase(key.getAlgorithm())) {
+            throw new InvalidKeyException(
+                    "Unsupported key algorithm: " + key.getAlgorithm() + ". Only " +
+                            KeyProperties.KEY_ALGORITHM_3DES + " supported");
+        }
+        setKey((AndroidKeyStoreSecretKey) key);
+    }
+
+    @Override
+    protected int engineGetBlockSize() {
+        return BLOCK_SIZE_BYTES;
+    }
+
+    @Override
+    protected int engineGetOutputSize(int inputLen) {
+        return inputLen + 3 * BLOCK_SIZE_BYTES;
+    }
+
+    @Override
+    protected final byte[] engineGetIV() {
+        return ArrayUtils.cloneIfNotEmpty(mIv);
+    }
+
+    @Override
+    protected AlgorithmParameters engineGetParameters() {
+        if (!mIvRequired) {
+            return null;
+        }
+        if ((mIv != null) && (mIv.length > 0)) {
+            try {
+                AlgorithmParameters params = AlgorithmParameters.getInstance("DESede");
+                params.init(new IvParameterSpec(mIv));
+                return params;
+            } catch (NoSuchAlgorithmException e) {
+                throw new ProviderException(
+                        "Failed to obtain 3DES AlgorithmParameters", e);
+            } catch (InvalidParameterSpecException e) {
+                throw new ProviderException(
+                        "Failed to initialize 3DES AlgorithmParameters with an IV",
+                        e);
+            }
+        }
+        return null;
+    }
+
+    @Override
+    protected void initAlgorithmSpecificParameters() throws InvalidKeyException {
+        if (!mIvRequired) {
+            return;
+        }
+
+        // IV is used
+        if (!isEncrypting()) {
+            throw new InvalidKeyException("IV required when decrypting"
+                    + ". Use IvParameterSpec or AlgorithmParameters to provide it.");
+        }
+    }
+
+    @Override
+    protected void initAlgorithmSpecificParameters(AlgorithmParameterSpec params)
+            throws InvalidAlgorithmParameterException {
+        if (!mIvRequired) {
+            if (params != null) {
+                throw new InvalidAlgorithmParameterException("Unsupported parameters: " + params);
+            }
+            return;
+        }
+
+        // IV is used
+        if (params == null) {
+            if (!isEncrypting()) {
+                // IV must be provided by the caller
+                throw new InvalidAlgorithmParameterException(
+                        "IvParameterSpec must be provided when decrypting");
+            }
+            return;
+        }
+        if (!(params instanceof IvParameterSpec)) {
+            throw new InvalidAlgorithmParameterException("Only IvParameterSpec supported");
+        }
+        mIv = ((IvParameterSpec) params).getIV();
+        if (mIv == null) {
+            throw new InvalidAlgorithmParameterException("Null IV in IvParameterSpec");
+        }
+    }
+
+    @Override
+    protected void initAlgorithmSpecificParameters(AlgorithmParameters params)
+            throws InvalidAlgorithmParameterException {
+        if (!mIvRequired) {
+            if (params != null) {
+                throw new InvalidAlgorithmParameterException("Unsupported parameters: " + params);
+            }
+            return;
+        }
+
+        // IV is used
+        if (params == null) {
+            if (!isEncrypting()) {
+                // IV must be provided by the caller
+                throw new InvalidAlgorithmParameterException("IV required when decrypting"
+                        + ". Use IvParameterSpec or AlgorithmParameters to provide it.");
+            }
+            return;
+        }
+
+        if (!"DESede".equalsIgnoreCase(params.getAlgorithm())) {
+            throw new InvalidAlgorithmParameterException(
+                    "Unsupported AlgorithmParameters algorithm: " + params.getAlgorithm()
+                            + ". Supported: DESede");
+        }
+
+        IvParameterSpec ivSpec;
+        try {
+            ivSpec = params.getParameterSpec(IvParameterSpec.class);
+        } catch (InvalidParameterSpecException e) {
+            if (!isEncrypting()) {
+                // IV must be provided by the caller
+                throw new InvalidAlgorithmParameterException("IV required when decrypting"
+                        + ", but not found in parameters: " + params, e);
+            }
+            mIv = null;
+            return;
+        }
+        mIv = ivSpec.getIV();
+        if (mIv == null) {
+            throw new InvalidAlgorithmParameterException("Null IV in AlgorithmParameters");
+        }
+    }
+
+    @Override
+    protected final int getAdditionalEntropyAmountForBegin() {
+        if ((mIvRequired) && (mIv == null) && (isEncrypting())) {
+            // IV will need to be generated
+            return BLOCK_SIZE_BYTES;
+        }
+
+        return 0;
+    }
+
+    @Override
+    protected int getAdditionalEntropyAmountForFinish() {
+        return 0;
+    }
+
+    @Override
+    protected void addAlgorithmSpecificParametersToBegin(KeymasterArguments keymasterArgs) {
+        if ((isEncrypting()) && (mIvRequired) && (mIvHasBeenUsed)) {
+            // IV is being reused for encryption: this violates security best practices.
+            throw new IllegalStateException(
+                    "IV has already been used. Reusing IV in encryption mode violates security best"
+                            + " practices.");
+        }
+
+        keymasterArgs.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_3DES);
+        keymasterArgs.addEnum(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockMode);
+        keymasterArgs.addEnum(KeymasterDefs.KM_TAG_PADDING, mKeymasterPadding);
+        if ((mIvRequired) && (mIv != null)) {
+            keymasterArgs.addBytes(KeymasterDefs.KM_TAG_NONCE, mIv);
+        }
+    }
+
+    @Override
+    protected void loadAlgorithmSpecificParametersFromBeginResult(
+            KeymasterArguments keymasterArgs) {
+        mIvHasBeenUsed = true;
+
+        // NOTE: Keymaster doesn't always return an IV, even if it's used.
+        byte[] returnedIv = keymasterArgs.getBytes(KeymasterDefs.KM_TAG_NONCE, null);
+        if ((returnedIv != null) && (returnedIv.length == 0)) {
+            returnedIv = null;
+        }
+
+        if (mIvRequired) {
+            if (mIv == null) {
+                mIv = returnedIv;
+            } else if ((returnedIv != null) && (!Arrays.equals(returnedIv, mIv))) {
+                throw new ProviderException("IV in use differs from provided IV");
+            }
+        } else {
+            if (returnedIv != null) {
+                throw new ProviderException(
+                        "IV in use despite IV not being used by this transformation");
+            }
+        }
+    }
+
+    @Override
+    protected final void resetAll() {
+        mIv = null;
+        mIvHasBeenUsed = false;
+        super.resetAll();
+    }
+}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreBCWorkaroundProvider.java b/keystore/java/android/security/keystore/AndroidKeyStoreBCWorkaroundProvider.java
index be390ff..e4cf84a 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreBCWorkaroundProvider.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreBCWorkaroundProvider.java
@@ -93,6 +93,16 @@
         putSymmetricCipherImpl("AES/CTR/NoPadding",
                 PACKAGE_NAME + ".AndroidKeyStoreUnauthenticatedAESCipherSpi$CTR$NoPadding");
 
+        putSymmetricCipherImpl("DESede/CBC/NoPadding",
+                PACKAGE_NAME + ".AndroidKeyStore3DESCipherSpi$CBC$NoPadding");
+        putSymmetricCipherImpl("DESede/CBC/PKCS7Padding",
+                PACKAGE_NAME + ".AndroidKeyStore3DESCipherSpi$CBC$PKCS7Padding");
+
+        putSymmetricCipherImpl("DESede/ECB/NoPadding",
+                PACKAGE_NAME + ".AndroidKeyStore3DESCipherSpi$ECB$NoPadding");
+        putSymmetricCipherImpl("DESede/ECB/PKCS7Padding",
+                PACKAGE_NAME + ".AndroidKeyStore3DESCipherSpi$ECB$PKCS7Padding");
+
         putSymmetricCipherImpl("AES/GCM/NoPadding",
                 PACKAGE_NAME + ".AndroidKeyStoreAuthenticatedAESCipherSpi$GCM$NoPadding");
 
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java b/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java
index fdebf37..5bcb34a 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java
@@ -307,7 +307,7 @@
      *
      * <p>This implementation returns {@code null}.
      *
-     * @returns stream or {@code null} if AAD is not supported by this cipher.
+     * @return stream or {@code null} if AAD is not supported by this cipher.
      */
     @Nullable
     protected KeyStoreCryptoOperationStreamer createAdditionalAuthenticationDataStreamer(
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
index f1d1e16..379e177 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
@@ -60,6 +60,12 @@
         }
     }
 
+    public static class DESede extends AndroidKeyStoreKeyGeneratorSpi {
+        public DESede() {
+            super(KeymasterDefs.KM_ALGORITHM_3DES, 168);
+        }
+    }
+
     protected static abstract class HmacBase extends AndroidKeyStoreKeyGeneratorSpi {
         protected HmacBase(int keymasterDigest) {
             super(KeymasterDefs.KM_ALGORITHM_HMAC,
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
index 55e6519..1018926 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
@@ -80,6 +80,7 @@
 
         // javax.crypto.KeyGenerator
         put("KeyGenerator.AES", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$AES");
+        put("KeyGenerator.DESede", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$DESede");
         put("KeyGenerator.HmacSHA1", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$HmacSHA1");
         put("KeyGenerator.HmacSHA224", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$HmacSHA224");
         put("KeyGenerator.HmacSHA256", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$HmacSHA256");
@@ -88,6 +89,7 @@
 
         // java.security.SecretKeyFactory
         putSecretKeyFactoryImpl("AES");
+        putSecretKeyFactoryImpl("DESede");
         putSecretKeyFactoryImpl("HmacSHA1");
         putSecretKeyFactoryImpl("HmacSHA224");
         putSecretKeyFactoryImpl("HmacSHA256");
@@ -348,7 +350,8 @@
         }
 
         if (keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC ||
-                keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_AES) {
+                keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_AES ||
+                keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_3DES) {
             return loadAndroidKeyStoreSecretKeyFromKeystore(userKeyAlias, uid,
                     keyCharacteristics);
         } else if (keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_RSA ||
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
index d73a9e2..440e086 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
@@ -18,6 +18,7 @@
 
 import libcore.util.EmptyArray;
 import android.security.Credentials;
+import android.security.GateKeeper;
 import android.security.KeyStore;
 import android.security.KeyStoreParameter;
 import android.security.keymaster.KeyCharacteristics;
@@ -25,6 +26,7 @@
 import android.security.keymaster.KeymasterDefs;
 import android.security.keystore.KeyProperties;
 import android.security.keystore.KeyProtection;
+import android.security.keystore.WrappedKeyEntry;
 import android.util.Log;
 
 import java.io.ByteArrayInputStream;
@@ -744,6 +746,31 @@
         }
     }
 
+    private void setWrappedKeyEntry(String alias, byte[] wrappedKeyBytes, String wrappingKeyAlias,
+            java.security.KeyStore.ProtectionParameter param) throws KeyStoreException {
+        if (param != null) {
+            throw new KeyStoreException("Protection parameters are specified inside wrapped keys");
+        }
+
+        byte[] maskingKey = new byte[32];
+        KeymasterArguments args = new KeymasterArguments(); // TODO: populate wrapping key args.
+
+        int errorCode = mKeyStore.importWrappedKey(
+            Credentials.USER_SECRET_KEY + alias,
+            wrappedKeyBytes,
+            Credentials.USER_PRIVATE_KEY + wrappingKeyAlias,
+            maskingKey,
+            args,
+            GateKeeper.getSecureUserId(),
+            0, // FIXME fingerprint id?
+            mUid,
+            new KeyCharacteristics());
+        if (errorCode != KeyStore.NO_ERROR) {
+            throw new KeyStoreException("Failed to import wrapped key. Keystore error code: "
+                + errorCode);
+        }
+    }
+
     @Override
     public void engineSetKeyEntry(String alias, byte[] userKey, Certificate[] chain)
             throws KeyStoreException {
@@ -974,6 +1001,9 @@
         } else if (entry instanceof SecretKeyEntry) {
             SecretKeyEntry secE = (SecretKeyEntry) entry;
             setSecretKeyEntry(alias, secE.getSecretKey(), param);
+        } else if (entry instanceof WrappedKeyEntry) {
+            WrappedKeyEntry wke = (WrappedKeyEntry) entry;
+            setWrappedKeyEntry(alias, wke.getWrappedKeyBytes(), wke.getWrappingKeyAlias(), param);
         } else {
             throw new KeyStoreException(
                     "Entry must be a PrivateKeyEntry, SecretKeyEntry or TrustedCertificateEntry"
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index 1238d87..1e2b873 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -262,6 +262,7 @@
     private final boolean mUniqueIdIncluded;
     private final boolean mUserAuthenticationValidWhileOnBody;
     private final boolean mInvalidatedByBiometricEnrollment;
+    private final boolean mIsStrongBoxBacked;
 
     /**
      * @hide should be built with Builder
@@ -289,7 +290,8 @@
             byte[] attestationChallenge,
             boolean uniqueIdIncluded,
             boolean userAuthenticationValidWhileOnBody,
-            boolean invalidatedByBiometricEnrollment) {
+            boolean invalidatedByBiometricEnrollment,
+            boolean isStrongBoxBacked) {
         if (TextUtils.isEmpty(keyStoreAlias)) {
             throw new IllegalArgumentException("keyStoreAlias must not be empty");
         }
@@ -335,6 +337,7 @@
         mUniqueIdIncluded = uniqueIdIncluded;
         mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody;
         mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment;
+        mIsStrongBoxBacked = isStrongBoxBacked;
     }
 
     /**
@@ -625,6 +628,13 @@
     }
 
     /**
+     * Returns {@code true} if the key is protected by a Strongbox security chip.
+     */
+    public boolean isStrongBoxBacked() {
+        return mIsStrongBoxBacked;
+    }
+
+    /**
      * Builder of {@link KeyGenParameterSpec} instances.
      */
     public final static class Builder {
@@ -652,6 +662,7 @@
         private boolean mUniqueIdIncluded = false;
         private boolean mUserAuthenticationValidWhileOnBody;
         private boolean mInvalidatedByBiometricEnrollment = true;
+        private boolean mIsStrongBoxBacked = false;
 
         /**
          * Creates a new instance of the {@code Builder}.
@@ -1177,6 +1188,15 @@
         }
 
         /**
+         * Sets whether this key should be protected by a StrongBox security chip.
+         */
+        @NonNull
+        public Builder setIsStrongBoxBacked(boolean isStrongBoxBacked) {
+            mIsStrongBoxBacked = isStrongBoxBacked;
+            return this;
+        }
+
+        /**
          * Builds an instance of {@code KeyGenParameterSpec}.
          */
         @NonNull
@@ -1204,7 +1224,8 @@
                     mAttestationChallenge,
                     mUniqueIdIncluded,
                     mUserAuthenticationValidWhileOnBody,
-                    mInvalidatedByBiometricEnrollment);
+                    mInvalidatedByBiometricEnrollment,
+                    mIsStrongBoxBacked);
         }
     }
 }
diff --git a/keystore/java/android/security/keystore/KeyProperties.java b/keystore/java/android/security/keystore/KeyProperties.java
index a250d1f0..f54b6de 100644
--- a/keystore/java/android/security/keystore/KeyProperties.java
+++ b/keystore/java/android/security/keystore/KeyProperties.java
@@ -44,6 +44,7 @@
             PURPOSE_DECRYPT,
             PURPOSE_SIGN,
             PURPOSE_VERIFY,
+            PURPOSE_WRAP_KEY,
     })
     public @interface PurposeEnum {}
 
@@ -68,6 +69,11 @@
     public static final int PURPOSE_VERIFY = 1 << 3;
 
     /**
+     * Purpose of key: wrapping and unwrapping wrapped keys for secure import.
+     */
+    public static final int PURPOSE_WRAP_KEY = 1 << 5;
+
+    /**
      * @hide
      */
     public static abstract class Purpose {
@@ -83,6 +89,8 @@
                     return KeymasterDefs.KM_PURPOSE_SIGN;
                 case PURPOSE_VERIFY:
                     return KeymasterDefs.KM_PURPOSE_VERIFY;
+                case PURPOSE_WRAP_KEY:
+                    return KeymasterDefs.KM_PURPOSE_WRAP;
                 default:
                     throw new IllegalArgumentException("Unknown purpose: " + purpose);
             }
@@ -98,6 +106,8 @@
                     return PURPOSE_SIGN;
                 case KeymasterDefs.KM_PURPOSE_VERIFY:
                     return PURPOSE_VERIFY;
+                case KeymasterDefs.KM_PURPOSE_WRAP:
+                    return PURPOSE_WRAP_KEY;
                 default:
                     throw new IllegalArgumentException("Unknown purpose: " + purpose);
             }
@@ -146,6 +156,15 @@
     /** Advanced Encryption Standard (AES) key. */
     public static final String KEY_ALGORITHM_AES = "AES";
 
+    /**
+     * Triple Data Encryption Algorithm (3DES) key.
+     *
+     * @deprecated Included for interoperability with legacy systems. Prefer {@link
+     * KeyProperties#KEY_ALGORITHM_AES} for new development.
+     */
+    @Deprecated
+    public static final String KEY_ALGORITHM_3DES = "DESede";
+
     /** Keyed-Hash Message Authentication Code (HMAC) key using SHA-1 as the hash. */
     public static final String KEY_ALGORITHM_HMAC_SHA1 = "HmacSHA1";
 
@@ -196,6 +215,8 @@
                 @NonNull @KeyAlgorithmEnum String algorithm) {
             if (KEY_ALGORITHM_AES.equalsIgnoreCase(algorithm)) {
                 return KeymasterDefs.KM_ALGORITHM_AES;
+            } else if (KEY_ALGORITHM_3DES.equalsIgnoreCase(algorithm)) {
+                return KeymasterDefs.KM_ALGORITHM_3DES;
             } else if (algorithm.toUpperCase(Locale.US).startsWith("HMAC")) {
                 return KeymasterDefs.KM_ALGORITHM_HMAC;
             } else {
@@ -210,6 +231,8 @@
             switch (keymasterAlgorithm) {
                 case KeymasterDefs.KM_ALGORITHM_AES:
                     return KEY_ALGORITHM_AES;
+                case KeymasterDefs.KM_ALGORITHM_3DES:
+                    return KEY_ALGORITHM_3DES;
                 case KeymasterDefs.KM_ALGORITHM_HMAC:
                     switch (keymasterDigest) {
                         case KeymasterDefs.KM_DIGEST_SHA1:
@@ -666,6 +689,10 @@
      */
     public static final int ORIGIN_UNKNOWN = 1 << 2;
 
+    /** Key was imported into the AndroidKeyStore in an encrypted wrapper */
+    public static final int ORIGIN_SECURELY_IMPORTED = 1 << 3;
+
+
     /**
      * @hide
      */
@@ -680,6 +707,8 @@
                     return ORIGIN_IMPORTED;
                 case KeymasterDefs.KM_ORIGIN_UNKNOWN:
                     return ORIGIN_UNKNOWN;
+                case KeymasterDefs.KM_ORIGIN_SECURELY_IMPORTED:
+                    return ORIGIN_SECURELY_IMPORTED;
                 default:
                     throw new IllegalArgumentException("Unknown origin: " + origin);
             }
diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java
index 2eb0663..dbacb9c 100644
--- a/keystore/java/android/security/keystore/KeyProtection.java
+++ b/keystore/java/android/security/keystore/KeyProtection.java
@@ -488,9 +488,9 @@
         private int mUserAuthenticationValidityDurationSeconds = -1;
         private boolean mUserAuthenticationValidWhileOnBody;
         private boolean mInvalidatedByBiometricEnrollment = true;
-
         private long mBoundToSecureUserId = GateKeeper.INVALID_SECURE_USER_ID;
         private boolean mCriticalToDeviceEncryption = false;
+
         /**
          * Creates a new instance of the {@code Builder}.
          *
diff --git a/core/java/android/security/keystore/KeychainSnapshot.aidl b/keystore/java/android/security/keystore/StrongBoxUnavailableException.java
similarity index 72%
copy from core/java/android/security/keystore/KeychainSnapshot.aidl
copy to keystore/java/android/security/keystore/StrongBoxUnavailableException.java
index b35713f..ad41a58 100644
--- a/core/java/android/security/keystore/KeychainSnapshot.aidl
+++ b/keystore/java/android/security/keystore/StrongBoxUnavailableException.java
@@ -16,5 +16,13 @@
 
 package android.security.keystore;
 
-/* @hide */
-parcelable KeychainSnapshot;
+import java.security.ProviderException;
+
+/**
+ * Indicates that an operation could not be performed because the requested security hardware
+ * is not available.
+ */
+public class StrongBoxUnavailableException extends ProviderException {
+
+}
+
diff --git a/keystore/java/android/security/keystore/WrappedKeyEntry.java b/keystore/java/android/security/keystore/WrappedKeyEntry.java
new file mode 100644
index 0000000..a8f4afe
--- /dev/null
+++ b/keystore/java/android/security/keystore/WrappedKeyEntry.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package android.security.keystore;
+
+import java.security.KeyStore.Entry;
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * An {@link Entry} that holds a wrapped key.
+ */
+public class WrappedKeyEntry implements Entry {
+
+    private final byte[] mWrappedKeyBytes;
+    private final String mWrappingKeyAlias;
+    private final String mTransformation;
+    private final AlgorithmParameterSpec mAlgorithmParameterSpec;
+
+    public WrappedKeyEntry(byte[] wrappedKeyBytes, String wrappingKeyAlias, String transformation,
+            AlgorithmParameterSpec algorithmParameterSpec) {
+        mWrappedKeyBytes = wrappedKeyBytes;
+        mWrappingKeyAlias = wrappingKeyAlias;
+        mTransformation = transformation;
+        mAlgorithmParameterSpec = algorithmParameterSpec;
+    }
+
+    public byte[] getWrappedKeyBytes() {
+        return mWrappedKeyBytes;
+    }
+
+    public String getWrappingKeyAlias() {
+        return mWrappingKeyAlias;
+    }
+
+    public String getTransformation() {
+        return mTransformation;
+    }
+
+    public AlgorithmParameterSpec getAlgorithmParameterSpec() {
+        return mAlgorithmParameterSpec;
+    }
+}
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 0990dcc..018db9a 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -89,6 +89,10 @@
     ProviderProperties getProviderProperties(String provider);
     String getNetworkProviderPackage();
     boolean isProviderEnabled(String provider);
+    boolean isProviderEnabledForUser(String provider, int userId);
+    boolean setProviderEnabledForUser(String provider, boolean enabled, int userId);
+    boolean isLocationEnabledForUser(int userId);
+    void setLocationEnabledForUser(boolean enabled, int userId);
 
     void addTestProvider(String name, in ProviderProperties properties, String opPackageName);
     void removeTestProvider(String provider, String opPackageName);
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index f0b2774..9db9d33 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -16,7 +16,10 @@
 
 package android.location;
 
-import com.android.internal.location.ProviderProperties;
+import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
+import static android.Manifest.permission.ACCESS_FINE_LOCATION;
+import static android.Manifest.permission.LOCATION_HARDWARE;
+import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
 
 import android.Manifest;
 import android.annotation.NonNull;
@@ -24,7 +27,6 @@
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
-import android.annotation.TestApi;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
@@ -33,17 +35,15 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.os.Process;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.util.Log;
-
+import com.android.internal.location.ProviderProperties;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 
-import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
-import static android.Manifest.permission.ACCESS_FINE_LOCATION;
-import static android.Manifest.permission.LOCATION_HARDWARE;
-
 /**
  * This class provides access to the system location services.  These
  * services allow applications to obtain periodic updates of the
@@ -1171,13 +1171,57 @@
     }
 
     /**
+     * Returns the current enabled/disabled status of location
+     *
+     * @return true if location is enabled. false if location is disabled.
+     */
+    public boolean isLocationEnabled() {
+        return isLocationEnabledForUser(Process.myUserHandle());
+    }
+
+    /**
+     * Method for enabling or disabling location.
+     *
+     * @param enabled true to enable location. false to disable location
+     * @param userHandle the user to set
+     * @return true if the value was set, false on database errors
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(WRITE_SECURE_SETTINGS)
+    public void setLocationEnabledForUser(boolean enabled, UserHandle userHandle) {
+        try {
+            mService.setLocationEnabledForUser(enabled, userHandle.getIdentifier());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns the current enabled/disabled status of location
+     *
+     * @param userHandle the user to query
+     * @return true location is enabled. false if location is disabled.
+     *
+     * @hide
+     */
+    @SystemApi
+    public boolean isLocationEnabledForUser(UserHandle userHandle) {
+        try {
+            return mService.isLocationEnabledForUser(userHandle.getIdentifier());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Returns the current enabled/disabled status of the given provider.
      *
      * <p>If the user has enabled this provider in the Settings menu, true
      * is returned otherwise false is returned
      *
-     * <p>Callers should instead use
-     * {@link android.provider.Settings.Secure#LOCATION_MODE}
+     * <p>Callers should instead use {@link #isLocationEnabled()}
      * unless they depend on provider-specific APIs such as
      * {@link #requestLocationUpdates(String, long, float, LocationListener)}.
      *
@@ -1202,6 +1246,64 @@
     }
 
     /**
+     * Returns the current enabled/disabled status of the given provider and user.
+     *
+     * <p>If the user has enabled this provider in the Settings menu, true
+     * is returned otherwise false is returned
+     *
+     * <p>Callers should instead use {@link #isLocationEnabled()}
+     * unless they depend on provider-specific APIs such as
+     * {@link #requestLocationUpdates(String, long, float, LocationListener)}.
+     *
+     * <p>
+     * Before API version {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this
+     * method would throw {@link SecurityException} if the location permissions
+     * were not sufficient to use the specified provider.
+     *
+     * @param provider the name of the provider
+     * @param userHandle the user to query
+     * @return true if the provider exists and is enabled
+     *
+     * @throws IllegalArgumentException if provider is null
+     * @hide
+     */
+    @SystemApi
+    public boolean isProviderEnabledForUser(String provider, UserHandle userHandle) {
+        checkProvider(provider);
+
+        try {
+            return mService.isProviderEnabledForUser(provider, userHandle.getIdentifier());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Method for enabling or disabling a single location provider.
+     *
+     * @param provider the name of the provider
+     * @param enabled true to enable the provider. false to disable the provider
+     * @param userHandle the user to set
+     * @return true if the value was set, false on database errors
+     *
+     * @throws IllegalArgumentException if provider is null
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(WRITE_SECURE_SETTINGS)
+    public boolean setProviderEnabledForUser(
+            String provider, boolean enabled, UserHandle userHandle) {
+        checkProvider(provider);
+
+        try {
+            return mService.setProviderEnabledForUser(
+                    provider, enabled, userHandle.getIdentifier());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Get the last known location.
      *
      * <p>This location could be very old so use
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index d7861e3..44a2ff9 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -880,7 +880,9 @@
     }
 
     /** @hide */
-    public void toProto(ProtoOutputStream proto) {
+    public void writeToProto(ProtoOutputStream proto, long fieldId) {
+        final long token = proto.start(fieldId);
+
         proto.write(AudioAttributesProto.USAGE, mUsage);
         proto.write(AudioAttributesProto.CONTENT_TYPE, mContentType);
         proto.write(AudioAttributesProto.FLAGS, mFlags);
@@ -892,6 +894,8 @@
             }
         }
         // TODO: is the data in mBundle useful for debugging?
+
+        proto.end(token);
     }
 
     /** @hide */
diff --git a/media/java/android/media/IMediaSession2.aidl b/media/java/android/media/IMediaSession2.aidl
index bc8121e..078b611 100644
--- a/media/java/android/media/IMediaSession2.aidl
+++ b/media/java/android/media/IMediaSession2.aidl
@@ -47,6 +47,11 @@
     PlaybackState getPlaybackState();
 
     //////////////////////////////////////////////////////////////////////////////////////////////
+    // Get library service specific
+    //////////////////////////////////////////////////////////////////////////////////////////////
+    oneway void getBrowserRoot(IMediaSession2Callback callback, in Bundle rootHints);
+
+    //////////////////////////////////////////////////////////////////////////////////////////////
     // Callbacks -- remove them
     //////////////////////////////////////////////////////////////////////////////////////////////
     /**
diff --git a/media/java/android/media/IMediaSession2Callback.aidl b/media/java/android/media/IMediaSession2Callback.aidl
index 0058e79..a63b6bf 100644
--- a/media/java/android/media/IMediaSession2Callback.aidl
+++ b/media/java/android/media/IMediaSession2Callback.aidl
@@ -44,4 +44,9 @@
     //               Follow-up TODO: Add similar functions to the session.
     // TODO(jaewan): Is term 'accepted/rejected' correct? For permission, 'grant' is used.
     void onConnectionChanged(IMediaSession2 sessionBinder, in Bundle commandGroup);
+
+    //////////////////////////////////////////////////////////////////////////////////////////////
+    // Browser sepcific
+    //////////////////////////////////////////////////////////////////////////////////////////////
+    void onGetRootResult(in Bundle rootHints, String rootMediaId, in Bundle rootExtra);
 }
diff --git a/media/java/android/media/MediaBrowser2.java b/media/java/android/media/MediaBrowser2.java
new file mode 100644
index 0000000..fa00902
--- /dev/null
+++ b/media/java/android/media/MediaBrowser2.java
@@ -0,0 +1,69 @@
+/*
+ * 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.media;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.media.update.ApiLoader;
+import android.media.update.MediaBrowser2Provider;
+import android.os.Bundle;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Browses media content offered by a {@link MediaLibraryService2}.
+ * @hide
+ */
+public class MediaBrowser2 extends MediaController2 {
+    // Equals to the ((MediaBrowser2Provider) getProvider())
+    private final MediaBrowser2Provider mProvider;
+
+    /**
+     * Callback to listen events from {@link MediaLibraryService2}.
+     */
+    public abstract static class BrowserCallback extends MediaController2.ControllerCallback {
+        /**
+         * Called with the result of {@link #getBrowserRoot(Bundle)}.
+         * <p>
+         * {@code rootMediaId} and {@code rootExtra} can be {@code null} if the browser root isn't
+         * available.
+         *
+         * @param rootHints rootHints that you previously requested.
+         * @param rootMediaId media id of the browser root. Can be {@code null}
+         * @param rootExtra extra of the browser root. Can be {@code null}
+         */
+        public abstract void onGetRootResult(Bundle rootHints, @Nullable String rootMediaId,
+                @Nullable Bundle rootExtra);
+    }
+
+    public MediaBrowser2(Context context, SessionToken token, BrowserCallback callback,
+            Executor executor) {
+        super(context, token, callback, executor);
+        mProvider = (MediaBrowser2Provider) getProvider();
+    }
+
+    @Override
+    MediaBrowser2Provider createProvider(Context context, SessionToken token,
+            ControllerCallback callback, Executor executor) {
+        return ApiLoader.getProvider(context)
+                .createMediaBrowser2(this, context, token, (BrowserCallback) callback, executor);
+    }
+
+    public void getBrowserRoot(Bundle rootHints) {
+        mProvider.getBrowserRoot_impl(rootHints);
+    }
+}
diff --git a/media/java/android/media/MediaController2.java b/media/java/android/media/MediaController2.java
index 550eee2..9112450 100644
--- a/media/java/android/media/MediaController2.java
+++ b/media/java/android/media/MediaController2.java
@@ -104,7 +104,13 @@
         // session whose session binder is only valid while it's active.
         // prevent a controller from reusable after the
         // session is released and recreated.
-        mProvider = ApiLoader.getProvider(context)
+        mProvider = createProvider(context, token, callback, executor);
+    }
+
+    MediaController2Provider createProvider(@NonNull Context context,
+            @NonNull SessionToken token, @NonNull ControllerCallback callback,
+            @NonNull Executor executor) {
+        return ApiLoader.getProvider(context)
                 .createMediaController2(this, context, token, callback, executor);
     }
 
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index 6466149..063186d 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -26,6 +26,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.Parcel;
+import android.os.PersistableBundle;
 import android.util.Log;
 import dalvik.system.CloseGuard;
 import java.lang.annotation.Retention;
@@ -1218,7 +1219,6 @@
     public native void setPropertyByteArray(@NonNull @ArrayProperty
             String propertyName, @NonNull byte[] value);
 
-
     private static final native void setCipherAlgorithmNative(
             @NonNull MediaDrm drm, @NonNull byte[] sessionId, @NonNull String algorithm);
 
@@ -1245,6 +1245,25 @@
             @NonNull byte[] keyId, @NonNull byte[] message, @NonNull byte[] signature);
 
     /**
+     * Return Metrics data about the current MediaDrm instance.
+     *
+     * @return a {@link PersistableBundle} containing the set of attributes and values
+     * available for this instance of MediaDrm.
+     * The attributes are described in {@link MetricsConstants}.
+     *
+     * Additional vendor-specific fields may also be present in
+     * the return value.
+     *
+     * @hide - not part of the public API at this time
+     */
+    public PersistableBundle getMetrics() {
+        PersistableBundle bundle = getMetricsNative();
+        return bundle;
+    }
+
+    private native PersistableBundle getMetricsNative();
+
+    /**
      * In addition to supporting decryption of DASH Common Encrypted Media, the
      * MediaDrm APIs provide the ability to securely deliver session keys from
      * an operator's session key server to a client device, based on the factory-installed
@@ -1548,4 +1567,31 @@
         System.loadLibrary("media_jni");
         native_init();
     }
+
+    /**
+     * Definitions for the metrics that are reported via the
+     * {@link #getMetrics} call.
+     *
+     * @hide - not part of the public API at this time
+     */
+    public final static class MetricsConstants
+    {
+        private MetricsConstants() {}
+
+        /**
+         * Key to extract the number of successful {@link #openSession} calls
+         * from the {@link PersistableBundle} returned by a
+         * {@link #getMetrics} call.
+         */
+        public static final String OPEN_SESSION_OK_COUNT
+            = "/drm/mediadrm/open_session/ok/count";
+
+        /**
+         * Key to extract the number of failed {@link #openSession} calls
+         * from the {@link PersistableBundle} returned by a
+         * {@link #getMetrics} call.
+         */
+        public static final String OPEN_SESSION_ERROR_COUNT
+            = "/drm/mediadrm/open_session/error/count";
+    }
 }
diff --git a/media/java/android/media/MediaLibraryService2.java b/media/java/android/media/MediaLibraryService2.java
new file mode 100644
index 0000000..bbc9407
--- /dev/null
+++ b/media/java/android/media/MediaLibraryService2.java
@@ -0,0 +1,144 @@
+/*
+ * 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.media;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.media.MediaSession2.BuilderBase;
+import android.media.MediaSession2.ControllerInfo;
+import android.media.update.ApiLoader;
+import android.media.update.MediaSessionService2Provider;
+import android.os.Bundle;
+import android.service.media.MediaBrowserService.BrowserRoot;
+
+/**
+ * Base class for media library services.
+ * <p>
+ * Media library services enable applications to browse media content provided by an application
+ * and ask the application to start playing it. They may also be used to control content that
+ * is already playing by way of a {@link MediaSession2}.
+ * <p>
+ * To extend this class, adding followings directly to your {@code AndroidManifest.xml}.
+ * <pre>
+ * &lt;service android:name="component_name_of_your_implementation" &gt;
+ *   &lt;intent-filter&gt;
+ *     &lt;action android:name="android.media.MediaLibraryService2" /&gt;
+ *   &lt;/intent-filter&gt;
+ * &lt;/service&gt;</pre>
+ * <p>
+ * A {@link MediaLibraryService2} is extension of {@link MediaSessionService2}. IDs shouldn't
+ * be shared between the {@link MediaSessionService2} and {@link MediaSession2}. By
+ * default, an empty string will be used for ID of the service. If you want to specify an ID,
+ * declare metadata in the manifest as follows.
+ * @hide
+ */
+// TODO(jaewan): Unhide
+public abstract class MediaLibraryService2 extends MediaSessionService2 {
+    /**
+     * This is the interface name that a service implementing a session service should say that it
+     * support -- that is, this is the action it uses for its intent filter.
+     */
+    public static final String SERVICE_INTERFACE = "android.media.MediaLibraryService2";
+
+    /**
+     * Session for the media library service.
+     */
+    public class MediaLibrarySession extends MediaSession2 {
+        MediaLibrarySession(Context context, MediaPlayerBase player, String id,
+                SessionCallback callback) {
+            super(context, player, id, callback);
+        }
+        // TODO(jaewan): Place public methods here.
+    }
+
+    public static abstract class MediaLibrarySessionCallback extends MediaSession2.SessionCallback {
+        /**
+         * Called to get the root information for browsing by a particular client.
+         * <p>
+         * The implementation should verify that the client package has permission
+         * to access browse media information before returning the root id; it
+         * should return null if the client is not allowed to access this
+         * information.
+         *
+         * @param controllerInfo information of the controller requesting access to browse media.
+         * @param rootHints An optional bundle of service-specific arguments to send
+         * to the media browser service when connecting and retrieving the
+         * root id for browsing, or null if none. The contents of this
+         * bundle may affect the information returned when browsing.
+         * @return The {@link BrowserRoot} for accessing this app's content or null.
+         * @see BrowserRoot#EXTRA_RECENT
+         * @see BrowserRoot#EXTRA_OFFLINE
+         * @see BrowserRoot#EXTRA_SUGGESTED
+         */
+        public abstract @Nullable BrowserRoot onGetRoot(
+                @NonNull ControllerInfo controllerInfo, @Nullable Bundle rootHints);
+    }
+
+    /**
+     * Builder for {@link MediaLibrarySession}.
+     */
+    // TODO(jaewan): Move this to updatable.
+    public class MediaLibrarySessionBuilder
+            extends BuilderBase<MediaLibrarySessionBuilder, MediaLibrarySessionCallback> {
+        public MediaLibrarySessionBuilder(
+                @NonNull Context context, @NonNull MediaPlayerBase player,
+                @NonNull MediaLibrarySessionCallback callback) {
+            super(context, player);
+            setSessionCallback(callback);
+        }
+
+        @Override
+        public MediaLibrarySessionBuilder setSessionCallback(
+                @NonNull MediaLibrarySessionCallback callback) {
+            if (callback == null) {
+                throw new IllegalArgumentException("MediaLibrarySessionCallback cannot be null");
+            }
+            return super.setSessionCallback(callback);
+        }
+
+        @Override
+        public MediaLibrarySession build() throws IllegalStateException {
+            return new MediaLibrarySession(mContext, mPlayer, mId, mCallback);
+        }
+    }
+
+    @Override
+    MediaSessionService2Provider createProvider() {
+        return ApiLoader.getProvider(this).createMediaLibraryService2(this);
+    }
+
+    /**
+     * Called when another app requested to start this service.
+     * <p>
+     * Library service will accept or reject the connection with the
+     * {@link MediaLibrarySessionCallback} in the created session.
+     * <p>
+     * Service wouldn't run if {@code null} is returned or session's ID doesn't match with the
+     * expected ID that you've specified through the AndroidManifest.xml.
+     * <p>
+     * This method will be called on the main thread.
+     *
+     * @param sessionId session id written in the AndroidManifest.xml.
+     * @return a new browser session
+     * @see MediaLibrarySessionBuilder
+     * @see #getSession()
+     * @throws RuntimeException if returned session is invalid
+     */
+    @Override
+    public @NonNull abstract MediaLibrarySession onCreateSession(String sessionId);
+}
diff --git a/media/java/android/media/MediaSession2.java b/media/java/android/media/MediaSession2.java
index 807535b..33a5807 100644
--- a/media/java/android/media/MediaSession2.java
+++ b/media/java/android/media/MediaSession2.java
@@ -16,7 +16,6 @@
 
 package android.media;
 
-import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
@@ -29,12 +28,9 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Parcelable;
-import android.os.Process;
 import android.text.TextUtils;
 import android.util.ArraySet;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -55,20 +51,17 @@
  * instead. With it, your playback can be revived even after you've finished playback. See
  * {@link MediaSessionService2} for details.
  * <p>
- * A session can be obtained by {@link #getInstance(Context, Handler)}. The owner of the session may
- * pass its session token to other processes to allow them to create a {@link MediaController2}
- * to interact with the session.
+ * A session can be obtained by {@link Builder}. The owner of the session may pass its session token
+ * to other processes to allow them to create a {@link MediaController2} to interact with the
+ * session.
  * <p>
- * To receive transport control commands, an underlying media player must be set with
- * {@link #setPlayer(MediaPlayerBase)}. Commands will be sent to the underlying player directly
- * on the thread that had been specified by {@link #getInstance(Context, Handler)}.
+ * When a session receive transport control commands, the session sends the commands directly to
+ * the the underlying media player set by {@link Builder} or {@link #setPlayer(MediaPlayerBase)}.
  * <p>
- * When an app is finished performing playback it must call
- * {@link #setPlayer(MediaPlayerBase)} with {@code null} to clean up the session and notify any
- * controllers. It's developers responsibility of cleaning the session and releasing resources.
+ * When an app is finished performing playback it must call {@link #close()} to clean up the session
+ * and notify any controllers.
  * <p>
- * MediaSession2 objects should be used on the handler's thread that is initially given by
- * {@link #getInstance(Context, Handler)}.
+ * {@link MediaSession2} objects should be used on the thread on the looper.
  *
  * @see MediaSessionService2
  * @hide
@@ -81,7 +74,7 @@
 // TODO(jaewan): Should we make APIs for MediaSessionService2 public? It's helpful for
 //               developers that doesn't want to override from Browser, but user may not use this
 //               correctly.
-public final class MediaSession2 extends MediaPlayerBase {
+public class MediaSession2 extends MediaPlayerBase {
     private final MediaSession2Provider mProvider;
 
     // Note: Do not define IntDef because subclass can add more command code on top of these.
@@ -321,19 +314,16 @@
     };
 
     /**
-     * Builder for {@link MediaSession2}.
-     * <p>
-     * Any incoming event from the {@link MediaController2} will be handled on the thread
-     * that created session with the {@link Builder#build()}.
+     * Base builder class for MediaSession2 and its subclass.
+     *
+     * @hide
      */
-    // TODO(jaewan): Move this to updatable
-    // TODO(jaewan): Add setRatingType()
-    // TODO(jaewan): Add setSessionActivity()
-    public final static class Builder {
-        private final Context mContext;
-        private final MediaPlayerBase mPlayer;
-        private String mId;
-        private SessionCallback mCallback;
+    static abstract class BuilderBase
+            <T extends MediaSession2.BuilderBase<T, C>, C extends SessionCallback> {
+        final Context mContext;
+        final MediaPlayerBase mPlayer;
+        String mId;
+        C mCallback;
 
         /**
          * Constructor.
@@ -343,7 +333,8 @@
          * @throws IllegalArgumentException if any parameter is null, or the player is a
          *      {@link MediaSession2} or {@link MediaController2}.
          */
-        public Builder(@NonNull Context context, @NonNull MediaPlayerBase player) {
+        // TODO(jaewan): Also need executor
+        public BuilderBase(@NonNull Context context, @NonNull MediaPlayerBase player) {
             if (context == null) {
                 throw new IllegalArgumentException("context shouldn't be null");
             }
@@ -370,12 +361,12 @@
          * @throws IllegalArgumentException if id is {@code null}
          * @return
          */
-        public Builder setId(@NonNull String id) {
+        public T setId(@NonNull String id) {
             if (id == null) {
                 throw new IllegalArgumentException("id shouldn't be null");
             }
             mId = id;
-            return this;
+            return (T) this;
         }
 
         /**
@@ -384,9 +375,9 @@
          * @param callback session callback.
          * @return
          */
-        public Builder setSessionCallback(@Nullable SessionCallback callback) {
+        public T setSessionCallback(@Nullable C callback) {
             mCallback = callback;
-            return this;
+            return (T) this;
         }
 
         /**
@@ -396,6 +387,24 @@
          * @throws IllegalStateException if the session with the same id is already exists for the
          *      package.
          */
+        public abstract MediaSession2 build() throws IllegalStateException;
+    }
+
+    /**
+     * Builder for {@link MediaSession2}.
+     * <p>
+     * Any incoming event from the {@link MediaController2} will be handled on the thread
+     * that created session with the {@link Builder#build()}.
+     */
+    // TODO(jaewan): Move this to updatable
+    // TODO(jaewan): Add setRatingType()
+    // TODO(jaewan): Add setSessionActivity()
+    public static final class Builder extends BuilderBase<Builder, SessionCallback> {
+        public Builder(Context context, @NonNull MediaPlayerBase player) {
+            super(context, player);
+        }
+
+        @Override
         public MediaSession2 build() throws IllegalStateException {
             if (mCallback == null) {
                 mCallback = new SessionCallback();
@@ -492,7 +501,7 @@
      *       framework had to add heuristics to figure out if an app is
      * @hide
      */
-    private MediaSession2(Context context, MediaPlayerBase player, String id,
+    MediaSession2(Context context, MediaPlayerBase player, String id,
             SessionCallback callback) {
         super();
         mProvider = ApiLoader.getProvider(context)
diff --git a/media/java/android/media/MediaSessionService2.java b/media/java/android/media/MediaSessionService2.java
index f1f5467..1a12d68 100644
--- a/media/java/android/media/MediaSessionService2.java
+++ b/media/java/android/media/MediaSessionService2.java
@@ -29,7 +29,7 @@
 import android.os.IBinder;
 
 /**
- * Service version of the {@link MediaSession2}.
+ * Base class for media session services, which is the service version of the {@link MediaSession2}.
  * <p>
  * It's highly recommended for an app to use this instead of {@link MediaSession2} if it wants
  * to keep media playback in the background.
@@ -43,11 +43,11 @@
  * </ul>
  * For example, user's voice command can start playback of your app even when it's not running.
  * <p>
- * To use this class, adding followings directly to your {@code AndroidManifest.xml}.
+ * To extend this class, adding followings directly to your {@code AndroidManifest.xml}.
  * <pre>
  * &lt;service android:name="component_name_of_your_implementation" &gt;
  *   &lt;intent-filter&gt;
- *     &lt;action android:name="android.media.session.MediaSessionService2" /&gt;
+ *     &lt;action android:name="android.media.MediaSessionService2" /&gt;
  *   &lt;/intent-filter&gt;
  * &lt;/service&gt;</pre>
  * <p>
@@ -58,7 +58,7 @@
  * <pre>
  * &lt;service android:name="component_name_of_your_implementation" &gt;
  *   &lt;intent-filter&gt;
- *     &lt;action android:name="android.media.session.MediaSessionService2" /&gt;
+ *     &lt;action android:name="android.media.MediaSessionService2" /&gt;
  *   &lt;/intent-filter&gt;
  *   &lt;meta-data android:name="android.media.session"
  *       android:value="session_id"/&gt;
@@ -120,8 +120,7 @@
      * This is the interface name that a service implementing a session service should say that it
      * support -- that is, this is the action it uses for its intent filter.
      */
-    public static final String SERVICE_INTERFACE =
-            "android.media.session.MediaSessionService2";
+    public static final String SERVICE_INTERFACE = "android.media.MediaSessionService2";
 
     /**
      * Name under which a MediaSessionService2 component publishes information about itself.
@@ -129,21 +128,13 @@
      */
     public static final String SERVICE_META_DATA = "android.media.session";
 
-    /**
-     * Default notification channel ID used by {@link #onUpdateNotification(PlaybackState)}.
-     *
-     */
-    public static final String DEFAULT_MEDIA_NOTIFICATION_CHANNEL_ID = "media_session_service";
-
-    /**
-     * Default notification channel ID used by {@link #onUpdateNotification(PlaybackState)}.
-     *
-     */
-    public static final int DEFAULT_MEDIA_NOTIFICATION_ID = 1001;
-
     public MediaSessionService2() {
         super();
-        mProvider = ApiLoader.getProvider(this).createMediaSessionService2(this);
+        mProvider = createProvider();
+    }
+
+    MediaSessionService2Provider createProvider() {
+        return ApiLoader.getProvider(this).createMediaSessionService2(this);
     }
 
     /**
@@ -168,32 +159,24 @@
      * Service wouldn't run if {@code null} is returned or session's ID doesn't match with the
      * expected ID that you've specified through the AndroidManifest.xml.
      * <p>
-     * This method will be call on the main thread.
+     * This method will be called on the main thread.
      *
      * @param sessionId session id written in the AndroidManifest.xml.
      * @return a new session
      * @see MediaSession2.Builder
      * @see #getSession()
      */
-    // TODO(jaewan): Replace this with onCreateSession(). Its sesssion callback will replace
-    //               this abstract method.
-    // TODO(jaewan): Should we also include/documents notification listener access?
-    // TODO(jaewan): Is term accepted/rejected correct? For permission, granted is more common.
-    // TODO(jaewan): Return ConnectResult() that encapsulate supported action and player.
     public @NonNull abstract MediaSession2 onCreateSession(String sessionId);
 
     /**
      * Called when the playback state of this session is changed, and notification needs update.
-     * <p>
-     * Default media style notification will be shown if you don't override this or return
-     * {@code null}. Override this method to show your own notification UI.
+     * Override this method to show your own notification UI.
      * <p>
      * With the notification returned here, the service become foreground service when the playback
      * is started. It becomes background service after the playback is stopped.
      *
      * @param state playback state
-     * @return a {@link MediaNotification}. If it's {@code null}, default notification will be shown
-     *     instead.
+     * @return a {@link MediaNotification}. If it's {@code null}, notification wouldn't be shown.
      */
     // TODO(jaewan): Also add metadata
     public MediaNotification onUpdateNotification(PlaybackState state) {
diff --git a/media/java/android/media/SessionToken.java b/media/java/android/media/SessionToken.java
index b470dea..53fc24a 100644
--- a/media/java/android/media/SessionToken.java
+++ b/media/java/android/media/SessionToken.java
@@ -42,12 +42,13 @@
 // TODO(jaewan): Find better name for this (SessionToken or Session2Token)
 public final class SessionToken {
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef(value = {TYPE_SESSION, TYPE_SESSION_SERVICE})
+    @IntDef(value = {TYPE_SESSION, TYPE_SESSION_SERVICE, TYPE_LIBRARY_SERVICE})
     public @interface TokenType {
     }
 
     public static final int TYPE_SESSION = 0;
     public static final int TYPE_SESSION_SERVICE = 1;
+    public static final int TYPE_LIBRARY_SERVICE = 2;
 
     private static final String KEY_TYPE = "android.media.token.type";
     private static final String KEY_PACKAGE_NAME = "android.media.token.package_name";
@@ -73,6 +74,7 @@
      * @hide
      */
     // TODO(jaewan): UID is also needed.
+    // TODO(jaewan): Unhide
     public SessionToken(@TokenType int type, @NonNull String packageName, @NonNull String id,
             @Nullable String serviceName, @Nullable IMediaSession2 sessionBinder) {
         // TODO(jaewan): Add sanity check.
diff --git a/core/java/android/security/keystore/KeychainSnapshot.aidl b/media/java/android/media/update/MediaBrowser2Provider.java
similarity index 68%
copy from core/java/android/security/keystore/KeychainSnapshot.aidl
copy to media/java/android/media/update/MediaBrowser2Provider.java
index b35713f..355dbc9 100644
--- a/core/java/android/security/keystore/KeychainSnapshot.aidl
+++ b/media/java/android/media/update/MediaBrowser2Provider.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -14,7 +14,13 @@
  * limitations under the License.
  */
 
-package android.security.keystore;
+package android.media.update;
 
-/* @hide */
-parcelable KeychainSnapshot;
+import android.os.Bundle;
+
+/**
+ * @hide
+ */
+public interface MediaBrowser2Provider extends MediaController2Provider {
+    void getBrowserRoot_impl(Bundle rootHints);
+}
diff --git a/media/java/android/media/update/MediaControlView2Provider.java b/media/java/android/media/update/MediaControlView2Provider.java
index 83763b4..b3719c8 100644
--- a/media/java/android/media/update/MediaControlView2Provider.java
+++ b/media/java/android/media/update/MediaControlView2Provider.java
@@ -40,7 +40,6 @@
     void show_impl(int timeout);
     boolean isShowing_impl();
     void hide_impl();
-    void showCCButton_impl();
     boolean isPlaying_impl();
     int getCurrentPosition_impl();
     int getBufferPercentage_impl();
diff --git a/core/java/android/security/keystore/KeychainSnapshot.aidl b/media/java/android/media/update/MediaLibraryService2Provider.java
similarity index 72%
copy from core/java/android/security/keystore/KeychainSnapshot.aidl
copy to media/java/android/media/update/MediaLibraryService2Provider.java
index b35713f..7e3444f 100644
--- a/core/java/android/security/keystore/KeychainSnapshot.aidl
+++ b/media/java/android/media/update/MediaLibraryService2Provider.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -14,7 +14,11 @@
  * limitations under the License.
  */
 
-package android.security.keystore;
+package android.media.update;
 
-/* @hide */
-parcelable KeychainSnapshot;
+/**
+ * @hide
+ */
+public interface MediaLibraryService2Provider extends MediaSessionService2Provider {
+    // Nothing new for now
+}
diff --git a/media/java/android/media/update/StaticProvider.java b/media/java/android/media/update/StaticProvider.java
index 91c9c66..fef2cbb 100644
--- a/media/java/android/media/update/StaticProvider.java
+++ b/media/java/android/media/update/StaticProvider.java
@@ -19,7 +19,11 @@
 import android.annotation.Nullable;
 import android.content.Context;
 import android.media.IMediaSession2Callback;
+import android.media.MediaBrowser2;
+import android.media.MediaBrowser2.BrowserCallback;
 import android.media.MediaController2;
+import android.media.MediaController2.ControllerCallback;
+import android.media.MediaLibraryService2;
 import android.media.MediaPlayerBase;
 import android.media.MediaSession2;
 import android.media.MediaSessionService2;
@@ -53,7 +57,12 @@
             String packageName, IMediaSession2Callback callback);
     MediaController2Provider createMediaController2(
             MediaController2 instance, Context context, SessionToken token,
-            MediaController2.ControllerCallback callback, Executor executor);
+            ControllerCallback callback, Executor executor);
+    MediaBrowser2Provider createMediaBrowser2(
+            MediaBrowser2 instance, Context context, SessionToken token,
+            BrowserCallback callback, Executor executor);
     MediaSessionService2Provider createMediaSessionService2(
             MediaSessionService2 instance);
+    MediaSessionService2Provider createMediaLibraryService2(
+            MediaLibraryService2 instance);
 }
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index dca469f..95b07f1 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -19,6 +19,7 @@
 #include <utils/Log.h>
 
 #include "android_media_MediaDrm.h"
+#include "android_media_MediaMetricsJNI.h"
 
 #include "android_runtime/AndroidRuntime.h"
 #include "android_runtime/Log.h"
@@ -1618,6 +1619,31 @@
     return match;
 }
 
+static jobject
+android_media_MediaDrm_native_getMetrics(JNIEnv *env, jobject thiz)
+{
+    sp<IDrm> drm = GetDrm(env, thiz);
+    if (drm == NULL ) {
+        jniThrowException(env, "java/lang/IllegalStateException",
+                          "MediaDrm obj is null");
+        return NULL;
+    }
+
+    // Retrieve current metrics snapshot from drm.
+    MediaAnalyticsItem item ;
+    status_t err = drm->getMetrics(&item);
+    if (err != OK) {
+        ALOGE("getMetrics failed: %d", (int)err);
+        return (jobject) NULL;
+    }
+
+    jobject mybundle = MediaMetricsJNI::writeMetricsToBundle(env, &item, NULL);
+    if (mybundle == NULL) {
+        ALOGE("getMetrics metric conversion failed");
+    }
+
+    return mybundle;
+}
 
 static jbyteArray android_media_MediaDrm_signRSANative(
     JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
@@ -1754,6 +1780,9 @@
 
     { "signRSANative", "(Landroid/media/MediaDrm;[BLjava/lang/String;[B[B)[B",
       (void *)android_media_MediaDrm_signRSANative },
+
+    { "getMetricsNative", "()Landroid/os/PersistableBundle;",
+      (void *)android_media_MediaDrm_native_getMetrics },
 };
 
 int register_android_media_Drm(JNIEnv *env) {
diff --git a/packages/SettingsLib/res/drawable/btn_borderless_rect.xml b/packages/SettingsLib/res/drawable/btn_borderless_rect.xml
new file mode 100644
index 0000000..9eaba83
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/btn_borderless_rect.xml
@@ -0,0 +1,31 @@
+<!--
+     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.
+-->
+<inset
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:insetTop="4dp"
+    android:insetBottom="4dp">
+    <ripple
+        android:color="?android:attr/colorControlHighlight" >
+
+        <item android:id="@android:id/mask">
+            <shape>
+                <corners android:radius="2dp" />
+                <solid android:color="@android:color/white" />
+            </shape>
+        </item>
+
+    </ripple>
+</inset>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/drawable/ic_minus.xml b/packages/SettingsLib/res/drawable/ic_minus.xml
new file mode 100644
index 0000000..9a929a4
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_minus.xml
@@ -0,0 +1,24 @@
+<!--
+     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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="24.0dp"
+        android:viewportHeight="24.0"
+        android:viewportWidth="24.0"
+        android:width="24.0dp" >
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M18,13H6c-0.55,0 -1,-0.45 -1,-1v0c0,-0.55 0.45,-1 1,-1h12c0.55,0 1,0.45 1,1v0C19,12.55 18.55,13 18,13z"/>
+</vector>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/drawable/ic_plus.xml b/packages/SettingsLib/res/drawable/ic_plus.xml
new file mode 100644
index 0000000..2a10e70
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_plus.xml
@@ -0,0 +1,24 @@
+<!--
+     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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="24.0dp"
+        android:viewportHeight="24.0"
+        android:viewportWidth="24.0"
+        android:width="24.0dp" >
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M18,13h-5v5c0,0.55 -0.45,1 -1,1h0c-0.55,0 -1,-0.45 -1,-1v-5H6c-0.55,0 -1,-0.45 -1,-1v0c0,-0.55 0.45,-1 1,-1h5V6c0,-0.55 0.45,-1 1,-1h0c0.55,0 1,0.45 1,1v5h5c0.55,0 1,0.45 1,1v0C19,12.55 18.55,13 18,13z"/>
+</vector>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/layout/zen_mode_condition.xml b/packages/SettingsLib/res/layout/zen_mode_condition.xml
new file mode 100644
index 0000000..c85a892
--- /dev/null
+++ b/packages/SettingsLib/res/layout/zen_mode_condition.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:clipChildren="false"
+                android:layout_marginStart="1dp"
+                android:layout_marginEnd="0dp"
+                android:layout_weight="1"
+                android:gravity="center_vertical" >
+
+    <LinearLayout
+        android:id="@android:id/content"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:minHeight="48dp"
+        android:gravity="center_vertical"
+        android:layout_centerVertical="true"
+        android:orientation="vertical"
+        android:layout_toEndOf="@android:id/checkbox"
+        android:layout_toStartOf="@android:id/button1">
+
+        <TextView
+            android:id="@android:id/text1"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:ellipsize="end"
+            android:textAlignment="viewStart"
+            android:maxLines="1"
+            android:textColor="?android:attr/textColorPrimary"
+            android:textSize="16sp"/>
+
+        <TextView
+            android:id="@android:id/text2"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="@dimen/zen_mode_condition_detail_item_interline_spacing"
+            android:ellipsize="end"
+            android:textAlignment="viewStart"
+            android:maxLines="1"
+            android:textColor="?android:attr/textColorSecondary"
+            android:textSize="14sp"/>
+
+    </LinearLayout>
+
+    <ImageView
+        android:id="@android:id/button1"
+        style="@style/BorderlessButton"
+        android:layout_width="48dp"
+        android:layout_height="48dp"
+        android:layout_centerVertical="true"
+        android:scaleType="center"
+        android:layout_toStartOf="@android:id/button2"
+        android:contentDescription="@string/accessibility_manual_zen_less_time"
+        android:tint="?android:attr/colorAccent"
+        android:src="@drawable/ic_minus" />
+
+    <ImageView
+        android:id="@android:id/button2"
+        style="@style/BorderlessButton"
+        android:layout_width="48dp"
+        android:layout_height="48dp"
+        android:layout_alignParentEnd="true"
+        android:scaleType="center"
+        android:layout_centerVertical="true"
+        android:contentDescription="@string/accessibility_manual_zen_more_time"
+        android:tint="?android:attr/colorAccent"
+        android:src="@drawable/ic_plus" />
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/layout/zen_mode_radio_button.xml b/packages/SettingsLib/res/layout/zen_mode_radio_button.xml
new file mode 100644
index 0000000..4c0faed
--- /dev/null
+++ b/packages/SettingsLib/res/layout/zen_mode_radio_button.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     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.
+-->
+<RadioButton
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/checkbox"
+    android:layout_width="40dp"
+    android:layout_marginStart="7dp"
+    android:layout_marginEnd="4dp"
+    android:layout_height="48dp"
+    android:layout_alignParentStart="true"
+    android:gravity="center"
+    android:paddingTop="10dp"
+    android:paddingBottom="10dp">
+
+</RadioButton>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/layout/zen_mode_turn_on_dialog_container.xml b/packages/SettingsLib/res/layout/zen_mode_turn_on_dialog_container.xml
new file mode 100644
index 0000000..ac56a2d
--- /dev/null
+++ b/packages/SettingsLib/res/layout/zen_mode_turn_on_dialog_container.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     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.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+            android:id="@+id/container"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:fillViewport ="true"
+            android:orientation="vertical">
+
+    <com.android.settingslib.notification.ZenRadioLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/zen_conditions"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="8dp"
+        android:layout_marginEnd="4dp"
+        android:layout_marginStart="4dp"
+        android:paddingBottom="4dp"
+        android:orientation="horizontal">
+        <RadioGroup
+            android:id="@+id/zen_radio_buttons"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
+        <LinearLayout
+            android:id="@+id/zen_radio_buttons_content"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:orientation="vertical"/>
+    </com.android.settingslib.notification.ZenRadioLayout>
+
+</ScrollView>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index ff81fc1..93c0e10 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Inligtingruiling"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Draadlose skermsertifisering"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Aktiveer Wi-Fi-woordryke aanmelding"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Aggressiewe Wi‑Fi-na-mobiel-oorhandiging"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Laat altyd Wi-Fi-swerfskanderings toe"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobiele data is altyd aktief"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardewareversnelling vir verbinding"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Voer gasheernaam van DNS-verskaffer in"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Wys opsies vir draadlose skermsertifisering"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Verhoog Wi-Fi-aantekeningvlak, wys per SSID RSSI in Wi‑Fi-kieser"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Wanneer dit geaktiveer is, sal Wi-Fi die dataverbinding aggressiewer na mobiel oordra wanneer die Wi-Fi-sein swak is"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Laat toe of verbied Wi-Fi-swerfskanderings op grond van die hoeveelheid dataverkeer wat op die koppelvlak teenwoordig is"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Loggerbuffer se groottes"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Kies loggergroottes per logbuffer"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 111b7cf..83fd2af 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"አውታረ መረብ"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"የገመድ አልባ ማሳያ እውቅና ማረጋገጫ"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"የWi‑Fi ተጨማሪ ቃላት ምዝግብ ማስታወሻ መያዝ"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"አስገዳጅ ከWi‑Fi ወደ ሞባይል ማቀበል"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ሁልጊዜ የWi‑Fi ማንቀሳቀስ ቅኝቶችን ይፍቀዱ"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"የተንቀሳቃሽ ስልክ ውሂብ ሁልጊዜ ገቢር ነው"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"የሃርድዌር ማቀላጠፊያን በማስተሳሰር ላይ"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"የዲኤንኤስ አቅራቢ አስተናጋጅ ስም ያስገቡ"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"የገመድ አልባ ማሳያ እውቅና ማረጋገጫ አማራጮችን አሳይ"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"የWi‑Fi ምዝግብ ማስታወሻ አያያዝ ደረጃ ጨምር፣ በWi‑Fi መምረጫ ውስጥ በአንድ SSID RSSI አሳይ"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"ሲነቃ የWi‑Fi ምልክት ዝቅተኛ ሲሆን Wi‑Fi የውሂብ ግንኙነት ለሞባይል ማስረከብ ላይ ይበልጥ አስገዳጅ ይሆናል"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"በበይነገጹ ላይ ባለው የውሂብ ትራፊክ መጠን ላይ ተመስርተው የWi‑Fi ማንቀሳቀስ ቅኝቶችን ይፍቀዱ/ይከልክሉ"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"የምዝግብ ማስታወሻ ያዥ መጠኖች"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"በአንድ ምዝግብ ማስታወሻ ቋጥ የሚኖረው የምዝግብ ማስታወሻ ያዥ መጠኖች ይምረጡ"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index b101a1d..a541cbd 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"الشبكات"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"شهادة عرض شاشة لاسلكي"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"‏تمكين تسجيل Wi‑Fi Verbose"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"‏تسليم Wi-Fi حاد إلى جوّال"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"‏السماح دائمًا بعمليات فحص Wi-Fi للتجوال"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"بيانات الجوّال نشطة دائمًا"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"تسريع الأجهزة للتوصيل"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"أدخل اسم مضيف مزوّد نظام أسماء النطاقات"</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>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"‏عند تمكينه، سيكون Wi-Fi أكثر حدة في تسليم اتصال البيانات إلى الجوّال، وذلك عندما تكون إشارة WiFi منخفضة"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"‏السماح/عدم السماح بعمليات فحص Wi-Fi للتجوال بناءً على حجم حركة البيانات في الواجهة"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"أحجام ذاكرة التخزين المؤقت للتسجيل"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"حدد أحجامًا أكبر لكل ذاكرة تخزين مؤقت للتسجيل"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 03c9b92..5b4e45c 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Şəbəkələşmə"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Simsiz displey sertifikatlaşması"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi Çoxsözlü Girişə icazə verin"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Möbül ötürücüyə aqressiv Wi‑Fi"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi axtarışlarına həmişə icazə verin"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobil data həmişə aktiv"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Birləşmə üçün avadanlıq akselerasiyası"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS provayderinin host adını daxil edin"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Simsiz displey sertifikatlaşması üçün seçimləri göstərir"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi giriş səviyyəsini qaldırın, Wi‑Fi seçəndə hər SSID RSSI üzrə göstərin"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Aktiv edildikdə, Wi-Fi siqnalı zəif olan zaman, data bağlantısını mobilə ötürərəkən Wi-Fi daha aqressiv olacaq"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Wi‑Fi Axtarışlarına data trafikinə əsasən İcazə verin/Qadağan edin"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Logger bufer ölçüləri"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Hər jurnal buferinı Logger ölçüsü seçin"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 62e4b4c..0545021 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Umrežavanje"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Sertifikacija bežičnog ekrana"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Omogući detaljniju evidenciju za Wi‑Fi"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agresivan prelaz sa Wi‑Fi mreže na mobilnu"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Uvek dozvoli skeniranje Wi‑Fi-ja u romingu"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilni podaci su uvek aktivni"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardversko ubrzanje privezivanja"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Unesite ime hosta dobavljača usluge DNS-a"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Prikaz opcija za sertifikaciju bežičnog ekrana"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Povećava nivo evidentiranja za Wi‑Fi. Prikaz po SSID RSSI-u u biraču Wi‑Fi mreže"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Kad se omogući, Wi‑Fi će biti agresivniji pri prebacivanju mreže za prenos podataka na mobilnu ako je Wi‑Fi signal slab"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Dozvoli/zabrani skeniranje Wi-Fi-ja u romingu na osnovu prisutnog protoka podataka na interfejsu"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Veličine bafera podataka u programu za evidentiranje"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Izaberite veličine po baferu evidencije"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index c648ea5..05be2228 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Сеткі"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Сертыфікацыя бесправаднога дысплея"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Уключыць падрабязны журнал Wi‑Fi"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Інтэнсіўны пераход з Wi‑Fi на маб. сетку"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Заўсёды дазваляць роўмінгавае сканіраванне Wi‑Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Мабільная перадача даных заўсёды актыўная"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Апаратнае паскарэнне ў рэжыме мадэма"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Увядзіце імя вузла аператара DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Паказаць опцыі сертыфікацыі бесправаднога дысплея"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Падвыс. узровень дэтал-цыі журнала Wi‑Fi у залежн. ад SSID RSSI у Wi‑Fi Picker"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Калі гэта функцыя ўключана, Wi-Fi будзе больш інтэнсіўна імкнуцца перайсці на падключ. маб. перад. даных пры слабым сігнале Wi‑Fi"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Дазволіць/забараніць роўмінгавае сканіраванне Wi‑Fi ў залежнасці ад аб\'ёму трафіку даных у інтэрфейсе"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Памеры буфера для сродку вядзення журнала"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Выберыце памеры сродку вядзення журнала для буфераў журнала"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 83c1ec0..ea67a98 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Мрежи"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Безжичен дисплей"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"„Многословно“ регистр. на Wi‑Fi: Актив."</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Wi-Fi към моб. мрежи: Агресивно предав."</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Сканирането за роуминг на Wi-Fi да е разрешено винаги"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Винаги активни мобилни данни"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Хардуерно ускорение за тетъринга"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Въведете името на хоста на DNS доставчика"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Показване на опциите за сертифициране на безжичния дисплей"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"По-подробно регистр. на Wi‑Fi – данни за RSSI на SSID в инстр. за избор на Wi‑Fi"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"При активиране предаването на връзката за данни от Wi-Fi към мобилната мрежа ще е по-агресивно, когато сигналът за Wi-Fi е слаб"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Разрешаване/забраняване на сканирането за роуминг на Wi-Fi въз основа на посочения в интерфейса обем на трафика на данни"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Размери на регистрац. буфери"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Размер на един рег. буфер: Избор"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index baf9e2c..f30ed2b 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"নেটওয়ার্কিং"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"ওয়্যারলেস ডিসপ্লে সার্টিফিকেশন"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"ওয়াই-ফাই ভারবোস লগিং সক্ষম করুন"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"ওয়াই-ফাই থেকে মোবাইলে তৎপর হস্তান্তর"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"সর্বদা ওয়াই ফাই রোম স্ক্যানকে অনুমতি দিন"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"মোবাইল ডেটা সব সময় সক্রিয় থাক"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"টিথারিং হার্ডওয়্যার অ্যাক্সিলারেশন"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"ডিএনএস প্রদানকারীর হোস্টনেম লিখুন"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"ওয়্যারলেস প্রদর্শন সার্টিফিকেশন জন্য বিকল্পগুলি দেখান"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"ওয়াই-ফাই লগিং স্তর বাড়ান, ওয়াই-ফাই চয়নকারীতে SSID RSSI অনুযায়ী দেখান"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"সক্ষম করা থাকলে, ওয়াই ফাই সিগন্যালের মান খারাপ হলে ডেটা সংযোগ মোবাইলের কাছে হস্তান্তর করার জন্য ওয়াই ফাই আরো বেশি তৎপর হবে।"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ইন্টারফেসে উপস্থিত ডেটা ট্রাফিকের পরিমাণের উপরে ভিত্তি করে ওয়াই-ফাই রোম স্ক্যানকে অনুমোদিত/অননুমোদিত করুন"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"লগার বাফারের আকারগুলি"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"লগ বাফার প্রতি অপেক্ষাকৃত বড় আকারগুলির বেছে নিন"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 88b01e9..915eb49 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Umrežavanje"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Certifikacija bežičnog prikaza"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Omogućiti Wi-Fi Verbose zapisivanje"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agresivni prijenos s Wi-Fi mreže na mob."</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Uvijek dopustiti Wi-Fi lutajuće skeniranje"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilna mreža za prijenos podataka je uvijek aktivna"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardversko ubrzavanje dijeljenja veze"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Unesite naziv host računara pružaoca DNS-a"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Pokaži opcije za certifikaciju Bežičnog prikaza"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Povećajte nivo Wi-Fi zapisivanja, pokazati po SSID RSSI Wi-Fi Picker"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Kada je omogućeno, Wi-Fi veza će u slučaju slabog signala agresivnije predavati vezu za prijenos podataka na mobilnu vezu"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Dozvoli/Zabrani Wi-Fi lutajuće skeniranje na osnovu količine podatkovnog saobraćaja prisutnog na interfejsu"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Veličine bafera za zapisnik"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Odaberite veličine za Logger prema međumemoriji evidencije"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 48223ce..d8c6693 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Xarxes"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Certificació de pantalla sense fil"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Activa el registre Wi‑Fi detallat"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Transferència agressiva de Wi-Fi a mòbil"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permet sempre cerca de Wi-Fi en ininerància"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Dades mòbils sempre actives"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Acceleració per maquinari per compartir la xarxa"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Introdueix el nom d\'amfitrió del proveïdor de DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostra les opcions de certificació de pantalla sense fil"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Augmenta nivell de registre Wi‑Fi i mostra\'l per SSID RSSI al Selector de Wi‑Fi"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Quan s\'activa, la Wi-Fi és més agressiva en transferir la connexió de dades al mòbil quan el senyal de la Wi-Fi sigui dèbil"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permet/No permetis cerques de xarxes Wi-Fi en itinerància basades en la quantitat de dades presents a la interfície"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Mides memòria intermèdia Logger"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Mida Logger per memòria intermèdia"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 88bbaa7..41ff8e2 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Sítě"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Certifikace bezdrát. displeje"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Podrobné protokolování Wi‑Fi"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agresivní předání z Wi-Fi na mobilní síť"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vždy povolit Wi-Fi roaming"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilní data jsou vždy aktivní"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardwarová akcelerace tetheringu"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Zadejte název hostitele poskytovatele DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Zobrazit možnosti certifikace bezdrátového displeje"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Zvýšit úroveň protokolování Wi‑Fi zobrazenou v SSID a RSSI při výběru sítě Wi‑Fi."</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Pokud je tato možnost zapnuta, bude síť Wi-Fi při předávání datového připojení mobilní síti při slabém signálu Wi-Fi agresivnější."</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Povolí nebo zakáže Wi-Fi roaming na základě množství datového provozu na rozhraní."</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Vyrovnávací paměť protokol. nástroje"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Velikost vyrovnávací paměti protokol. nástroje"</string>
@@ -395,7 +393,7 @@
     <string name="content_description_menu_button" msgid="8182594799812351266">"Nabídka"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Chcete-li v ukázkovém režimu obnovit zařízení do továrního nastavení, zadejte heslo"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Další"</string>
-    <string name="retail_demo_reset_title" msgid="696589204029930100">"Je třeba zadat heslo"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Zadejte heslo"</string>
     <string name="active_input_method_subtypes" msgid="3596398805424733238">"Aktivní metody zadávání"</string>
     <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Použít systémové jazyky"</string>
     <string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Nastavení aplikace <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> se nepodařilo otevřít"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 6f36bc5..17d1f08 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Netværk"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Certificering af trådløs skærm"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Aktivér detaljeret Wi-Fi-logføring"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Tvungen skift fra Wi-Fi til mobildata"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Tillad altid scanning af Wi-Fi-roaming"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobildata er altid aktiveret"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardwareacceleration ved netdeling"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Angiv hostname for DNS-udbyder"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Vis valgmuligheder for certificering af trådløs skærm"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Øg mængden af Wi‑Fi-logføring. Vis opdelt efter SSID RSSI i Wi‑Fi-vælgeren"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Når dette er aktiveret, gennemtvinges en overdragelse af dataforbindelsen fra Wi-Fi til mobilnetværk, når Wi-Fi-signalet er svagt"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Tillad/forbyd scanning i forbindelse med Wi-Fi-roaming afhængigt af mængden af datatrafik i grænsefladen"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Størrelser for Logger-buffer"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Vælg Logger-størrelser pr. logbuffer"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 4d53e2d..2fbac93 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Netzwerke"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Kabellose Übertragung"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Ausführliche WLAN-Protokolle aktivieren"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Aggressives Handover von WLAN an Mobilfunk"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"WLAN-Roamingsuchen immer zulassen"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile Datennutzung immer aktiviert"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardwarebeschleunigung für Tethering"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Hostname des DNS-Anbieters eingeben"</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>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Wenn diese Option aktiviert ist, ist das WLAN bei schwachem Signal bei der Übergabe der Datenverbindung an den Mobilfunk aggressiver"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"WLAN-Roamingsuchen je nach Umfang des Datentraffics an der Schnittstelle zulassen bzw. nicht zulassen"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Logger-Puffergrößen"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Größe pro Protokollpuffer wählen"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index e510356..25de914 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Δικτύωση"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Πιστοποίηση ασύρματης οθόνης"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Ενεργοποίηση λεπτομερ. καταγραφής Wi-Fi"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Επιθ.μεταβ. Wi-Fi σε δίκτυο κιν.τηλ."</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Να επιτρέπεται πάντα η σάρωση Wi-Fi κατά την περιαγωγή"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Πάντα ενεργά δεδομένα κινητής τηλεφωνίας"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Σύνδεση επιτάχυνσης υλικού"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Εισαγάγετε το όνομα κεντρικού υπολογιστή του παρόχου DNS"</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>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Όταν είναι ενεργό, το Wi-Fi θα μεταβιβάζει πιο επιθετικά τη σύνδ.δεδομένων σε δίκτυο κινητής τηλ., όταν το σήμα Wi-Fi είναι χαμηλό"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Να επιτρέπεται/να μην επιτρέπεται η σάρωση Wi-Fi κατά την περιαγωγή, βάσει της ποσότητας επισκεψιμότητας δεδομένων στη διεπαφή"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Μέγεθος προσωρινής μνήμης για τη λειτουργία καταγραφής"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Μέγεθος αρχείων κατ/φής ανά προ/νή μνήμη αρχείου κατ/φής"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index a322388..9f5353f 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Networking"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Wireless display certification"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Enable Wi‑Fi verbose logging"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Aggressive Wi‑Fi to mobile handover"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Always allow Wi‑Fi Roam Scans"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile data always active"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering hardware acceleration"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Enter hostname of DNS provider"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Show options for wireless display certification"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Increase Wi‑Fi logging level, show per SSID RSSI in Wi‑Fi Picker"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"When enabled, Wi‑Fi will be more aggressive in handing over the data connection to mobile, when Wi‑Fi signal is low"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Allow/Disallow Wi‑Fi Roam Scans based on the amount of data traffic present at the interface"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Logger buffer sizes"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Select Logger sizes per log buffer"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index a322388..9f5353f 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Networking"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Wireless display certification"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Enable Wi‑Fi verbose logging"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Aggressive Wi‑Fi to mobile handover"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Always allow Wi‑Fi Roam Scans"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile data always active"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering hardware acceleration"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Enter hostname of DNS provider"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Show options for wireless display certification"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Increase Wi‑Fi logging level, show per SSID RSSI in Wi‑Fi Picker"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"When enabled, Wi‑Fi will be more aggressive in handing over the data connection to mobile, when Wi‑Fi signal is low"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Allow/Disallow Wi‑Fi Roam Scans based on the amount of data traffic present at the interface"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Logger buffer sizes"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Select Logger sizes per log buffer"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index a322388..9f5353f 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Networking"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Wireless display certification"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Enable Wi‑Fi verbose logging"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Aggressive Wi‑Fi to mobile handover"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Always allow Wi‑Fi Roam Scans"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile data always active"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering hardware acceleration"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Enter hostname of DNS provider"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Show options for wireless display certification"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Increase Wi‑Fi logging level, show per SSID RSSI in Wi‑Fi Picker"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"When enabled, Wi‑Fi will be more aggressive in handing over the data connection to mobile, when Wi‑Fi signal is low"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Allow/Disallow Wi‑Fi Roam Scans based on the amount of data traffic present at the interface"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Logger buffer sizes"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Select Logger sizes per log buffer"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index a322388..9f5353f 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Networking"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Wireless display certification"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Enable Wi‑Fi verbose logging"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Aggressive Wi‑Fi to mobile handover"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Always allow Wi‑Fi Roam Scans"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile data always active"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering hardware acceleration"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Enter hostname of DNS provider"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Show options for wireless display certification"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Increase Wi‑Fi logging level, show per SSID RSSI in Wi‑Fi Picker"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"When enabled, Wi‑Fi will be more aggressive in handing over the data connection to mobile, when Wi‑Fi signal is low"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Allow/Disallow Wi‑Fi Roam Scans based on the amount of data traffic present at the interface"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Logger buffer sizes"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Select Logger sizes per log buffer"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 80c2eb8..a8561fa 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‎‎‎‎‏‏‎‎‏‎‏‎‏‏‎‎‎‎‏‎‏‏‎‏‏‎‎‏‎‏‎‎‎‏‏‏‎‎‎‎‎‏‏‏‎‎‏‏‏‏‏‏‎‎Networking‎‏‎‎‏‎"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‎‎‎‏‎‎‏‏‏‎‎‎‎‏‏‎‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‎‎‎‎‎‎‏‏‏‎‏‎‏‏‎‎‎‎‏‏‎‏‎Wireless display certification‎‏‎‎‏‎"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‎‎‏‎‏‎‏‏‎‏‎‏‎‎‏‎‏‏‏‏‏‎‎‎‎‏‏‎‏‏‎‎‎‏‏‏‎‏‏‏‏‎‏‏‏‎‏‎‎‎‏‏‎‏‎‎‎‎Enable Wi‑Fi Verbose Logging‎‏‎‎‏‎"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‎‎‏‏‎‏‎‏‏‎‏‏‏‎‏‎‎‏‏‎‏‏‎‏‎‎‏‎‎‎‎‎‎‎‏‏‎‏‏‏‎‎‏‏‏‎‎‎‏‎‎‏‎‎‎‏‎‎‎‎Aggressive Wi‑Fi to mobile handover‎‏‎‎‏‎"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‎‎‏‏‏‏‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‎‏‎‏‏‎‎‏‏‏‏‎‎‏‏‎‎‎‏‏‎‏‏‎‏‏‎‎‎‏‎‏‏‏‎‏‎‎Always allow Wi‑Fi Roam Scans‎‏‎‎‏‎"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‏‏‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‎‏‏‎‏‎‏‏‎‎‎‏‏‏‏‏‎‎‎‏‏‏‎‎‏‏‎‏‏‏‎‎‏‎‎Mobile data always active‎‏‎‎‏‎"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‎‏‎‏‏‎‎‎‎‏‏‎‎‎‎‏‏‎‏‎‎‏‎‏‎‎‎‎‎‎‎‏‏‏‏‎‏‏‎‏‎‎‎‎‏‎‎‏‏‎‏‏‎‎Tethering hardware acceleration‎‏‎‎‏‎"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‎‏‎‎‎‎‏‎‏‎‏‎‏‏‎‎‏‎‎‏‎‎‏‎‏‏‎‎‎‏‎‏‎‏‏‏‎‎‏‎‎‎‎‎‎‎‏‎‎‎‎‎‎‏‏‏‏‎Enter hostname of DNS provider‎‏‎‎‏‎"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‎‎‎‎‎‏‎‎‎‎‎‎‎‏‎‎‎‎‎‏‏‎‎‎‎‏‎‎‏‎‏‎‎‏‎‏‏‎‎‏‏‎‎‎‎‏‏‎‏‎‏‎‏‏‏‎‏‎Show options for wireless display certification‎‏‎‎‏‎"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‎‎‏‏‎‏‎‏‏‏‎‏‎‎‏‎‎‏‎‏‏‎‎‎‏‏‎‎‏‎‎‎‎‏‏‎‏‏‏‏‏‎‎‏‎‎‏‏‏‏‎‏‏‎‎Increase Wi‑Fi logging level, show per SSID RSSI in Wi‑Fi Picker‎‏‎‎‏‎"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‎‏‎‏‏‏‎‎‏‏‎‎‎‎‎‏‎‏‎‎‎‎‏‎‎‏‏‏‎‎‎‎‎‏‎‏‏‎‎‏‎‎‏‏‎‏‎‎‏‏‏‎‏‏‎When enabled, Wi‑Fi will be more aggressive in handing over the data connection to mobile, when Wi‑Fi signal is low‎‏‎‎‏‎"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‏‏‎‏‏‏‏‎‎‏‎‎‏‏‎‎‏‎‎‎‏‏‎‏‎‎‏‎‎‎‎‎‎‎‎‎‏‏‎‎‏‎‏‏‎‎‎‏‏‏‏‏‎‎‏‏‎‎Allow/Disallow Wi‑Fi Roam Scans based on the amount of data traffic present at the interface‎‏‎‎‏‎"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‎‎‏‏‏‏‏‎‎‏‏‏‎‏‏‎‏‎‎‎‏‎‏‎‎‏‏‎‏‏‏‏‎‎‎‏‏‏‏‎‎‏‎‎‏‎‎‏‎‎‏‎‎‎Logger buffer sizes‎‏‎‎‏‎"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‏‎‎‏‎‏‏‎‎‏‏‏‏‏‎‎‏‏‏‏‏‎‏‎‎‎‎‎‏‎‏‎‏‎‏‏‎‎‎‎Select Logger sizes per log buffer‎‏‎‎‏‎"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 65000b3..eeaf18f 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Redes"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Certificación de pantalla inalámbrica"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Habilitar registro detallado de Wi-Fi"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Priorizar cambio de red Wi-Fi a móvil"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permitir siempre búsquedas de Wi-Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Datos móviles siempre activados"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleración de hardware de conexión mediante dispositivo portátil"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Ingresa el nombre de host del proveedor de DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opciones de certificación de pantalla inalámbrica"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar nivel de registro Wi-Fi; mostrar por SSID RSSI en el selector de Wi-Fi"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Si habilitas esta opción, se priorizará el cambio de Wi-Fi a datos móviles cuando la señal de Wi-Fi sea débil"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permitir/no permitir las búsquedas de Wi-Fi basadas la cantidad de tráfico de datos presente en la interfaz"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Tamaños de búfer de Logger"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Selecciona el tamaño del Logger por búfer"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 2a5e41b..97d9a10 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Redes"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Certificación de pantalla inalámbrica"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Habilitar registro Wi-Fi detallado"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Transferencia agresiva de Wi-Fi a móvil"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permitir siempre búsquedas de Wi-Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Datos móviles siempre activos"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleración por hardware para conexión compartida"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Introduce el nombre de host del proveedor de DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opciones para la certificación de la pantalla inalámbrica"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar el nivel de registro de Wi-Fi, mostrar por SSID RSSI en el selector Wi-Fi"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Si se activa esta opción, la conexión Wi-Fi será más agresiva al pasar la conexión a datos móviles (si la señal Wi-Fi es débil)"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permitir/No permitir búsquedas de Wi-Fi basadas en la cantidad de tráfico de datos presente en la interfaz"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Tamaños de búfer de registrador"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Elige el tamaño del Logger por búfer"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index a8ac99f..b680b84 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Võrgustik"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Juhtmeta ekraaniühenduse sertifitseerimine"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Luba WiFi paljusõnaline logimine"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agress. üleminek WiFi-lt mobiilsidele"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Luba alati WiFi-rändluse skannimine"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobiilne andmeside on alati aktiivne"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Jagamise riistvaraline kiirendus"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Sisestage DNS-i teenusepakkuja hostinimi"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Juhtmeta ekraaniühenduse sertifitseerimisvalikute kuvamine"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Suurenda WiFi logimistaset, kuva WiFi valijas SSID RSSI järgi"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Kui seade on lubatud, asendatakse nõrga signaaliga WiFi-ühendus agressiivsemalt mobiilse andmesideühendusega"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Luba/keela WiFi-rändluse skannimine liidese andmeliikluse põhjal"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Logija puhvri suurused"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Vali logija suur. logipuhvri kohta"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 2c81f2e..ca8ea03 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Sareak"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Hari gabeko bistaratze-egiaztatzea"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Gaitu Wi-Fi sareetan saioa hasteko modu xehatua"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Behartu Wi-Fi konexiotik datuenera aldatzera"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Onartu beti ibiltaritzan Wi-Fi sareak bilatzea"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Datu mugikorrak beti aktibo"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Konexioa partekatzeko hardwarearen azelerazioa"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Idatzi DNS hornitzailearen ostalari-izena"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Erakutsi hari gabeko bistaratze-egiaztapenaren aukerak"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Erakutsi datu gehiago Wi-Fi sareetan saioa hasterakoan. Erakutsi sarearen identifikatzailea eta seinalearen indarra Wi‑Fi sareen hautagailuan."</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Aukera hori gaituz gero, gailua nahitaez aldatuko da datu mugikorren konexiora Wi-Fi seinalea ahultzen dela nabaritutakoan"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Onartu edo debekatu ibiltaritzan Wi-Fi sareak bilatzea, interfazeko datu-trafikoaren arabera"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Erregistroen buffer-tamainak"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Hautatu erregistroen buffer-tamainak"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 4f3c77f..675e382 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"شبکه"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"گواهینامه نمایش بی‌سیم"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"‏فعال کردن گزارش‌گیری طولانی Wi‑Fi"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"‏Wi‑Fi قوی برای واگذاری به دستگاه همراه"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"‏اسکن‌های رومینگ Wi‑Fi همیشه مجاز است"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"داده تلفن همراه همیشه فعال باشد"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"شتاب سخت‌افزاری اتصال به اینترنت با تلفن همراه"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"‏نام میزبان ارائه‌دهنده DNS خصوصی را وارد کنید"</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>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"‏زمانی‌که فعال است، درشرایطی که سیگنال Wi-Fi ضعیف باشد، Wi‑Fi برای واگذاری اتصال داده به دستگاه همراه قوی‌تر عمل خواهد کرد."</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"‏مجاز/غیرمجاز کردن اسکن‌های رومینگ Wi‑Fi براساس مقدار ترافیک داده موجود در واسط"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"اندازه‌های حافظه موقت ثبت‌کننده"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"انتخاب اندازه‌ ثبت‌کننده در حافظه موقت ثبت"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 5932d00..ba7fcd3 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Yhteysominaisuudet"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Langattoman näytön sertifiointi"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Käytä Wi-Fin laajennettua lokikirjausta"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Vaihda herkästi Wi-Fi mobiiliyhteyteen"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Salli Wi-Fi-verkkovierailuskannaus aina"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobiilidata aina käytössä"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Laitteistokiihdytyksen yhteyden jakaminen"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Anna isäntänimi tai DNS-tarjoaja."</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Näytä langattoman näytön sertifiointiin liittyvät asetukset"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Lisää Wi‑Fin lokikirjaustasoa, näytä SSID RSSI -kohtaisesti Wi‑Fi-valitsimessa."</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Kun asetus on käytössä, datayhteys siirtyy helpommin Wi-Fistä matkapuhelinverkkoon, jos Wi-Fi-signaali on heikko."</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Salli/estä Wi-Fi-verkkovierailuskannaus liittymässä esiintyvän dataliikenteen perusteella."</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Lokipuskurien koot"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Valitse puskurikohtaiset lokikoot"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index c0c29d3..f266e2d 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Réseautage"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Certification de l\'affichage sans fil"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Autoriser enreg. données Wi-Fi détaillées"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Passage forcé du Wi-Fi aux données cell."</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Toujours autoriser la détection de réseaux Wi-Fi en itinérance"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Données cellulaires toujours actives"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Accélération matérielle pour le partage de connexion"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Entrez le nom d\'hôte du fournisseur DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Afficher les options pour la certification d\'affichage sans fil"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Détailler davantage les données Wi-Fi, afficher par SSID RSSI dans sélect. Wi-Fi"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Si cette option est activée, le passage du Wi-Fi aux données cellulaires est forcé lorsque le signal Wi-Fi est faible"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Autoriser ou non la détection de réseaux Wi-Fi en itinérance en fonction de l\'importance du transfert de données dans l\'interface"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Tailles des mémoires tampons d\'enregistreur"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Tailles enreg. par tampon journal"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 50c99e2..87f00d1 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Mise en réseau"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Certification affichage sans fil"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Autoriser enreg. infos Wi-Fi détaillées"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Passage forcé Wi-Fi vers données mobiles"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Toujours autoriser la détection de réseaux Wi-Fi en itinérance"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Données mobiles toujours actives"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Accélération matérielle pour le partage de connexion"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Saisissez le nom d\'hôte du fournisseur DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Afficher les options de la certification de l\'affichage sans fil"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Détailler plus infos Wi-Fi, afficher par RSSI de SSID dans outil sélection Wi-Fi"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Si cette option est activée, le passage du Wi-Fi aux données mobiles est forcé en cas de signal Wi-Fi faible."</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Autoriser ou non la détection de réseaux Wi-Fi en itinérance en fonction de l\'importance du trafic de données dans l\'interface"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Tailles mémoires tampons enregistr."</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Tailles enreg. par tampon journal"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 775bbf1..9026aab 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Redes"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Certificado de visualización sen fíos"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Activar rexistro detallado da wifi"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Transferencia agresiva de wifi a móbil"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permitir sempre buscas de itinerancia da wifi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Datos móbiles sempre activados"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleración de hardware para conexión compartida"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Introduce o nome de host de provedor de DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostra opcións para o certificado de visualización sen fíos"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar o nivel de rexistro da wifi, mostrar por SSID RSSI no selector de wifi"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Cando estea activada esta función, a wifi será máis agresiva ao transferir a conexión de datos ao móbil cando o sinal wifi sexa feble"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permitir/Non permitir buscas de itinerancia da wifi baseadas na cantidade de tráfico de datos presente na interface"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Tamaños de búfer de rexistrador"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Seleccionar tamaños por búfer"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 712e57e..b1ee90b 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"નેટવર્કિંગ"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"વાયરલેસ ડિસ્પ્લે પ્રમાણન"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"વાઇ-ફાઇ વર્બોઝ લૉગિંગ સક્ષમ કરો"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"સશક્ત Wi‑Fiથી મોબાઇલ પર હૅન્ડઓવર"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"હંમેશા વાઇ-ફાઇ રોમ સ્કૅન્સને મંજૂરી આપો"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"મોબાઇલ ડેટા હંમેશાં સક્રિય"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"ટિથરિંગ માટે હાર્ડવેર ગતિવૃદ્ધિ"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS પ્રદાતાના હોસ્ટનું નામ દાખલ કરો"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"વાયરલેસ ડિસ્પ્લે પ્રમાણપત્ર માટેના વિકલ્પો બતાવો"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"વાઇ-ફાઇ લોગિંગ સ્તર વધારો, વાઇ-ફાઇ પીકરમાં SSID RSSI દીઠ બતાવો"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"જ્યારે સક્ષમ કરેલ હોય, ત્યારે વાઇ-ફાઇ સિગ્નલ નબળું હોવા પર, વાઇ-ફાઇ વધુ ઝડપથી ડેટા કનેક્શનને મોબાઇલ પર મોકલશે"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ઇન્ટરફેસ પર હાજર ડેટા ટ્રાફિકના પ્રમાણનાં આધારે વાઇ-ફાઇ રોમ સ્કૅન્સને મંજૂરી આપો/નામંજૂર કરો"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"લોગર બફર કદ"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"લૉગ દીઠ લૉગર કદ બફર પસંદ કરો"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index a88abb5..e235fc5 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"नेटवर्किंग"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"वायरलेस दिखाई देने के लिए प्रमाणन"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"वाई-फ़ाई वर्बोस लॉगिंग चालू करें"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"वाई-फ़ाई से मोबाइल पर ज़्यादा तेज़ी से हैंडओवर"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"हमेशा वाई-फ़ाई रोम स्कैन करने दें"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"मोबाइल डेटा हमेशा सक्रिय"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"हार्डवेयर से तेज़ी लाने के लिए टेदर करें"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS सेवा देने वाले का होस्टनाम डालें"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"वायरलेस दिखाई देने के लिए प्रमाणन विकल्प दिखाएं"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"वाई-फ़ाई प्रवेश स्तर बढ़ाएं, वाई-फ़ाई पिकर में प्रति SSID RSSI दिखाएं"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"इसके सक्षम होने पर, जब वाई-फ़ाई संकेत कमज़ोर हों तो वाई-फ़ाई, डेटा कनेक्शन को मोबाइल पर ज़्यादा तेज़ी से भेजेगा"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"इंटरफ़ेस पर वर्तमान में मौजूद डेटा ट्रैफ़िक के आधार पर वाई-फ़ाई रोम स्कैन करने देता/नहीं देता है"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"लॉगर बफ़र आकार"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"प्रति लॉग बफ़र लॉगर आकार चुनें"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index a417cc1..a854987 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Umrežavanje"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Certifikacija bežičnog prikaza"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Omogući opširnu prijavu na Wi-Fi"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Aktivni prijelaz s Wi‑Fi na mob. mrežu"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Uvijek dopusti slobodno traženje Wi-Fi mreže"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilni podaci uvijek aktivni"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardversko ubrzanje za modemsko povezivanje"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Unesite naziv hosta davatelja usluge DNS-a"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Prikaži opcije za certifikaciju bežičnog prikaza"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Povećana razina prijave na Wi‑Fi, prikaz po SSID RSSI-ju u Biraču Wi‑Fi-ja"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Ako je omogućeno, Wi-Fi će aktivno prebacivati podatkovnu vezu mobilnoj mreži kada je Wi-Fi signal slab."</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Dopustite ili blokirajte slobodno traženje Wi-Fi mreža na temelju količine podatkovnog prometa na sučelju."</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Veličine međuspremnika zapisnika"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Odaberite veličinu međuspremnika zapisnika"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index b6f1460..553ed88 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Hálózatok"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Vezeték nélküli kijelző tanúsítványa"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Részletes Wi-Fi-naplózás engedélyezése"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agresszív Wi‑Fi–mobilhálózat átadás"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi-roaming ellenőrzésének engedélyezése mindig"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"A mobilhálózati kapcsolat mindig aktív"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Internetmegosztás hardveres gyorsítása"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Adja meg a DNS-szolgáltató gazdagépnevét"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Vezeték nélküli kijelző tanúsítványával kapcsolatos lehetőségek megjelenítése"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi-naplózási szint növelése, RSSI/SSID megjelenítése a Wi‑Fi-választóban"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Ha engedélyezi, a Wi-Fi agresszívebben fogja átadni az adatkapcsolatot a mobilhálózatnak gyenge Wi-Fi-jel esetén"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"A Wi-Fi-roaming ellenőrzésének engedélyezése vagy letiltása az interfészen jelen lévő adatforgalom mennyiségétől függően"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Naplózási puffer mérete"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Naplózási pufferméret kiválasztása"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 3ba3f45..dced49f5 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Ցանց"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Անլար էկրանի վկայագրում"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Միացնել Wi‑Fi մանրամասն գրանցամատյանները"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Wi-Fi-ից կտրուկ անցում բջջային ինտերնետի"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Միշտ թույլատրել Wi‑Fi ռոումինգի որոնումը"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Բջջային ինտերնետը միշտ ակտիվ է"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Սարքակազմի արագացման միացում"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Մուտքագրեք DNS ծառայության մատակարարի խնամորդի անունը"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Ցույց տալ անլար էկրանի հավաստագրման ընտրանքները"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Բարձրացնել մակարդակը, Wi‑Fi ընտրիչում ամեն մի SSID-ի համար ցույց տալ RSSI"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Եթե այս գործառույթը միացված է, Wi-Fi-ի թույլ ազդանշանի դեպքում Wi‑Fi ինտերնետից բջջային ինտերնետի անցումը ավելի կտրուկ կկատարվի"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Թույլատրել/արգելել Wi‑Fi ռոումինգի որոնումը՝ կախված միջերեսում տվյալների երթևեկի ծավալից"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Տեղեկամատյանի պահնակի չափերը"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Ընտրեք տեղեկամատյանի չափը մեկ պահնակի համար"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 2bb9ae0..5c06766 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Jaringan"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Sertifikasi layar nirkabel"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Aktifkan Pencatatan Log Panjang Wi-Fi"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Pengalihan Wi-Fi Agresif ke seluler"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Selalu izinkan Pemindaian Roaming Wi-Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Data seluler selalu aktif"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Akselerasi hardware tethering"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Masukkan hostname penyedia DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Tampilkan opsi untuk sertifikasi layar nirkabel"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Tingkatkan level pencatatan log Wi-Fi, tampilkan per SSID RSSI di Pemilih Wi‑Fi"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Jika diaktifkan, Wi-Fi akan menjadi lebih agresif dalam mengalihkan sambungan data ke seluler saat sinyal Wi-Fi lemah"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Izinkan/Larang Pemindaian Roaming Wi-Fi berdasarkan jumlah lalu lintas data yang ada di antarmuka"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Ukuran penyangga pencatat log"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Ukuran Pencatat Log per penyangga log"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 311227f..21b8b0e 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Netkerfi"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Vottun þráðlausra skjáa"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Kveikja á ítarlegri skráningu Wi-Fi"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Hröð skipti úr Wi‑Fi í farsímagögn"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Leyfa alltaf reikileit með Wi-Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Alltaf kveikt á farsímagögnum"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Vélbúnaðarhröðun fyrir tjóðrun"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Slá inn hýsilheiti DNS-veitu"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Sýna valkosti fyrir vottun þráðlausra skjáa"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Auka skráningarstig Wi-Fi, sýna RSSI fyrir hvert SSID í Wi-Fi vali"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Þegar þetta er virkt mun Wi-Fi skipta hraðar yfir í farsímagagnatengingu þegar Wi-Fi-tenging er léleg"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Leyfa/banna reikileit með Wi-Fi á grunni þess hversu mikil gagnaumferð er fyrir hendi í viðmótinu"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Annálsritastærðir biðminna"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Veldu annálsritastærðir á biðminni"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index b63232d..7408b25 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Reti"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Certificazione display wireless"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Attiva registrazione dettagliata Wi-Fi"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Wi‑Fi aggressivo per passaggio a cellulare"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Consenti sempre scansioni roaming Wi-Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Dati mobili sempre attivi"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering accelerazione hardware"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Inserisci il nome host del provider DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostra opzioni per la certificazione display wireless"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumenta il livello di registrazione Wi-Fi, mostrando il SSID RSSI nel selettore Wi-Fi"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Con questa impostazione attivata, il Wi-Fi è più aggressivo nel passare la connessione dati al cellulare, con segnale Wi-Fi basso"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Consenti/vieta scansioni roaming Wi-Fi basate sulla quantità di traffico dati presente a livello di interfaccia"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Dimensioni buffer Logger"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Seleziona dimensioni Logger per buffer log"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 538da91..fceaacc 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"תקשורת רשתות"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"‏אישור של תצוגת WiFi"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"‏הפעל רישום מפורט של Wi‑Fi ביומן"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"‏העברה אגרסיבית מ-Wi‑Fi לרשת סלולרית"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"‏התר תמיד סריקות נדידה של Wi‑Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"חבילת הגלישה פעילה תמיד"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"שיפור מהירות באמצעות חומרה לצורך שיתוף אינטרנט בין ניידים"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"‏צריך להזין את שם המארח של ספק DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"‏הצג אפשרויות עבור אישור של תצוגת WiFi"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"‏העלה את רמת הרישום של Wi‑Fi ביומן, הצג לכל SSID RSSI ב-Wi‑Fi Picker"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"‏כשאפשרות זו מופעלת, Wi-Fi יתנהג בצורה אגרסיבית יותר בעת העברת חיבור הנתונים לרשת הסלולרית כשאות ה-Wi-Fi חלש."</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"‏התר/מנע סריקות נדידה של Wi-Fi בהתבסס על נפח תנועת הנתונים הקיימת בממשק"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"גדלי מאגר של יומן רישום"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"בחר גדלים של יוצר יומן לכל מאגר יומן"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index db1baa1..671320b 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"ネットワーク"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"ワイヤレスディスプレイ認証"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi-Fi詳細ログの有効化"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Wi-Fi を強制的にモバイル接続に切り替える"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fiローミングスキャンを常に許可する"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"モバイルデータを常に ON にする"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"テザリング時のハードウェア アクセラレーション"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS プロバイダのホスト名を入力"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"ワイヤレスディスプレイ認証のオプションを表示"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi-Fiログレベルを上げて、Wi-Fi選択ツールでSSID RSSIごとに表示します"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"ON にすると、Wi-Fi の電波強度が弱い場合は強制的にモバイルデータ接続に切り替わるようになります"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"インターフェースのデータトラフィック量に基づいたWi-Fiローミングスキャンを許可するかしないかを設定できます"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"ログバッファのサイズ"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"各ログバッファのログサイズを選択"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 00eaf84..1948460 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"ქსელი"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"უსადენო ეკრანის სერტიფიცირება"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi-ს დაწვრილებითი აღრიცხვის ჩართვა"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Wi‑Fi-ს მობ. ინტერნეტზე აგრესიული გადართვა"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi Roam სკანირების მუდამ დაშვება"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"მობილური ინტერნეტის ყოველთვის გააქტიურება"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"ტეტერინგის აპარატურული აჩქარება"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"შეიყვანეთ DNS პროვაიდერის სერვერის სახელი"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"უსადენო ეკრანის სერტიფიცირების ვარიანტების ჩვენება"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi-ს აღრიცხვის დონის გაზრდა, Wi‑Fi ამომრჩეველში ყოველ SSID RSSI-ზე ჩვენება"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"ჩართვის შემთხვევაში, Wi‑Fi უფრო აქტიურად შეეცდება მობილურ ინტერნეტზე გადართვას, როცა Wi‑Fi სიგნალი სუსტია"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Wifi Roam სკანირების დაშვება/აკრძალვა, ინტერფეისზე არსებული მონაცემთა ტრაფიკზე დაფუძნებით"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"ჟურნალიზაციის ბუფერის ზომები"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"აირჩიეთ ჟურნ. ზომა / ჟურნ. ბუფერზე"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index a318bd8..2d03f7f 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Желі орнату"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Сымсыз дисплей сертификаты"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi егжей-тегжейлі журналға тір. қосу"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Wi-Fi желісінен мобильдік желіге ауысу"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi роумингін іздеулерге әрқашан рұқсат ету"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Мобильдік деректер әрқашан қосулы"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Тетерингтің аппараттық жеделдетуі"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS провайдерінің хост атауын енгізіңіз"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Сымсыз дисплей растау опцияларын көрсету"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi жур. тір. дең. арт., Wi‑Fi желісін таңдағышта әр SSID RSSI бойынша көрсету"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Wi‑Fi сигналы әлсіз болғанда, деректер байланысы мәжбүрлі түрде мобильдік желіге ауысады"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Интерфейсте бар деректер трафигінің мөлшерінің негізінде Wi-Fi роумингін іздеулерге рұқсат ету/тыйым салу"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Журналға тіркеуші буферінің өлшемдері"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Әр журнал буфері үшін журналға тіркеуші өлшемдерін таңдау"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index ae47318..1d2476c 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"ការភ្ជាប់បណ្ដាញ"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"បង្ហាញ​ការ​កំណត់​រចនាសម្ព័ន្ធ​ឥត​ខ្សែ"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"បើក​កំណត់ហេតុ​រៀបរាប់​វ៉ាយហ្វាយ"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"ប្តូរទៅប្រើបណ្តាញចល័តពេល Wi‑Fi មានរលកសញ្ញាខ្លាំងពេក"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"តែងតែ​អនុញ្ញាត​​​ការវិភាគ​រ៉ូម​វ៉ាយហ្វាយ"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"ទិន្នន័យទូរសព្ទចល័តដំណើរការជានិច្ច"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"ការ​បង្កើនល្បឿន​ផ្នែករឹងសម្រាប់​ការភ្ជាប់"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"បញ្ចូលឈ្មោះម៉ាស៊ីនរបស់ក្រុមហ៊ុនផ្ដល់សេវា DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"បង្ហាញ​ជម្រើស​សម្រាប់​វិញ្ញាបនបត្រ​បង្ហាញ​ឥត​ខ្សែ"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"បង្កើនកម្រិតកំណត់ហេតុវ៉ាយហ្វាយបង្ហាញក្នុង SSID RSSI ក្នុងកម្មវិធីជ្រើស​វ៉ាយហ្វាយ"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"នៅពេលដែលបើក នោះ Wi‑Fi នឹងផ្តល់ការតភ្ជាប់ទិន្នន័យយ៉ាងគំហុកទៅបណ្តាញទូរសព្ទចល័ត នៅពេលរលកសញ្ញា Wi‑Fi ចុះខ្សោយ។"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"អនុញ្ញាត/មិន​អនុញ្ញាត​ការ​វិភាគ​រ៉ូម​​វ៉ាយហ្វាយ​ផ្អែក​លើ​​​ចំនួន​ការ​បង្ហាញ​ចរាចរណ៍​ទិន្នន័យ​​នៅ​ចំណុច​ប្រទាក់"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"ទំហំ buffer របស់ Logger"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"ជ្រើស​ទំហំ Logger per log buffer"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index fbabb62..385308a 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"ನೆಟ್‌ವರ್ಕಿಂಗ್"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"ವೈರ್‌ಲೆಸ್ ಪ್ರದರ್ಶನ ಪ್ರಮಾಣೀಕರಣ"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi ವೆರ್ಬೋಸ್ ಲಾಗಿಂಗ್ ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"ವೈ-ಫೈನಿಂದ ಮೊಬೈಲ್‌ಗೆ ಆಕ್ರಮಣಕಾರಿ ಹಸ್ತಾಂತರ"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ವೈ-ಫೈ ರೋಮ್ ಸ್ಕ್ಯಾನ್‌ಗಳನ್ನು ಯಾವಾಗಲೂ ಅನುಮತಿಸಿ"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"ಮೊಬೈಲ್ ಡೇಟಾ ಯಾವಾಗಲೂ ಸಕ್ರಿಯ"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"ಹಾರ್ಡ್‌ವೇರ್‌ನ ವೇಗವರ್ಧನೆಯನ್ನು ಟೆಥರಿಂಗ್ ಮಾಡಿ"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS ಪೂರೈಕೆದಾರರ ಹೋಸ್ಟ್‌ಹೆಸರನ್ನು ನಮೂದಿಸಿ"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"ವೈರ್‌ಲೆಸ್‌‌‌ ಪ್ರದರ್ಶನ ಪ್ರಮಾಣೀಕರಣಕ್ಕಾಗಿ ಆಯ್ಕೆಗಳನ್ನು ತೋರಿಸು"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi ಲಾಗಿಂಗ್ ಮಟ್ಟನ್ನು ಹೆಚ್ಚಿಸಿ, Wi‑Fi ಆಯ್ಕೆಯಲ್ಲಿ ಪ್ರತಿಯೊಂದು SSID RSSI ತೋರಿಸಿ"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"ಇದು ಸಕ್ರಿಯಗೊಂಡರೆ, ವೈ-ಫೈ ಸಿಗ್ನಲ್ ದುರ್ಬಲವಾಗಿದ್ದಾಗ, ಮೊಬೈಲ್‌ಗೆ ಡೇಟಾ ಸಂಪರ್ಕವನ್ನು ಹಸ್ತಾಂತರಿಸುವಲ್ಲಿ ವೈ-ಫೈ ಹೆಚ್ಚು ಆಕ್ರಮಣಕಾರಿಯಾಗಿರುತ್ತದೆ"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ಇಂಟರ್‌ಫೇಸ್‌ನಲ್ಲಿ ಲಭ್ಯವಿರುವ ಡೇಟಾ ಟ್ರಾಫಿಕ್ ಆಧಾರದ ಮೇಲೆ Wi‑Fi ರೋಮ್ ಸ್ಕ್ಯಾನ್‌ಗಳನ್ನು ಅನುಮತಿಸಿ/ನಿರಾಕರಿಸಿ"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"ಲಾಗರ್ ಬಫರ್ ಗಾತ್ರಗಳು"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"ಪ್ರತಿ ಲಾಗ್ ಬಫರ್‌ಗೆ ಲಾಗರ್ ಗಾತ್ರಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 4b7d0a4..e1be8dc 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"네트워크"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"무선 디스플레이 인증서"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi-Fi 상세 로깅 사용"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"적극적인 Wi-Fi-모바일 핸드오버"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi 로밍 스캔 항상 허용"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"항상 모바일 데이터 활성화"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"테더링 하드웨어 가속"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS 제공업체의 호스트 이름 입력"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"무선 디스플레이 인증서 옵션 표시"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi 로깅 수준을 높이고, Wi‑Fi 선택도구에서 SSID RSSI당 값을 표시합니다."</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"사용 설정하면 Wi-Fi 신호가 약할 때 데이터 연결을 Wi-Fi에서 모바일 네트워크로 더욱 적극적으로 핸드오버합니다."</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"인터페이스에 표시되는 데이터 트래픽의 양을 기반으로 Wi-Fi 로밍 스캔을 허용하거나 허용하지 않습니다."</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"로거 버퍼 크기"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"로그 버퍼당 로거 크기 선택"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 98ca36a..d323df2 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Тармактык байланыштарды кеңейтүү"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Зымсыз дисплейди аныктоо"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi дайын-даректүү протоколун иштетүү"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Wi‑Fi начар болсо, мобилдик Инт-ке өтсүн"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi-Fi Роуминг Скандоо мүмкүнчүлүгүнө ар дайым уруксат берилсин"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Мобилдик Интернет иштей берсин"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Тетерингдин иштешин тездетүү"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS түйүндүн аталышын киргизиңиз"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Зымсыз дисплейди сертификатто мүмкүнчүлүктөрүн көргөзүү"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi-Fi Кармагычта Wi‑Fi протокол деңгээлин жогорулатуу жана ар бир SSID RSSI үчүн көрсөтүү."</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Иштетилсе, Wi-Fi байланышы үзүл-кесил болуп жатканда, Wi-Fi тармагы туташууну мобилдик Интернетке өжөрлүк менен өткөрүп берет"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Интерфейстеги дайындар трафигинин көлөмүнө жараша Wi-Fi Роуминг скандоо мүмкүнчүлүгүн иштетүү/өчүрүү"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Каттагыч буферлеринин өлчөмдөрү"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Каттоо буфери үчүн Каттагычтын көлөмүн тандаңыз"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 6de2a2e..1e58af1 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"ການ​ສ້າງເຄືອຂ່າຍ"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"ສະແດງການຮັບຮອງຂອງລະບົບໄຮ້ສາຍ"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"​ເປີດ​ນຳ​ໃຊ້ການ​ເກັບ​ປະ​ຫວັດ​ Verbose Wi‑Fi"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"ສະຫຼັບເປັນ Wi-Fi ເມື່ອມືຖືສັນຍານອ່ອນ"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ອະ​ນຸ​ຍາດ​ການ​ສະ​ແກນ​ການ​ໂຣມ Wi‑Fi ​ສະ​ເໝີ"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"ເປີດໃຊ້ອິນເຕີເນັດມືຖືຕະຫຼອດເວລາ"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"ເປີດໃຊ້ການເລັ່ງຄວາມໄວດ້ວຍຮາດແວ"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"ລະບຸຊື່ໂຮສຂອງຜູ້ໃຫ້ບໍລິການ DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"ສະແດງໂຕເລືອກສຳລັບການສະແດງການຮັບຮອງລະບົບໄຮ້ສາຍ"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"ເພີ່ມ​ລະ​ດັບ​ການ​ເກັບ​ປະ​ຫວັດ Wi‑Fi, ສະ​ແດງ​ຕໍ່ SSID RSSI ​ໃນ​ Wi‑Fi Picker"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"ເມື່ອເປີດໃຊ້ແລ້ວ, Wi-Fi ຈະສົ່ງຜ່ານການເຊື່ອມຕໍ່ຂໍ້ມູນໄປຫາເຄືອຂ່າຍມືຖືເມື່ອສັນຍານ Wi-Fi ອ່ອນ"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"​ອະ​ນຸ​ຍາດ/ບໍ່​ອະ​ນຸ​ຍາດການ​ສະ​ແກນ​ການ​ໂຣມ Wi-Fi ອີງ​ຕາມ​ຈຳ​ນວນ​ຂໍ້​ມູນທີ່​ເກີດ​ຂຶ້ນ​ໃນ​ລະ​ດັບ​ສ່ວນ​ຕິດ​ຕໍ່"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"ຂະ​ໜາດ​​ບັບ​ເຟີໂຕ​ລັອກ"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"ເລືອກ​ຂະ​ໜາດ​ລັອກ​ຕໍ່​ບັບ​ເຟີ"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 66fa62a..a35cd3c 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Tinklai"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Belaidžio rodymo sertifikavimas"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Įgal. „Wi‑Fi“ daugiaž. įraš. į žurnalą"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agres. „Wi‑Fi“ perd. į mob. r. tinklą"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Visada leisti „Wi-Fi“ tarptiklinio ryšio nuskaitymą"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobiliojo ryšio duomenys visada suaktyvinti"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Įrenginio kaip modemo naudojimo aparatinės įrangos spartinimas"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Įveskite DNS teikėjo prieglobos serverio pavadinimą"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Rodyti belaidžio rodymo sertifikavimo parinktis"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Padidinti „Wi‑Fi“ įrašymo į žurnalą lygį, rodyti SSID RSSI „Wi-Fi“ rinkiklyje"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Jei ši parinktis įgalinta, „Wi‑Fi“ agresyviau perduos duomenų ryšiu į mobiliojo ryšio tinklą, kai „Wi‑Fi“ signalas silpnas"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Leisti / neleisti „Wi‑Fi“ tarptinklinio ryšio nuskaitymo, atsižvelgiant į sąsajos duomenų srauto kiekį"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Registruotuvo buferio dydžiai"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Pasir. registr. dydž. žurn. bufer."</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index f32accd..8239d9f 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Tīklošana"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Bezvadu attēlošanas sertifikācija"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Iespējot Wi‑Fi detalizēto reģistrēšanu"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agresīva pāreja no Wi‑Fi uz mobilo tīklu"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vienmēr atļaut Wi‑Fi meklēšanu"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Vienmēr aktīvs mobilo datu savienojums"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Paātrināta aparatūras darbība piesaistei"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Ievadiet DNS pakalpojumu sniedzēja saimniekdatora nosaukumu"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Rādīt bezvadu attēlošanas sertifikācijas iespējas"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Palieliniet Wi‑Fi reģistrēšanas līmeni; rādīt katram SSID RSSI Wi‑Fi atlasītājā."</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Ja opcija ir iespējota un Wi‑Fi signāls ir vājš, datu savienojuma pāreja no Wi-Fi uz mobilo tīklu tiks veikta agresīvāk."</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Atļaujiet/neatļaujiet Wi‑Fi meklēšanu, pamatojoties uz saskarnē saņemto datplūsmas apjomu."</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Reģistrētāja buferu lielumi"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Atlasīt reģistrētāja bufera liel."</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 3151f56..eaa5539 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Вмрежување"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Приказ на сертификација на безжична мрежа"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Овозможи преопширно пријавување Wi‑Fi"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Агресивно предавање од Wi‑Fi на мобилен"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Секогаш дозволувај Wi‑Fi скенирање во роаминг"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Мобилниот интернет е секогаш активен"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Хардверско забрзување за врзување"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Внесете име на хост на операторот на DNS"</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>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Кога е овозможено, Wi-Fi ќе биде поагресивна при предавање на интернет-врската на мобилната мрежа при слаб сигнал на Wi-Fi"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Дозволи/Забрани Wi‑Fi скенирање во роаминг според количината на постоечкиот податочен сообраќај на интерфејсот."</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Величини на меѓумеморија на забележувач"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Величина/меѓумеморија на дневник"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 2b86e50..0ddfc79 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"നെറ്റ്‍വര്‍ക്കിംഗ്"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"വയർലെസ് ഡിസ്‌പ്ലേ സർട്ടിഫിക്കേഷൻ"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"വൈഫൈ വെർബോസ് ലോഗിംഗ് പ്രവർത്തനക്ഷമമാക്കുക"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"മൊബൈൽ ഹാൻഡ്ഓവറിലേക്ക് വൈഫൈ സക്രിയമാക്കുക"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"എപ്പോഴും വൈഫൈ റോം സ്‌‌കാൻ അനുവദിക്കൂ"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"മൊബൈൽ ഡാറ്റ എല്ലായ്‌പ്പോഴും സജീവം"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"ടെതറിംഗ് ഹാർഡ്‌വെയർ ത്വരിതപ്പെടുത്തൽ"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS ദാതാവിന്‍റെ ഹോസ്റ്റുനാമം നൽകുക"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"വയർലെസ് ഡിസ്‌പ്ലേ സർട്ടിഫിക്കേഷനായി ഓപ്‌ഷനുകൾ ദൃശ്യമാക്കുക"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"വൈഫൈ പിക്കറിൽ ഓരോ SSID RSSI പ്രകാരം കാണിക്കാൻ വൈഫൈ ലോഗിംഗ് നില വർദ്ധിപ്പിക്കുക"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"പ്രവർത്തനക്ഷമമായിരിക്കുമ്പോൾ, വൈഫൈ സിഗ്‌നൽ കുറവായിരിക്കുന്ന സമയത്ത് മൊബൈലിലേക്ക് ഡാറ്റ കണക്ഷൻ വഴി കൈമാറുന്നതിൽ വൈഫൈ കൂടുതൽ സക്രിയമായിരിക്കും"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ഇന്റർഫേസിലെ ഡാറ്റ ട്രാഫിക്ക് സാന്നിദ്ധ്യത്തിന്റെ കണക്ക് അടിസ്ഥാനമാക്കി വൈഫൈ റോം സ്‌കാനുകൾ അനുവദിക്കുക/അനുവദിക്കാതിരിക്കുക"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"ലോഗർ ബഫർ വലുപ്പം"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"ഓരോ ലോഗ് ബഫറിനും വലുപ്പം തിരഞ്ഞെടുക്കൂ"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 152408a..67c6495 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Сүлжээ"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Утасгүй дэлгэцийн сертификат"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi Verbose лог-г идэвхжүүлэх"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Идэвхтэй Wi‑Fi-с мобайл сүлжээнд"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi Роум сканыг байнга зөвшөөрөх"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Мобайл дата байнга идэвхтэй"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Модем болгох хардвер хурдасгуур"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS-н үйлчилгээ үзүүлэгчийн хостын нэрийг оруулах"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Утасгүй дэлгэцийн сертификатын сонголтыг харуулах"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi лог-н түвшинг нэмэгдүүлэх, Wi‑Fi Сонгогч дээрх SSID-д ногдох RSSI-г харуулах"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Идэвхжүүлсэн үед Wi‑Fi холболт сул байх үед дата холболтыг мобайлд шилжүүлэхэд илүү идэвхтэй байх болно"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Интерфэйс дээрх дата трафикын хэмжээнээс хамааран Wi‑Fi Роум Скан-г зөвшөөрөх/үл зөвшөөрөх"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Логгерын буферын хэмжээ"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Лог буфер бүрт ногдох логгерын хэмжээг сонгоно уу"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 7402d29..eeb0a16 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"नेटवर्किंग"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"वायरलेस डिस्प्ले प्रमाणीकरण"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"वाय-फाय व्हर्बोझ लॉगिंग सक्षम करा"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"मोबाइलकडे सोपवण्यासाठी अॅग्रेसिव्ह वाय-फाय"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"वाय-फाय रोम स्‍कॅनला नेहमी अनुमती द्या"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"मोबाइल डेटा नेहमी सक्रिय"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"टेदरिंग हार्डवेअर प्रवेग"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS पुरवठादाराचे होस्टनाव टाका"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"वायरलेस डिस्प्ले प्रमाणिकरणाचे पर्याय दाखवा"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"वाय-फाय लॉगिंग स्‍तर वाढवा, वाय-फाय सिलेक्टरमध्‍ये प्रति SSID RSSI दर्शवा"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"सक्षम केले असताना, वाय-फाय सिग्‍नल कमी असताना, मोबाइलकडे डेटा कनेक्‍शन सोपवण्यासाठी वाय-फाय अधिक अॅग्रेसिव्ह असेल."</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"वाय-फाय रोम स्‍कॅनला इंटरफेसवर उपस्‍थित असलेल्‍या रहदारी डेटाच्या प्रमाणावर आधारित अनुमती द्या/अनुमती देऊ नका"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"लॉगर बफर आकार"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"प्रति लॉग बफर लॉगर आकार निवडा"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 51ab84e..a69024c 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Perangkaian"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Pensijilan paparan wayarles"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Dayakan Pengelogan Berjela-jela Wi-Fi"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Penyerahan Wi-Fi ke mudah alih agresif"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Sentiasa benarkan Imbasan Perayauan Wi-Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Data mudah alih sentiasa aktif"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Pecutan perkakasan penambatan"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Masukkan nama hos pembekal DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Tunjukkan pilihan untuk pensijilan paparan wayarles"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Tingkatkan tahap pengelogan Wi-Fi, tunjuk setiap SSID RSSI dalam Pemilih Wi-Fi"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Apabila didayakan, Wi-Fi akan menjadi lebih agresif dalam menyerahkan sambungan data ke mudah alih, apabila isyarat Wi-Fi rendah"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Benarkan/Jangan benarkan Imbasan Perayauan Wi-Fi berdasarkan jumlah trafik data yang ada pada antara muka"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Saiz penimbal pengelog"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Pilih saiz Pengelog bagi setiap penimbal log"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index c643c59..5e78249 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"ချိတ်ဆက်ဆောင်ရွက်ခြင်း"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"ကြိုးမဲ့ပြသမှု အသိအမှတ်ပြုလက်မှတ်"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi Verbose မှတ်တမ်းတင်ခြင်းအား ဖွင့်မည်"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Wi‑Fi မှ မိုဘိုင်းသို့ လွှဲပြောင်းရန်"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi ရွမ်းရှာဖွေမှုကို အမြဲတမ်း ခွင့်ပြုမည်"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"မိုဘိုင်းဒေတာကို အမြဲဖွင့်ထားရန်"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"ဖုန်းကို မိုဒမ်အဖြစ်အသုံးပြုမှု စက်ပစ္စည်းဖြင့် အရှိန်မြှင့်တင်ခြင်း"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS ဝန်ဆောင်မှုပေးသူ၏ အင်တာနက်လက်ခံဝန်ဆောင်ပေးသူအမည်ကို ထည့်ပါ"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"ကြိုးမဲ့ အခင်းအကျင်း အသိအမှတ်ပြုလက်မှတ်အတွက် ရွေးချယ်စရာများပြရန်"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi မှတ်တမ်းတင်ခြင်း နှုန်းအားမြင့်ကာ၊ Wi‑Fi ရွေးရာတွင် SSID RSSI ဖြင့်ပြပါ"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"ဖွင့်ထားပါက Wi‑Fi လွှင့်အား နည်းချိန်တွင် Wi‑Fi မှ မိုဘိုင်းသို့ ဒေတာချိတ်ဆက်မှုကို လွှဲပြောင်းရာ၌ ပိုမိုထိရောက်ပါသည်"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"မျက်နှာပြင်တွင် ဖော်ပြသည့် အချက်လက် အသွားအလာ ပမာဏပေါ်တွင် အခြေခံ၍ WIFI ရွမ်းရှာဖွေမှုအား ဖွင့်/ပိတ်မည်"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"လော့ဂါး ဘာဖား ဆိုက်များ"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"လော့ ဘာဖားတွက် လော့ဂါးဆိုက် ရွေး"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 0cea1a7..d45bbc3 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Nettverk"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Trådløs skjermsertifisering"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Aktiver detaljert Wi-Fi-loggføring"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Aggressiv overføring fra Wi-Fi til mobil"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Tillat alltid skanning for Wi-Fi-roaming"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobildata er alltid aktiv"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Maskinvareakselerasjon for internettdeling"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Skriv inn vertsnavnet til DNS-leverandøren"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Vis alternativer for sertifisering av trådløs skjerm"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Øk Wi-Fi-loggenivå – vis per SSID RSSI i Wi-Fi-velgeren"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Hvis dette slås på, overfører Wi-Fi-nettverket datatilkoblingen til mobil mer aggressivt når Wi-Fi-signalet er svakt"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Tillat / ikke tillat skanning for Wi-Fi-roaming basert på mengden datatrafikk til stede i grensesnittet"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Bufferstørrelser for logg"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Velg loggstørrelse per loggbuffer"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index d0ec0f5..d26541c 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"नेटवर्किङ"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"ताररहित प्रदर्शन प्रमाणीकरण"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi-Fi वर्बोज लग सक्षम पार्नुहोस्"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"आक्रामक ढंगले Wi‑Fi बाट मोबाइलमा हस्तान्तरण"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi-Fi घुम्ने स्क्यान गर्न सधैँ अनुमति दिनुहोस्"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"मोबाइल डेटा सधैँ सक्रिय राख्नुहोस्"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"टेदरिङको लागि हार्डवेयरको प्रवेग"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS प्रदायकको होस्टनाम प्रविष्ट गर्नुहोस्"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"ताररहित प्रदर्शन प्रमाणीकरणका लागि विकल्पहरू देखाउनुहोस्"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi-Fi लग स्तर बढाउनुहोस्, Wi-Fi चयनकर्तामा प्रति SSID RSSI देखाइन्छ"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"सक्षम गरिएको अवस्थामा, Wi-Fi सिग्नल न्यून हुँदा, Wi-Fi ले बढी आक्रामक ढंगले मोबाइलमा डेटा जडान हस्तान्तरण गर्नेछ"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Wi-Fi घुम्ने स्क्यान इन्टरफेसमा रहेको डेटा यातायातको मात्रामा आधारित अनुमति दिनुहोस्/नदिनुहोस्"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"लगर बफर आकारहरू"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"लग बफर प्रति लगर आकार चयन गर्नुहोस्"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 87d20c2..ce25cc7 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Netwerken"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Certificering van draadloze weergave"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Uitgebreide wifi-logregistratie insch."</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agressieve handover van wifi naar mobiel"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Altijd roamingscans voor wifi toestaan"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobiele data altijd actief"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardwareversnelling voor tethering"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Geef hostnaam van DNS-provider op"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Opties weergeven voor certificering van draadloze weergave"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Logniveau voor wifi verhogen, weergeven per SSID RSSI in wifi-kiezer"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Indien ingeschakeld, is wifi agressiever bij het overgeven van de gegevensverbinding aan mobiel wanneer het wifi-signaal zwak is"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Roamingscans voor wifi (niet) toestaan op basis van de hoeveelheid dataverkeer die aanwezig is bij de interface"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Logger-buffergrootten"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Kies Logger-grootten per logbuffer"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index d870a99..d64c30f 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"ਨੈੱਟਵਰਕਿੰਗ"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"ਵਾਇਰਲੈੱਸ ਡਿਸਪਲੇ ਪ੍ਰਮਾਣੀਕਰਨ"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"ਵਾਈ-ਫਾਈ ਵਰਬੋਸ ਲੌਗਿੰਗ ਚਾਲੂ ਕਰੋ"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"ਆਕਰਮਣਸ਼ੀਲ ਵਾਈ‑ਫਾਈ ਤੋਂ ਮੋਬਾਈਲ ਹੈਂਡਓਵਰ"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ਹਮੇਸ਼ਾਂ ਵਾਈ‑ਫਾਈ ਰੋਮ ਸਕੈਨਾਂ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"ਮੋਬਾਈਲ ਡਾਟਾ ਹਮੇਸ਼ਾਂ ਕਿਰਿਆਸ਼ੀਲ"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"ਟੈਦਰਿੰਗ ਹਾਰਡਵੇਅਰ ਐਕਸੈੱਲਰੇਸ਼ਨ"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS ਪ੍ਰਦਾਨਕ ਦਾ ਹੋਸਟਨਾਮ ਦਾਖਲ ਕਰੋ"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"ਵਾਇਰਲੈੱਸ ਡਿਸਪਲੇ ਪ੍ਰਮਾਣੀਕਰਨ ਲਈ ਚੋਣਾਂ ਪ੍ਰਦਰਸ਼ਿਤ ਕਰੋ"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"ਵਾਈ‑ਫਾਈ ਲੌਗਿੰਗ ਪੱਧਰ ਵਧਾਓ, ਵਾਈ‑ਫਾਈ Picker ਵਿੱਚ ਪ੍ਰਤੀ SSID RSSI ਦਿਖਾਓ"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"ਜਦੋਂ ਯੋਗ ਬਣਾਇਆ ਹੋਵੇ, ਤਾਂ ਵਾਈ‑ਫਾਈ ਸਿਗਨਲ ਘੱਟ ਹੋਣ \'ਤੇ ਵਾਈ‑ਫਾਈ ਡਾਟਾ ਕਨੈਕਸ਼ਨ ਮੋਬਾਈਲ ਨੂੰ ਹੈਂਡ ਓਵਰ ਕਰਨ ਵਿੱਚ ਵੱਧ ਆਕਰਮਣਸ਼ੀਲ ਹੋਵੇਗਾ।"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ਇੰਟਰਫੇਸ ਤੇ ਮੌਜੂਦ ਡਾਟਾ ਟ੍ਰੈਫਿਕ ਦੀ ਮਾਤਰਾ ਦੇ ਆਧਾਰ ਤੇ ਵਾਈ-ਫਾਈ ਰੋਮ ਸਕੈਨ ਦੀ ਆਗਿਆ ਦਿਓ/ਅਸਵੀਕਾਰ ਕਰੋ"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"ਲੌਗਰ ਬਫ਼ਰ ਆਕਾਰ"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"ਪ੍ਰਤੀ ਲੌਗ ਬਫ਼ਰ ਲੌਗਰ ਆਕਾਰ ਚੁਣੋ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 7b66aa5..d50528d 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Sieci"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Wyświetlacz bezprzewodowy"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Szczegółowy dziennik Wi-Fi"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Przełączaj z Wi-Fi na sieć komórkową"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Zawsze szukaj Wi-Fi w roamingu"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilna transmisja danych zawsze aktywna"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Akceleracja sprzętowa tetheringu"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Wpisz nazwę hosta dostawcy DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Pokaż opcje certyfikacji wyświetlacza bezprzewodowego"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Zwiększ poziom rejestrowania Wi‑Fi, pokazuj według RSSI SSID w selektorze Wi‑Fi"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Po włączeniu połączenie danych będzie bardziej agresywnie przełączać się z Wi-Fi na sieć komórkową przy słabym sygnale Wi-Fi"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Zezwalaj/nie zezwalaj na wyszukiwanie sieci Wi-Fi w roamingu w zależności od natężenia ruchu"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Rozmiary bufora Rejestratora"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Wybierz rozmiary Rejestratora/bufor dziennika"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index d99097a..67fda03 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Redes"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Certificação de Display sem fio"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Ativar registro extenso de Wi-Fi"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Mudança agressiva de Wi-Fi para móvel"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Sempre permitir verif. de roaming de Wi-Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Dados móveis sempre ativos"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleração de hardware de tethering"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Informe o nome do host do provedor de DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opções de certificação de Display sem fio"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar o nível de registro do Wi-Fi; mostrar conforme o RSSI de SSID na Seleção de Wi-Fi"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Quando ativada, o Wi-Fi será mais agressivo em passar a conexão de dados para móvel, quando o sinal de Wi-Fi estiver fraco"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permitir/proibir verificações de roaming de Wi-Fi com base no volume do tráfego de dados presente na interface"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Tamanhos de buffer de logger"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Sel. tam. de logger/buffer de log"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 8c7fbba..d7496454c4 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Redes"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Certificação de display sem fios"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Ativar o registo verboso de Wi-Fi"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Mudança brusca de Wi‑Fi para rede móvel"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permitir sempre a deteção de Wi-Fi em roaming"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Dados móveis sempre ativos"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleração de hardware para ligação (à Internet) via telemóvel"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Introduza o nome de anfitrião do fornecedor DNS."</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opções da certificação de display sem fios"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar o nível de reg. de Wi-Fi, mostrar por RSSI de SSID no Selec. de Wi-Fi"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Se estiver ativado, o Wi-Fi será mais agressivo ao transmitir a lig. de dados para a rede móvel quando o sinal Wi-Fi estiver fraco"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permitir/impedir a deteção de Wi-Fi em roaming com base na quantidade de tráfego de dados presente na interface"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Tamanhos da memória intermédia do registo"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Selec. tam. reg. p/ mem. int. reg."</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index d99097a..67fda03 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Redes"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Certificação de Display sem fio"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Ativar registro extenso de Wi-Fi"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Mudança agressiva de Wi-Fi para móvel"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Sempre permitir verif. de roaming de Wi-Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Dados móveis sempre ativos"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleração de hardware de tethering"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Informe o nome do host do provedor de DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opções de certificação de Display sem fio"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar o nível de registro do Wi-Fi; mostrar conforme o RSSI de SSID na Seleção de Wi-Fi"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Quando ativada, o Wi-Fi será mais agressivo em passar a conexão de dados para móvel, quando o sinal de Wi-Fi estiver fraco"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permitir/proibir verificações de roaming de Wi-Fi com base no volume do tráfego de dados presente na interface"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Tamanhos de buffer de logger"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Sel. tam. de logger/buffer de log"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 1c67550..1e91d82 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Conectare la rețele"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Certificare Ecran wireless"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Înregistrare prin Wi-Fi de volume mari de date"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Predare agresivă de la Wi-Fi la mobilă"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Se permite întotdeauna scanarea traficului Wi-Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Date mobile permanent active"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Accelerare hardware pentru tethering"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Introduceți numele de gazdă al furnizorului de DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Afișați opțiunile pentru certificarea Ecran wireless"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Măriți niv. de înr. prin Wi‑Fi, afișați în fcț. de SSID RSSI în Selectorul Wi‑Fi"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Când este activată, Wi-Fi va fi mai agresivă la predarea conexiunii de date către rețeaua mobilă când semnalul Wi-Fi este slab"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permiteți/Nu permiteți scanarea traficului Wi-Fi în funcție de traficul de date din interfață"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Dimensiunile tamponului jurnalului"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Dimensiuni jurnal / tampon jurnal"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 4b11594..693332f 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Сети"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Серт. беспроводн. мониторов"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Подробный журнал Wi‑Fi"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Переключаться на мобильную сеть"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Всегда включать поиск сетей Wi-Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Не отключать мобильный Интернет"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Аппаратное ускорение в режиме модема"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Введите имя хоста поставщика услуг DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Показывать параметры сертификации беспроводных мониторов"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"При выборе Wi‑Fi указывать в журнале RSSI для каждого SSID"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Принудительно переключаться на мобильную сеть, если сигнал Wi-Fi слабый"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Включать или отключать поиск сетей Wi-Fi во время передачи данных в зависимости от объема трафика"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Размер буфера журнала"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Выберите размер буфера журнала"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 2ffe814d..6abd14d 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"ජාලකරණය"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"නොරැහැන් සංදර්ශක සහතිකය"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"විස්තරාත්මක Wi‑Fi ලොග් කිරීම සබල කරන්න"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"ආක්‍රමණික Wi‑Fi සිට ජංගම බාර දීම"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi රෝම් පරිලෝකන වෙතට සැමවිට අවසර දෙන්න"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"ජංගම දත්ත සැමවිට ක්‍රියාකාරීය"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"ටෙදරින් දෘඪාංග ත්වරණය"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS සැපයුම්කරුගේ සත්කාරක නම ඇතුළු කරන්න"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"නොරැහැන් සංදර්ශක සහතිකය සඳහා විකල්ප පෙන්වන්න"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi ලොග් මට්ටම වැඩි කරන්න, Wi‑Fi තෝරනයෙහි SSID RSSI අනුව පෙන්වන්න"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"සබල විට Wi‑Fi සිග්නලය අඩු විට Wi‑Fi දත්ත සම්බන්ධතාවය ජංගම වෙත භාර දීමට වඩා ආක්‍රමණික වේ"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"අතුරු මුහුණතෙහි ඇති දත්ත තදබදය අනුව Wi‑Fi රෝම් පරිලෝකන වෙත ඉඩ දෙන්න/නොදෙන්න"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"ලෝගයේ අන්තරාවක ප්‍රමාණය"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"ලොග අන්තරාවකට ලෝගයේ ප්‍රමාණය තෝරන්න"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 0cefd71..8cc2dac 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Siete"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Certifikácia bezdrôtového zobrazenia"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Podrobné denníky Wi‑Fi"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agres. odovzdávať Wi‑Fi na mobilnú sieť"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vždy povoliť funkciu Wi‑Fi Roam Scans"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilné dáta ponechať vždy aktívne"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardvérovú akcelerácia pre tethering"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Zadajte názov hostiteľa poskytovateľa DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Zobraziť možnosti certifikácie bezdrôtového zobrazenia"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Zvýšiť úroveň denníkov Wi‑Fi, zobrazovať podľa SSID RSSI pri výbere siete Wi‑Fi"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Keď túto možnosť zapnete, Wi‑Fi bude agresívnejšie odovzdávať dátové pripojenie na mobilnú sieť vtedy, keď bude slabý signál Wi‑Fi"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Povoliť alebo zakázať funkciu Wifi Roam Scans na základe objemu prenosu údajov v rozhraní"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Vyrovnávacia pamäť nástroja denníkov"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Veľkosť vyrovnávacej pamäte nástroja denníkov"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 0864d5b..af8eb6e 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Omrežja"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Potrdilo brezžičnega zaslona"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Omogoči podrob. zapis. dnevnika za Wi-Fi"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Odločen prehod iz Wi-Fi-ja v mobil. omr."</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vedno omogoči iskanje omrežij Wi-Fi za gostovanje"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Prenos podatkov v mobilnem omrežju je vedno aktiven"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Strojno pospeševanje za internetno povezavo prek mobilnega telefona"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Vnesite ime gostitelja pri ponudniku strežnika DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Pokaži možnosti za potrdilo brezžičnega zaslona"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Povečaj raven zapis. dnev. za Wi-Fi; v izbir. Wi‑Fi-ja pokaži glede na SSID RSSI"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Če je ta možnost omogočena, Wi-Fi odločneje preda podatkovno povezavo mobilnemu omrežju, ko je signal Wi-Fi šibek."</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Omogoči/onemogoči iskanje omrežij Wi-Fi za gostovanje glede na količino podatkovnega prometa pri vmesniku"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Velikosti medpomn. zapisov. dnevnika"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Izberite velikost medpomnilnika dnevnika"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 63da6ff..88b1057 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Rrjetet"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Certifikimi i ekranit valor"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Aktivizo hyrjen Wi-Fi Verbose"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Dorëzimi agresiv i Wi‑Fi te rrjeti celular"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Lejo gjithmonë skanimet për Wi-Fi edhe kur je në lëvizje"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Të dhënat celulare gjithmonë aktive"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Përshpejtimi i harduerit për ndarjen"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Fut emrin e pritësit të ofruesit të DNS-së"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Shfaq opsionet për certifikimin e ekranit valor"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Rrit nivelin regjistrues të Wi‑Fi duke shfaqur SSID RSSI-në te Zgjedhësi i Wi‑Fi"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Kur ky funksion aktivizohet, Wi‑Fi bëhet më agresiv në kalimin e lidhjes së të dhënave te rrjeti celular, në rastet kur sinjali Wi‑Fi është i dobët"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Lejo/Ndalo skanimet për Wi‑Fi në roaming, bazuar në sasinë e trafikut të të dhënave të pranishme në ndërfaqe"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Madhësitë e regjistruesit"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Përzgjidh madhësitë e regjistruesit"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 4c7aed8..362fc1f 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Умрежавање"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Сертификација бежичног екрана"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Омогући детаљнију евиденцију за Wi‑Fi"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Агресиван прелаз са Wi‑Fi мреже на мобилну"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Увек дозволи скенирање Wi‑Fi-ја у ромингу"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Мобилни подаци су увек активни"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Хардверско убрзање привезивања"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Унесите име хоста добављача услуге DNS-а"</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>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Кад се омогући, Wi‑Fi ће бити агресивнији при пребацивању мреже за пренос података на мобилну ако је Wi‑Fi сигнал слаб"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Дозволи/забрани скенирање Wi-Fi-ја у ромингу на основу присутног протока података на интерфејсу"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Величине бафера података у програму за евидентирање"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Изаберите величине по баферу евиденције"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index e44dcd8..230dfee 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Nätverk"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Certifiering för Wi-Fi-skärmdelning"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Aktivera utförlig loggning för Wi-Fi"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Aggressiv överlämning fr. Wi-Fi t. mobil"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Tillåt alltid sökning efter Wi-Fi-roaming"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobildata alltid aktiverad"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Maskinvaruacceleration för internetdelning"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Ange värdnamn för DNS-leverantör"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Visa certifieringsalternativ för Wi-Fi-skärmdelning"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Öka loggningsnivån för Wi-Fi, visa per SSID RSSI i Wi‑Fi Picker"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"När funktionen har aktiverats kommer dataanslutningen lämnas över från Wi-Fi till mobilen på ett aggressivare sätt när Wi-Fi-signalen är svag"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Tillåt/tillåt inte sökning efter Wi-Fi-roaming utifrån mängden datatrafik i gränssnittet"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Buffertstorlekar för logg"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Välj loggstorlekar per loggbuffert"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 66cfda8..1d46260 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Mtandao"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Chaguo za cheti cha kuonyesha pasiwaya"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Washa Uwekaji kumbukumbu za WiFi kutumia Sauti"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Ukabidhi hima kutoka Wifi kwenda mtandao wa simu"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Ruhusu Uchanganuzi wa Matumizi ya Mitandao mingine"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Iendelee kutumia data ya simu"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Kuongeza kasi kwa kutumia maunzi ili kusambaza mtandao"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Weka jina la mpangishi wa huduma za DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Onyesha chaguo za cheti cha kuonyesha pasiwaya"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Ongeza hatua ya uwekaji kumbukumbu ya Wi-Fi, onyesha kwa kila SSID RSSI kwenye Kichukuzi cha Wi-Fi"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Ikiwashwa, Wi-Fi itakabidhi kwa hima muunganisho wa data kwa mtandao wa simu, wakati mtandao wa Wi-Fi si thabiti"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Ruhusu au Zuia Uchanganuzi wa Matumizi ya Mitandao mingine ya Wifi kulingana na kiasi cha trafiki ya data kilicho kwenye kiolesura"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Ukubwa wa kiweka bafa ya kumbukumbu"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Chagua ukubwa wa kila Kumbukumbu"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index dd218c6..e9fd79b 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"நெட்வொர்க்கிங்"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"வயர்லெஸ் காட்சிக்கான சான்றிதழ்"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"வைஃபை அதிவிவர நுழைவை இயக்கு"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"ஒத்துழைக்காத வைஃபையிலிருந்து மொபைல் தரவிற்கு மாறு"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"எப்போதும் வைஃபை ரோமிங் ஸ்கேன்களை அனுமதி"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"மொபைல் டேட்டாவை எப்போதும் இயக்கத்திலேயே வை"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"வன்பொருள் விரைவுப்படுத்துதல் இணைப்பு முறை"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS வழங்குநரின் ஹோஸ்ட் பெயரை உள்ளிடவும்"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"வயர்லெஸ் காட்சி சான்றுக்கான விருப்பங்களைக் காட்டு"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wifi நுழைவு அளவை அதிகரித்து, வைஃபை தேர்வியில் ஒவ்வொன்றிற்கும் SSID RSSI ஐ காட்டுக"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"இயக்கப்பட்டதும், வைஃபை சிக்னல் குறையும் போது, வைஃபை முழுமையாக ஒத்துழைக்காமல் இருந்தால் மொபைல் தரவிற்கு மாறும்"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"இடைமுகத்தில் உள்ள ட்ராஃபிக் தரவின் அளவைப் பொறுத்து வைஃபை ரோமிங் ஸ்கேன்களை அனுமதி/அனுமதிக்காதே"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"லாகர் பஃபர் அளவுகள்"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"லாக் பஃபர் ஒன்றிற்கு லாகர் அளவுகளைத் தேர்வுசெய்க"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index b21eb8c..c2b738a 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"నెట్‌వర్కింగ్"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"వైర్‌లెస్ ప్రదర్శన ప్రమాణీకరణ"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi విశదీకృత లాగింగ్‌ను ప్రారంభించండి"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"మొబైల్‌కి మార్చేలా చురుకైన Wi‑Fi"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi సంచార స్కాన్‌లను ఎల్లప్పుడూ అనుమతించు"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"మొబైల్ డేటాని ఎల్లప్పుడూ సక్రియంగా ఉంచు"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"టెథెరింగ్ హార్డ్‌వేర్ వేగవృద్ధి"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS ప్రదాత యొక్క హోస్ట్‌పేరును నమోదు చేయండి"</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>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"ప్రారంభించబడినప్పుడు, Wi‑Fi సిగ్నల్ బలహీనంగా ఉంటే డేటా కనెక్షన్‌ను మొబైల్‌కి మార్చేలా Wi‑Fi చురుగ్గా వ్యవహరిస్తుంది"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ఇంటర్‌ఫేస్‌లో ఉండే డేటా ట్రాఫిక్ పరిమాణం ఆధారంగా Wi‑Fi సంచార స్కాన్‌లను అనుమతించు/నిరాకరించు"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"లాగర్ బఫర్ పరిమాణాలు"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"లాగ్ బఫర్‌కి లాగర్ పరిమా. ఎంచుకోండి"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 447b188..57b12a5 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"เครือข่าย"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"การรับรองการแสดงผลแบบไร้สาย"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"เปิดใช้การบันทึกรายละเอียด Wi-Fi"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"สลับ Wi‑Fi เป็นมือถือเมื่อสัญญาณอ่อน"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ใช้การสแกน Wi-Fi ข้ามเครือข่ายเสมอ"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"เปิดใช้อินเทอร์เน็ตมือถือเสมอ"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"การเร่งฮาร์ดแวร์การเชื่อมต่ออินเทอร์เน็ตผ่านมือถือ"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"ป้อนชื่อโฮสต์ของผู้ให้บริการ DNS"</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>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"เมื่อเปิดใช้แล้ว Wi-Fi จะส่งผ่านการเชื่อมต่อข้อมูลไปยังเครือข่ายมือถือเมื่อสัญญาณ Wi-Fi อ่อน"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"อนุญาต/ไม่อนุญาตการสแกน Wi-Fi ข้ามเครือข่าย ตามปริมาณข้อมูลการเข้าชมที่ปรากฏในอินเทอร์เฟซ"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"ขนาดบัฟเฟอร์ของ Logger"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"เลือกขนาด Logger ต่อบัฟเฟอร์ไฟล์บันทึก"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index a5e0b89..72261af 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Networking"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Certification ng wireless display"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"I-enable ang Pagla-log sa Wi‑Fi Verbose"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agresibong paglipat ng Wi‑Fi sa mobile"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Palaging payagan ang Mga Pag-scan sa Roaming ng Wi‑Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Palaging aktibo ang mobile data"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardware acceleration para sa pag-tether"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Ilagay ang hostname ng DNS provider"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Ipakita ang mga opsyon para sa certification ng wireless display"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Pataasin ang antas ng Wi‑Fi logging, ipakita sa bawat SSID RSSI sa Wi‑Fi Picker"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Kapag na-enable, magiging mas agresibo ang Wi‑Fi sa paglipat sa koneksyon ng mobile data kapag mahina ang signal ng Wi‑Fi"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Payagan/Huwag payagan ang Mga Pag-scan sa Roaming ng Wi‑Fi batay sa dami ng trapiko ng data na mayroon sa interface"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Mga laki ng buffer ng Logger"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Pumili ng mga laki ng Logger bawat log buffer"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index e6bba5b..948e4e5 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Ağ işlemleri"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Kablosuz ekran sertifikası"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Kablosuz Ayrıntılı Günlük Kaydını etkinleştir"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Kablosuzdan mobil ağa agresif geçiş"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Kablosuz Dolaşım Taramalarına daima izin ver"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobil veri her zaman etkin"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering donanım hızlandırıcısı"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS sağlayıcının ana makine adını gir"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Kablosuz ekran sertifikası seçeneklerini göster"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Kablosuz günlük kaydı seviyesini artır. Kablosuz Seçici\'de her bir SSID RSSI için göster."</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Etkinleştirildiğinde, kablosuz ağ sinyali zayıfken veri bağlantısının mobil ağa geçirilmesinde daha agresif olunur"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Arayüzde mevcut veri trafiği miktarına bağlı olarak Kablosuz Dolaşım Taramalarına İzin Verin/Vermeyin"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Günlük Kaydedici arabellek boyutları"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Gün. arabel. başına Gün. Kayd. boyutunu seç"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 65f39ed..664fda7 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Мережі"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Сертифікація бездрот. екрана"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Докладний запис у журнал Wi-Fi"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Перемикатися з Wi-Fi на мобільну мережу"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Завжди шукати мережі Wi-Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Не вимикати мобільне передавання даних"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Апаратне прискорення під час використання телефона в режимі модема"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Введіть ім’я хосту постачальника послуг DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Показати параметри сертифікації бездротового екрана"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Показувати в журналі RSSI для кожного SSID під час вибору Wi-Fi"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Примусово перемикатися на мобільну мережу, коли сигнал Wi-Fi слабкий"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Дозволити чи заборонити Wi-Fi шукати роумінг на основі обсягу трафіку даних в інтерфейсі"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Розміри буфера журналу"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Виберіть розміри буфера журналу"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 7830bb8..226b862 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"نیٹ ورکنگ"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"وائرلیس ڈسپلے سرٹیفیکیشن"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"‏Wi‑Fi وربوس لاگنگ فعال کریں"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"‏Wi‑Fi سے موبائل کو جارحانہ ہینڈ اوور"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"‏ہمیشہ Wi‑Fi روم اسکینز کی اجازت دیں"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"موبائل ڈیٹا ہمیشہ فعال رکھیں"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"ٹیدرنگ ہارڈویئر سرعت کاری"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"‏DNS فراہم کنندہ کے میزبان کا نام درج کریں"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"وائرلیس ڈسپلے سرٹیفیکیشن کیلئے اختیارات دکھائیں"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"‏Wi‑Fi لاگنگ لیول میں اضافہ کریں، Wi‑Fi منتخب کنندہ میں فی SSID RSSI دکھائیں"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"‏فعال کئے جانے پر، جب Wi‑Fi سگنل کمزور ہوگا، تو Wi‑Fi موبائل پر ڈیٹا کنکشن بھیجنے کیلئے مزید جارحانہ کارروائی کرے گا"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"‏انٹرفیس پر موجود ڈیٹا ٹریفک کی مقدار کی بنیاد پر Wi‑Fi روم اسکینز کی اجازت دیں/اجازت نہ دیں"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"لاگر بفر کے سائز"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"فی لاگ بفر لاگر کے سائز منتخب کریں"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index acaaaf1..fdb3ef4 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Tarmoqlar"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Simsiz monitor sertifikatlari"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Batafsil Wi-Fi jurnali"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Mobil internetga o‘tish"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi-Fi tarmoqlarini qidirishga doim ruxsat"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobil internet doim yoniq tursin"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Modem rejimida apparatli tezlashtirish"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS provayderining host nomini kiriting"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Simsiz monitorlarni sertifikatlash parametrini ko‘rsatish"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi-Fi ulanishini tanlashda har bir SSID uchun jurnalda ko‘rsatilsin"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Agar ushbu funksiya yoqilsa, Wi-Fi signali past bo‘lganda internetga ulanish majburiy ravishda mobil internetga o‘tkaziladi"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Ma’lumotlarni uzatish vaqtida  trafik hajmiga qarab Wi-Fi tarmoqlarni qidirish funksiyasini yoqish yoki o‘chirish"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Jurnal buferi hajmi"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Jurnal xotirasi hajmini tanlang"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 7732b54..a7a5855 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Mạng"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Chứng nhận hiển thị không dây"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Bật ghi nhật ký chi tiết Wi‑Fi"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Chuyển vùng Wi‑Fi tích cực sang mạng DĐ"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Luôn cho phép quét chuyển vùng Wi‑Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Dữ liệu di động luôn hiện hoạt"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Tăng tốc phần cứng cho chia sẻ kết nối"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Nhập tên máy chủ của nhà cung cấp DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Hiển thị tùy chọn chứng nhận hiển thị không dây"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Tăng mức ghi nhật ký Wi‑Fi, hiển thị mỗi SSID RSSI trong bộ chọn Wi‑Fi"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Khi được bật, Wi‑Fi sẽ tích cực hơn trong việc chuyển vùng kết nối dữ liệu sang mạng di động khi tín hiệu Wi‑Fi yếu"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Cho phép/Không cho phép quét chuyển vùng Wi‑Fi dựa trên lưu lượng truy cập dữ liệu có tại giao diện"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Kích cỡ tải trình ghi"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Chọn kích thước Trình ghi/lần tải nhật ký"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index f036eae..5a1d067 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"网络"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"无线显示认证"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"启用WLAN详细日志记录功能"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"主动从 WLAN 网络切换到移动数据网络"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"一律允许WLAN漫游扫描"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"始终开启移动数据网络"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"网络共享硬件加速"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"输入 DNS 提供商的主机名"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"显示无线显示认证选项"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"提升WLAN日志记录级别(在WLAN选择器中显示每个SSID的RSSI)"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"开启此设置后,系统会在 WLAN 信号较弱时,主动将网络模式从 WLAN 网络切换到移动数据网络"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"根据接口中目前的数据流量允许/禁止WLAN漫游扫描"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"日志记录器缓冲区大小"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"选择每个日志缓冲区的日志记录器大小"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index d57a8fd..acc3bb8 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"網絡"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"無線螢幕分享認證"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"啟用 Wi‑Fi 詳細記錄"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"加強 Wi-Fi 至流動數據轉換"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"永遠允許 Wi-Fi 漫遊掃描"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"一律保持啟用流動數據"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"網絡共享硬件加速"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"輸入網域名稱系統 (DNS) 供應商的主機名稱"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"顯示無線螢幕分享認證的選項"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"讓 Wi‑Fi 記錄功能升級,在 Wi‑Fi 選擇器中依每個 SSID RSSI 顯示 Wi‑Fi 詳細紀錄"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"啟用後,Wi-Fi 連線會在訊號不穩定的情況下更積極轉換成流動數據連線"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"根據介面中目前的數據流量允許/禁止 WiFi 漫遊掃描"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"記錄器緩衝區空間"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"選取每個記錄緩衝區的記錄器空間"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 5a329fa..775b928 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"網路連線"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"無線螢幕分享認證"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"啟用 Wi‑Fi 詳細紀錄設定"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Wi-Fi 至行動數據轉換強化"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"一律允許 Wi-Fi 漫遊掃描"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"行動數據連線一律保持啟用狀態"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"數據連線硬體加速"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"輸入 DNS 供應商的主機名稱"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"顯示無線螢幕分享認證的選項"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"讓 Wi‑Fi 記錄功能升級,在 Wi‑Fi 選擇器中依每個 SSID RSSI 顯示 Wi‑Fi 詳細紀錄"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"啟用時,Wi-Fi 連線在訊號不穩的情況下會更積極轉換成行動數據連線"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"根據介面中目前的數據流量允許/禁止 Wi-Fi 漫遊掃描"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"紀錄器緩衝區空間"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"選取每個紀錄緩衝區的紀錄器空間"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 3649ba2..13b1603 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -196,7 +196,6 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Ukunethiwekha"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Ukunikezwa isitifiketi sokubukeka okungenantambo"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Nika amandlaukungena kwe-Wi-Fi Verbose"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Ukudluliselwa okunamandla kakhulu kwe-Wi-Fi ukuya kuselula"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vumela njalo ukuskena kokuzula kwe-Wi-Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Idatha yeselula ihlala isebenza"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"I-Tethering hardware acceleration"</string>
@@ -223,7 +222,6 @@
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Faka igama lomsingathi womhlinzeki we-DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Bonisa izinketho zokunikeza isitifiketi ukubukeka okungenantambo"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"khuphula izinga lokungena le-Wi-Fi, bonisa nge-SSID RSSI engayodwana kusikhethi se-Wi-Fi"</string>
-    <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Uma inikwe amandla, i-Wi-Fi izoba namandla kakhulu ekudluliseleni ukuxhumeka kwedatha kuselula, uma isignali ye-Wi-Fi iphansi"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Vumela/Ungavumeli ukuskena kokuzula kwe-Wi-Fi okususelwa kunani ledatha yethrafikhi ekhona ekusebenzisaneni"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Amasayizi weloga ngebhafa"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Khetha amasayizi weloga ngebhafa ngayinye yelogu"</string>
diff --git a/packages/SettingsLib/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml
index bd963e9..ddb49b6 100644
--- a/packages/SettingsLib/res/values/dimens.xml
+++ b/packages/SettingsLib/res/values/dimens.xml
@@ -74,4 +74,13 @@
          fraction of a pixel.-->
     <fraction name="battery_subpixel_smoothing_left">0%</fraction>
     <fraction name="battery_subpixel_smoothing_right">0%</fraction>
+
+    <!-- Zen mode panel: condition item button padding -->
+    <dimen name="zen_mode_condition_detail_button_padding">8dp</dimen>
+    <!-- Zen mode panel: spacing between condition items -->
+    <dimen name="zen_mode_condition_detail_item_spacing">12dp</dimen>
+    <!-- Zen mode panel: spacing between two-line condition upper and lower lines -->
+    <dimen name="zen_mode_condition_detail_item_interline_spacing">4dp</dimen>
+    <!-- Zen mode panel: bottom padding, a bit less than qs_panel_padding -->
+    <dimen name="zen_mode_condition_detail_bottom_padding">4dp</dimen>
 </resources>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 042767d..5dcc927 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1025,4 +1025,9 @@
         <item quantity="other">%1$d devices connected</item>
     </plurals>
 
+    <!-- Content description of zen mode time condition plus button (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_manual_zen_more_time">More time.</string>
+    <!-- Content description of zen mode time condition minus button (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_manual_zen_less_time">Less time.</string>
+
 </resources>
diff --git a/packages/SettingsLib/res/values/styles.xml b/packages/SettingsLib/res/values/styles.xml
index 3f312f4..bae8387 100644
--- a/packages/SettingsLib/res/values/styles.xml
+++ b/packages/SettingsLib/res/values/styles.xml
@@ -21,4 +21,10 @@
     <style name="TextAppearanceMedium">
         <item name="android:textAppearance">?android:attr/textAppearanceMedium</item>
     </style>
+
+    <style name="BorderlessButton">
+        <item name="android:padding">12dp</item>
+        <item name="android:background">@drawable/btn_borderless_rect</item>
+        <item name="android:gravity">center</item>
+    </style>
 </resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index 3c46d99..d001e66 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -21,10 +21,9 @@
 import android.os.UserManager;
 import android.print.PrintManager;
 import android.provider.Settings;
-
 import com.android.internal.util.UserIcons;
 import com.android.settingslib.drawable.UserIconDrawable;
-
+import com.android.settingslib.wrapper.LocationManagerWrapper;
 import java.text.NumberFormat;
 
 public class Utils {
@@ -45,6 +44,24 @@
         com.android.internal.R.drawable.ic_wifi_signal_4
     };
 
+    public static void updateLocationEnabled(Context context, boolean enabled, int userId) {
+        Intent intent = new Intent(LocationManager.MODE_CHANGING_ACTION);
+
+        final int oldMode = Settings.Secure.getIntForUser(context.getContentResolver(),
+                Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF, userId);
+        final int newMode = enabled
+                ? Settings.Secure.LOCATION_MODE_HIGH_ACCURACY
+                : Settings.Secure.LOCATION_MODE_OFF;
+        intent.putExtra(CURRENT_MODE_KEY, oldMode);
+        intent.putExtra(NEW_MODE_KEY, newMode);
+        context.sendBroadcastAsUser(
+                intent, UserHandle.of(userId), android.Manifest.permission.WRITE_SECURE_SETTINGS);
+        LocationManager locationManager =
+                (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
+        LocationManagerWrapper wrapper = new LocationManagerWrapper(locationManager);
+        wrapper.setLocationEnabledForUser(enabled, UserHandle.of(userId));
+    }
+
     public static boolean updateLocationMode(Context context, int oldMode, int newMode, int userId) {
         Intent intent = new Intent(LocationManager.MODE_CHANGING_ACTION);
         intent.putExtra(CURRENT_MODE_KEY, oldMode);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenRadioLayout.java b/packages/SettingsLib/src/com/android/settingslib/notification/ZenRadioLayout.java
similarity index 94%
rename from packages/SystemUI/src/com/android/systemui/volume/ZenRadioLayout.java
rename to packages/SettingsLib/src/com/android/settingslib/notification/ZenRadioLayout.java
index 360907b..1140028 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenRadioLayout.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/ZenRadioLayout.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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
@@ -12,7 +12,7 @@
  * permissions and limitations under the License.
  */
 
-package com.android.systemui.volume;
+package com.android.settingslib.notification;
 
 import android.content.Context;
 import android.util.AttributeSet;
@@ -22,7 +22,7 @@
 
 /**
  * Specialized layout for zen mode that allows the radio buttons to reside within
- * a RadioGroup, but also makes sure that all the heights off the radio buttons align
+ * a RadioGroup, but also makes sure that all the heights of the radio buttons align
  * with the corresponding content in the second child of this view.
  */
 public class ZenRadioLayout extends LinearLayout {
diff --git a/packages/SettingsLib/src/com/android/settingslib/wrapper/LocationManagerWrapper.java b/packages/SettingsLib/src/com/android/settingslib/wrapper/LocationManagerWrapper.java
new file mode 100644
index 0000000..1a268a6
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/wrapper/LocationManagerWrapper.java
@@ -0,0 +1,64 @@
+/*
+ * 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.settingslib.wrapper;
+
+import android.location.LocationManager;
+import android.os.UserHandle;
+
+/**
+ * This class replicates some methods of android.location.LocationManager that are new and not
+ * yet available in our current version of Robolectric. It provides a thin wrapper to call the real
+ * methods in production and a mock in tests.
+ */
+public class LocationManagerWrapper {
+
+    private LocationManager mLocationManager;
+
+    public LocationManagerWrapper(LocationManager locationManager) {
+        mLocationManager = locationManager;
+    }
+
+    /** Returns the real {@code LocationManager} object */
+    public LocationManager getLocationManager() {
+        return mLocationManager;
+    }
+
+    /** Wraps {@code LocationManager.isProviderEnabled} method */
+    public boolean isProviderEnabled(String provider) {
+        return mLocationManager.isProviderEnabled(provider);
+    }
+
+    /** Wraps {@code LocationManager.setProviderEnabledForUser} method */
+    public void setProviderEnabledForUser(String provider, boolean enabled, UserHandle userHandle) {
+        mLocationManager.setProviderEnabledForUser(provider, enabled, userHandle);
+    }
+
+    /** Wraps {@code LocationManager.isLocationEnabled} method */
+    public boolean isLocationEnabled() {
+        return mLocationManager.isLocationEnabled();
+    }
+
+    /** Wraps {@code LocationManager.isLocationEnabledForUser} method */
+    public boolean isLocationEnabledForUser(UserHandle userHandle) {
+        return mLocationManager.isLocationEnabledForUser(userHandle);
+    }
+
+    /** Wraps {@code LocationManager.setLocationEnabledForUser} method */
+    public void setLocationEnabledForUser(boolean enabled, UserHandle userHandle) {
+        mLocationManager.setLocationEnabledForUser(enabled, userHandle);
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
index 976bbee..327c1c8 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
@@ -15,28 +15,8 @@
  */
 package com.android.settingslib;
 
-import android.app.ActivityManager;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.location.LocationManager;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.provider.Settings.Secure;
-import android.text.TextUtils;
-import java.util.HashMap;
-import java.util.Map;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentMatcher;
-import org.mockito.ArgumentMatchers;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
 import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
 import static com.google.common.truth.Truth.assertThat;
-
 import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
@@ -44,7 +24,28 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.app.ActivityManager;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
 import android.content.res.Resources;
+import android.location.LocationManager;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.provider.Settings.Secure;
+import android.text.TextUtils;
+import com.android.settingslib.wrapper.LocationManagerWrapper;
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentMatcher;
+import org.mockito.ArgumentMatchers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
 import org.robolectric.shadows.ShadowSettings;
@@ -53,7 +54,9 @@
 @Config(
         manifest = TestConfig.MANIFEST_PATH,
         sdk = TestConfig.SDK_VERSION,
-        shadows = {UtilsTest.ShadowSecure.class})
+        shadows = {
+            UtilsTest.ShadowSecure.class,
+            UtilsTest.ShadowLocationManagerWrapper.class})
 public class UtilsTest {
     private static final double[] TEST_PERCENTAGES = {0, 0.4, 0.5, 0.6, 49, 49.3, 49.8, 50, 100};
     private static final String PERCENTAGE_0 = "0%";
@@ -63,10 +66,14 @@
     private static final String PERCENTAGE_100 = "100%";
 
     private Context mContext;
+    @Mock
+    private LocationManager mLocationManager;
 
     @Before
     public void setUp() {
+        MockitoAnnotations.initMocks(this);
         mContext = spy(RuntimeEnvironment.application);
+        when(mContext.getSystemService(Context.LOCATION_SERVICE)).thenReturn(mLocationManager);
         ShadowSecure.reset();
     }
 
@@ -86,6 +93,17 @@
     }
 
     @Test
+    public void testUpdateLocationEnabled_sendBroadcast() {
+        int currentUserId = ActivityManager.getCurrentUser();
+        Utils.updateLocationEnabled(mContext, true, currentUserId);
+
+        verify(mContext).sendBroadcastAsUser(
+            argThat(actionMatches(LocationManager.MODE_CHANGING_ACTION)),
+            ArgumentMatchers.eq(UserHandle.of(currentUserId)),
+            ArgumentMatchers.eq(WRITE_SECURE_SETTINGS));
+    }
+
+    @Test
     public void testFormatPercentage_RoundTrue_RoundUpIfPossible() {
         final String[] expectedPercentages = {PERCENTAGE_0, PERCENTAGE_0, PERCENTAGE_1,
                 PERCENTAGE_1, PERCENTAGE_49, PERCENTAGE_49, PERCENTAGE_50, PERCENTAGE_50,
@@ -137,8 +155,26 @@
             return true;
         }
 
+        @Implementation
+        public static int getIntForUser(ContentResolver cr, String name, int def, int userHandle) {
+            if (map.containsKey(name)) {
+                return map.get(name);
+            } else {
+                return def;
+            }
+        }
+
         public static void reset() {
             map.clear();
         }
     }
+
+    @Implements(value = LocationManagerWrapper.class)
+    public static class ShadowLocationManagerWrapper {
+
+        @Implementation
+        public void setLocationEnabledForUser(boolean enabled, UserHandle userHandle) {
+            // Do nothing
+        }
+    }
 }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index fc765f4..cfd33a1 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -16,6 +16,7 @@
 
 package com.android.providers.settings;
 
+import android.os.Process;
 import com.android.internal.R;
 import com.android.internal.app.LocalePicker;
 import com.android.internal.annotations.VisibleForTesting;
@@ -288,12 +289,12 @@
         }
         final String GPS = LocationManager.GPS_PROVIDER;
         boolean enabled =
-                GPS.equals(value) ||
+            GPS.equals(value) ||
                 value.startsWith(GPS + ",") ||
                 value.endsWith("," + GPS) ||
                 value.contains("," + GPS + ",");
-        Settings.Secure.setLocationProviderEnabled(
-                mContext.getContentResolver(), GPS, enabled);
+        LocationManager lm = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
+        lm.setProviderEnabledForUser(GPS, enabled, Process.myUserHandle());
     }
 
     private void setSoundEffects(boolean enable) {
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 5a75681..55f7a0a 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1223,9 +1223,6 @@
         dumpSetting(s, p,
                 Settings.Secure.LOCATION_MODE,
                 SecureSettingsProto.LOCATION_MODE);
-        dumpSetting(s, p,
-                Settings.Secure.LOCATION_PREVIOUS_MODE,
-                SecureSettingsProto.LOCATION_PREVIOUS_MODE);
         // Settings.Secure.LOCK_BIOMETRIC_WEAK_FLAGS intentionally excluded since it's deprecated.
         dumpSetting(s, p,
                 Settings.Secure.LOCK_TO_APP_EXIT_LOCKED,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 2a697b8..5435e11 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -2892,11 +2892,14 @@
             for (int i = 0; i < users.size(); i++) {
                 final int userId = users.get(i).id;
 
+                // Do we have to increment the generation for users that are not running?
+                // Yeah let's assume so...
+                final int key = makeKey(SETTINGS_TYPE_SECURE, userId);
+                mGenerationRegistry.incrementGeneration(key);
+
                 if (!mUserManager.isUserRunning(UserHandle.of(userId))) {
                     continue;
                 }
-
-                final int key = makeKey(SETTINGS_TYPE_GLOBAL, userId);
                 final Uri uri = getNotificationUriFor(key, Secure.LOCATION_PROVIDERS_ALLOWED);
 
                 mHandler.obtainMessage(MyHandler.MSG_NOTIFY_URI_CHANGED,
diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk
index 73fcdd7..251ae2d 100644
--- a/packages/SystemUI/Android.mk
+++ b/packages/SystemUI/Android.mk
@@ -27,7 +27,12 @@
 
 LOCAL_MODULE_TAGS := optional
 
-LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-Iaidl-files-under, src)
+RELATIVE_FINGERPRINT_PATH := ../../core/java/android/hardware/fingerprint
+
+LOCAL_SRC_FILES := \
+    $(call all-java-files-under, src) \
+    $(call all-Iaidl-files-under, src) \
+    $(call all-Iaidl-files-under, $(RELATIVE_FINGERPRINT_PATH))
 
 LOCAL_STATIC_ANDROID_LIBRARIES := \
     SystemUIPluginLib \
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 80ac825..4b2e62c 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -323,7 +323,7 @@
         </activity>
 
         <!-- Springboard for launching the share activity -->
-        <receiver android:name=".screenshot.GlobalScreenshot$ShareReceiver"
+        <receiver android:name=".screenshot.GlobalScreenshot$ScreenshotActionReceiver"
             android:process=":screenshot"
             android:exported="false" />
 
diff --git a/packages/SystemUI/res/anim/car_user_switcher_close_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_close_animation.xml
new file mode 100644
index 0000000..ed637a7
--- /dev/null
+++ b/packages/SystemUI/res/anim/car_user_switcher_close_animation.xml
@@ -0,0 +1,20 @@
+<!-- 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.
+-->
+<animator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:duration="133"
+    android:valueType="intType"
+    android:valueFrom="@dimen/car_user_switcher_container_height"
+    android:valueTo="0"
+    android:interpolator="@android:interpolator/fast_out_slow_in" />
diff --git a/packages/SystemUI/res/anim/car_user_switcher_close_icon_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_close_icon_animation.xml
new file mode 100644
index 0000000..227c981
--- /dev/null
+++ b/packages/SystemUI/res/anim/car_user_switcher_close_icon_animation.xml
@@ -0,0 +1,24 @@
+<!-- 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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <objectAnimator
+        android:duration="167"
+        android:propertyName="rotation"
+        android:valueType="floatType"
+        android:valueFrom="180"
+        android:valueTo="0"
+        android:interpolator="@android:interpolator/fast_out_slow_in" />
+</set>
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/car_user_switcher_close_name_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_close_name_animation.xml
new file mode 100644
index 0000000..5901ff4
--- /dev/null
+++ b/packages/SystemUI/res/anim/car_user_switcher_close_name_animation.xml
@@ -0,0 +1,23 @@
+<!-- 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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <objectAnimator
+        android:duration="83"
+        android:propertyName="alpha"
+        android:valueType="floatType"
+        android:valueFrom="0"
+        android:valueTo="1" />
+</set>
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/car_user_switcher_close_pages_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_close_pages_animation.xml
new file mode 100644
index 0000000..41cbe4b
--- /dev/null
+++ b/packages/SystemUI/res/anim/car_user_switcher_close_pages_animation.xml
@@ -0,0 +1,23 @@
+<!-- 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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <objectAnimator
+        android:duration="83"
+        android:propertyName="alpha"
+        android:valueType="floatType"
+        android:valueFrom="1"
+        android:valueTo="0" />
+</set>
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/car_user_switcher_close_pod_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_close_pod_animation.xml
new file mode 100644
index 0000000..341e7e0
--- /dev/null
+++ b/packages/SystemUI/res/anim/car_user_switcher_close_pod_animation.xml
@@ -0,0 +1,24 @@
+<!-- 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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+    android:ordering="together" >
+
+    <objectAnimator
+        android:duration="50"
+        android:propertyName="alpha"
+        android:valueType="floatType"
+        android:valueFrom="1"
+        android:valueTo="0" />
+</set>
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/car_user_switcher_open_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_open_animation.xml
new file mode 100644
index 0000000..6ae7413
--- /dev/null
+++ b/packages/SystemUI/res/anim/car_user_switcher_open_animation.xml
@@ -0,0 +1,20 @@
+<!-- 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.
+-->
+<animator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:duration="200"
+    android:valueType="intType"
+    android:valueFrom="0"
+    android:valueTo="@dimen/car_user_switcher_container_height"
+    android:interpolator="@android:interpolator/fast_out_slow_in" />
diff --git a/packages/SystemUI/res/anim/car_user_switcher_open_icon_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_open_icon_animation.xml
new file mode 100644
index 0000000..06ac9e3
--- /dev/null
+++ b/packages/SystemUI/res/anim/car_user_switcher_open_icon_animation.xml
@@ -0,0 +1,24 @@
+<!-- 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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <objectAnimator
+        android:duration="167"
+        android:propertyName="rotation"
+        android:valueType="floatType"
+        android:valueFrom="0"
+        android:valueTo="180"
+        android:interpolator="@android:interpolator/fast_out_slow_in" />
+</set>
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/car_user_switcher_open_name_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_open_name_animation.xml
new file mode 100644
index 0000000..4baefb8
--- /dev/null
+++ b/packages/SystemUI/res/anim/car_user_switcher_open_name_animation.xml
@@ -0,0 +1,24 @@
+<!-- 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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <objectAnimator
+        android:duration="83"
+        android:startOffset="83"
+        android:propertyName="alpha"
+        android:valueType="floatType"
+        android:valueFrom="1"
+        android:valueTo="0" />
+</set>
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/car_user_switcher_open_pages_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_open_pages_animation.xml
new file mode 100644
index 0000000..2d0deb9
--- /dev/null
+++ b/packages/SystemUI/res/anim/car_user_switcher_open_pages_animation.xml
@@ -0,0 +1,24 @@
+<!-- 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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <objectAnimator
+        android:duration="83"
+        android:startOffset="83"
+        android:propertyName="alpha"
+        android:valueType="floatType"
+        android:valueFrom="0"
+        android:valueTo="1" />
+</set>
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/car_user_switcher_open_pod_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_open_pod_animation.xml
new file mode 100644
index 0000000..3315220
--- /dev/null
+++ b/packages/SystemUI/res/anim/car_user_switcher_open_pod_animation.xml
@@ -0,0 +1,33 @@
+<!-- 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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+    android:ordering="together" >
+
+    <objectAnimator
+        android:duration="167"
+        android:startOffset="67"
+        android:propertyName="translationY"
+        android:valueType="floatType"
+        android:valueFrom="@dimen/car_user_switcher_container_anim_height"
+        android:valueTo="0"
+        android:interpolator="@android:interpolator/fast_out_slow_in" />
+    <objectAnimator
+        android:duration="83"
+        android:startOffset="117"
+        android:propertyName="alpha"
+        android:valueType="floatType"
+        android:valueFrom="0"
+        android:valueTo="1" />
+</set>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/car_ic_arrow.xml b/packages/SystemUI/res/drawable/car_ic_arrow.xml
index 2c5ad27..d400ed8 100644
--- a/packages/SystemUI/res/drawable/car_ic_arrow.xml
+++ b/packages/SystemUI/res/drawable/car_ic_arrow.xml
@@ -1,5 +1,5 @@
 <!--
-  ~ Copyright (C) 2015 The Android Open Source Project
+  ~ 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.
diff --git a/packages/SystemUI/res/drawable/car_ic_arrow_drop_up.xml b/packages/SystemUI/res/drawable/car_ic_arrow_drop_up.xml
new file mode 100644
index 0000000..33a512e
--- /dev/null
+++ b/packages/SystemUI/res/drawable/car_ic_arrow_drop_up.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ Copyright (C) 2015 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="48.0dp"
+        android:height="48.0dp"
+        android:viewportWidth="48.0"
+        android:viewportHeight="48.0">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M14 28l10-10 10 10z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/fingerprint_dialog_bg.xml b/packages/SystemUI/res/drawable/fingerprint_dialog_bg.xml
new file mode 100644
index 0000000..4a77af9
--- /dev/null
+++ b/packages/SystemUI/res/drawable/fingerprint_dialog_bg.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@color/fingerprint_dialog_bg_color" />
+    <corners android:radius="1dp"
+        android:topLeftRadius="16dp"
+        android:topRightRadius="16dp"
+        android:bottomLeftRadius="0dp"
+        android:bottomRightRadius="0dp"/>
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/fingerprint_icon.xml b/packages/SystemUI/res/drawable/fingerprint_icon.xml
new file mode 100644
index 0000000..76a86ae
--- /dev/null
+++ b/packages/SystemUI/res/drawable/fingerprint_icon.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="60dp"
+    android:height="60dp"
+    android:viewportWidth="60"
+    android:viewportHeight="60">
+
+    <path
+        android:fillColor="#1A73E8"
+        android:fillType="evenOdd"
+        android:strokeWidth="1"
+        android:pathData="M 30 0 C 46.5685424949 0 60 13.4314575051 60 30 C 60 46.5685424949 46.5685424949 60 30 60 C 13.4314575051 60 0 46.5685424949 0 30 C 0 13.4314575051 13.4314575051 0 30 0 Z" />
+    <group
+        android:translateX="17.727273"
+        android:translateY="16.363636">
+        <path
+            android:fillColor="#FFFFFF"
+            android:strokeWidth="1"
+            android:pathData="M20.3065726,3.44516129 C20.1974817,3.44516129 20.0883908,3.41788856
+19.9929362,3.36334311 C17.3747544,2.01334311 15.111118,1.44061584
+12.3974817,1.44061584 C9.69748166,1.44061584 7.1338453,2.08152493
+4.80202711,3.36334311 C4.47475439,3.54061584 4.06566348,3.41788856
+3.87475439,3.09061584 C3.69748166,2.76334311 3.82020893,2.34061584
+4.14748166,2.16334311 C6.6838453,0.786070381 9.46566348,0.0769794721
+12.3974817,0.0769794721 C15.3020271,0.0769794721 17.8383908,0.717888563
+20.6202089,2.14970674 C20.961118,2.32697947 21.0838453,2.73607038
+20.9065726,3.06334311 C20.7838453,3.30879765 20.5520271,3.44516129
+20.3065726,3.44516129 L20.3065726,3.44516129 Z M0.792936205,10.6042522
+C0.656572568,10.6042522 0.520208932,10.5633431 0.397481659,10.4815249
+C0.0838452956,10.2633431 0.0156634774,9.84061584 0.233845296,9.52697947
+C1.5838453,7.61788856 3.30202711,6.11788856 5.34748166,5.06788856
+C9.62929984,2.85879765 15.111118,2.84516129 19.4065726,5.0542522
+C21.4520271,6.1042522 23.1702089,7.59061584 24.5202089,9.48607038
+C24.7383908,9.78607038 24.6702089,10.222434 24.3565726,10.4406158
+C24.0429362,10.6587977 23.6202089,10.5906158 23.4020271,10.2769795
+C22.1747544,8.55879765 20.6202089,7.20879765 18.7792998,6.26788856
+C14.8656635,4.26334311 9.86111802,4.26334311 5.96111802,6.28152493
+C4.10657257,7.23607038 2.55202711,8.59970674 1.32475439,10.3178886
+C1.21566348,10.5087977 1.01111802,10.6042522 0.792936205,10.6042522
+L0.792936205,10.6042522 Z M9.31566348,27.0633431 C9.13839075,27.0633431
+8.96111802,26.9951613 8.83839075,26.8587977 C7.65202711,25.672434
+7.01111802,24.9087977 6.09748166,23.2587977 C5.15657257,21.5815249
+4.66566348,19.5360704 4.66566348,17.3406158 C4.66566348,13.2906158
+8.12929984,9.99061584 12.3838453,9.99061584 C16.6383908,9.99061584
+20.1020271,13.2906158 20.1020271,17.3406158 C20.1020271,17.722434
+19.8020271,18.022434 19.4202089,18.022434 C19.0383908,18.022434
+18.7383908,17.722434 18.7383908,17.3406158 C18.7383908,14.0406158
+15.8883908,11.3542522 12.3838453,11.3542522 C8.87929984,11.3542522
+6.02929984,14.0406158 6.02929984,17.3406158 C6.02929984,19.3042522
+6.46566348,21.1178886 7.29748166,22.5906158 C8.17020893,24.1587977
+8.77020893,24.8269795 9.82020893,25.8906158 C10.0792998,26.1633431
+10.0792998,26.5860704 9.82020893,26.8587977 C9.67020893,26.9951613
+9.4929362,27.0633431 9.31566348,27.0633431 Z M19.0929362,24.5406158
+C17.4702089,24.5406158 16.0383908,24.1315249 14.8656635,23.3269795
+C12.8338453,21.9497067 11.6202089,19.7133431 11.6202089,17.3406158
+C11.6202089,16.9587977 11.9202089,16.6587977 12.3020271,16.6587977
+C12.6838453,16.6587977 12.9838453,16.9587977 12.9838453,17.3406158
+C12.9838453,19.2633431 13.9656635,21.0769795 15.6292998,22.1951613
+C16.5974817,22.8497067 17.7292998,23.1633431 19.0929362,23.1633431
+C19.4202089,23.1633431 19.9656635,23.122434 20.511118,23.0269795
+C20.8792998,22.9587977 21.2338453,23.2042522 21.3020271,23.5860704
+C21.3702089,23.9542522 21.1247544,24.3087977 20.7429362,24.3769795
+C19.9656635,24.5269795 19.2838453,24.5406158 19.0929362,24.5406158
+L19.0929362,24.5406158 Z M16.3520271,27.3497067 C16.2974817,27.3497067
+16.2292998,27.3360704 16.1747544,27.322434 C14.0065726,26.722434
+12.5883908,25.9178886 11.1020271,24.4587977 C9.1929362,22.5633431
+8.1429362,20.0406158 8.1429362,17.3406158 C8.1429362,15.1315249
+10.0247544,13.3315249 12.3429362,13.3315249 C14.661118,13.3315249
+16.5429362,15.1315249 16.5429362,17.3406158 C16.5429362,18.7997067
+17.811118,19.9860704 19.3792998,19.9860704 C20.9474817,19.9860704
+22.2156635,18.7997067 22.2156635,17.3406158 C22.2156635,12.1997067
+17.7838453,8.02697947 12.3292998,8.02697947 C8.45657257,8.02697947
+4.91111802,10.1815249 3.31566348,13.522434 C2.7838453,14.6269795
+2.51111802,15.922434 2.51111802,17.3406158 C2.51111802,18.4042522
+2.60657257,20.0815249 3.42475439,22.2633431 C3.56111802,22.6178886
+3.3838453,23.0133431 3.02929984,23.1360704 C2.67475439,23.272434
+2.27929984,23.0815249 2.15657257,22.7406158 C1.48839075,20.9542522
+1.16111802,19.1815249 1.16111802,17.3406158 C1.16111802,15.7042522
+1.47475439,14.2178886 2.08839075,12.922434 C3.90202711,9.11788856
+7.92475439,6.64970674 12.3292998,6.64970674 C18.5338453,6.64970674
+23.5792998,11.4360704 23.5792998,17.3269795 C23.5792998,19.5360704
+21.6974817,21.3360704 19.3792998,21.3360704 C17.061118,21.3360704
+15.1792998,19.5360704 15.1792998,17.3269795 C15.1792998,15.8678886
+13.911118,14.6815249 12.3429362,14.6815249 C10.7747544,14.6815249
+9.50657257,15.8678886 9.50657257,17.3269795 C9.50657257,19.6587977
+10.4065726,21.8406158 12.0565726,23.4769795 C13.3520271,24.7587977
+14.5929362,25.4678886 16.5156635,25.9997067 C16.8838453,26.0951613
+17.0883908,26.4769795 16.9929362,26.8315249 C16.9247544,27.1451613
+16.6383908,27.3497067 16.3520271,27.3497067 L16.3520271,27.3497067 Z" />
+    </group>
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml b/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
index 2f16516..0ee40d7 100644
--- a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
+++ b/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
@@ -15,27 +15,40 @@
      limitations under the License.
 -->
 
-<LinearLayout
+<RelativeLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
+    android:clipChildren="false"
+    android:alpha="0"
     android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:gravity="center" >
+    android:layout_height="@dimen/car_fullscreen_user_pod_height"
+    android:layout_gravity="center_horizontal|bottom" >
 
     <ImageView android:id="@+id/user_avatar"
-        android:layout_gravity="center"
+        android:layout_centerHorizontal="true"
+        android:layout_marginTop="@dimen/car_fullscreen_user_pod_margin_image_top"
         android:layout_width="@dimen/car_fullscreen_user_pod_image_avatar_width"
-        android:layout_height="@dimen/car_fullscreen_user_pod_image_avatar_height" />
+        android:layout_height="@dimen/car_fullscreen_user_pod_image_avatar_height"
+        android:layout_above="@id/user_name" />
 
     <TextView android:id="@+id/user_name"
         android:layout_width="@dimen/car_fullscreen_user_pod_width"
         android:layout_height="wrap_content"
         android:layout_marginTop="@dimen/car_fullscreen_user_pod_margin_name_top"
         android:layout_marginBottom="@dimen/car_fullscreen_user_pod_margin_name_bottom"
-        android:textSize="@dimen/car_fullscreen_user_pod_text_size"
+        android:textSize="@dimen/car_fullscreen_user_pod_name_text_size"
         android:textColor="@color/qs_user_detail_name"
         android:ellipsize="end"
         android:singleLine="true"
         android:gravity="center_horizontal"
-        android:layout_gravity="center_horizontal" />
-</LinearLayout>
+        android:layout_above="@id/device_name" />
+
+    <TextView android:id="@+id/device_name"
+        android:layout_width="@dimen/car_fullscreen_user_pod_width"
+        android:layout_height="wrap_content"
+        android:textSize="@dimen/car_fullscreen_user_pod_device_text_size"
+        android:textColor="@color/qs_user_detail_name"
+        android:ellipsize="end"
+        android:singleLine="true"
+        android:gravity="center_horizontal"
+        android:layout_alignParentBottom="true" />
+</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_pod_container.xml b/packages/SystemUI/res/layout/car_fullscreen_user_pod_container.xml
index 99d010f..d666a20 100644
--- a/packages/SystemUI/res/layout/car_fullscreen_user_pod_container.xml
+++ b/packages/SystemUI/res/layout/car_fullscreen_user_pod_container.xml
@@ -16,10 +16,10 @@
 -->
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
+    android:clipChildren="false"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:gravity="center"
-    android:layout_gravity="center" >
+    android:gravity="center" >
 
     <!-- car_fullscreen_user_pods will be dynamically added here. -->
 </LinearLayout>
diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml b/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
index 257e281..478b656 100644
--- a/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
+++ b/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
@@ -54,13 +54,13 @@
             android:layout_height="wrap_content"
             android:layout_marginLeft="@dimen/car_margin"
             android:layout_marginRight="@dimen/car_margin"
+            android:layout_marginBottom="@dimen/car_user_grid_margin_bottom"
             android:layout_centerInParent="true" />
 
         <com.android.systemui.statusbar.car.PageIndicator
             android:id="@+id/user_switcher_page_indicator"
             android:layout_width="match_parent"
             android:layout_height="@dimen/car_page_indicator_dot_diameter"
-            android:layout_marginTop="@dimen/car_page_indicator_margin_top"
             android:layout_below="@+id/user_grid" />
 
         <Button
diff --git a/packages/SystemUI/res/layout/car_qs_footer.xml b/packages/SystemUI/res/layout/car_qs_footer.xml
index 044090b..3afd4ea 100644
--- a/packages/SystemUI/res/layout/car_qs_footer.xml
+++ b/packages/SystemUI/res/layout/car_qs_footer.xml
@@ -35,7 +35,6 @@
         android:layout_centerVertical="true"
         android:layout_width="@dimen/car_qs_footer_icon_width"
         android:layout_height="@dimen/car_qs_footer_icon_height"
-        android:layout_marginRight="@dimen/car_qs_footer_user_switch_margin_right"
         android:background="@drawable/ripple_drawable"
         android:focusable="true">
 
@@ -47,6 +46,18 @@
             android:scaleType="fitCenter"/>
     </com.android.systemui.statusbar.phone.MultiUserSwitch>
 
+    <ImageView
+        android:id="@+id/user_switch_expand_icon"
+        android:layout_height="match_parent"
+        android:layout_width="@dimen/car_qs_footer_user_switch_icon_width"
+        android:layout_centerVertical="true"
+        android:layout_toEndOf="@+id/multi_user_switch"
+        android:layout_marginLeft="@dimen/car_qs_footer_user_switch_icon_margin"
+        android:layout_marginRight="@dimen/car_qs_footer_user_switch_icon_margin"
+        android:src="@drawable/car_ic_arrow_drop_up"
+        android:scaleType="fitCenter">
+    </ImageView>
+
     <TextView android:id="@+id/user_name"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
@@ -54,7 +65,7 @@
         android:textColor="@color/car_qs_footer_user_name_color"
         android:gravity="start|center_vertical"
         android:layout_centerVertical="true"
-        android:layout_toEndOf="@id/multi_user_switch" />
+        android:layout_toEndOf="@id/user_switch_expand_icon" />
 
     <com.android.systemui.statusbar.phone.SettingsButton
         android:id="@+id/settings_button"
diff --git a/packages/SystemUI/res/layout/car_qs_panel.xml b/packages/SystemUI/res/layout/car_qs_panel.xml
index 4cb0fd5..7844cac 100644
--- a/packages/SystemUI/res/layout/car_qs_panel.xml
+++ b/packages/SystemUI/res/layout/car_qs_panel.xml
@@ -16,6 +16,7 @@
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/quick_settings_container"
+    android:clipChildren="false"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:background="@color/car_qs_background_primary"
@@ -26,10 +27,32 @@
     <include layout="@layout/car_status_bar_header"/>
     <include layout="@layout/car_qs_footer"/>
 
-    <com.android.systemui.statusbar.car.UserGridView
-        android:id="@+id/user_grid"
+    <RelativeLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/user_switcher_container"
+        android:clipChildren="false"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginLeft="@dimen/car_margin"
-        android:layout_marginRight="@dimen/car_margin" />
+        android:layout_height="@dimen/car_user_switcher_container_height"
+        android:layout_gravity="center_horizontal" >
+
+        <com.android.systemui.statusbar.car.UserGridView
+            android:id="@+id/user_grid"
+            android:clipChildren="false"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="@dimen/car_margin"
+            android:layout_marginRight="@dimen/car_margin"
+            android:layout_marginBottom="@dimen/car_user_grid_margin_bottom"
+            android:layout_above="@id/user_switcher_page_indicator" />
+
+        <com.android.systemui.statusbar.car.PageIndicator
+            android:id="@+id/user_switcher_page_indicator"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/car_page_indicator_dot_diameter"
+            android:layout_marginBottom="@dimen/car_page_indicator_margin_bottom"
+            android:alpha="0"
+            android:layout_alignParentBottom="true" />
+
+    </RelativeLayout>
+
 </LinearLayout>
diff --git a/packages/SystemUI/res/layout/fingerprint_dialog.xml b/packages/SystemUI/res/layout/fingerprint_dialog.xml
new file mode 100644
index 0000000..e5f62b3
--- /dev/null
+++ b/packages/SystemUI/res/layout/fingerprint_dialog.xml
@@ -0,0 +1,163 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+<LinearLayout 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/fingerprint_dialog_dim_color"
+    android:orientation="vertical">
+
+    <!-- This is not a Space since Spaces cannot be clicked -->
+    <View
+        android:id="@+id/space"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_weight="1" />
+
+    <LinearLayout
+        android:id="@+id/dialog"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:elevation="2dp"
+        android:background="@drawable/fingerprint_dialog_bg">
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:gravity="center_vertical"
+            android:elevation="2dp">
+
+            <ImageView
+                android:id="@+id/icon"
+                android:layout_width="@dimen/fingerprint_dialog_icon_size"
+                android:layout_height="@dimen/fingerprint_dialog_icon_size"
+                android:layout_marginTop="16dp"
+                android:layout_marginStart="16dp"
+                android:scaleType="centerInside" />
+
+            <TextView
+                android:id="@+id/title"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_toRightOf="@+id/icon"
+                android:layout_marginEnd="16dp"
+                android:layout_marginStart="16dp"
+                android:layout_marginTop="16dp"
+                android:textSize="20sp"
+                android:maxLines="1"
+                android:singleLine="true"
+                android:ellipsize="marquee"
+                android:marqueeRepeatLimit="marquee_forever"
+                android:textColor="@color/fingerprint_dialog_text_color"/>
+
+            <TextView
+                android:id="@+id/subtitle"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_toRightOf="@+id/icon"
+                android:layout_below="@+id/title"
+                android:layout_marginEnd="16dp"
+                android:layout_marginStart="16dp"
+                android:layout_marginTop="4dp"
+                android:textSize="12sp"
+                android:maxLines="2"
+                android:textColor="@color/fingerprint_dialog_text_color"/>
+
+        </RelativeLayout>
+
+        <TextView
+            android:id="@+id/description"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginEnd="16dp"
+            android:layout_marginStart="16dp"
+            android:paddingTop="16dp"
+            android:paddingBottom="20dp"
+            android:textSize="16sp"
+            android:maxLines="4"
+            android:textColor="@color/fingerprint_dialog_text_color"/>
+
+        <ImageView
+            android:id="@+id/fingerprint_icon"
+            android:layout_width="@dimen/fingerprint_dialog_fp_icon_size"
+            android:layout_height="@dimen/fingerprint_dialog_fp_icon_size"
+            android:layout_gravity="center_horizontal"
+            android:scaleType="centerInside"
+            android:src="@drawable/fingerprint_icon"/>
+
+        <TextView
+            android:id="@+id/error"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginEnd = "16dp"
+            android:layout_marginStart="16dp"
+            android:paddingTop="16dp"
+            android:paddingBottom="60dp"
+            android:textSize="12sp"
+            android:visibility="invisible"
+            android:gravity="center_horizontal"
+            android:textColor="@color/fingerprint_error_message_color"/>
+
+        <LinearLayout android:id="@+id/buttonPanel"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:minHeight="54dip"
+            android:orientation="vertical" >
+            <LinearLayout
+                style="?android:attr/buttonBarStyle"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="horizontal"
+                android:paddingTop="4dip"
+                android:paddingStart="2dip"
+                android:paddingEnd="2dip"
+                android:measureWithLargestChild="true">
+                <LinearLayout android:id="@+id/leftSpacer"
+                    android:layout_weight="0.25"
+                    android:layout_width="0dip"
+                    android:layout_height="wrap_content"
+                    android:orientation="horizontal"
+                    android:visibility="gone" />
+                <!-- Positive Button -->
+                <Button android:id="@+id/button1"
+                    android:layout_width="0dip"
+                    android:layout_gravity="start"
+                    android:layout_weight="1"
+                    style="?android:attr/buttonBarButtonStyle"
+                    android:maxLines="2"
+                    android:layout_height="wrap_content"/>
+                <!-- Negative Button -->
+                <Button android:id="@+id/button2"
+                    android:layout_width="0dip"
+                    android:layout_gravity="end"
+                    android:layout_weight="1"
+                    style="?android:attr/buttonBarButtonStyle"
+                    android:maxLines="2"
+                    android:layout_height="wrap_content" />
+                <LinearLayout android:id="@+id/rightSpacer"
+                    android:layout_width="0dip"
+                    android:layout_weight="0.25"
+                    android:layout_height="wrap_content"
+                    android:orientation="horizontal"
+                    android:visibility="gone" />
+            </LinearLayout>
+        </LinearLayout>
+    </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/zen_mode_panel.xml b/packages/SystemUI/res/layout/zen_mode_panel.xml
index 3826bdd..5862413 100644
--- a/packages/SystemUI/res/layout/zen_mode_panel.xml
+++ b/packages/SystemUI/res/layout/zen_mode_panel.xml
@@ -93,7 +93,7 @@
 
         </RelativeLayout>
 
-        <com.android.systemui.volume.ZenRadioLayout
+        <com.android.settingslib.notification.ZenRadioLayout
             android:id="@+id/zen_conditions"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
@@ -111,7 +111,7 @@
                 android:layout_width="fill_parent"
                 android:layout_height="fill_parent"
                 android:orientation="vertical"/>
-        </com.android.systemui.volume.ZenRadioLayout>
+        </com.android.settingslib.notification.ZenRadioLayout>
 
         <TextView
             android:id="@+id/zen_alarm_warning"
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 0f4c3b8..4fcfdf7 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -156,6 +156,14 @@
 
     <color name="zen_introduction">#ffffffff</color>
 
+
     <color name="smart_reply_button_text">#ff4285f4</color><!-- blue 500 -->
     <color name="smart_reply_button_background">#fff7f7f7</color>
+
+    <!-- Fingerprint dialog colors -->
+    <color name="fingerprint_dialog_bg_color">#f4ffffff</color> <!-- 96% white -->
+    <color name="fingerprint_dialog_text_color">#ff424242</color> <!-- gray 800-->
+    <color name="fingerprint_dialog_dim_color">#80000000</color> <!-- 50% black -->
+    <color name="fingerprint_error_message_color">#ff5722</color>
+
 </resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index b33f857..6768470 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -350,6 +350,7 @@
         <item>com.android.systemui.globalactions.GlobalActionsComponent</item>
         <item>com.android.systemui.RoundedCorners</item>
         <item>com.android.systemui.EmulatedDisplayCutout</item>
+        <item>com.android.systemui.fingerprint.FingerprintDialogImpl</item>
     </string-array>
 
     <!-- SystemUI vender service, used in config_systemUIServiceComponents. -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 887d3cb..b749a18 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -579,7 +579,7 @@
     <dimen name="keyguard_affordance_icon_width">24dp</dimen>
 
     <dimen name="keyguard_indication_margin_bottom">65dp</dimen>
-    <dimen name="keyguard_indication_margin_bottom_ambient">30dp</dimen>
+    <dimen name="keyguard_indication_margin_bottom_ambient">16dp</dimen>
 
     <!-- The text size for battery level -->
     <dimen name="battery_level_text_size">12sp</dimen>
@@ -889,4 +889,8 @@
     <dimen name="smart_reply_button_spacing">8dp</dimen>
     <dimen name="smart_reply_button_padding_vertical">4dp</dimen>
     <dimen name="smart_reply_button_font_size">14sp</dimen>
+
+    <dimen name="fingerprint_dialog_icon_size">44dp</dimen>
+    <dimen name="fingerprint_dialog_fp_icon_size">60dp</dimen>
+    <dimen name="fingerprint_dialog_animation_translation_offset">350dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/dimens_car.xml b/packages/SystemUI/res/values/dimens_car.xml
index 8853587..f3c9f89 100644
--- a/packages/SystemUI/res/values/dimens_car.xml
+++ b/packages/SystemUI/res/values/dimens_car.xml
@@ -18,20 +18,23 @@
 <resources>
     <dimen name="car_margin">148dp</dimen>
 
+    <dimen name="car_fullscreen_user_pod_margin_image_top">24dp</dimen>
     <dimen name="car_fullscreen_user_pod_margin_name_top">24dp</dimen>
-    <dimen name="car_fullscreen_user_pod_margin_name_bottom">64dp</dimen>
+    <dimen name="car_fullscreen_user_pod_margin_name_bottom">20dp</dimen>
     <dimen name="car_fullscreen_user_pod_margin_between">24dp</dimen>
     <dimen name="car_fullscreen_user_pod_icon_text_size">96dp</dimen>
     <dimen name="car_fullscreen_user_pod_image_avatar_width">192dp</dimen>
     <dimen name="car_fullscreen_user_pod_image_avatar_height">192dp</dimen>
     <dimen name="car_fullscreen_user_pod_width">264dp</dimen>
-    <dimen name="car_fullscreen_user_pod_text_size">40sp</dimen> <!-- B1 -->
+    <dimen name="car_fullscreen_user_pod_height">356dp</dimen>
+    <dimen name="car_fullscreen_user_pod_name_text_size">40sp</dimen> <!-- B1 -->
+    <dimen name="car_fullscreen_user_pod_device_text_size">@dimen/car_body2_size</dimen>
 
     <dimen name="car_navigation_button_width">64dp</dimen>
     <dimen name="car_navigation_bar_width">760dp</dimen>
 
     <dimen name="car_page_indicator_dot_diameter">12dp</dimen>
-    <dimen name="car_page_indicator_margin_top">32dp</dimen>
+    <dimen name="car_page_indicator_margin_bottom">24dp</dimen>
 
     <dimen name="car_user_switcher_progress_bar_height">6dp</dimen>
     <dimen name="car_user_switcher_progress_bar_margin_top">@dimen/status_bar_height</dimen>
@@ -47,8 +50,14 @@
     <dimen name="car_qs_footer_padding_start">46dp</dimen>
     <dimen name="car_qs_footer_icon_width">56dp</dimen>
     <dimen name="car_qs_footer_icon_height">56dp</dimen>
-    <dimen name="car_qs_footer_user_switch_margin_right">46dp</dimen>
+    <dimen name="car_qs_footer_user_switch_icon_margin">5dp</dimen>
+    <dimen name="car_qs_footer_user_switch_icon_width">36dp</dimen>
     <dimen name="car_qs_footer_user_name_text_size">@dimen/car_body2_size</dimen>
 
+    <dimen name="car_user_switcher_container_height">420dp</dimen>
+    <!-- This must be the negative of car_user_switcher_container_height for the animation. -->
+    <dimen name="car_user_switcher_container_anim_height">-420dp</dimen>
+    <dimen name="car_user_grid_margin_bottom">28dp</dimen>
+
     <dimen name="car_body2_size">26sp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/integers_car.xml b/packages/SystemUI/res/values/integers_car.xml
index 320ee9f..f84dd4b 100644
--- a/packages/SystemUI/res/values/integers_car.xml
+++ b/packages/SystemUI/res/values/integers_car.xml
@@ -19,4 +19,5 @@
     <integer name="car_user_switcher_timeout_ms">15000</integer>
     <!-- This values less than ProgressBar.PROGRESS_ANIM_DURATION for a smooth animation. -->
     <integer name="car_user_switcher_anim_update_ms">60</integer>
+    <integer name="car_user_switcher_anim_cascade_delay_ms">27</integer>
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index ab83bcf..edf19fd 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -675,6 +675,15 @@
     <string name="quick_settings_bluetooth_off_label">Bluetooth Off</string>
     <!-- QuickSettings: Bluetooth detail panel, text when there are no items [CHAR LIMIT=NONE] -->
     <string name="quick_settings_bluetooth_detail_empty_text">No paired devices available</string>
+    <!-- QuickSettings: Bluetooth secondary label for the battery level of a connected device [CHAR LIMIT=20]-->
+    <string name="quick_settings_bluetooth_secondary_label_battery_level"><xliff:g id="battery_level_as_percentage">%s</xliff:g> battery</string>
+    <!-- QuickSettings: Bluetooth secondary label for an audio device being connected [CHAR LIMIT=20]-->
+    <string name="quick_settings_bluetooth_secondary_label_audio">Audio</string>
+    <!-- QuickSettings: Bluetooth secondary label for a headset being connected [CHAR LIMIT=20]-->
+    <string name="quick_settings_bluetooth_secondary_label_headset">Headset</string>
+    <!-- QuickSettings: Bluetooth secondary label for an input/IO device being connected [CHAR LIMIT=20]-->
+    <string name="quick_settings_bluetooth_secondary_label_input">Input</string>
+
     <!-- QuickSettings: Brightness [CHAR LIMIT=NONE] -->
     <string name="quick_settings_brightness_label">Brightness</string>
     <!-- QuickSettings: Rotation Unlocked [CHAR LIMIT=NONE] -->
@@ -755,6 +764,11 @@
     <string name="quick_settings_tethering_label">Tethering</string>
     <!-- QuickSettings: Hotspot. [CHAR LIMIT=NONE] -->
     <string name="quick_settings_hotspot_label">Hotspot</string>
+    <!-- QuickSettings: Hotspot: Secondary label for how many devices are connected to the hotspot [CHAR LIMIT=NONE] -->
+    <plurals name="quick_settings_hotspot_num_devices">
+        <item quantity="one">%d device</item>
+        <item quantity="other">%d devices</item>
+    </plurals>
     <!-- QuickSettings: Notifications [CHAR LIMIT=NONE] -->
     <string name="quick_settings_notifications_label">Notifications</string>
     <!-- QuickSettings: Flashlight [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 2873afb..2b656c2 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -171,15 +171,16 @@
     }
 
     private void onSliceContentChanged(boolean hasHeader) {
-        final float clockScale = hasHeader ? mSmallClockScale : 1;
+        final boolean smallClock = hasHeader || mPulsing;
+        final float clockScale = smallClock ? mSmallClockScale : 1;
         float translation = (mClockView.getHeight() - (mClockView.getHeight() * clockScale)) / 2f;
-        if (hasHeader) {
+        if (smallClock) {
             translation -= mWidgetPadding;
         }
         mClockView.setTranslationY(translation);
         mClockView.setScaleX(clockScale);
         mClockView.setScaleY(clockScale);
-        mClockSeparator.setVisibility(hasHeader ? VISIBLE : GONE);
+        mClockSeparator.setVisibility(hasHeader && !mPulsing ? VISIBLE : GONE);
     }
 
     @Override
@@ -329,6 +330,8 @@
 
     public void setPulsing(boolean pulsing) {
         mPulsing = pulsing;
+        mKeyguardSlice.setVisibility(pulsing ? GONE : VISIBLE);
+        onSliceContentChanged(mKeyguardSlice.hasHeader());
         updateDozeVisibleViews();
     }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 19afcf5..9e4b405 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -1257,7 +1257,8 @@
                 mFingerprintCancelSignal.cancel();
             }
             mFingerprintCancelSignal = new CancellationSignal();
-            mFpm.authenticate(null, mFingerprintCancelSignal, 0, mAuthenticationCallback, null, userId);
+            mFpm.authenticate(null, mFingerprintCancelSignal, 0, mAuthenticationCallback, null,
+                    userId);
             setFingerprintRunningState(FINGERPRINT_STATE_RUNNING);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java b/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java
new file mode 100644
index 0000000..262c71a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java
@@ -0,0 +1,220 @@
+/*
+ * 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.fingerprint;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.hardware.fingerprint.FingerprintDialog;
+import android.hardware.fingerprint.IFingerprintDialogReceiver;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.WindowManager;
+
+import com.android.internal.os.SomeArgs;
+import com.android.systemui.SystemUI;
+import com.android.systemui.statusbar.CommandQueue;
+
+public class FingerprintDialogImpl extends SystemUI implements CommandQueue.Callbacks {
+    private static final String TAG = "FingerprintDialogImpl";
+    private static final boolean DEBUG = true;
+
+    protected static final int MSG_SHOW_DIALOG = 1;
+    protected static final int MSG_FINGERPRINT_AUTHENTICATED = 2;
+    protected static final int MSG_FINGERPRINT_HELP = 3;
+    protected static final int MSG_FINGERPRINT_ERROR = 4;
+    protected static final int MSG_HIDE_DIALOG = 5;
+    protected static final int MSG_BUTTON_NEGATIVE = 6;
+    protected static final int MSG_USER_CANCELED = 7;
+    protected static final int MSG_BUTTON_POSITIVE = 8;
+    protected static final int MSG_CLEAR_MESSAGE = 9;
+
+
+    private FingerprintDialogView mDialogView;
+    private WindowManager mWindowManager;
+    private IFingerprintDialogReceiver mReceiver;
+    private boolean mDialogShowing;
+
+    private Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch(msg.what) {
+                case MSG_SHOW_DIALOG:
+                    handleShowDialog((SomeArgs) msg.obj);
+                    break;
+                case MSG_FINGERPRINT_AUTHENTICATED:
+                    handleFingerprintAuthenticated();
+                    break;
+                case MSG_FINGERPRINT_HELP:
+                    handleFingerprintHelp((String) msg.obj);
+                    break;
+                case MSG_FINGERPRINT_ERROR:
+                    handleFingerprintError((String) msg.obj);
+                    break;
+                case MSG_HIDE_DIALOG:
+                    handleHideDialog((Boolean) msg.obj);
+                    break;
+                case MSG_BUTTON_NEGATIVE:
+                    handleButtonNegative();
+                    break;
+                case MSG_USER_CANCELED:
+                    handleUserCanceled();
+                    break;
+                case MSG_BUTTON_POSITIVE:
+                    handleButtonPositive();
+                    break;
+                case MSG_CLEAR_MESSAGE:
+                    handleClearMessage();
+                    break;
+            }
+        }
+    };
+
+    @Override
+    public void start() {
+        if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
+            return;
+        }
+        getComponent(CommandQueue.class).addCallbacks(this);
+        mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+        mDialogView = new FingerprintDialogView(mContext, mHandler);
+    }
+
+    @Override
+    public void showFingerprintDialog(Bundle bundle, IFingerprintDialogReceiver receiver) {
+        if (DEBUG) Log.d(TAG, "showFingerprintDialog");
+        // Remove these messages as they are part of the previous client
+        mHandler.removeMessages(MSG_FINGERPRINT_ERROR);
+        mHandler.removeMessages(MSG_FINGERPRINT_HELP);
+        mHandler.removeMessages(MSG_FINGERPRINT_AUTHENTICATED);
+        SomeArgs args = SomeArgs.obtain();
+        args.arg1 = bundle;
+        args.arg2 = receiver;
+        mHandler.obtainMessage(MSG_SHOW_DIALOG, args).sendToTarget();
+    }
+
+    @Override
+    public void onFingerprintAuthenticated() {
+        if (DEBUG) Log.d(TAG, "onFingerprintAuthenticated");
+        mHandler.obtainMessage(MSG_FINGERPRINT_AUTHENTICATED).sendToTarget();
+    }
+
+    @Override
+    public void onFingerprintHelp(String message) {
+        if (DEBUG) Log.d(TAG, "onFingerprintHelp: " + message);
+        mHandler.obtainMessage(MSG_FINGERPRINT_HELP, message).sendToTarget();
+    }
+
+    @Override
+    public void onFingerprintError(String error) {
+        if (DEBUG) Log.d(TAG, "onFingerprintError: " + error);
+        mHandler.obtainMessage(MSG_FINGERPRINT_ERROR, error).sendToTarget();
+    }
+
+    @Override
+    public void hideFingerprintDialog() {
+        if (DEBUG) Log.d(TAG, "hideFingerprintDialog");
+        mHandler.obtainMessage(MSG_HIDE_DIALOG, false /* userCanceled */).sendToTarget();
+    }
+
+    private void handleShowDialog(SomeArgs args) {
+        if (DEBUG) Log.d(TAG, "handleShowDialog");
+        if (mDialogShowing) {
+            Log.w(TAG, "Dialog already showing");
+            return;
+        }
+        mReceiver = (IFingerprintDialogReceiver) args.arg2;
+        mDialogView.setBundle((Bundle)args.arg1);
+        mWindowManager.addView(mDialogView, mDialogView.getLayoutParams());
+        mDialogShowing = true;
+    }
+
+    private void handleFingerprintAuthenticated() {
+        if (DEBUG) Log.d(TAG, "handleFingerprintAuthenticated");
+        handleHideDialog(false /* userCanceled */);
+    }
+
+    private void handleFingerprintHelp(String message) {
+        if (DEBUG) Log.d(TAG, "handleFingerprintHelp: " + message);
+        mDialogView.showHelpMessage(message);
+    }
+
+    private void handleFingerprintError(String error) {
+        if (DEBUG) Log.d(TAG, "handleFingerprintError: " + error);
+        if (!mDialogShowing) {
+            if (DEBUG) Log.d(TAG, "Dialog already dismissed");
+            return;
+        }
+        mDialogView.showErrorMessage(error);
+    }
+
+    private void handleHideDialog(boolean userCanceled) {
+        if (DEBUG) Log.d(TAG, "handleHideDialog");
+        if (!mDialogShowing) {
+            // This can happen if there's a race and we get called from both
+            // onAuthenticated and onError, etc.
+            Log.w(TAG, "Dialog already dismissed, userCanceled: " + userCanceled);
+            return;
+        }
+        if (userCanceled) {
+            try {
+                mReceiver.onDialogDismissed(FingerprintDialog.DISMISSED_REASON_USER_CANCEL);
+            } catch (RemoteException e) {
+                Log.e(TAG, "RemoteException when hiding dialog", e);
+            }
+        }
+        mReceiver = null;
+        mWindowManager.removeView(mDialogView);
+        mDialogShowing = false;
+    }
+
+    private void handleButtonNegative() {
+        if (mReceiver == null) {
+            Log.e(TAG, "Receiver is null");
+            return;
+        }
+        try {
+            mReceiver.onDialogDismissed(FingerprintDialog.DISMISSED_REASON_NEGATIVE);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Remote exception when handling negative button", e);
+        }
+        handleHideDialog(false /* userCanceled */);
+    }
+
+    private void handleButtonPositive() {
+        if (mReceiver == null) {
+            Log.e(TAG, "Receiver is null");
+            return;
+        }
+        try {
+            mReceiver.onDialogDismissed(FingerprintDialog.DISMISSED_REASON_POSITIVE);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Remote exception when handling positive button", e);
+        }
+        handleHideDialog(false /* userCanceled */);
+    }
+
+    private void handleClearMessage() {
+        mDialogView.clearMessage();
+    }
+
+    private void handleUserCanceled() {
+        handleHideDialog(true /* userCanceled */);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogView.java b/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogView.java
new file mode 100644
index 0000000..19bc2ec
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogView.java
@@ -0,0 +1,228 @@
+/*
+ * 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.fingerprint;
+
+import android.app.ActivityManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.Drawable;
+import android.hardware.fingerprint.FingerprintDialog;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.view.animation.Interpolator;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.PackageManagerWrapper;
+
+/**
+ * This class loads the view for the system-provided dialog. The view consists of:
+ * Application Icon, Title, Subtitle, Description, Fingerprint Icon, Error/Help message area,
+ * and positive/negative buttons.
+ */
+public class FingerprintDialogView extends LinearLayout {
+
+    private static final String TAG = "FingerprintDialogView";
+
+    private static final int ANIMATION_DURATION = 250; // ms
+
+    private final IBinder mWindowToken = new Binder();
+    private final ActivityManagerWrapper mActivityManagerWrapper;
+    private final PackageManagerWrapper mPackageManageWrapper;
+    private final Interpolator mLinearOutSlowIn;
+    private final Interpolator mFastOutLinearIn;
+    private final float mAnimationTranslationOffset;
+
+    private ViewGroup mLayout;
+    private final TextView mErrorText;
+    private Handler mHandler;
+    private Bundle mBundle;
+    private final LinearLayout mDialog;
+
+    public FingerprintDialogView(Context context, Handler handler) {
+        super(context);
+        mHandler = handler;
+        mActivityManagerWrapper = ActivityManagerWrapper.getInstance();
+        mPackageManageWrapper = PackageManagerWrapper.getInstance();
+        mLinearOutSlowIn = Interpolators.LINEAR_OUT_SLOW_IN;
+        mFastOutLinearIn = Interpolators.FAST_OUT_LINEAR_IN;
+        mAnimationTranslationOffset = getResources()
+                .getDimension(R.dimen.fingerprint_dialog_animation_translation_offset);
+
+        // Create the dialog
+        LayoutInflater factory = LayoutInflater.from(getContext());
+        mLayout = (ViewGroup) factory.inflate(R.layout.fingerprint_dialog, this, false);
+        addView(mLayout);
+
+        mDialog = mLayout.findViewById(R.id.dialog);
+
+        mErrorText = mLayout.findViewById(R.id.error);
+
+        mLayout.setOnKeyListener(new View.OnKeyListener() {
+            boolean downPressed = false;
+            @Override
+            public boolean onKey(View v, int keyCode, KeyEvent event) {
+                if (keyCode != KeyEvent.KEYCODE_BACK) {
+                    return false;
+                }
+                if (event.getAction() == KeyEvent.ACTION_DOWN && downPressed == false) {
+                    downPressed = true;
+                } else if (event.getAction() == KeyEvent.ACTION_DOWN) {
+                    downPressed = false;
+                } else if (event.getAction() == KeyEvent.ACTION_UP && downPressed == true) {
+                    downPressed = false;
+                    mHandler.obtainMessage(FingerprintDialogImpl.MSG_USER_CANCELED).sendToTarget();
+                }
+                return true;
+            }
+        });
+
+        final View space = mLayout.findViewById(R.id.space);
+        final Button negative = mLayout.findViewById(R.id.button2);
+        final Button positive = mLayout.findViewById(R.id.button1);
+
+        space.setClickable(true);
+        space.setOnTouchListener((View view, MotionEvent event) -> {
+            mHandler.obtainMessage(FingerprintDialogImpl.MSG_HIDE_DIALOG, true /* userCanceled*/)
+                    .sendToTarget();
+            return true;
+        });
+
+        negative.setOnClickListener((View v) -> {
+            mHandler.obtainMessage(FingerprintDialogImpl.MSG_BUTTON_NEGATIVE).sendToTarget();
+        });
+
+        positive.setOnClickListener((View v) -> {
+            mHandler.obtainMessage(FingerprintDialogImpl.MSG_BUTTON_POSITIVE).sendToTarget();
+        });
+
+        mLayout.setFocusableInTouchMode(true);
+        mLayout.requestFocus();
+    }
+
+    @Override
+    public void onAttachedToWindow() {
+        super.onAttachedToWindow();
+
+        final TextView title = mLayout.findViewById(R.id.title);
+        final TextView subtitle = mLayout.findViewById(R.id.subtitle);
+        final TextView description = mLayout.findViewById(R.id.description);
+        final Button negative = mLayout.findViewById(R.id.button2);
+        final ImageView image = mLayout.findViewById(R.id.icon);
+        final Button positive = mLayout.findViewById(R.id.button1);
+        final ImageView fingerprint_icon = mLayout.findViewById(R.id.fingerprint_icon);
+
+        title.setText(mBundle.getCharSequence(FingerprintDialog.KEY_TITLE));
+        title.setSelected(true);
+        subtitle.setText(mBundle.getCharSequence(FingerprintDialog.KEY_SUBTITLE));
+        description.setText(mBundle.getCharSequence(FingerprintDialog.KEY_DESCRIPTION));
+        negative.setText(mBundle.getCharSequence(FingerprintDialog.KEY_NEGATIVE_TEXT));
+        image.setImageDrawable(getAppIcon());
+
+        final CharSequence positiveText =
+                mBundle.getCharSequence(FingerprintDialog.KEY_POSITIVE_TEXT);
+        positive.setText(positiveText); // needs to be set for marquee to work
+        if (positiveText != null) {
+            positive.setVisibility(View.VISIBLE);
+        } else {
+            positive.setVisibility(View.GONE);
+        }
+
+        // Dim the background and slide the dialog up
+        mDialog.setTranslationY(mAnimationTranslationOffset);
+        mLayout.setAlpha(0f);
+        postOnAnimation(new Runnable() {
+            @Override
+            public void run() {
+                mLayout.animate()
+                        .alpha(1f)
+                        .setDuration(ANIMATION_DURATION)
+                        .setInterpolator(mLinearOutSlowIn)
+                        .withLayer()
+                        .start();
+                mDialog.animate()
+                        .translationY(0)
+                        .setDuration(ANIMATION_DURATION)
+                        .setInterpolator(mLinearOutSlowIn)
+                        .withLayer()
+                        .start();
+            }
+        });
+    }
+
+    public void setBundle(Bundle bundle) {
+        mBundle = bundle;
+    }
+
+    protected void clearMessage() {
+        mErrorText.setVisibility(View.INVISIBLE);
+    }
+
+    private void showMessage(String message) {
+        mHandler.removeMessages(FingerprintDialogImpl.MSG_CLEAR_MESSAGE);
+        mErrorText.setText(message);
+        mErrorText.setVisibility(View.VISIBLE);
+        mHandler.sendMessageDelayed(mHandler.obtainMessage(FingerprintDialogImpl.MSG_CLEAR_MESSAGE),
+                FingerprintDialog.HIDE_DIALOG_DELAY);
+    }
+
+    public void showHelpMessage(String message) {
+        showMessage(message);
+    }
+
+    public void showErrorMessage(String error) {
+        showMessage(error);
+        mHandler.sendMessageDelayed(mHandler.obtainMessage(FingerprintDialogImpl.MSG_HIDE_DIALOG,
+                false /* userCanceled */), FingerprintDialog.HIDE_DIALOG_DELAY);
+    }
+
+    private Drawable getAppIcon() {
+        final ActivityManager.RunningTaskInfo taskInfo = mActivityManagerWrapper.getRunningTask();
+        final ComponentName cn = taskInfo.topActivity;
+        final int userId = mActivityManagerWrapper.getCurrentUserId();
+        final ActivityInfo activityInfo = mPackageManageWrapper.getActivityInfo(cn, userId);
+        return mActivityManagerWrapper.getBadgedActivityIcon(activityInfo, userId);
+    }
+
+    public WindowManager.LayoutParams getLayoutParams() {
+        final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
+                WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
+                PixelFormat.TRANSLUCENT);
+        lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+        lp.setTitle("FingerprintDialogView");
+        lp.token = mWindowToken;
+        return lp;
+    }
+}
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 142aab2..23d3ebbb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
@@ -47,7 +47,7 @@
     private MultiUserSwitch mMultiUserSwitch;
     private TextView mUserName;
     private ImageView mMultiUserAvatar;
-    private UserGridView mUserGridView;
+    private CarQSFragment.UserSwitchCallback mUserSwitchCallback;
 
     public CarQSFooter(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -63,15 +63,15 @@
         mUserInfoController = Dependency.get(UserInfoController.class);
 
         mMultiUserSwitch.setOnClickListener(v -> {
-            if (mUserGridView == null) {
+            if (mUserSwitchCallback == null) {
                 Log.e(TAG, "CarQSFooter not properly set up; cannot display user switcher.");
                 return;
             }
 
-            if (!mUserGridView.isShowing()) {
-                mUserGridView.show();
+            if (!mUserSwitchCallback.isShowing()) {
+                mUserSwitchCallback.show();
             } else {
-                mUserGridView.hide();
+                mUserSwitchCallback.hide();
             }
         });
 
@@ -102,8 +102,8 @@
         }
     }
 
-    public void setUserGridView(UserGridView view) {
-        mUserGridView = view;
+    public void setUserSwitchCallback(CarQSFragment.UserSwitchCallback callback) {
+        mUserSwitchCallback = callback;
     }
 
     @Override
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 13298d3..0ee6d1f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
@@ -13,6 +13,12 @@
  */
 package com.android.systemui.qs.car;
 
+import android.animation.Animator;
+import android.animation.AnimatorInflater;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
 import android.app.Fragment;
 import android.os.Bundle;
 import android.support.annotation.Nullable;
@@ -26,18 +32,29 @@
 import com.android.systemui.R;
 import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.qs.QSFooter;
+import com.android.systemui.statusbar.car.PageIndicator;
 import com.android.systemui.statusbar.car.UserGridView;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * A quick settings fragment for the car. For auto, there is no row for quick settings or ability
  * to expand the quick settings panel. Instead, the only thing is that displayed is the
  * status bar, and a static row with access to the user switcher and settings.
  */
 public class CarQSFragment extends Fragment implements QS {
+    private ViewGroup mPanel;
     private View mHeader;
+    private View mUserSwitcherContainer;
     private CarQSFooter mFooter;
+    private View mFooterUserName;
+    private View mFooterExpandIcon;
     private UserGridView mUserGridView;
+    private PageIndicator mPageIndicator;
+    private AnimatorSet mAnimatorSet;
+    private UserSwitchCallback mUserSwitchCallback;
 
     @Override
     public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@@ -48,14 +65,26 @@
     @Override
     public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
+        mPanel = (ViewGroup) view;
         mHeader = view.findViewById(R.id.header);
         mFooter = view.findViewById(R.id.qs_footer);
+        mFooterUserName = mFooter.findViewById(R.id.user_name);
+        mFooterExpandIcon = mFooter.findViewById(R.id.user_switch_expand_icon);
+
+        mUserSwitcherContainer = view.findViewById(R.id.user_switcher_container);
+
+        updateUserSwitcherHeight(0);
 
         mUserGridView = view.findViewById(R.id.user_grid);
         mUserGridView.init(null, Dependency.get(UserSwitcherController.class),
-                false /* showInitially */);
+                false /* overrideAlpha */);
 
-        mFooter.setUserGridView(mUserGridView);
+        mPageIndicator = view.findViewById(R.id.user_switcher_page_indicator);
+        mPageIndicator.setupWithViewPager(mUserGridView);
+
+        mUserSwitchCallback = new UserSwitchCallback();
+        mFooter.setUserSwitchCallback(mUserSwitchCallback);
+        mUserGridView.setUserSwitchCallback(mUserSwitchCallback);
     }
 
     @Override
@@ -82,11 +111,13 @@
     @Override
     public void setHeaderListening(boolean listening) {
         mFooter.setListening(listening);
+        mUserGridView.setListening(listening);
     }
 
     @Override
     public void setListening(boolean listening) {
         mFooter.setListening(listening);
+        mUserGridView.setListening(listening);
     }
 
     @Override
@@ -171,4 +202,126 @@
     public void setExpandClickListener(OnClickListener onClickListener) {
         // No ability to expand the quick settings.
     }
+
+    public class UserSwitchCallback {
+        private boolean mShowing;
+
+        public boolean isShowing() {
+            return mShowing;
+        }
+
+        public void show() {
+            mShowing = true;
+            animateHeightChange(true /* opening */);
+        }
+
+        public void hide() {
+            mShowing = false;
+            animateHeightChange(false /* opening */);
+        }
+
+        public void resetShowing() {
+            if (mShowing) {
+                for (int i = 0; i < mUserGridView.getChildCount(); i++) {
+                    ViewGroup podContainer = (ViewGroup) mUserGridView.getChildAt(i);
+                    // Need to bring the last child to the front to maintain the order in the pod
+                    // container. Why? ¯\_(ツ)_/¯
+                    if (podContainer.getChildCount() > 0) {
+                        podContainer.getChildAt(podContainer.getChildCount() - 1).bringToFront();
+                    }
+                    // The alpha values are default to 0, so if the pods have been refreshed, they
+                    // need to be set to 1 when showing.
+                    for (int j = 0; j < podContainer.getChildCount(); j++) {
+                        podContainer.getChildAt(j).setAlpha(1f);
+                    }
+                }
+            }
+        }
+    }
+
+    private void updateUserSwitcherHeight(int height) {
+        ViewGroup.LayoutParams layoutParams = mUserSwitcherContainer.getLayoutParams();
+        layoutParams.height = height;
+        mUserSwitcherContainer.requestLayout();
+    }
+
+    private void animateHeightChange(boolean opening) {
+        // Animation in progress; cancel it to avoid contention.
+        if (mAnimatorSet != null){
+            mAnimatorSet.cancel();
+        }
+
+        List<Animator> allAnimators = new ArrayList<>();
+        ValueAnimator heightAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(getContext(),
+                opening ? R.anim.car_user_switcher_open_animation
+                        : R.anim.car_user_switcher_close_animation);
+        heightAnimator.addUpdateListener(valueAnimator -> {
+            updateUserSwitcherHeight((Integer) valueAnimator.getAnimatedValue());
+        });
+        allAnimators.add(heightAnimator);
+
+        // The user grid contains pod containers that each contain a number of pods.  Animate
+        // all pods to avoid any discrepancy/race conditions with possible changes during the
+        // animation.
+        int cascadeDelay = getResources().getInteger(
+                R.integer.car_user_switcher_anim_cascade_delay_ms);
+        for (int i = 0; i < mUserGridView.getChildCount(); i++) {
+            ViewGroup podContainer = (ViewGroup) mUserGridView.getChildAt(i);
+            for (int j = 0; j < podContainer.getChildCount(); j++) {
+                View pod = podContainer.getChildAt(j);
+                Animator podAnimator = AnimatorInflater.loadAnimator(getContext(),
+                        opening ? R.anim.car_user_switcher_open_pod_animation
+                                : R.anim.car_user_switcher_close_pod_animation);
+                // Add the cascading delay between pods
+                if (opening) {
+                    podAnimator.setStartDelay(podAnimator.getStartDelay() + j * cascadeDelay);
+                }
+                podAnimator.setTarget(pod);
+                allAnimators.add(podAnimator);
+            }
+        }
+
+        Animator nameAnimator = AnimatorInflater.loadAnimator(getContext(),
+                opening ? R.anim.car_user_switcher_open_name_animation
+                        : R.anim.car_user_switcher_close_name_animation);
+        nameAnimator.setTarget(mFooterUserName);
+        allAnimators.add(nameAnimator);
+
+        Animator iconAnimator = AnimatorInflater.loadAnimator(getContext(),
+                opening ? R.anim.car_user_switcher_open_icon_animation
+                        : R.anim.car_user_switcher_close_icon_animation);
+        iconAnimator.setTarget(mFooterExpandIcon);
+        allAnimators.add(iconAnimator);
+
+        Animator pageAnimator = AnimatorInflater.loadAnimator(getContext(),
+                opening ? R.anim.car_user_switcher_open_pages_animation
+                        : R.anim.car_user_switcher_close_pages_animation);
+        pageAnimator.setTarget(mPageIndicator);
+        allAnimators.add(pageAnimator);
+
+        mAnimatorSet = new AnimatorSet();
+        mAnimatorSet.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mAnimatorSet = null;
+            }
+        });
+        mAnimatorSet.playTogether(allAnimators.toArray(new Animator[0]));
+
+        // Setup all values to the start values in the animations, since there are delays, but need
+        // to have all values start at the beginning.
+        setupInitialValues(mAnimatorSet);
+
+        mAnimatorSet.start();
+    }
+
+    private void setupInitialValues(Animator anim) {
+        if (anim instanceof AnimatorSet) {
+            for (Animator a : ((AnimatorSet) anim).getChildAnimations()) {
+                setupInitialValues(a);
+            }
+        } else if (anim instanceof ObjectAnimator) {
+            ((ObjectAnimator) anim).setCurrentFraction(0.0f);
+        }
+    }
 }
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 fff9f8e..2607ebb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -18,7 +18,9 @@
 
 import static com.android.settingslib.graph.BluetoothDeviceLayerDrawable.createLayerDrawable;
 
+import android.annotation.Nullable;
 import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothClass;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothProfile;
 import android.content.Context;
@@ -26,7 +28,6 @@
 import android.graphics.drawable.Drawable;
 import android.provider.Settings;
 import android.service.quicksettings.Tile;
-import android.text.TextUtils;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Switch;
@@ -35,6 +36,7 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settingslib.Utils;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.graph.BluetoothDeviceLayerDrawable;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.plugins.ActivityStarter;
@@ -126,21 +128,25 @@
         }
         state.slash.isSlashed = !enabled;
         state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
+
         if (enabled) {
             if (connected) {
                 state.icon = ResourceIcon.get(R.drawable.ic_qs_bluetooth_connected);
-                state.secondaryLabel = mController.getLastDeviceName();
-                CachedBluetoothDevice lastDevice = mController.getLastDevice();
+                state.contentDescription = mContext.getString(
+                        R.string.accessibility_bluetooth_name, state.label);
+
+                final CachedBluetoothDevice lastDevice = mController.getLastDevice();
                 if (lastDevice != null) {
-                    int batteryLevel = lastDevice.getBatteryLevel();
+                    final int batteryLevel = lastDevice.getBatteryLevel();
                     if (batteryLevel != BluetoothDevice.BATTERY_LEVEL_UNKNOWN) {
-                        state.icon = new BluetoothBatteryTileIcon(lastDevice,
+                        state.icon = new BluetoothBatteryTileIcon(
+                                batteryLevel,
                                 mContext.getResources().getFraction(
                                         R.fraction.bt_battery_scale_fraction, 1, 1));
                     }
                 }
-                state.contentDescription = mContext.getString(
-                        R.string.accessibility_bluetooth_name, state.secondaryLabel);
+
+                state.label = mController.getLastDeviceName();
             } else if (state.isTransient) {
                 state.icon = ResourceIcon.get(R.drawable.ic_bluetooth_transient_animation);
                 state.contentDescription = mContext.getString(
@@ -159,11 +165,53 @@
             state.state = Tile.STATE_INACTIVE;
         }
 
+        state.secondaryLabel = getSecondaryLabel(enabled, connected);
+
         state.dualLabelContentDescription = mContext.getResources().getString(
                 R.string.accessibility_quick_settings_open_settings, getTileLabel());
         state.expandedAccessibilityClassName = Switch.class.getName();
     }
 
+    /**
+     * Returns the secondary label to use for the given bluetooth connection in the form of the
+     * battery level or bluetooth profile name. If the bluetooth is disabled, there's no connected
+     * devices, or we can't map the bluetooth class to a profile, this instead returns {@code null}.
+     *
+     * @param enabled whether bluetooth is enabled
+     * @param connected whether there's a device connected via bluetooth
+     */
+    @Nullable
+    private String getSecondaryLabel(boolean enabled, boolean connected) {
+        final CachedBluetoothDevice lastDevice = mController.getLastDevice();
+
+        if (enabled && connected && lastDevice != null) {
+            final int batteryLevel = lastDevice.getBatteryLevel();
+
+            if (batteryLevel != BluetoothDevice.BATTERY_LEVEL_UNKNOWN) {
+                return mContext.getString(
+                        R.string.quick_settings_bluetooth_secondary_label_battery_level,
+                        Utils.formatPercentage(batteryLevel));
+
+            } else {
+                final BluetoothClass bluetoothClass = lastDevice.getBtClass();
+                if (bluetoothClass != null) {
+                    if (bluetoothClass.doesClassMatch(BluetoothClass.PROFILE_A2DP)) {
+                        return mContext.getString(
+                                R.string.quick_settings_bluetooth_secondary_label_audio);
+                    } else if (bluetoothClass.doesClassMatch(BluetoothClass.PROFILE_HEADSET)) {
+                        return mContext.getString(
+                                R.string.quick_settings_bluetooth_secondary_label_headset);
+                    } else if (bluetoothClass.doesClassMatch(BluetoothClass.PROFILE_HID)) {
+                        return mContext.getString(
+                                R.string.quick_settings_bluetooth_secondary_label_input);
+                    }
+                }
+            }
+        }
+
+        return null;
+    }
+
     @Override
     public int getMetricsCategory() {
         return MetricsEvent.QS_BLUETOOTH;
@@ -207,20 +255,29 @@
         return new BluetoothDetailAdapter();
     }
 
+    /**
+     * Bluetooth icon wrapper for Quick Settings with a battery indicator that reflects the
+     * connected device's battery level. This is used instead of
+     * {@link com.android.systemui.qs.tileimpl.QSTileImpl.DrawableIcon} in order to use a context
+     * that reflects dark/light theme attributes.
+     */
     private class BluetoothBatteryTileIcon extends Icon {
+        private int mBatteryLevel;
         private float mIconScale;
-        private CachedBluetoothDevice mDevice;
 
-        BluetoothBatteryTileIcon(CachedBluetoothDevice device, float iconScale) {
+        BluetoothBatteryTileIcon(int batteryLevel, float iconScale) {
+            mBatteryLevel = batteryLevel;
             mIconScale = iconScale;
-            mDevice = device;
         }
 
         @Override
         public Drawable getDrawable(Context context) {
             // This method returns Pair<Drawable, String> while first value is the drawable
-            return com.android.settingslib.bluetooth.Utils.getBtClassDrawableWithDescription(
-                    context, mDevice, mIconScale).first;
+            return BluetoothDeviceLayerDrawable.createLayerDrawable(
+                    context,
+                    R.drawable.ic_qs_bluetooth_connected,
+                    mBatteryLevel,
+                    mIconScale);
         }
     }
 
@@ -302,8 +359,7 @@
                         item.iconResId = R.drawable.ic_qs_bluetooth_connected;
                         int batteryLevel = device.getBatteryLevel();
                         if (batteryLevel != BluetoothDevice.BATTERY_LEVEL_UNKNOWN) {
-                            item.icon = new BluetoothBatteryTileIcon(device,
-                                    1 /* iconScale */);
+                            item.icon = new BluetoothBatteryTileIcon(batteryLevel,1 /* iconScale */);
                             item.line2 = mContext.getString(
                                     R.string.quick_settings_connected_battery_level,
                                     Utils.formatPercentage(batteryLevel));
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index 910b6b1..e1b58fe 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.qs.tiles;
 
+import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -37,7 +38,7 @@
 /** Quick settings tile: Hotspot **/
 public class HotspotTile extends QSTileImpl<AirplaneBooleanState> {
     static final Intent TETHER_SETTINGS = new Intent().setComponent(new ComponentName(
-             "com.android.settings", "com.android.settings.TetherSettings"));
+            "com.android.settings", "com.android.settings.TetherSettings"));
 
     private final Icon mEnabledStatic = ResourceIcon.get(R.drawable.ic_hotspot);
     private final Icon mUnavailable = ResourceIcon.get(R.drawable.ic_hotspot_unavailable);
@@ -115,11 +116,19 @@
         state.label = mContext.getString(R.string.quick_settings_hotspot_label);
 
         checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_CONFIG_TETHERING);
-        if (arg instanceof Boolean) {
-            state.value = (boolean) arg;
+
+        final int numConnectedDevices;
+        if (arg instanceof CallbackInfo) {
+            CallbackInfo info = (CallbackInfo) arg;
+            state.value = info.enabled;
+            numConnectedDevices = info.numConnectedDevices;
         } else {
             state.value = mController.isHotspotEnabled();
+            numConnectedDevices = mController.getNumConnectedDevices();
         }
+
+        state.secondaryLabel = getSecondaryLabel(state.value, numConnectedDevices);
+
         state.icon = mEnabledStatic;
         state.isAirplaneMode = mAirplaneMode.getValue() != 0;
         state.isTransient = mController.isHotspotTransient();
@@ -133,6 +142,18 @@
                 : state.value || state.isTransient ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
     }
 
+    @Nullable
+    private String getSecondaryLabel(boolean enabled, int numConnectedDevices) {
+        if (numConnectedDevices > 0 && enabled) {
+            return mContext.getResources().getQuantityString(
+                    R.plurals.quick_settings_hotspot_num_devices,
+                    numConnectedDevices,
+                    numConnectedDevices);
+        }
+
+        return null;
+    }
+
     @Override
     public int getMetricsCategory() {
         return MetricsEvent.QS_HOTSPOT;
@@ -148,9 +169,30 @@
     }
 
     private final class Callback implements HotspotController.Callback {
+        final CallbackInfo mCallbackInfo = new CallbackInfo();
+
         @Override
-        public void onHotspotChanged(boolean enabled) {
-            refreshState(enabled);
+        public void onHotspotChanged(boolean enabled, int numConnectedDevices) {
+            mCallbackInfo.enabled = enabled;
+            mCallbackInfo.numConnectedDevices = numConnectedDevices;
+            refreshState(mCallbackInfo);
         }
-    };
+    }
+
+    /**
+     * Holder for any hotspot state info that needs to passed from the callback to
+     * {@link #handleUpdateState(State, Object)}.
+     */
+    protected static final class CallbackInfo {
+        boolean enabled;
+        int numConnectedDevices;
+
+        @Override
+        public String toString() {
+            return new StringBuilder("CallbackInfo[")
+                    .append("enabled=").append(enabled)
+                    .append(",numConnectedDevices=").append(numConnectedDevices)
+                    .append(']').toString();
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 675aa8f..0132fa8 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -185,7 +185,7 @@
 
         // The public notification will show similar info but with the actual screenshot omitted
         mPublicNotificationBuilder =
-                new Notification.Builder(context, NotificationChannels.SCREENSHOTS)
+                new Notification.Builder(context, NotificationChannels.SCREENSHOTS_HEADSUP)
                         .setContentTitle(r.getString(R.string.screenshot_saving_title))
                         .setContentText(r.getString(R.string.screenshot_saving_text))
                         .setSmallIcon(R.drawable.stat_notify_image)
@@ -196,7 +196,8 @@
                                 com.android.internal.R.color.system_notification_accent_color));
         SystemUI.overrideNotificationAppName(context, mPublicNotificationBuilder);
 
-        mNotificationBuilder = new Notification.Builder(context, NotificationChannels.SCREENSHOTS)
+        mNotificationBuilder = new Notification.Builder(context,
+                NotificationChannels.SCREENSHOTS_HEADSUP)
             .setTicker(r.getString(R.string.screenshot_saving_ticker)
                     + (mTickerAddSpace ? " " : ""))
             .setContentTitle(r.getString(R.string.screenshot_saving_title))
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index c6abcf2..00bc62e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -18,6 +18,7 @@
 
 import android.content.ComponentName;
 import android.graphics.Rect;
+import android.hardware.fingerprint.IFingerprintDialogReceiver;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -83,6 +84,11 @@
     private static final int MSG_SHOW_SHUTDOWN_UI              = 36 << MSG_SHIFT;
     private static final int MSG_SET_TOP_APP_HIDES_STATUS_BAR  = 37 << MSG_SHIFT;
     private static final int MSG_ROTATION_PROPOSAL             = 38 << MSG_SHIFT;
+    private static final int MSG_FINGERPRINT_SHOW              = 39 << MSG_SHIFT;
+    private static final int MSG_FINGERPRINT_AUTHENTICATED     = 40 << MSG_SHIFT;
+    private static final int MSG_FINGERPRINT_HELP              = 41 << MSG_SHIFT;
+    private static final int MSG_FINGERPRINT_ERROR             = 42 << MSG_SHIFT;
+    private static final int MSG_FINGERPRINT_HIDE              = 43 << MSG_SHIFT;
 
     public static final int FLAG_EXCLUDE_NONE = 0;
     public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -145,6 +151,12 @@
         default void handleShowShutdownUi(boolean isReboot, String reason) { }
 
         default void onRotationProposal(int rotation, boolean isValid) { }
+
+        default void showFingerprintDialog(Bundle bundle, IFingerprintDialogReceiver receiver) { }
+        default void onFingerprintAuthenticated() { }
+        default void onFingerprintHelp(String message) { }
+        default void onFingerprintError(String error) { }
+        default void hideFingerprintDialog() { }
     }
 
     @VisibleForTesting
@@ -470,6 +482,45 @@
         }
     }
 
+    @Override
+    public void showFingerprintDialog(Bundle bundle, IFingerprintDialogReceiver receiver) {
+        synchronized (mLock) {
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = bundle;
+            args.arg2 = receiver;
+            mHandler.obtainMessage(MSG_FINGERPRINT_SHOW, args)
+                    .sendToTarget();
+        }
+    }
+
+    @Override
+    public void onFingerprintAuthenticated() {
+        synchronized (mLock) {
+            mHandler.obtainMessage(MSG_FINGERPRINT_AUTHENTICATED).sendToTarget();
+        }
+    }
+
+    @Override
+    public void onFingerprintHelp(String message) {
+        synchronized (mLock) {
+            mHandler.obtainMessage(MSG_FINGERPRINT_HELP, message).sendToTarget();
+        }
+    }
+
+    @Override
+    public void onFingerprintError(String error) {
+        synchronized (mLock) {
+            mHandler.obtainMessage(MSG_FINGERPRINT_ERROR, error).sendToTarget();
+        }
+    }
+
+    @Override
+    public void hideFingerprintDialog() {
+        synchronized (mLock) {
+            mHandler.obtainMessage(MSG_FINGERPRINT_HIDE).sendToTarget();
+        }
+    }
+
     private final class H extends Handler {
         private H(Looper l) {
             super(l);
@@ -671,6 +722,35 @@
                         mCallbacks.get(i).onRotationProposal(msg.arg1, msg.arg2 != 0);
                     }
                     break;
+                case MSG_FINGERPRINT_SHOW:
+                    mHandler.removeMessages(MSG_FINGERPRINT_ERROR);
+                    mHandler.removeMessages(MSG_FINGERPRINT_HELP);
+                    mHandler.removeMessages(MSG_FINGERPRINT_AUTHENTICATED);
+                    for (int i = 0; i < mCallbacks.size(); i++) {
+                        mCallbacks.get(i).showFingerprintDialog(
+                                (Bundle)((SomeArgs)msg.obj).arg1,
+                                (IFingerprintDialogReceiver)((SomeArgs)msg.obj).arg2);
+                    }
+                    break;
+                case MSG_FINGERPRINT_AUTHENTICATED:
+                    for (int i = 0; i < mCallbacks.size(); i++) {
+                        mCallbacks.get(i).onFingerprintAuthenticated();
+                    }
+                    break;
+                case MSG_FINGERPRINT_HELP:
+                    for (int i = 0; i < mCallbacks.size(); i++) {
+                        mCallbacks.get(i).onFingerprintHelp((String) msg.obj);
+                    }
+                    break;
+                case MSG_FINGERPRINT_ERROR:
+                    for (int i = 0; i < mCallbacks.size(); i++) {
+                        mCallbacks.get(i).onFingerprintError((String) msg.obj);
+                    }
+                    break;
+                case MSG_FINGERPRINT_HIDE:
+                    for (int i = 0; i < mCallbacks.size(); i++) {
+                        mCallbacks.get(i).hideFingerprintDialog();
+                    }
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
index 172c62a..3ec8913 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -53,7 +53,7 @@
         mParent = containerStub.inflate();
         mContainer = mParent.findViewById(R.id.container);
         mUserGridView = mContainer.findViewById(R.id.user_grid);
-        mUserGridView.init(statusBar, mUserSwitcherController, true /* showInitially */);
+        mUserGridView.init(statusBar, mUserSwitcherController, true /* overrideAlpha */);
         mUserGridView.setUserSelectionListener(record -> {
             if (!record.isCurrent) {
                 toggleSwitchInProgress(true);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
index e551801..1bd820d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
@@ -16,9 +16,6 @@
 
 package com.android.systemui.statusbar.car;
 
-import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
-import android.animation.ValueAnimator;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
@@ -29,62 +26,110 @@
 import android.graphics.drawable.GradientDrawable;
 import android.support.v4.view.PagerAdapter;
 import android.support.v4.view.ViewPager;
-import android.support.v4.view.animation.FastOutSlowInInterpolator;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ImageView;
-import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import com.android.systemui.Dependency;
 import com.android.systemui.R;
+import com.android.systemui.qs.car.CarQSFragment;
 import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.policy.UserInfoController;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Vector;
+
 /**
  * Displays a ViewPager with icons for the users in the system to allow switching between users.
  * One of the uses of this is for the lock screen in auto.
  */
-public class UserGridView extends ViewPager {
-    private static final int EXPAND_ANIMATION_TIME_MS = 200;
-    private static final int HIDE_ANIMATION_TIME_MS = 133;
-
+public class UserGridView extends ViewPager implements
+        UserInfoController.OnUserInfoChangedListener {
     private StatusBar mStatusBar;
     private UserSwitcherController mUserSwitcherController;
     private Adapter mAdapter;
     private UserSelectionListener mUserSelectionListener;
-    private ValueAnimator mHeightAnimator;
-    private int mTargetHeight;
-    private int mHeightChildren;
-    private boolean mShowing;
+    private UserInfoController mUserInfoController;
+    private Vector mUserContainers;
+    private int mContainerWidth;
+    private boolean mOverrideAlpha;
+    private CarQSFragment.UserSwitchCallback mUserSwitchCallback;
 
     public UserGridView(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
 
     public void init(StatusBar statusBar, UserSwitcherController userSwitcherController,
-            boolean showInitially) {
+            boolean overrideAlpha) {
         mStatusBar = statusBar;
         mUserSwitcherController = userSwitcherController;
         mAdapter = new Adapter(mUserSwitcherController);
-        addOnLayoutChangeListener(mAdapter);
+        mUserInfoController = Dependency.get(UserInfoController.class);
+        mOverrideAlpha = overrideAlpha;
+        // Whenever the container width changes, the containers must be refreshed. Instead of
+        // doing an initial refreshContainers() to populate the containers, this listener will
+        // refresh them on layout change because that affects how the users are split into
+        // containers. Furthermore, at this point, the container width is unknown, so
+        // refreshContainers() cannot populate any containers.
+        addOnLayoutChangeListener(
+                (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
+                    int newWidth = Math.max(left - right, right - left);
+                    if (mContainerWidth != newWidth) {
+                        mContainerWidth = newWidth;
+                        refreshContainers();
+                    }
+                });
+    }
+
+    private void refreshContainers() {
+        mUserContainers = new Vector();
+
+        Context context = getContext();
+        LayoutInflater inflater = LayoutInflater.from(context);
+
+        for (int i = 0; i < mAdapter.getCount(); i++) {
+            ViewGroup pods = (ViewGroup) inflater.inflate(
+                    R.layout.car_fullscreen_user_pod_container, null);
+
+            int iconsPerPage = mAdapter.getIconsPerPage();
+            int limit = Math.min(mUserSwitcherController.getUsers().size(), (i + 1) * iconsPerPage);
+            for (int j = i * iconsPerPage; j < limit; j++) {
+                View v = mAdapter.makeUserPod(inflater, context, j, pods);
+                if (mOverrideAlpha) {
+                    v.setAlpha(1f);
+                }
+                pods.addView(v);
+                // This is hacky, but the dividers on the pod container LinearLayout don't seem
+                // to work for whatever reason.  Instead, set a right margin on the pod if it's not
+                // the right-most pod and there is more than one pod in the container.
+                if (i < limit - 1 && limit > 1) {
+                    ViewGroup.MarginLayoutParams params =
+                            (ViewGroup.MarginLayoutParams) v.getLayoutParams();
+                    params.setMargins(0, 0, getResources().getDimensionPixelSize(
+                            R.dimen.car_fullscreen_user_pod_margin_between), 0);
+                    v.setLayoutParams(params);
+                }
+            }
+            mUserContainers.add(pods);
+        }
+
+        mAdapter = new Adapter(mUserSwitcherController);
         setAdapter(mAdapter);
-        mShowing = showInitially;
     }
 
-    public boolean isShowing() {
-        return mShowing;
+    @Override
+    public void onUserInfoChanged(String name, Drawable picture, String userAccount) {
+        refreshContainers();
     }
 
-    public void show() {
-        mShowing = true;
-        animateHeightChange(getMeasuredHeight(), mHeightChildren);
-    }
-
-    public void hide() {
-        mShowing = false;
-        animateHeightChange(getMeasuredHeight(), 0);
+    public void setUserSwitchCallback(CarQSFragment.UserSwitchCallback callback) {
+        mUserSwitchCallback = callback;
     }
 
     public void onUserSwitched(int newUserId) {
@@ -96,6 +141,14 @@
         mUserSelectionListener = userSelectionListener;
     }
 
+    public void setListening(boolean listening) {
+        if (listening) {
+            mUserInfoController.addCallback(this);
+        } else {
+            mUserInfoController.removeCallback(this);
+        }
+    }
+
     void showOfflineAuthUi() {
         // TODO: Show keyguard UI in-place.
         mStatusBar.executeRunnableDismissingKeyguard(null, null, true, true, true);
@@ -115,13 +168,6 @@
                 height = Math.max(child.getMeasuredHeight(), height);
             }
 
-            mHeightChildren = height;
-
-            // Override the height if it's not showing.
-            if (!mShowing) {
-                height = 0;
-            }
-
             // Respect the AT_MOST request from parent.
             if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
                 height = Math.min(MeasureSpec.getSize(heightMeasureSpec), height);
@@ -132,72 +178,19 @@
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
     }
 
-    private void animateHeightChange(int oldHeight, int newHeight) {
-        // If there is no change in height or an animation is already in progress towards the
-        // desired height, then there's no need to make any changes.
-        if (oldHeight == newHeight || newHeight == mTargetHeight) {
-            return;
-        }
-
-        // Animation in progress is not going towards the new target, so cancel it.
-        if (mHeightAnimator != null){
-            mHeightAnimator.cancel();
-        }
-
-        mTargetHeight = newHeight;
-        mHeightAnimator = ValueAnimator.ofInt(oldHeight, mTargetHeight);
-        mHeightAnimator.addUpdateListener(valueAnimator -> {
-            ViewGroup.LayoutParams layoutParams = getLayoutParams();
-            layoutParams.height = (Integer) valueAnimator.getAnimatedValue();
-            requestLayout();
-        });
-        mHeightAnimator.addListener(new AnimatorListener() {
-            @Override
-            public void onAnimationStart(Animator animator) {}
-
-            @Override
-            public void onAnimationEnd(Animator animator) {
-                // ValueAnimator does not guarantee that the update listener will get an update
-                // to the final value, so here, the final value is set.  Though the final calculated
-                // height (mTargetHeight) could be set, WRAP_CONTENT is more appropriate.
-                ViewGroup.LayoutParams layoutParams = getLayoutParams();
-                layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
-                requestLayout();
-                mHeightAnimator = null;
-            }
-
-            @Override
-            public void onAnimationCancel(Animator animator) {}
-
-            @Override
-            public void onAnimationRepeat(Animator animator) {}
-        });
-
-        mHeightAnimator.setInterpolator(new FastOutSlowInInterpolator());
-        if (oldHeight < newHeight) {
-            // Expanding
-            mHeightAnimator.setDuration(EXPAND_ANIMATION_TIME_MS);
-        } else {
-            // Hiding
-            mHeightAnimator.setDuration(HIDE_ANIMATION_TIME_MS);
-        }
-        mHeightAnimator.start();
-    }
-
     /**
      * This is a ViewPager.PagerAdapter which deletegates the work to a
      * UserSwitcherController.BaseUserAdapter. Java doesn't support multiple inheritance so we have
      * to use composition instead to achieve the same goal since both the base classes are abstract
      * classes and not interfaces.
      */
-    private final class Adapter extends PagerAdapter implements View.OnLayoutChangeListener {
+    private final class Adapter extends PagerAdapter {
         private final int mPodWidth;
         private final int mPodMarginBetween;
         private final int mPodImageAvatarWidth;
         private final int mPodImageAvatarHeight;
 
         private final WrappedBaseUserAdapter mUserAdapter;
-        private int mContainerWidth;
 
         public Adapter(UserSwitcherController controller) {
             super();
@@ -229,30 +222,20 @@
         }
 
         @Override
-        public Object instantiateItem(ViewGroup container, int position) {
-            Context context = getContext();
-            LayoutInflater inflater = LayoutInflater.from(context);
-
-            ViewGroup pods = (ViewGroup) inflater.inflate(
-                    R.layout.car_fullscreen_user_pod_container, null);
-
-            int iconsPerPage = getIconsPerPage();
-            int limit = Math.min(mUserAdapter.getCount(), (position + 1) * iconsPerPage);
-            for (int i = position * iconsPerPage; i < limit; i++) {
-                View v = makeUserPod(inflater, context, i, pods);
-                pods.addView(v);
-                // This is hacky, but the dividers on the pod container LinearLayout don't seem
-                // to work for whatever reason.  Instead, set a right margin on the pod if it's not
-                // the right-most pod and there is more than one pod in the container.
-                if (i < limit - 1 && limit > 1) {
-                    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
-                            LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
-                    params.setMargins(0, 0, mPodMarginBetween, 0);
-                    v.setLayoutParams(params);
-                }
+        public void finishUpdate(ViewGroup container) {
+            if (mUserSwitchCallback != null) {
+                mUserSwitchCallback.resetShowing();
             }
-            container.addView(pods);
-            return pods;
+        }
+
+        @Override
+        public Object instantiateItem(ViewGroup container, int position) {
+            if (position < mUserContainers.size()) {
+                container.addView((View) mUserContainers.get(position));
+                return mUserContainers.get(position);
+            } else {
+                return null;
+            }
         }
 
         /**
@@ -353,17 +336,10 @@
         public boolean isViewFromObject(View view, Object object) {
             return view == object;
         }
-
-        @Override
-        public void onLayoutChange(View v, int left, int top, int right, int bottom,
-                int oldLeft, int oldTop, int oldRight, int oldBottom) {
-            mContainerWidth = Math.max(left - right, right - left);
-            notifyDataSetChanged();
-        }
     }
 
     private final class WrappedBaseUserAdapter extends UserSwitcherController.BaseUserAdapter {
-        private Adapter mContainer;
+        private final Adapter mContainer;
 
         public WrappedBaseUserAdapter(UserSwitcherController controller, Adapter container) {
             super(controller);
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 149ec0b..36f9f6b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
@@ -127,7 +127,7 @@
 
     private final HotspotController.Callback mHotspotCallback = new Callback() {
         @Override
-        public void onHotspotChanged(boolean enabled) {
+        public void onHotspotChanged(boolean enabled, int numDevices) {
             if (mAutoTracker.isAdded(HOTSPOT)) return;
             if (enabled) {
                 mHost.addTile(HOTSPOT);
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 0cc7f5d..66cb59e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -72,6 +72,7 @@
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.stack.StackStateAnimator;
 
+import java.util.Collection;
 import java.util.List;
 
 public class NotificationPanelView extends PanelView implements
@@ -2621,8 +2622,10 @@
         }
     }
 
-    public void setPulsing(boolean pulsing) {
-        mKeyguardStatusView.setPulsing(pulsing);
+    public void setPulsing(Collection<HeadsUpManager.HeadsUpEntry> pulsing) {
+        mKeyguardStatusView.setPulsing(pulsing != null);
+        mNotificationStackScroller.setPulsing(pulsing, mKeyguardStatusView.getLocationOnScreen()[1]
+                + mKeyguardStatusView.getClockBottom());
     }
 
     public void setAmbientIndicationBottomPadding(int ambientIndicationBottomPadding) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 6857337..20b5018 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -665,7 +665,7 @@
 
     private final HotspotController.Callback mHotspotCallback = new HotspotController.Callback() {
         @Override
-        public void onHotspotChanged(boolean enabled) {
+        public void onHotspotChanged(boolean enabled, int numDevices) {
             mIconController.setIconVisibility(mSlotHotspot, enabled);
         }
     };
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 c30fb22..3b783c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -4620,8 +4620,7 @@
                 }
 
                 private void setPulsing(Collection<HeadsUpManager.HeadsUpEntry> pulsing) {
-                    mStackScroller.setPulsing(pulsing);
-                    mNotificationPanel.setPulsing(pulsing != null);
+                    mNotificationPanel.setPulsing(pulsing);
                     mVisualStabilityManager.setPulsing(pulsing != null);
                     mIgnoreTouchWhilePulsing = false;
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java
index 6457209..830b50e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java
@@ -26,7 +26,9 @@
     void setHotspotEnabled(boolean enabled);
     boolean isHotspotSupported();
 
-    public interface Callback {
-        void onHotspotChanged(boolean enabled);
+    int getNumConnectedDevices();
+
+    interface Callback {
+        void onHotspotChanged(boolean enabled, int numDevices);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
index 1ebb986..8792b4f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
@@ -23,31 +23,35 @@
 import android.content.IntentFilter;
 import android.net.ConnectivityManager;
 import android.net.wifi.WifiManager;
-import android.os.Handler;
 import android.os.UserManager;
 import android.util.Log;
 
+import com.android.systemui.Dependency;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 
-public class HotspotControllerImpl implements HotspotController {
+public class HotspotControllerImpl implements HotspotController, WifiManager.SoftApCallback {
 
     private static final String TAG = "HotspotController";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
-    private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
-    private final Receiver mReceiver = new Receiver();
+    private final ArrayList<Callback> mCallbacks = new ArrayList<>();
+    private final WifiStateReceiver mWifiStateReceiver = new WifiStateReceiver();
     private final ConnectivityManager mConnectivityManager;
+    private final WifiManager mWifiManager;
     private final Context mContext;
 
     private int mHotspotState;
+    private int mNumConnectedDevices;
     private boolean mWaitingForCallback;
 
     public HotspotControllerImpl(Context context) {
         mContext = context;
-        mConnectivityManager = (ConnectivityManager) context.getSystemService(
-                Context.CONNECTIVITY_SERVICE);
+        mConnectivityManager =
+                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
     }
 
     @Override
@@ -84,7 +88,8 @@
             if (callback == null || mCallbacks.contains(callback)) return;
             if (DEBUG) Log.d(TAG, "addCallback " + callback);
             mCallbacks.add(callback);
-            mReceiver.setListening(!mCallbacks.isEmpty());
+
+            updateWifiStateListeners(!mCallbacks.isEmpty());
         }
     }
 
@@ -94,7 +99,26 @@
         if (DEBUG) Log.d(TAG, "removeCallback " + callback);
         synchronized (mCallbacks) {
             mCallbacks.remove(callback);
-            mReceiver.setListening(!mCallbacks.isEmpty());
+
+            updateWifiStateListeners(!mCallbacks.isEmpty());
+        }
+    }
+
+    /**
+     * Updates the wifi state receiver to either start or stop listening to get updates to the
+     * hotspot status. Additionally starts listening to wifi manager state to track the number of
+     * connected devices.
+     *
+     * @param shouldListen whether we should start listening to various wifi statuses
+     */
+    private void updateWifiStateListeners(boolean shouldListen) {
+        mWifiStateReceiver.setListening(shouldListen);
+        if (shouldListen) {
+            mWifiManager.registerSoftApCallback(
+                    this,
+                    Dependency.get(Dependency.MAIN_HANDLER));
+        } else {
+            mWifiManager.unregisterSoftApCallback(this);
         }
     }
 
@@ -116,20 +140,55 @@
             if (DEBUG) Log.d(TAG, "Starting tethering");
             mConnectivityManager.startTethering(
                     ConnectivityManager.TETHERING_WIFI, false, callback);
-            fireCallback(isHotspotEnabled());
+            fireHotspotChangedCallback(isHotspotEnabled());
         } else {
             mConnectivityManager.stopTethering(ConnectivityManager.TETHERING_WIFI);
         }
     }
 
-    private void fireCallback(boolean isEnabled) {
+    @Override
+    public int getNumConnectedDevices() {
+        return mNumConnectedDevices;
+    }
+
+    /**
+     * Sends a hotspot changed callback with the new enabled status. Wraps
+     * {@link #fireHotspotChangedCallback(boolean, int)} and assumes that the number of devices has
+     * not changed.
+     *
+     * @param enabled whether the hotspot is enabled
+     */
+    private void fireHotspotChangedCallback(boolean enabled) {
+        fireHotspotChangedCallback(enabled, mNumConnectedDevices);
+    }
+
+    /**
+     * Sends a hotspot changed callback with the new enabled status & the number of devices
+     * connected to the hotspot. Be careful when calling over multiple threads, especially if one of
+     * them is the main thread (as it can be blocked).
+     *
+     * @param enabled whether the hotspot is enabled
+     * @param numConnectedDevices number of devices connected to the hotspot
+     */
+    private void fireHotspotChangedCallback(boolean enabled, int numConnectedDevices) {
         synchronized (mCallbacks) {
             for (Callback callback : mCallbacks) {
-                callback.onHotspotChanged(isEnabled);
+                callback.onHotspotChanged(enabled, numConnectedDevices);
             }
         }
     }
 
+    @Override
+    public void onStateChanged(int state, int failureReason) {
+        // Do nothing - we don't care about changing anything here.
+    }
+
+    @Override
+    public void onNumClientsChanged(int numConnectedDevices) {
+        mNumConnectedDevices = numConnectedDevices;
+        fireHotspotChangedCallback(isHotspotEnabled(), numConnectedDevices);
+    }
+
     private final class OnStartTetheringCallback extends
             ConnectivityManager.OnStartTetheringCallback {
         @Override
@@ -143,12 +202,15 @@
         public void onTetheringFailed() {
             if (DEBUG) Log.d(TAG, "onTetheringFailed");
             mWaitingForCallback = false;
-            fireCallback(isHotspotEnabled());
+            fireHotspotChangedCallback(isHotspotEnabled());
           // TODO: Show error.
         }
     }
 
-    private final class Receiver extends BroadcastReceiver {
+    /**
+     * Class to listen in on wifi state and update the hotspot state
+     */
+    private final class WifiStateReceiver extends BroadcastReceiver {
         private boolean mRegistered;
 
         public void setListening(boolean listening) {
@@ -170,8 +232,17 @@
             int state = intent.getIntExtra(
                     WifiManager.EXTRA_WIFI_AP_STATE, WifiManager.WIFI_AP_STATE_FAILED);
             if (DEBUG) Log.d(TAG, "onReceive " + state);
+
+            // Update internal hotspot state for tracking before using any enabled/callback methods.
             mHotspotState = state;
-            fireCallback(mHotspotState == WifiManager.WIFI_AP_STATE_ENABLED);
+
+            if (!isHotspotEnabled()) {
+                // Reset num devices if the hotspot is no longer enabled so we don't get ghost
+                // counters.
+                mNumConnectedDevices = 0;
+            }
+
+            fireHotspotChangedCallback(isHotspotEnabled());
         }
     }
 }
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 4ee4ef4..0b666a6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
@@ -16,11 +16,12 @@
 
 package com.android.systemui.statusbar.policy;
 
+import static com.android.settingslib.Utils.updateLocationEnabled;
+
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
 import android.app.StatusBarManager;
 import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -28,19 +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 android.support.annotation.VisibleForTesting;
-
-import com.android.systemui.R;
 import com.android.systemui.util.Utils;
-
 import java.util.ArrayList;
 import java.util.List;
 
-import static com.android.settingslib.Utils.updateLocationMode;
-
 /**
  * A controller to manage changes of location related states and update the views accordingly.
  */
@@ -101,32 +97,27 @@
      * @return true if attempt to change setting was successful.
      */
     public boolean setLocationEnabled(boolean enabled) {
+        // QuickSettings always runs as the owner, so specifically set the settings
+        // for the current foreground user.
         int currentUserId = ActivityManager.getCurrentUser();
         if (isUserLocationRestricted(currentUserId)) {
             return false;
         }
-        final ContentResolver cr = mContext.getContentResolver();
         // When enabling location, a user consent dialog will pop up, and the
         // setting won't be fully enabled until the user accepts the agreement.
-        int currentMode = Settings.Secure.getIntForUser(cr, Settings.Secure.LOCATION_MODE, 
-                Settings.Secure.LOCATION_MODE_OFF, currentUserId);
-        int mode = enabled
-                ? Settings.Secure.LOCATION_MODE_PREVIOUS : Settings.Secure.LOCATION_MODE_OFF;
-        // QuickSettings always runs as the owner, so specifically set the settings
-        // for the current foreground user.
-        return updateLocationMode(mContext, currentMode, mode, currentUserId);
+        updateLocationEnabled(mContext, enabled, currentUserId);
+        return true;
     }
 
     /**
-     * Returns true if location isn't disabled in settings.
+     * Returns true if location is enabled in settings.
      */
     public boolean isLocationEnabled() {
-        ContentResolver resolver = mContext.getContentResolver();
         // QuickSettings always runs as the owner, so specifically retrieve the settings
         // for the current foreground user.
-        int mode = Settings.Secure.getIntForUser(resolver, Settings.Secure.LOCATION_MODE,
-                Settings.Secure.LOCATION_MODE_OFF, ActivityManager.getCurrentUser());
-        return mode != Settings.Secure.LOCATION_MODE_OFF;
+        LocationManager locationManager =
+                (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
+        return locationManager.isLocationEnabledForUser(Process.myUserHandle());
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 443e760..af3d64b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -399,6 +399,7 @@
     private final int mSeparatorWidth;
     private final int mSeparatorThickness;
     private final Rect mTmpRect = new Rect();
+    private int mClockBottom;
 
     public NotificationStackScrollLayout(Context context) {
         this(context, null);
@@ -510,7 +511,9 @@
         final int darkTop = (int) (mRegularTopPadding + mSeparatorThickness / 2f);
         final int darkBottom = darkTop + mSeparatorThickness;
 
-        if (mAmbientState.isDark()) {
+        if (mAmbientState.hasPulsingNotifications()) {
+            // TODO draw divider between notification and shelf
+        } else if (mAmbientState.isDark()) {
             // Only draw divider on AOD if we actually have notifications
             if (mFirstVisibleBackgroundChild != null) {
                 canvas.drawRect(darkLeft, darkTop, darkRight, darkBottom, mBackgroundPaint);
@@ -684,7 +687,11 @@
     }
 
     private void updateAlgorithmHeightAndPadding() {
-        mTopPadding = mAmbientState.isDark() ? mDarkTopPadding : mRegularTopPadding;
+        if (mPulsing != null) {
+            mTopPadding = mClockBottom;
+        } else {
+            mTopPadding = mAmbientState.isDark() ? mDarkTopPadding : mRegularTopPadding;
+        }
         mAmbientState.setLayoutHeight(getLayoutHeight());
         updateAlgorithmLayoutMinHeight();
         mAmbientState.setTopPadding(mTopPadding);
@@ -4322,13 +4329,15 @@
         return mIsExpanded;
     }
 
-    public void setPulsing(Collection<HeadsUpManager.HeadsUpEntry> pulsing) {
+    public void setPulsing(Collection<HeadsUpManager.HeadsUpEntry> pulsing, int clockBottom) {
         if (mPulsing == null && pulsing == null) {
             return;
         }
         mPulsing = pulsing;
+        mClockBottom = clockBottom;
         mAmbientState.setPulsing(pulsing);
         updateNotificationAnimationStates();
+        updateAlgorithmHeightAndPadding();
         updateContentHeight();
         notifyHeightChangeListener(mShelf);
         requestChildrenUpdate();
diff --git a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
index 87bc0e6..14d5c6f5 100644
--- a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
+++ b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
@@ -31,7 +31,8 @@
 
 public class NotificationChannels extends SystemUI {
     public static String ALERTS      = "ALR";
-    public static String SCREENSHOTS = "SCN";
+    public static String SCREENSHOTS_LEGACY = "SCN";
+    public static String SCREENSHOTS_HEADSUP = "SCN_HEADSUP";
     public static String GENERAL     = "GEN";
     public static String STORAGE     = "DSK";
     public static String TVPIP       = "TPP";
@@ -56,10 +57,6 @@
                         context.getString(R.string.notification_channel_alerts),
                         NotificationManager.IMPORTANCE_HIGH),
                 new NotificationChannel(
-                        SCREENSHOTS,
-                        context.getString(R.string.notification_channel_screenshot),
-                        NotificationManager.IMPORTANCE_LOW),
-                new NotificationChannel(
                         GENERAL,
                         context.getString(R.string.notification_channel_general),
                         NotificationManager.IMPORTANCE_MIN),
@@ -69,9 +66,18 @@
                         isTv(context)
                                 ? NotificationManager.IMPORTANCE_DEFAULT
                                 : NotificationManager.IMPORTANCE_LOW),
+                createScreenshotChannel(
+                        context.getString(R.string.notification_channel_screenshot),
+                        nm.getNotificationChannel(SCREENSHOTS_LEGACY)),
                 batteryChannel
         ));
 
+        // Delete older SS channel if present.
+        // Screenshots promoted to heads-up in P, this cleans up the lower priority channel from O.
+        // This line can be deleted in Q.
+        nm.deleteNotificationChannel(SCREENSHOTS_LEGACY);
+
+
         if (isTv(context)) {
             // TV specific notification channel for TV PIP controls.
             // Importance should be {@link NotificationManager#IMPORTANCE_MAX} to have the highest
@@ -83,6 +89,40 @@
         }
     }
 
+    /**
+     * Set up screenshot channel, respecting any previously committed user settings on legacy
+     * channel.
+     * @return
+     */
+    @VisibleForTesting static NotificationChannel createScreenshotChannel(
+            String name, NotificationChannel legacySS) {
+        NotificationChannel screenshotChannel = new NotificationChannel(SCREENSHOTS_HEADSUP,
+                name, NotificationManager.IMPORTANCE_HIGH); // pop on screen
+
+        screenshotChannel.setSound(Uri.parse(""), // silent
+                new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION).build());
+
+        if (legacySS != null) {
+            // Respect any user modified fields from the old channel.
+            int userlock = legacySS.getUserLockedFields();
+            if ((userlock & NotificationChannel.USER_LOCKED_IMPORTANCE) != 0) {
+                screenshotChannel.setImportance(legacySS.getImportance());
+            }
+            if ((userlock & NotificationChannel.USER_LOCKED_SOUND) != 0)  {
+                screenshotChannel.setSound(legacySS.getSound(), legacySS.getAudioAttributes());
+            }
+            if ((userlock & NotificationChannel.USER_LOCKED_VIBRATION) != 0)  {
+                screenshotChannel.setVibrationPattern(legacySS.getVibrationPattern());
+            }
+            if ((userlock & NotificationChannel.USER_LOCKED_LIGHTS) != 0)  {
+                screenshotChannel.setLightColor(legacySS.getLightColor());
+            }
+            // skip show_badge, irrelevant for system channel
+        }
+
+        return screenshotChannel;
+    }
+
     @Override
     public void start() {
         createAll(mContext);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index e76bf57..385438c 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -368,16 +368,16 @@
                 mController.setActiveStream(row.stream);
                 if (row.stream == AudioManager.STREAM_RING) {
                     final boolean hasVibrator = mController.hasVibrator();
-                    if (mState.ringerModeExternal == AudioManager.RINGER_MODE_NORMAL) {
+                    if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) {
                         if (hasVibrator) {
-                            mController.setRingerMode(AudioManager.RINGER_MODE_VIBRATE, true);
+                            mController.setRingerMode(AudioManager.RINGER_MODE_VIBRATE, false);
                         } else {
                             final boolean wasZero = row.ss.level == 0;
                             mController.setStreamVolume(stream,
                                     wasZero ? row.lastAudibleLevel : 0);
                         }
                     } else {
-                        mController.setRingerMode(AudioManager.RINGER_MODE_NORMAL, true);
+                        mController.setRingerMode(AudioManager.RINGER_MODE_NORMAL, false);
                         if (row.ss.level == 0) {
                             mController.setStreamVolume(stream, 1);
                         }
@@ -403,15 +403,15 @@
                 return;
             }
             final boolean hasVibrator = mController.hasVibrator();
-            if (mState.ringerModeExternal == AudioManager.RINGER_MODE_NORMAL) {
+            if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) {
                 if (hasVibrator) {
-                    mController.setRingerMode(AudioManager.RINGER_MODE_VIBRATE, true);
+                    mController.setRingerMode(AudioManager.RINGER_MODE_VIBRATE, false);
                 } else {
                     final boolean wasZero = ss.level == 0;
                     mController.setStreamVolume(AudioManager.STREAM_RING, wasZero ? 1 : 0);
                 }
             } else {
-                mController.setRingerMode(AudioManager.RINGER_MODE_NORMAL, true);
+                mController.setRingerMode(AudioManager.RINGER_MODE_NORMAL, false);
                 if (ss.level == 0) {
                     mController.setStreamVolume(AudioManager.STREAM_RING, 1);
                 }
@@ -552,7 +552,7 @@
             if (ss == null) {
                 return;
             }
-            switch (mState.ringerModeExternal) {
+            switch (mState.ringerModeInternal) {
                 case AudioManager.RINGER_MODE_VIBRATE:
                     mRingerStatus.setText(R.string.volume_ringer_status_vibrate);
                     mRingerIcon.setImageResource(R.drawable.ic_volume_ringer_vibrate);
@@ -653,9 +653,9 @@
         final boolean isAlarmStream = row.stream == AudioManager.STREAM_ALARM;
         final boolean isMusicStream = row.stream == AudioManager.STREAM_MUSIC;
         final boolean isRingVibrate = isRingStream
-                && mState.ringerModeExternal == AudioManager.RINGER_MODE_VIBRATE;
+                && mState.ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE;
         final boolean isRingSilent = isRingStream
-                && mState.ringerModeExternal == AudioManager.RINGER_MODE_SILENT;
+                && mState.ringerModeInternal == AudioManager.RINGER_MODE_SILENT;
         final boolean isZenAlarms = mState.zenMode == Global.ZEN_MODE_ALARMS;
         final boolean isZenNone = mState.zenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
         final boolean zenMuted = isZenAlarms ? (isRingStream || isSystemStream)
diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml
index 859dc2f..f5e079c 100644
--- a/packages/SystemUI/tests/AndroidManifest.xml
+++ b/packages/SystemUI/tests/AndroidManifest.xml
@@ -47,6 +47,7 @@
     <uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" />
     <uses-permission android:name="android.permission.REAL_GET_TASKS" />
     <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" />
+    <uses-permission android:name="android.permission.NETWORK_SETTINGS" />
 
     <application>
         <uses-library android:name="android.test.runner" />
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/ChannelsTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/ChannelsTest.java
index 04bdc04..80dc2c9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/ChannelsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/ChannelsTest.java
@@ -26,11 +26,14 @@
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.content.Context;
+import android.net.Uri;
+import android.provider.Settings;
 import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.ArraySet;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.util.NotificationChannels;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -54,7 +57,7 @@
     public void testChannelSetup() {
         Set<String> ALL_CHANNELS = new ArraySet<>(Arrays.asList(
                 NotificationChannels.ALERTS,
-                NotificationChannels.SCREENSHOTS,
+                NotificationChannels.SCREENSHOTS_HEADSUP,
                 NotificationChannels.STORAGE,
                 NotificationChannels.GENERAL,
                 NotificationChannels.BATTERY
@@ -66,4 +69,52 @@
         assertEquals(ALL_CHANNELS.size(), list.size());
         list.forEach((chan) -> assertTrue(ALL_CHANNELS.contains(chan.getId())));
     }
+
+    @Test
+    public void testChannelSetup_noLegacyScreenshot() {
+        // Assert old channel cleaned up.
+        // TODO: remove that code + this test after P.
+        NotificationChannels.createAll(mContext);
+        ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
+        verify(mMockNotificationManager).deleteNotificationChannel(
+                NotificationChannels.SCREENSHOTS_LEGACY);
+    }
+
+    @Test
+    public void testInheritFromLegacy_keepsUserLockedLegacySettings() {
+        NotificationChannel legacyChannel = new NotificationChannel("id", "oldName",
+                NotificationManager.IMPORTANCE_MIN);
+        legacyChannel.setImportance(NotificationManager.IMPORTANCE_NONE);;
+        legacyChannel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI,
+                legacyChannel.getAudioAttributes());
+        legacyChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE |
+                NotificationChannel.USER_LOCKED_SOUND);
+        NotificationChannel newChannel =
+                NotificationChannels.createScreenshotChannel("newName", legacyChannel);
+        // NONE importance user locked, so don't use HIGH for new channel.
+        assertEquals(NotificationManager.IMPORTANCE_NONE, newChannel.getImportance());
+        assertEquals(Settings.System.DEFAULT_NOTIFICATION_URI, newChannel.getSound());
+    }
+
+    @Test
+    public void testInheritFromLegacy_dropsUnlockedLegacySettings() {
+        NotificationChannel legacyChannel = new NotificationChannel("id", "oldName",
+                NotificationManager.IMPORTANCE_MIN);
+        NotificationChannel newChannel =
+                NotificationChannels.createScreenshotChannel("newName", legacyChannel);
+        assertEquals(Uri.EMPTY, newChannel.getSound());
+        assertEquals("newName", newChannel.getName());
+        // MIN importance not user locked, so HIGH wins out.
+        assertEquals(NotificationManager.IMPORTANCE_HIGH, newChannel.getImportance());
+    }
+
+    @Test
+    public void testInheritFromLegacy_noLegacyExists() {
+        NotificationChannel newChannel =
+                NotificationChannels.createScreenshotChannel("newName", null);
+        assertEquals(Uri.EMPTY, newChannel.getSound());
+        assertEquals("newName", newChannel.getName());
+        assertEquals(NotificationManager.IMPORTANCE_HIGH, newChannel.getImportance());
+    }
+
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeHotspotController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeHotspotController.java
index 5491147..016160a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeHotspotController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeHotspotController.java
@@ -44,4 +44,9 @@
     public boolean isHotspotSupported() {
         return false;
     }
+
+    @Override
+    public int getNumConnectedDevices() {
+        return 0;
+    }
 }
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 9b67f8f..4144bbd 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -5149,6 +5149,11 @@
     // OS: P
     FUELGAUGE_RESTRICTED_APP_DETAILS = 1285;
 
+    // OPEN: Settings > Sound & notification > Do Not Disturb > Turn on now
+    // CATEGORY: SETTINGS
+    // OS: P
+    NOTIFICATION_ZEN_MODE_ENABLE_DIALOG = 1286;
+
     // ---- End P Constants, all P constants go above this line ----
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS
diff --git a/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java
index 0a03b7f..0bc95f4 100644
--- a/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java
@@ -37,7 +37,9 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Message;
+import android.util.Log;
 import android.util.MathUtils;
 import android.util.Slog;
 import android.util.TypedValue;
@@ -154,6 +156,12 @@
             MagnificationController magnificationController,
             boolean detectTripleTap,
             boolean detectShortcutTrigger) {
+        if (DEBUG_ALL) {
+            Log.i(LOG_TAG,
+                    "MagnificationGestureHandler(detectTripleTap = " + detectTripleTap
+                            + ", detectShortcutTrigger = " + detectShortcutTrigger + ")");
+        }
+
         mMagnificationController = magnificationController;
 
         mDelegatingState = new DelegatingState();
@@ -581,7 +589,7 @@
 
         @VisibleForTesting boolean mShortcutTriggered;
 
-        Handler mHandler = new Handler(this);
+        @VisibleForTesting Handler mHandler = new Handler(this);
 
         public DetectingState(Context context) {
             mLongTapMinDelay = ViewConfiguration.getLongPressTimeout();
@@ -756,11 +764,14 @@
         @Override
         public void clear() {
             setShortcutTriggered(false);
-            mHandler.removeMessages(MESSAGE_ON_TRIPLE_TAP_AND_HOLD);
-            mHandler.removeMessages(MESSAGE_TRANSITION_TO_DELEGATING_STATE);
+            removePendingDelayedMessages();
             clearDelayedMotionEvents();
         }
 
+        private void removePendingDelayedMessages() {
+            mHandler.removeMessages(MESSAGE_ON_TRIPLE_TAP_AND_HOLD);
+            mHandler.removeMessages(MESSAGE_TRANSITION_TO_DELEGATING_STATE);
+        }
 
         private void cacheDelayedMotionEvent(MotionEvent event, MotionEvent rawEvent,
                 int policyFlags) {
@@ -811,7 +822,7 @@
         void transitionToDelegatingStateAndClear() {
             transitionTo(mDelegatingState);
             sendDelayedMotionEvents();
-            clear();
+            removePendingDelayedMessages();
         }
 
         private void onTripleTap(MotionEvent up) {
@@ -860,6 +871,7 @@
             if (mShortcutTriggered == state) {
                 return;
             }
+            if (DEBUG_DETECTING) Slog.i(LOG_TAG, "setShortcutTriggered(" + state + ")");
 
             mShortcutTriggered = state;
             mMagnificationController.setForceShowMagnifiableBounds(state);
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 978ed25..0e2ca14 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -119,6 +119,7 @@
 
     private final LocalLog mRequestsHistory = new LocalLog(20);
     private final LocalLog mUiLatencyHistory = new LocalLog(20);
+    private final LocalLog mWtfHistory = new LocalLog(50);
 
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
@@ -310,7 +311,8 @@
         AutofillManagerServiceImpl service = mServicesCache.get(resolvedUserId);
         if (service == null) {
             service = new AutofillManagerServiceImpl(mContext, mLock, mRequestsHistory,
-                    mUiLatencyHistory, resolvedUserId, mUi, mDisabledUsers.get(resolvedUserId));
+                    mUiLatencyHistory, mWtfHistory, resolvedUserId, mUi,
+                    mDisabledUsers.get(resolvedUserId));
             mServicesCache.put(userId, service);
         }
         return service;
@@ -878,10 +880,12 @@
                     mUi.dump(pw);
                 }
                 if (showHistory) {
-                    pw.println("Requests history:");
+                    pw.println(); pw.println("Requests history:"); pw.println();
                     mRequestsHistory.reverseDump(fd, pw, args);
-                    pw.println("UI latency history:");
+                    pw.println(); pw.println("UI latency history:"); pw.println();
                     mUiLatencyHistory.reverseDump(fd, pw, args);
+                    pw.println(); pw.println("WTF history:"); pw.println();
+                    mWtfHistory.reverseDump(fd, pw, args);
                 }
             } finally {
                 setDebugLocked(oldDebug);
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 6bcfc4b..07b0b77 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -43,7 +43,6 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Looper;
-import android.os.RemoteCallback;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.SystemClock;
@@ -116,6 +115,7 @@
 
     private final LocalLog mRequestsHistory;
     private final LocalLog mUiLatencyHistory;
+    private final LocalLog mWtfHistory;
     private final FieldClassificationStrategy mFieldClassificationStrategy;
 
     /**
@@ -179,11 +179,13 @@
     private long mLastPrune = 0;
 
     AutofillManagerServiceImpl(Context context, Object lock, LocalLog requestsHistory,
-            LocalLog uiLatencyHistory, int userId, AutoFillUI ui, boolean disabled) {
+            LocalLog uiLatencyHistory, LocalLog wtfHistory, int userId, AutoFillUI ui,
+            boolean disabled) {
         mContext = context;
         mLock = lock;
         mRequestsHistory = requestsHistory;
         mUiLatencyHistory = uiLatencyHistory;
+        mWtfHistory = wtfHistory;
         mUserId = userId;
         mUi = ui;
         mFieldClassificationStrategy = new FieldClassificationStrategy(context, userId);
@@ -484,8 +486,8 @@
         assertCallerLocked(componentName);
 
         final Session newSession = new Session(this, mUi, mContext, mHandlerCaller, mUserId, mLock,
-                sessionId, uid, activityToken, appCallbackToken, hasCallback,
-                mUiLatencyHistory, mInfo.getServiceInfo().getComponentName(), componentName, flags);
+                sessionId, uid, activityToken, appCallbackToken, hasCallback, mUiLatencyHistory,
+                mWtfHistory, mInfo.getServiceInfo().getComponentName(), componentName, flags);
         mSessions.put(newSession.id, newSession);
 
         return newSession;
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 63f8384..e1fb3a7 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -210,6 +210,9 @@
     @GuardedBy("mLock")
     private final LocalLog mUiLatencyHistory;
 
+    @GuardedBy("mLock")
+    private final LocalLog mWtfHistory;
+
     /**
      * Receiver of assist data from the app's {@link Activity}.
      */
@@ -241,7 +244,13 @@
                 // ONE_WAY warning because system_service could block on app calls. We need to
                 // change AssistStructure so it provides a "one-way" writeToParcel() method that
                 // sends all the data
-                structure.ensureData();
+                try {
+                    structure.ensureData();
+                } catch (RuntimeException e) {
+                    wtf(e, "Exception lazy loading assist structure for %s: %s",
+                            structure.getActivityComponent(), e);
+                    return;
+                }
 
                 // Sanitize structure before it's sent to service.
                 final ComponentName componentNameFromApp = structure.getActivityComponent();
@@ -447,6 +456,7 @@
             @NonNull Context context, @NonNull HandlerCaller handlerCaller, int userId,
             @NonNull Object lock, int sessionId, int uid, @NonNull IBinder activityToken,
             @NonNull IBinder client, boolean hasCallback, @NonNull LocalLog uiLatencyHistory,
+            @NonNull LocalLog wtfHistory,
             @NonNull ComponentName serviceComponentName, @NonNull ComponentName componentName,
             int flags) {
         id = sessionId;
@@ -461,6 +471,7 @@
         mActivityToken = activityToken;
         mHasCallback = hasCallback;
         mUiLatencyHistory = uiLatencyHistory;
+        mWtfHistory = wtfHistory;
         mComponentName = componentName;
         mClient = IAutoFillManagerClient.Stub.asInterface(client);
 
@@ -1102,8 +1113,7 @@
         if (userData != null && fcStrategy != null) {
             logFieldClassificationScoreLocked(fcStrategy, ignoredDatasets, changedFieldIds,
                     changedDatasetIds, manuallyFilledFieldIds, manuallyFilledDatasetIds,
-                    manuallyFilledIds, userData,
-                    mViewStates.values());
+                    userData, mViewStates.values());
         } else {
             mService.logContextCommittedLocked(id, mClientState, mSelectedDatasetIds,
                     ignoredDatasets, changedFieldIds, changedDatasetIds,
@@ -1123,7 +1133,6 @@
             @NonNull ArrayList<String> changedDatasetIds,
             @NonNull ArrayList<AutofillId> manuallyFilledFieldIds,
             @NonNull ArrayList<ArrayList<String>> manuallyFilledDatasetIds,
-            @NonNull ArrayMap<AutofillId, ArraySet<String>> manuallyFilledIds,
             @NonNull UserData userData, @NonNull Collection<ViewState> viewStates) {
 
         final String[] userValues = userData.getValues();
@@ -1201,8 +1210,7 @@
                     }
                 }
             } catch (ArrayIndexOutOfBoundsException e) {
-                Slog.wtf(TAG, "Error accessing FC score at " + i + " x " + j + ": "
-                        + Arrays.toString(scores.scores), e);
+                wtf(e, "Error accessing FC score at [%d, %d] (%s): %s", i, j, scores, e);
                 return;
             }
 
@@ -2151,9 +2159,10 @@
         final Intent fillInIntent = new Intent();
 
         final FillContext context = getFillContextByRequestIdLocked(requestId);
+
         if (context == null) {
-            Slog.wtf(TAG, "createAuthFillInIntentLocked(): no FillContext. requestId=" + requestId
-                    + "; mContexts= " + mContexts);
+            wtf(null, "createAuthFillInIntentLocked(): no FillContext. requestId=%d; mContexts=%s",
+                    requestId, mContexts);
             return null;
         }
         fillInIntent.putExtra(AutofillManager.EXTRA_ASSIST_STRUCTURE, context.getStructure());
@@ -2418,4 +2427,15 @@
     private void writeLog(int category) {
         mMetricsLogger.write(newLogMaker(category));
     }
+
+    private void wtf(@Nullable Exception e, String fmt, Object...args) {
+        final String message = String.format(fmt, args);
+        mWtfHistory.log(message);
+
+        if (e != null) {
+            Slog.wtf(TAG, message, e);
+        } else {
+            Slog.wtf(TAG, message);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/ForceAppStandbyTracker.java b/services/core/java/com/android/server/ForceAppStandbyTracker.java
index de113a6..792fdfe 100644
--- a/services/core/java/com/android/server/ForceAppStandbyTracker.java
+++ b/services/core/java/com/android/server/ForceAppStandbyTracker.java
@@ -17,6 +17,7 @@
 
 import android.annotation.NonNull;
 import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
 import android.app.AppOpsManager;
 import android.app.AppOpsManager.PackageOps;
 import android.app.IActivityManager;
@@ -504,7 +505,7 @@
      */
     void uidToForeground(int uid) {
         synchronized (mLock) {
-            if (!UserHandle.isApp(uid)) {
+            if (UserHandle.isCore(uid)) {
                 return;
             }
             // TODO This can be optimized by calling indexOfKey and sharing the index for get and
@@ -522,7 +523,7 @@
      */
     void uidToBackground(int uid, boolean remove) {
         synchronized (mLock) {
-            if (!UserHandle.isApp(uid)) {
+            if (UserHandle.isCore(uid)) {
                 return;
             }
             // TODO This can be optimized by calling indexOfKey and sharing the index for get and
@@ -825,9 +826,10 @@
     /**
      * @return whether jobs should be restricted for a UID package-name.
      */
-    public boolean areJobsRestricted(int uid, @NonNull String packageName) {
+    public boolean areJobsRestricted(int uid, @NonNull String packageName,
+            boolean hasForegroundExemption) {
         return isRestricted(uid, packageName, /*useTempWhitelistToo=*/ true,
-                /* exemptOnBatterySaver =*/ false);
+                hasForegroundExemption);
     }
 
     /**
@@ -861,10 +863,12 @@
     /**
      * @return whether a UID is in the foreground or not.
      *
-     * Note clients normally shouldn't need to access it. It's only for dumpsys.
+     * Note this information is based on the UID proc state callback, meaning it's updated
+     * asynchronously and may subtly be stale. If the fresh data is needed, use
+     * {@link ActivityManagerInternal#getUidProcessState} instead.
      */
     public boolean isInForeground(int uid) {
-        if (!UserHandle.isApp(uid)) {
+        if (UserHandle.isCore(uid)) {
             return true;
         }
         synchronized (mLock) {
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index ef6bc43..24d493e 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -571,6 +571,8 @@
             mConfig = config;
             mSpi = spi;
             mSocket = socket;
+
+            spi.setOwnedByTransform();
         }
 
         public IpSecConfig getConfig() {
@@ -651,16 +653,6 @@
         /** always guarded by IpSecService#this */
         @Override
         public void freeUnderlyingResources() {
-            if (mOwnedByTransform) {
-                Log.d(TAG, "Cannot release Spi " + mSpi + ": Currently locked by a Transform");
-                // Because SPIs are "handed off" to transform, objects, they should never be
-                // freed from the SpiRecord once used in a transform. (They refer to the same SA,
-                // thus ownership and responsibility for freeing these resources passes to the
-                // Transform object). Thus, we should let the user free them without penalty once
-                // they are applied in a Transform object.
-                return;
-            }
-
             try {
                 mSrvConfig
                         .getNetdInstance()
@@ -694,6 +686,10 @@
             mOwnedByTransform = true;
         }
 
+        public boolean getOwnedByTransform() {
+            return mOwnedByTransform;
+        }
+
         @Override
         public void invalidate() throws RemoteException {
             getUserRecord().removeSpiRecord(mResourceId);
@@ -1107,6 +1103,11 @@
         // Retrieve SPI record; will throw IllegalArgumentException if not found
         SpiRecord s = userRecord.mSpiRecords.getResourceOrThrow(config.getSpiResourceId());
 
+        // Check to ensure that SPI has not already been used.
+        if (s.getOwnedByTransform()) {
+            throw new IllegalStateException("SPI already in use; cannot be used in new Transforms");
+        }
+
         // If no remote address is supplied, then use one from the SPI.
         if (TextUtils.isEmpty(config.getDestinationAddress())) {
             config.setDestinationAddress(s.getDestinationAddress());
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 6c63f43..5a4f7ca 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -16,11 +16,64 @@
 
 package com.android.server;
 
-import android.app.ActivityManager;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
 import android.annotation.NonNull;
+import android.app.ActivityManager;
+import android.app.AppOpsManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PackageManagerInternal;
+import android.content.pm.ResolveInfo;
+import android.content.pm.Signature;
+import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.hardware.location.ActivityRecognitionHardware;
+import android.location.Address;
+import android.location.Criteria;
+import android.location.GeocoderParams;
+import android.location.Geofence;
+import android.location.IBatchedLocationCallback;
+import android.location.IGnssMeasurementsListener;
+import android.location.IGnssNavigationMessageListener;
+import android.location.IGnssStatusListener;
+import android.location.IGnssStatusProvider;
+import android.location.IGpsGeofenceHardware;
+import android.location.ILocationListener;
+import android.location.ILocationManager;
+import android.location.INetInitiatedListener;
+import android.location.Location;
+import android.location.LocationManager;
+import android.location.LocationProvider;
+import android.location.LocationRequest;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.PowerManager;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.os.WorkSource;
+import android.provider.Settings;
+import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
-
+import android.util.EventLog;
+import android.util.Log;
+import android.util.Slog;
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.location.ProviderProperties;
 import com.android.internal.location.ProviderRequest;
@@ -45,60 +98,6 @@
 import com.android.server.location.LocationRequestStatistics.PackageStatistics;
 import com.android.server.location.MockProvider;
 import com.android.server.location.PassiveProvider;
-
-import android.app.AppOpsManager;
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManagerInternal;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ResolveInfo;
-import android.content.pm.Signature;
-import android.content.res.Resources;
-import android.database.ContentObserver;
-import android.hardware.location.ActivityRecognitionHardware;
-import android.location.Address;
-import android.location.Criteria;
-import android.location.GeocoderParams;
-import android.location.Geofence;
-import android.location.IBatchedLocationCallback;
-import android.location.IGnssMeasurementsListener;
-import android.location.IGnssStatusListener;
-import android.location.IGnssStatusProvider;
-import android.location.IGpsGeofenceHardware;
-import android.location.IGnssNavigationMessageListener;
-import android.location.ILocationListener;
-import android.location.ILocationManager;
-import android.location.INetInitiatedListener;
-import android.location.Location;
-import android.location.LocationManager;
-import android.location.LocationProvider;
-import android.location.LocationRequest;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.PowerManager;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.os.WorkSource;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.EventLog;
-import android.util.Log;
-import android.util.Slog;
-
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -1378,10 +1377,7 @@
         if (mDisabledProviders.contains(provider)) {
             return false;
         }
-        // Use system settings
-        ContentResolver resolver = mContext.getContentResolver();
-
-        return Settings.Secure.isLocationProviderEnabledForUser(resolver, provider, mCurrentUserId);
+        return isLocationProviderEnabledForUser(provider, mCurrentUserId);
     }
 
     /**
@@ -1400,6 +1396,23 @@
     }
 
     /**
+     * Returns "true" if access to the specified location provider is allowed by the specified
+     * user's settings. Access to all location providers is forbidden to non-location-provider
+     * processes belonging to background users.
+     *
+     * @param provider the name of the location provider
+     * @param uid      the requestor's UID
+     * @param userId   the user id to query
+     */
+    private boolean isAllowedByUserSettingsLockedForUser(
+            String provider, int uid, int userId) {
+        if (!isCurrentProfile(UserHandle.getUserId(uid)) && !isUidALocationProvider(uid)) {
+            return false;
+        }
+        return isLocationProviderEnabledForUser(provider, userId);
+    }
+
+    /**
      * Returns the permission string associated with the specified resolution level.
      *
      * @param resolutionLevel the resolution level
@@ -1425,10 +1438,10 @@
      */
     private int getAllowedResolutionLevel(int pid, int uid) {
         if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
-                pid, uid) == PackageManager.PERMISSION_GRANTED) {
+                pid, uid) == PERMISSION_GRANTED) {
             return RESOLUTION_LEVEL_FINE;
         } else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION,
-                pid, uid) == PackageManager.PERMISSION_GRANTED) {
+                pid, uid) == PERMISSION_GRANTED) {
             return RESOLUTION_LEVEL_COARSE;
         } else {
             return RESOLUTION_LEVEL_NONE;
@@ -2053,7 +2066,7 @@
         }
         boolean callerHasLocationHardwarePermission =
                 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
-                        == PackageManager.PERMISSION_GRANTED;
+                        == PERMISSION_GRANTED;
         LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel,
                 callerHasLocationHardwarePermission);
 
@@ -2326,7 +2339,7 @@
         // Require that caller can manage given document
         boolean callerHasLocationHardwarePermission =
                 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
-                        == PackageManager.PERMISSION_GRANTED;
+                        == PERMISSION_GRANTED;
         LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel,
                 callerHasLocationHardwarePermission);
 
@@ -2476,7 +2489,7 @@
 
         // and check for ACCESS_LOCATION_EXTRA_COMMANDS
         if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
-                != PackageManager.PERMISSION_GRANTED)) {
+                != PERMISSION_GRANTED)) {
             throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission");
         }
 
@@ -2546,8 +2559,64 @@
         return null;
     }
 
+    /**
+     * Method for enabling or disabling location.
+     *
+     * @param enabled true to enable location. false to disable location
+     * @param userId the user id to set
+     */
+    @Override
+    public void setLocationEnabledForUser(boolean enabled, int userId) {
+        // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
+        checkInteractAcrossUsersPermission(userId);
+
+        // enable all location providers
+        synchronized (mLock) {
+            for(String provider : getAllProviders()) {
+                setProviderEnabledForUser(provider, enabled, userId);
+            }
+        }
+    }
+
+    /**
+     * Returns the current enabled/disabled status of location
+     *
+     * @param userId the user id to query
+     * @return true if location is enabled. false if location is disabled.
+     */
+    @Override
+    public boolean isLocationEnabledForUser(int userId) {
+
+        // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
+        checkInteractAcrossUsersPermission(userId);
+
+        synchronized (mLock) {
+            for (String provider : getAllProviders()) {
+                if (isProviderEnabledForUser(provider, userId)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
     @Override
     public boolean isProviderEnabled(String provider) {
+        return isProviderEnabledForUser(provider, UserHandle.myUserId());
+    }
+
+    /**
+     * Method for determining if a location provider is enabled.
+     *
+     * @param provider the location provider to query
+     * @param userId the user id to query
+     * @return true if the provider is enabled
+     */
+    @Override
+    public boolean isProviderEnabledForUser(String provider, int userId) {
+        // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
+        checkInteractAcrossUsersPermission(userId);
+
         // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
         // so we discourage its use
         if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
@@ -2557,7 +2626,8 @@
         try {
             synchronized (mLock) {
                 LocationProviderInterface p = mProvidersByName.get(provider);
-                return p != null && isAllowedByUserSettingsLocked(provider, uid);
+                return p != null
+                    && isAllowedByUserSettingsLockedForUser(provider, uid, userId);
             }
         } finally {
             Binder.restoreCallingIdentity(identity);
@@ -2565,6 +2635,83 @@
     }
 
     /**
+     * Method for enabling or disabling a single location provider.
+     *
+     * @param provider the name of the provider
+     * @param enabled true to enable the provider. false to disable the provider
+     * @param userId the user id to set
+     * @return true if the value was set successfully. false on failure.
+     */
+    @Override
+    public boolean setProviderEnabledForUser(
+            String provider, boolean enabled, int userId) {
+        mContext.enforceCallingPermission(
+                android.Manifest.permission.WRITE_SECURE_SETTINGS,
+                "Requires WRITE_SECURE_SETTINGS permission");
+
+        // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
+        checkInteractAcrossUsersPermission(userId);
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            synchronized (mLock) {
+                // to ensure thread safety, we write the provider name with a '+' or '-'
+                // and let the SettingsProvider handle it rather than reading and modifying
+                // the list of enabled providers.
+                if (enabled) {
+                    provider = "+" + provider;
+                } else {
+                    provider = "-" + provider;
+                }
+                return Settings.Secure.putStringForUser(
+                        mContext.getContentResolver(),
+                        Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
+                        provider,
+                        userId);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * Read location provider status from Settings.Secure
+     *
+     * @param provider the location provider to query
+     * @param userId the user id to query
+     * @return true if the provider is enabled
+     */
+    private boolean isLocationProviderEnabledForUser(String provider, int userId) {
+        long identity = Binder.clearCallingIdentity();
+        try {
+            // Use system settings
+            ContentResolver cr = mContext.getContentResolver();
+            String allowedProviders = Settings.Secure.getStringForUser(
+                    cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, userId);
+            return TextUtils.delimitedStringContains(allowedProviders, ',', provider);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * Method for checking INTERACT_ACROSS_USERS permission if specified user id is not the same as
+     * current user id
+     *
+     * @param userId the user id to get or set value
+     */
+    private void checkInteractAcrossUsersPermission(int userId) {
+        int uid = Binder.getCallingUid();
+        if (UserHandle.getUserId(uid) != userId) {
+            if (ActivityManager.checkComponentPermission(
+                android.Manifest.permission.INTERACT_ACROSS_USERS, uid, -1, true)
+                != PERMISSION_GRANTED) {
+                throw new SecurityException("Requires INTERACT_ACROSS_USERS permission");
+            }
+        }
+    }
+
+    /**
      * Returns "true" if the UID belongs to a bound location provider.
      *
      * @param uid the uid
@@ -2585,7 +2732,7 @@
 
     private void checkCallerIsProvider() {
         if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
-                == PackageManager.PERMISSION_GRANTED) {
+                == PERMISSION_GRANTED) {
             return;
         }
 
diff --git a/services/core/java/com/android/server/am/ActiveInstrumentation.java b/services/core/java/com/android/server/am/ActiveInstrumentation.java
index 84e4ea9..4a65733 100644
--- a/services/core/java/com/android/server/am/ActiveInstrumentation.java
+++ b/services/core/java/com/android/server/am/ActiveInstrumentation.java
@@ -22,6 +22,9 @@
 import android.content.pm.ApplicationInfo;
 import android.os.Bundle;
 import android.util.PrintWriterPrinter;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.server.am.proto.ActiveInstrumentationProto;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -119,4 +122,26 @@
         pw.print(prefix); pw.print("mArguments=");
         pw.println(mArguments);
     }
+
+    void writeToProto(ProtoOutputStream proto, long fieldId) {
+        long token = proto.start(fieldId);
+        mClass.writeToProto(proto, ActiveInstrumentationProto.CLASS);
+        proto.write(ActiveInstrumentationProto.FINISHED, mFinished);
+        for (int i=0; i<mRunningProcesses.size(); i++) {
+            mRunningProcesses.get(i).writeToProto(proto,
+                    ActiveInstrumentationProto.RUNNING_PROCESSES);
+        }
+        for (String p : mTargetProcesses) {
+            proto.write(ActiveInstrumentationProto.TARGET_PROCESSES, p);
+        }
+        if (mTargetInfo != null) {
+            mTargetInfo.writeToProto(proto, ActiveInstrumentationProto.TARGET_INFO);
+        }
+        proto.write(ActiveInstrumentationProto.PROFILE_FILE, mProfileFile);
+        proto.write(ActiveInstrumentationProto.WATCHER, mWatcher.toString());
+        proto.write(ActiveInstrumentationProto.UI_AUTOMATION_CONNECTION,
+                mUiAutomationConnection.toString());
+        proto.write(ActiveInstrumentationProto.ARGUMENTS, mArguments.toString());
+        proto.end(token);
+    }
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 1eec982..5eb5b14 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -216,6 +216,7 @@
 import android.app.ActivityManagerInternal;
 import android.app.ActivityManagerInternal.ScreenObserver;
 import android.app.ActivityManagerInternal.SleepToken;
+import android.app.ActivityManagerProto;
 import android.app.ActivityOptions;
 import android.app.ActivityThread;
 import android.app.AlertDialog;
@@ -372,6 +373,7 @@
 import android.util.TimingsTraceLog;
 import android.util.Xml;
 import android.util.proto.ProtoOutputStream;
+import android.util.proto.ProtoUtils;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.RemoteAnimationDefinition;
@@ -428,12 +430,16 @@
 import com.android.server.ThreadPriorityBooster;
 import com.android.server.Watchdog;
 import com.android.server.am.ActivityStack.ActivityState;
-import com.android.server.am.EventLogTags;
 import com.android.server.am.proto.ActivityManagerServiceProto;
 import com.android.server.am.proto.BroadcastProto;
 import com.android.server.am.proto.GrantUriProto;
+import com.android.server.am.proto.ImportanceTokenProto;
 import com.android.server.am.proto.MemInfoProto;
 import com.android.server.am.proto.NeededUriGrantsProto;
+import com.android.server.am.proto.ProcessOomProto;
+import com.android.server.am.proto.ProcessToGcProto;
+import com.android.server.am.proto.ProcessesProto;
+import com.android.server.am.proto.ProcessesProto.UidObserverRegistrationProto;
 import com.android.server.am.proto.StickyBroadcastProto;
 import com.android.server.firewall.IntentFirewall;
 import com.android.server.job.JobSchedulerInternal;
@@ -939,6 +945,16 @@
             return "ImportanceToken { " + Integer.toHexString(System.identityHashCode(this))
                     + " " + reason + " " + pid + " " + token + " }";
         }
+
+        void writeToProto(ProtoOutputStream proto, long fieldId) {
+            final long pToken = proto.start(fieldId);
+            proto.write(ImportanceTokenProto.PID, pid);
+            if (token != null) {
+                proto.write(ImportanceTokenProto.TOKEN, token.toString());
+            }
+            proto.write(ImportanceTokenProto.REASON, reason);
+            proto.end(pToken);
+        }
     }
     final SparseArray<ImportanceToken> mImportantProcesses = new SparseArray<ImportanceToken>();
 
@@ -1317,6 +1333,14 @@
             duration = _duration;
             tag = _tag;
         }
+
+        void writeToProto(ProtoOutputStream proto, long fieldId) {
+            final long token = proto.start(fieldId);
+            proto.write(ProcessesProto.PendingTempWhitelist.TARGET_UID, targetUid);
+            proto.write(ProcessesProto.PendingTempWhitelist.DURATION_MS, duration);
+            proto.write(ProcessesProto.PendingTempWhitelist.TAG, tag);
+            proto.end(token);
+        }
     }
 
     final SparseArray<PendingTempWhitelist> mPendingTempWhitelist = new SparseArray<>();
@@ -1641,6 +1665,20 @@
 
         final SparseIntArray lastProcStates;
 
+        // Please keep the enum lists in sync
+        private static int[] ORIG_ENUMS = new int[]{
+                ActivityManager.UID_OBSERVER_IDLE,
+                ActivityManager.UID_OBSERVER_ACTIVE,
+                ActivityManager.UID_OBSERVER_GONE,
+                ActivityManager.UID_OBSERVER_PROCSTATE,
+        };
+        private static int[] PROTO_ENUMS = new int[]{
+                ActivityManagerProto.UID_OBSERVER_FLAG_IDLE,
+                ActivityManagerProto.UID_OBSERVER_FLAG_ACTIVE,
+                ActivityManagerProto.UID_OBSERVER_FLAG_GONE,
+                ActivityManagerProto.UID_OBSERVER_FLAG_PROCSTATE,
+        };
+
         UidObserverRegistration(int _uid, String _pkg, int _which, int _cutpoint) {
             uid = _uid;
             pkg = _pkg;
@@ -1652,6 +1690,25 @@
                 lastProcStates = null;
             }
         }
+
+        void writeToProto(ProtoOutputStream proto, long fieldId) {
+            final long token = proto.start(fieldId);
+            proto.write(UidObserverRegistrationProto.UID, uid);
+            proto.write(UidObserverRegistrationProto.PACKAGE, pkg);
+            ProtoUtils.writeBitWiseFlagsToProtoEnum(proto, UidObserverRegistrationProto.FLAGS,
+                    which, ORIG_ENUMS, PROTO_ENUMS);
+            proto.write(UidObserverRegistrationProto.CUT_POINT, cutpoint);
+            if (lastProcStates != null) {
+                final int NI = lastProcStates.size();
+                for (int i=0; i<NI; i++) {
+                    final long pToken = proto.start(UidObserverRegistrationProto.LAST_PROC_STATES);
+                    proto.write(UidObserverRegistrationProto.ProcState.UID, lastProcStates.keyAt(i));
+                    proto.write(UidObserverRegistrationProto.ProcState.STATE, lastProcStates.valueAt(i));
+                    proto.end(pToken);
+                }
+            }
+            proto.end(token);
+        }
     }
 
     final List<ScreenObserver> mScreenObservers = new ArrayList<>();
@@ -8849,7 +8906,7 @@
             case AppOpsManager.MODE_ALLOWED:
                 // If force-background-check is enabled, restrict all apps that aren't whitelisted.
                 if (mForceBackgroundCheck &&
-                        UserHandle.isApp(uid) &&
+                        !UserHandle.isCore(uid) &&
                         !isOnDeviceIdleWhitelistLocked(uid)) {
                     if (DEBUG_BACKGROUND_CHECK) {
                         Slog.i(TAG, "Force background check: " +
@@ -15251,7 +15308,6 @@
         boolean dumpVisibleStacksOnly = false;
         boolean dumpFocusedStackOnly = false;
         String dumpPackage = null;
-        int dumpAppId = -1;
 
         int opti = 0;
         while (opti < args.length) {
@@ -15325,6 +15381,15 @@
                 }
             } else if ("service".equals(cmd)) {
                 mServices.writeToProto(proto);
+            } else if ("processes".equals(cmd) || "p".equals(cmd)) {
+                if (opti < args.length) {
+                    dumpPackage = args[opti];
+                    opti++;
+                }
+                // output proto is ProcessProto
+                synchronized (this) {
+                    writeProcessesToProtoLocked(proto, dumpPackage);
+                }
             } else {
                 // default option, dump everything, output is ActivityManagerServiceProto
                 synchronized (this) {
@@ -15339,6 +15404,10 @@
                     long serviceToken = proto.start(ActivityManagerServiceProto.SERVICES);
                     mServices.writeToProto(proto);
                     proto.end(serviceToken);
+
+                    long processToken = proto.start(ActivityManagerServiceProto.PROCESSES);
+                    writeProcessesToProtoLocked(proto, dumpPackage);
+                    proto.end(processToken);
                 }
             }
             proto.flush();
@@ -15346,16 +15415,7 @@
             return;
         }
 
-        if (dumpPackage != null) {
-            try {
-                ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
-                        dumpPackage, 0);
-                dumpAppId = UserHandle.getAppId(info.uid);
-            } catch (NameNotFoundException e) {
-                e.printStackTrace();
-            }
-        }
-
+        int dumpAppId = getAppId(dumpPackage);
         boolean more = false;
         // Is the caller requesting to dump a particular piece of data?
         if (opti < args.length) {
@@ -15397,33 +15457,17 @@
                     pw.println(BinderInternal.nGetBinderProxyCount(Integer.parseInt(uid)));
                 }
             } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
-                String[] newArgs;
-                String name;
-                if (opti >= args.length) {
-                    name = null;
-                    newArgs = EMPTY_STRING_ARRAY;
-                } else {
+                if (opti < args.length) {
                     dumpPackage = args[opti];
                     opti++;
-                    newArgs = new String[args.length - opti];
-                    if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
-                            args.length - opti);
                 }
                 synchronized (this) {
                     dumpBroadcastsLocked(fd, pw, args, opti, true, dumpPackage);
                 }
             } else if ("broadcast-stats".equals(cmd)) {
-                String[] newArgs;
-                String name;
-                if (opti >= args.length) {
-                    name = null;
-                    newArgs = EMPTY_STRING_ARRAY;
-                } else {
+                if (opti < args.length) {
                     dumpPackage = args[opti];
                     opti++;
-                    newArgs = new String[args.length - opti];
-                    if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
-                            args.length - opti);
                 }
                 synchronized (this) {
                     if (dumpCheckinFormat) {
@@ -15434,33 +15478,17 @@
                     }
                 }
             } else if ("intents".equals(cmd) || "i".equals(cmd)) {
-                String[] newArgs;
-                String name;
-                if (opti >= args.length) {
-                    name = null;
-                    newArgs = EMPTY_STRING_ARRAY;
-                } else {
+                if (opti < args.length) {
                     dumpPackage = args[opti];
                     opti++;
-                    newArgs = new String[args.length - opti];
-                    if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
-                            args.length - opti);
                 }
                 synchronized (this) {
                     dumpPendingIntentsLocked(fd, pw, args, opti, true, dumpPackage);
                 }
             } else if ("processes".equals(cmd) || "p".equals(cmd)) {
-                String[] newArgs;
-                String name;
-                if (opti >= args.length) {
-                    name = null;
-                    newArgs = EMPTY_STRING_ARRAY;
-                } else {
+                if (opti < args.length) {
                     dumpPackage = args[opti];
                     opti++;
-                    newArgs = new String[args.length - opti];
-                    if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
-                            args.length - opti);
                 }
                 synchronized (this) {
                     dumpProcessesLocked(fd, pw, args, opti, true, dumpPackage, dumpAppId);
@@ -15881,8 +15909,21 @@
         }
     }
 
+    private int getAppId(String dumpPackage) {
+        if (dumpPackage != null) {
+            try {
+                ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
+                        dumpPackage, 0);
+                return UserHandle.getAppId(info.uid);
+            } catch (NameNotFoundException e) {
+                e.printStackTrace();
+            }
+        }
+        return -1;
+    }
+
     boolean dumpUids(PrintWriter pw, String dumpPackage, int dumpAppId, SparseArray<UidRecord> uids,
-            String header, boolean needSep) {
+                String header, boolean needSep) {
         boolean printed = false;
         for (int i=0; i<uids.size(); i++) {
             UidRecord uidRec = uids.valueAt(i);
@@ -16100,7 +16141,7 @@
                     "OnHold Norm", "OnHold PERS", dumpPackage);
         }
 
-        needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll, dumpPackage);
+        needSep = dumpProcessesToGc(pw, needSep, dumpPackage);
 
         needSep = mAppErrors.dumpLocked(fd, pw, needSep, dumpPackage);
 
@@ -16385,8 +16426,327 @@
         pw.println("  mForceBackgroundCheck=" + mForceBackgroundCheck);
     }
 
-    boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
-            int opti, boolean needSep, boolean dumpAll, String dumpPackage) {
+    void writeProcessesToProtoLocked(ProtoOutputStream proto, String dumpPackage) {
+        int numPers = 0;
+
+        final int NP = mProcessNames.getMap().size();
+        for (int ip=0; ip<NP; ip++) {
+            SparseArray<ProcessRecord> procs = mProcessNames.getMap().valueAt(ip);
+            final int NA = procs.size();
+            for (int ia = 0; ia<NA; ia++) {
+                ProcessRecord r = procs.valueAt(ia);
+                if (dumpPackage != null && !r.pkgList.containsKey(dumpPackage)) {
+                    continue;
+                }
+                r.writeToProto(proto, ProcessesProto.PROCS);
+                if (r.persistent) {
+                    numPers++;
+                }
+            }
+        }
+
+        for (int i=0; i<mIsolatedProcesses.size(); i++) {
+            ProcessRecord r = mIsolatedProcesses.valueAt(i);
+            if (dumpPackage != null && !r.pkgList.containsKey(dumpPackage)) {
+                continue;
+            }
+            r.writeToProto(proto, ProcessesProto.ISOLATED_PROCS);
+        }
+
+        for (int i=0; i<mActiveInstrumentation.size(); i++) {
+            ActiveInstrumentation ai = mActiveInstrumentation.get(i);
+            if (dumpPackage != null && !ai.mClass.getPackageName().equals(dumpPackage)
+                    && !ai.mTargetInfo.packageName.equals(dumpPackage)) {
+                continue;
+            }
+            ai.writeToProto(proto, ProcessesProto.ACTIVE_INSTRUMENTATIONS);
+        }
+
+        int whichAppId = getAppId(dumpPackage);
+        for (int i=0; i<mActiveUids.size(); i++) {
+            UidRecord uidRec = mActiveUids.valueAt(i);
+            if (dumpPackage != null && UserHandle.getAppId(uidRec.uid) != whichAppId) {
+                continue;
+            }
+            uidRec.writeToProto(proto, ProcessesProto.ACTIVE_UIDS);
+        }
+
+        for (int i=0; i<mValidateUids.size(); i++) {
+            UidRecord uidRec = mValidateUids.valueAt(i);
+            if (dumpPackage != null && UserHandle.getAppId(uidRec.uid) != whichAppId) {
+                continue;
+            }
+            uidRec.writeToProto(proto, ProcessesProto.VALIDATE_UIDS);
+        }
+
+        if (mLruProcesses.size() > 0) {
+            long lruToken = proto.start(ProcessesProto.LRU_PROCS);
+            int total = mLruProcesses.size();
+            proto.write(ProcessesProto.LruProcesses.SIZE, total);
+            proto.write(ProcessesProto.LruProcesses.NON_ACT_AT, total-mLruProcessActivityStart);
+            proto.write(ProcessesProto.LruProcesses.NON_SVC_AT, total-mLruProcessServiceStart);
+            writeProcessOomListToProto(proto, ProcessesProto.LruProcesses.LIST, this,
+                    mLruProcesses,false, dumpPackage);
+            proto.end(lruToken);
+        }
+
+        if (dumpPackage != null) {
+            synchronized (mPidsSelfLocked) {
+                for (int i=0; i<mPidsSelfLocked.size(); i++) {
+                    ProcessRecord r = mPidsSelfLocked.valueAt(i);
+                    if (!r.pkgList.containsKey(dumpPackage)) {
+                        continue;
+                    }
+                    r.writeToProto(proto, ProcessesProto.PIDS_SELF_LOCKED);
+                }
+            }
+        }
+
+        if (mImportantProcesses.size() > 0) {
+            synchronized (mPidsSelfLocked) {
+                for (int i=0; i<mImportantProcesses.size(); i++) {
+                    ImportanceToken it = mImportantProcesses.valueAt(i);
+                    ProcessRecord r = mPidsSelfLocked.get(it.pid);
+                    if (dumpPackage != null && (r == null
+                            || !r.pkgList.containsKey(dumpPackage))) {
+                        continue;
+                    }
+                    it.writeToProto(proto, ProcessesProto.IMPORTANT_PROCS);
+                }
+            }
+        }
+
+        for (int i=0; i<mPersistentStartingProcesses.size(); i++) {
+            ProcessRecord r = mPersistentStartingProcesses.get(i);
+            if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
+                continue;
+            }
+            r.writeToProto(proto, ProcessesProto.PERSISTENT_STARTING_PROCS);
+        }
+
+        for (int i=0; i<mRemovedProcesses.size(); i++) {
+            ProcessRecord r = mRemovedProcesses.get(i);
+            if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
+                continue;
+            }
+            r.writeToProto(proto, ProcessesProto.REMOVED_PROCS);
+        }
+
+        for (int i=0; i<mProcessesOnHold.size(); i++) {
+            ProcessRecord r = mProcessesOnHold.get(i);
+            if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
+                continue;
+            }
+            r.writeToProto(proto, ProcessesProto.ON_HOLD_PROCS);
+        }
+
+        writeProcessesToGcToProto(proto, ProcessesProto.GC_PROCS, dumpPackage);
+        mAppErrors.writeToProto(proto, ProcessesProto.APP_ERRORS, dumpPackage);
+
+        if (dumpPackage == null) {
+            mUserController.writeToProto(proto, ProcessesProto.USER_CONTROLLER);
+            getGlobalConfiguration().writeToProto(proto, ProcessesProto.GLOBAL_CONFIGURATION);
+            proto.write(ProcessesProto.CONFIG_WILL_CHANGE, getFocusedStack().mConfigWillChange);
+        }
+
+        if (mHomeProcess != null && (dumpPackage == null
+                || mHomeProcess.pkgList.containsKey(dumpPackage))) {
+            mHomeProcess.writeToProto(proto, ProcessesProto.HOME_PROC);
+        }
+
+        if (mPreviousProcess != null && (dumpPackage == null
+                || mPreviousProcess.pkgList.containsKey(dumpPackage))) {
+            mPreviousProcess.writeToProto(proto, ProcessesProto.PREVIOUS_PROC);
+            proto.write(ProcessesProto.PREVIOUS_PROC_VISIBLE_TIME_MS, mPreviousProcessVisibleTime);
+        }
+
+        if (mHeavyWeightProcess != null && (dumpPackage == null
+                || mHeavyWeightProcess.pkgList.containsKey(dumpPackage))) {
+            mHeavyWeightProcess.writeToProto(proto, ProcessesProto.HEAVY_WEIGHT_PROC);
+        }
+
+        for (Map.Entry<String, Integer> entry : mCompatModePackages.getPackages().entrySet()) {
+            String pkg = entry.getKey();
+            int mode = entry.getValue();
+            if (dumpPackage == null || dumpPackage.equals(pkg)) {
+                long compatToken = proto.start(ProcessesProto.SCREEN_COMPAT_PACKAGES);
+                proto.write(ProcessesProto.ScreenCompatPackage.PACKAGE, pkg);
+                proto.write(ProcessesProto.ScreenCompatPackage.MODE, mode);
+                proto.end(compatToken);
+            }
+        }
+
+        final int NI = mUidObservers.getRegisteredCallbackCount();
+        for (int i=0; i<NI; i++) {
+            final UidObserverRegistration reg = (UidObserverRegistration)
+                    mUidObservers.getRegisteredCallbackCookie(i);
+            if (dumpPackage == null || dumpPackage.equals(reg.pkg)) {
+                reg.writeToProto(proto, ProcessesProto.UID_OBSERVERS);
+            }
+        }
+
+        for (int v : mDeviceIdleWhitelist) {
+            proto.write(ProcessesProto.DEVICE_IDLE_WHITELIST, v);
+        }
+
+        for (int v : mDeviceIdleTempWhitelist) {
+            proto.write(ProcessesProto.DEVICE_IDLE_TEMP_WHITELIST, v);
+        }
+
+        if (mPendingTempWhitelist.size() > 0) {
+            for (int i=0; i < mPendingTempWhitelist.size(); i++) {
+                mPendingTempWhitelist.valueAt(i).writeToProto(proto,
+                        ProcessesProto.PENDING_TEMP_WHITELIST);
+            }
+        }
+
+        if (dumpPackage == null) {
+            final long sleepToken = proto.start(ProcessesProto.SLEEP_STATUS);
+            proto.write(ProcessesProto.SleepStatus.WAKEFULNESS,
+                    PowerManagerInternal.wakefulnessToProtoEnum(mWakefulness));
+            for (SleepToken st : mStackSupervisor.mSleepTokens) {
+                proto.write(ProcessesProto.SleepStatus.SLEEP_TOKENS, st.toString());
+            }
+            proto.write(ProcessesProto.SleepStatus.SLEEPING, mSleeping);
+            proto.write(ProcessesProto.SleepStatus.SHUTTING_DOWN, mShuttingDown);
+            proto.write(ProcessesProto.SleepStatus.TEST_PSS_MODE, mTestPssMode);
+            proto.end(sleepToken);
+
+            if (mRunningVoice != null) {
+                final long vrToken = proto.start(ProcessesProto.RUNNING_VOICE);
+                proto.write(ProcessesProto.VoiceProto.SESSION, mRunningVoice.toString());
+                mVoiceWakeLock.writeToProto(proto, ProcessesProto.VoiceProto.WAKELOCK);
+                proto.end(vrToken);
+            }
+
+            mVrController.writeToProto(proto, ProcessesProto.VR_CONTROLLER);
+        }
+
+        if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
+                || mOrigWaitForDebugger) {
+            if (dumpPackage == null || dumpPackage.equals(mDebugApp)
+                    || dumpPackage.equals(mOrigDebugApp)) {
+                final long debugAppToken = proto.start(ProcessesProto.DEBUG);
+                proto.write(ProcessesProto.DebugApp.DEBUG_APP, mDebugApp);
+                proto.write(ProcessesProto.DebugApp.ORIG_DEBUG_APP, mOrigDebugApp);
+                proto.write(ProcessesProto.DebugApp.DEBUG_TRANSIENT, mDebugTransient);
+                proto.write(ProcessesProto.DebugApp.ORIG_WAIT_FOR_DEBUGGER, mOrigWaitForDebugger);
+                proto.end(debugAppToken);
+            }
+        }
+
+        if (mCurAppTimeTracker != null) {
+            mCurAppTimeTracker.writeToProto(proto, ProcessesProto.CURRENT_TRACKER, true);
+        }
+
+        if (mMemWatchProcesses.getMap().size() > 0) {
+            final long token = proto.start(ProcessesProto.MEM_WATCH_PROCESSES);
+            ArrayMap<String, SparseArray<Pair<Long, String>>> procs = mMemWatchProcesses.getMap();
+            for (int i=0; i<procs.size(); i++) {
+                final String proc = procs.keyAt(i);
+                final SparseArray<Pair<Long, String>> uids = procs.valueAt(i);
+                final long ptoken = proto.start(ProcessesProto.MemWatchProcess.PROCS);
+                proto.write(ProcessesProto.MemWatchProcess.Process.NAME, proc);
+                for (int j=0; j<uids.size(); j++) {
+                    final long utoken = proto.start(ProcessesProto.MemWatchProcess.Process.MEM_STATS);
+                    Pair<Long, String> val = uids.valueAt(j);
+                    proto.write(ProcessesProto.MemWatchProcess.Process.MemStats.UID, uids.keyAt(j));
+                    proto.write(ProcessesProto.MemWatchProcess.Process.MemStats.SIZE,
+                            DebugUtils.sizeValueToString(val.first, new StringBuilder()));
+                    proto.write(ProcessesProto.MemWatchProcess.Process.MemStats.REPORT_TO, val.second);
+                    proto.end(utoken);
+                }
+                proto.end(ptoken);
+            }
+
+            final long dtoken = proto.start(ProcessesProto.MemWatchProcess.DUMP);
+            proto.write(ProcessesProto.MemWatchProcess.Dump.PROC_NAME, mMemWatchDumpProcName);
+            proto.write(ProcessesProto.MemWatchProcess.Dump.FILE, mMemWatchDumpFile);
+            proto.write(ProcessesProto.MemWatchProcess.Dump.PID, mMemWatchDumpPid);
+            proto.write(ProcessesProto.MemWatchProcess.Dump.UID, mMemWatchDumpUid);
+            proto.end(dtoken);
+
+            proto.end(token);
+        }
+
+        if (mTrackAllocationApp != null) {
+            if (dumpPackage == null || dumpPackage.equals(mTrackAllocationApp)) {
+                proto.write(ProcessesProto.TRACK_ALLOCATION_APP, mTrackAllocationApp);
+            }
+        }
+
+        if (mProfileApp != null || mProfileProc != null || (mProfilerInfo != null &&
+                (mProfilerInfo.profileFile != null || mProfilerInfo.profileFd != null))) {
+            if (dumpPackage == null || dumpPackage.equals(mProfileApp)) {
+                final long token = proto.start(ProcessesProto.PROFILE);
+                proto.write(ProcessesProto.Profile.APP_NAME, mProfileApp);
+                mProfileProc.writeToProto(proto,ProcessesProto.Profile.PROC);
+                if (mProfilerInfo != null) {
+                    mProfilerInfo.writeToProto(proto, ProcessesProto.Profile.INFO);
+                    proto.write(ProcessesProto.Profile.TYPE, mProfileType);
+                }
+                proto.end(token);
+            }
+        }
+
+        if (dumpPackage == null || dumpPackage.equals(mNativeDebuggingApp)) {
+            proto.write(ProcessesProto.NATIVE_DEBUGGING_APP, mNativeDebuggingApp);
+        }
+
+        if (dumpPackage == null) {
+            proto.write(ProcessesProto.ALWAYS_FINISH_ACTIVITIES, mAlwaysFinishActivities);
+            if (mController != null) {
+                final long token = proto.start(ProcessesProto.CONTROLLER);
+                proto.write(ProcessesProto.Controller.CONTROLLER, mController.toString());
+                proto.write(ProcessesProto.Controller.IS_A_MONKEY, mControllerIsAMonkey);
+                proto.end(token);
+            }
+            proto.write(ProcessesProto.TOTAL_PERSISTENT_PROCS, numPers);
+            proto.write(ProcessesProto.PROCESSES_READY, mProcessesReady);
+            proto.write(ProcessesProto.SYSTEM_READY, mSystemReady);
+            proto.write(ProcessesProto.BOOTED, mBooted);
+            proto.write(ProcessesProto.FACTORY_TEST, mFactoryTest);
+            proto.write(ProcessesProto.BOOTING, mBooting);
+            proto.write(ProcessesProto.CALL_FINISH_BOOTING, mCallFinishBooting);
+            proto.write(ProcessesProto.BOOT_ANIMATION_COMPLETE, mBootAnimationComplete);
+            proto.write(ProcessesProto.LAST_POWER_CHECK_UPTIME_MS, mLastPowerCheckUptime);
+            mStackSupervisor.mGoingToSleep.writeToProto(proto, ProcessesProto.GOING_TO_SLEEP);
+            mStackSupervisor.mLaunchingActivity.writeToProto(proto, ProcessesProto.LAUNCHING_ACTIVITY);
+            proto.write(ProcessesProto.ADJ_SEQ, mAdjSeq);
+            proto.write(ProcessesProto.LRU_SEQ, mLruSeq);
+            proto.write(ProcessesProto.NUM_NON_CACHED_PROCS, mNumNonCachedProcs);
+            proto.write(ProcessesProto.NUM_SERVICE_PROCS, mNumServiceProcs);
+            proto.write(ProcessesProto.NEW_NUM_SERVICE_PROCS, mNewNumServiceProcs);
+            proto.write(ProcessesProto.ALLOW_LOWER_MEM_LEVEL, mAllowLowerMemLevel);
+            proto.write(ProcessesProto.LAST_MEMORY_LEVEL, mLastMemoryLevel);
+            proto.write(ProcessesProto.LAST_NUM_PROCESSES, mLastNumProcesses);
+            long now = SystemClock.uptimeMillis();
+            ProtoUtils.toDuration(proto, ProcessesProto.LAST_IDLE_TIME, mLastIdleTime, now);
+            proto.write(ProcessesProto.LOW_RAM_SINCE_LAST_IDLE_MS, getLowRamTimeSinceIdle(now));
+        }
+
+    }
+
+    void writeProcessesToGcToProto(ProtoOutputStream proto, long fieldId, String dumpPackage) {
+        if (mProcessesToGc.size() > 0) {
+            long now = SystemClock.uptimeMillis();
+            for (int i=0; i<mProcessesToGc.size(); i++) {
+                ProcessRecord r = mProcessesToGc.get(i);
+                if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
+                    continue;
+                }
+                final long token = proto.start(fieldId);
+                r.writeToProto(proto, ProcessToGcProto.PROC);
+                proto.write(ProcessToGcProto.REPORT_LOW_MEMORY, r.reportLowMemory);
+                proto.write(ProcessToGcProto.NOW_UPTIME_MS, now);
+                proto.write(ProcessToGcProto.LAST_GCED_MS, r.lastRequestedGc);
+                proto.write(ProcessToGcProto.LAST_LOW_MEMORY_MS, r.lastLowMemory);
+                proto.end(token);
+            }
+        }
+    }
+
+    boolean dumpProcessesToGc(PrintWriter pw, boolean needSep, String dumpPackage) {
         if (mProcessesToGc.size() > 0) {
             boolean printed = false;
             long now = SystemClock.uptimeMillis();
@@ -16464,7 +16824,7 @@
             needSep = true;
         }
 
-        dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll, null);
+        dumpProcessesToGc(pw, needSep, null);
 
         pw.println();
         pw.println("  mHomeProcess: " + mHomeProcess);
@@ -17015,11 +17375,8 @@
         return numPers;
     }
 
-    private static final boolean dumpProcessOomList(PrintWriter pw,
-            ActivityManagerService service, List<ProcessRecord> origList,
-            String prefix, String normalLabel, String persistentLabel,
-            boolean inclDetails, String dumpPackage) {
-
+    private static final ArrayList<Pair<ProcessRecord, Integer>>
+        sortProcessOomList(List<ProcessRecord> origList, String dumpPackage) {
         ArrayList<Pair<ProcessRecord, Integer>> list
                 = new ArrayList<Pair<ProcessRecord, Integer>>(origList.size());
         for (int i=0; i<origList.size(); i++) {
@@ -17030,10 +17387,6 @@
             list.add(new Pair<ProcessRecord, Integer>(origList.get(i), i));
         }
 
-        if (list.size() <= 0) {
-            return false;
-        }
-
         Comparator<Pair<ProcessRecord, Integer>> comparator
                 = new Comparator<Pair<ProcessRecord, Integer>>() {
             @Override
@@ -17053,6 +17406,113 @@
         };
 
         Collections.sort(list, comparator);
+        return list;
+    }
+
+    private static final boolean writeProcessOomListToProto(ProtoOutputStream proto, long fieldId,
+            ActivityManagerService service, List<ProcessRecord> origList,
+            boolean inclDetails, String dumpPackage) {
+        ArrayList<Pair<ProcessRecord, Integer>> list = sortProcessOomList(origList, dumpPackage);
+        if (list.isEmpty()) return false;
+
+        final long curUptime = SystemClock.uptimeMillis();
+
+        for (int i = list.size() - 1; i >= 0; i--) {
+            ProcessRecord r = list.get(i).first;
+            long token = proto.start(fieldId);
+            String oomAdj = ProcessList.makeOomAdjString(r.setAdj);
+            proto.write(ProcessOomProto.PERSISTENT, r.persistent);
+            proto.write(ProcessOomProto.NUM, (origList.size()-1)-list.get(i).second);
+            proto.write(ProcessOomProto.OOM_ADJ, oomAdj);
+            int schedGroup = ProcessOomProto.SCHED_GROUP_UNKNOWN;
+            switch (r.setSchedGroup) {
+                case ProcessList.SCHED_GROUP_BACKGROUND:
+                    schedGroup = ProcessOomProto.SCHED_GROUP_BACKGROUND;
+                    break;
+                case ProcessList.SCHED_GROUP_DEFAULT:
+                    schedGroup = ProcessOomProto.SCHED_GROUP_DEFAULT;
+                    break;
+                case ProcessList.SCHED_GROUP_TOP_APP:
+                    schedGroup = ProcessOomProto.SCHED_GROUP_TOP_APP;
+                    break;
+                case ProcessList.SCHED_GROUP_TOP_APP_BOUND:
+                    schedGroup = ProcessOomProto.SCHED_GROUP_TOP_APP_BOUND;
+                    break;
+            }
+            if (schedGroup != ProcessOomProto.SCHED_GROUP_UNKNOWN) {
+                proto.write(ProcessOomProto.SCHED_GROUP, schedGroup);
+            }
+            if (r.foregroundActivities) {
+                proto.write(ProcessOomProto.ACTIVITIES, true);
+            } else if (r.foregroundServices) {
+                proto.write(ProcessOomProto.SERVICES, true);
+            }
+            proto.write(ProcessOomProto.STATE, ProcessList.makeProcStateProtoEnum(r.curProcState));
+            proto.write(ProcessOomProto.TRIM_MEMORY_LEVEL, r.trimMemoryLevel);
+            r.writeToProto(proto, ProcessOomProto.PROC);
+            proto.write(ProcessOomProto.ADJ_TYPE, r.adjType);
+            if (r.adjSource != null || r.adjTarget != null) {
+                if (r.adjTarget instanceof  ComponentName) {
+                    ComponentName cn = (ComponentName) r.adjTarget;
+                    cn.writeToProto(proto, ProcessOomProto.ADJ_TARGET_COMPONENT_NAME);
+                } else if (r.adjTarget != null) {
+                    proto.write(ProcessOomProto.ADJ_TARGET_OBJECT, r.adjTarget.toString());
+                }
+                if (r.adjSource instanceof ProcessRecord) {
+                    ProcessRecord p = (ProcessRecord) r.adjSource;
+                    p.writeToProto(proto, ProcessOomProto.ADJ_SOURCE_PROC);
+                } else if (r.adjSource != null) {
+                    proto.write(ProcessOomProto.ADJ_SOURCE_OBJECT, r.adjSource.toString());
+                }
+            }
+            if (inclDetails) {
+                long detailToken = proto.start(ProcessOomProto.DETAIL);
+                proto.write(ProcessOomProto.Detail.MAX_ADJ, r.maxAdj);
+                proto.write(ProcessOomProto.Detail.CUR_RAW_ADJ, r.curRawAdj);
+                proto.write(ProcessOomProto.Detail.SET_RAW_ADJ, r.setRawAdj);
+                proto.write(ProcessOomProto.Detail.CUR_ADJ, r.curAdj);
+                proto.write(ProcessOomProto.Detail.SET_ADJ, r.setAdj);
+                proto.write(ProcessOomProto.Detail.CURRENT_STATE,
+                        ProcessList.makeProcStateProtoEnum(r.curProcState));
+                proto.write(ProcessOomProto.Detail.SET_STATE,
+                        ProcessList.makeProcStateProtoEnum(r.setProcState));
+                proto.write(ProcessOomProto.Detail.LAST_PSS, DebugUtils.sizeValueToString(
+                        r.lastPss*1024, new StringBuilder()));
+                proto.write(ProcessOomProto.Detail.LAST_SWAP_PSS, DebugUtils.sizeValueToString(
+                        r.lastSwapPss*1024, new StringBuilder()));
+                proto.write(ProcessOomProto.Detail.LAST_CACHED_PSS, DebugUtils.sizeValueToString(
+                        r.lastCachedPss*1024, new StringBuilder()));
+                proto.write(ProcessOomProto.Detail.CACHED, r.cached);
+                proto.write(ProcessOomProto.Detail.EMPTY, r.empty);
+                proto.write(ProcessOomProto.Detail.HAS_ABOVE_CLIENT, r.hasAboveClient);
+
+                if (r.setProcState >= ActivityManager.PROCESS_STATE_SERVICE) {
+                    if (r.lastCpuTime != 0) {
+                        long uptimeSince = curUptime - service.mLastPowerCheckUptime;
+                        long timeUsed = r.curCpuTime - r.lastCpuTime;
+                        long cpuTimeToken = proto.start(ProcessOomProto.Detail.SERVICE_RUN_TIME);
+                        proto.write(ProcessOomProto.Detail.CpuRunTime.OVER_MS, uptimeSince);
+                        proto.write(ProcessOomProto.Detail.CpuRunTime.USED_MS, timeUsed);
+                        proto.write(ProcessOomProto.Detail.CpuRunTime.ULTILIZATION,
+                                (100.0*timeUsed)/uptimeSince);
+                        proto.end(cpuTimeToken);
+                    }
+                }
+                proto.end(detailToken);
+            }
+            proto.end(token);
+        }
+
+        return true;
+    }
+
+    private static final boolean dumpProcessOomList(PrintWriter pw,
+            ActivityManagerService service, List<ProcessRecord> origList,
+            String prefix, String normalLabel, String persistentLabel,
+            boolean inclDetails, String dumpPackage) {
+
+        ArrayList<Pair<ProcessRecord, Integer>> list = sortProcessOomList(origList, dumpPackage);
+        if (list.isEmpty()) return false;
 
         final long curUptime = SystemClock.uptimeMillis();
         final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
@@ -24120,7 +24580,7 @@
         final int size = mActiveUids.size();
         for (int i = 0; i < size; i++) {
             final int uid = mActiveUids.keyAt(i);
-            if (!UserHandle.isApp(uid)) {
+            if (UserHandle.isCore(uid)) {
                 continue;
             }
             final UidRecord uidRec = mActiveUids.valueAt(i);
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 0da7e0e..c7d93be 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -22,6 +22,7 @@
 import com.android.internal.os.ProcessCpuTracker;
 import com.android.server.RescueParty;
 import com.android.server.Watchdog;
+import com.android.server.am.proto.AppErrorsProto;
 
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
@@ -48,6 +49,7 @@
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
 
 import java.io.File;
 import java.io.FileDescriptor;
@@ -103,8 +105,76 @@
         mContext = context;
     }
 
-    boolean dumpLocked(FileDescriptor fd, PrintWriter pw, boolean needSep,
-            String dumpPackage) {
+    void writeToProto(ProtoOutputStream proto, long fieldId, String dumpPackage) {
+        if (mProcessCrashTimes.getMap().isEmpty() && mBadProcesses.getMap().isEmpty()) {
+            return;
+        }
+
+        final long token = proto.start(fieldId);
+        final long now = SystemClock.uptimeMillis();
+        proto.write(AppErrorsProto.NOW_UPTIME_MS, now);
+
+        if (!mProcessCrashTimes.getMap().isEmpty()) {
+            final ArrayMap<String, SparseArray<Long>> pmap = mProcessCrashTimes.getMap();
+            final int procCount = pmap.size();
+            for (int ip = 0; ip < procCount; ip++) {
+                final long ctoken = proto.start(AppErrorsProto.PROCESS_CRASH_TIMES);
+                final String pname = pmap.keyAt(ip);
+                final SparseArray<Long> uids = pmap.valueAt(ip);
+                final int uidCount = uids.size();
+
+                proto.write(AppErrorsProto.ProcessCrashTime.PROCESS_NAME, pname);
+                for (int i = 0; i < uidCount; i++) {
+                    final int puid = uids.keyAt(i);
+                    final ProcessRecord r = mService.mProcessNames.get(pname, puid);
+                    if (dumpPackage != null && (r == null || !r.pkgList.containsKey(dumpPackage))) {
+                        continue;
+                    }
+                    final long etoken = proto.start(AppErrorsProto.ProcessCrashTime.ENTRIES);
+                    proto.write(AppErrorsProto.ProcessCrashTime.Entry.UID, puid);
+                    proto.write(AppErrorsProto.ProcessCrashTime.Entry.LAST_CRASHED_AT_MS,
+                            uids.valueAt(i));
+                    proto.end(etoken);
+                }
+                proto.end(ctoken);
+            }
+
+        }
+
+        if (!mBadProcesses.getMap().isEmpty()) {
+            final ArrayMap<String, SparseArray<BadProcessInfo>> pmap = mBadProcesses.getMap();
+            final int processCount = pmap.size();
+            for (int ip = 0; ip < processCount; ip++) {
+                final long btoken = proto.start(AppErrorsProto.BAD_PROCESSES);
+                final String pname = pmap.keyAt(ip);
+                final SparseArray<BadProcessInfo> uids = pmap.valueAt(ip);
+                final int uidCount = uids.size();
+
+                proto.write(AppErrorsProto.BadProcess.PROCESS_NAME, pname);
+                for (int i = 0; i < uidCount; i++) {
+                    final int puid = uids.keyAt(i);
+                    final ProcessRecord r = mService.mProcessNames.get(pname, puid);
+                    if (dumpPackage != null && (r == null
+                            || !r.pkgList.containsKey(dumpPackage))) {
+                        continue;
+                    }
+                    final BadProcessInfo info = uids.valueAt(i);
+                    final long etoken = proto.start(AppErrorsProto.BadProcess.ENTRIES);
+                    proto.write(AppErrorsProto.BadProcess.Entry.UID, puid);
+                    proto.write(AppErrorsProto.BadProcess.Entry.CRASHED_AT_MS, info.time);
+                    proto.write(AppErrorsProto.BadProcess.Entry.SHORT_MSG, info.shortMsg);
+                    proto.write(AppErrorsProto.BadProcess.Entry.LONG_MSG, info.longMsg);
+                    proto.write(AppErrorsProto.BadProcess.Entry.STACK, info.stack);
+                    proto.end(etoken);
+                }
+                proto.end(btoken);
+            }
+        }
+
+        proto.end(token);
+    }
+
+    boolean dumpLocked(FileDescriptor fd, PrintWriter pw, boolean needSep, String dumpPackage) {
         if (!mProcessCrashTimes.getMap().isEmpty()) {
             boolean printed = false;
             final long now = SystemClock.uptimeMillis();
diff --git a/services/core/java/com/android/server/am/AppTimeTracker.java b/services/core/java/com/android/server/am/AppTimeTracker.java
index 910f33d..d96364a 100644
--- a/services/core/java/com/android/server/am/AppTimeTracker.java
+++ b/services/core/java/com/android/server/am/AppTimeTracker.java
@@ -25,6 +25,10 @@
 import android.util.ArrayMap;
 import android.util.MutableLong;
 import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
+import android.util.proto.ProtoUtils;
+
+import com.android.server.am.proto.AppTimeTrackerProto;
 
 import java.io.PrintWriter;
 
@@ -119,4 +123,22 @@
             pw.print(prefix); pw.print("mStartedPackage="); pw.println(mStartedPackage);
         }
     }
+
+    void writeToProto(ProtoOutputStream proto, long fieldId, boolean details) {
+        final long token = proto.start(fieldId);
+        proto.write(AppTimeTrackerProto.RECEIVER, mReceiver.toString());
+        proto.write(AppTimeTrackerProto.TOTAL_DURATION_MS, mTotalTime);
+        for (int i=0; i<mPackageTimes.size(); i++) {
+            final long ptoken = proto.start(AppTimeTrackerProto.PACKAGE_TIMES);
+            proto.write(AppTimeTrackerProto.PackageTime.PACKAGE, mPackageTimes.keyAt(i));
+            proto.write(AppTimeTrackerProto.PackageTime.DURATION_MS, mPackageTimes.valueAt(i).value);
+            proto.end(ptoken);
+        }
+        if (details && mStartedTime != 0) {
+            ProtoUtils.toDuration(proto, AppTimeTrackerProto.STARTED_TIME,
+                    mStartedTime, SystemClock.elapsedRealtime());
+            proto.write(AppTimeTrackerProto.STARTED_PACKAGE, mStartedPackage);
+        }
+        proto.end(token);
+    }
 }
diff --git a/services/core/java/com/android/server/am/ConnectionRecord.java b/services/core/java/com/android/server/am/ConnectionRecord.java
index 6df283c..d320fb1 100644
--- a/services/core/java/com/android/server/am/ConnectionRecord.java
+++ b/services/core/java/com/android/server/am/ConnectionRecord.java
@@ -20,6 +20,7 @@
 import android.app.PendingIntent;
 import android.content.Context;
 import android.util.proto.ProtoOutputStream;
+import android.util.proto.ProtoUtils;
 
 import com.android.server.am.proto.ConnectionRecordProto;
 
@@ -37,7 +38,43 @@
     final PendingIntent clientIntent; // How to launch the client.
     String stringName;              // Caching of toString.
     boolean serviceDead;            // Well is it?
-    
+
+    // Please keep the following two enum list synced.
+    private static int[] BIND_ORIG_ENUMS = new int[] {
+            Context.BIND_AUTO_CREATE,
+            Context.BIND_DEBUG_UNBIND,
+            Context.BIND_NOT_FOREGROUND,
+            Context.BIND_IMPORTANT_BACKGROUND,
+            Context.BIND_ABOVE_CLIENT,
+            Context.BIND_ALLOW_OOM_MANAGEMENT,
+            Context.BIND_WAIVE_PRIORITY,
+            Context.BIND_IMPORTANT,
+            Context.BIND_ADJUST_WITH_ACTIVITY,
+            Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
+            Context.BIND_FOREGROUND_SERVICE,
+            Context.BIND_TREAT_LIKE_ACTIVITY,
+            Context.BIND_VISIBLE,
+            Context.BIND_SHOWING_UI,
+            Context.BIND_NOT_VISIBLE,
+    };
+    private static int[] BIND_PROTO_ENUMS = new int[] {
+            ConnectionRecordProto.AUTO_CREATE,
+            ConnectionRecordProto.DEBUG_UNBIND,
+            ConnectionRecordProto.NOT_FG,
+            ConnectionRecordProto.IMPORTANT_BG,
+            ConnectionRecordProto.ABOVE_CLIENT,
+            ConnectionRecordProto.ALLOW_OOM_MANAGEMENT,
+            ConnectionRecordProto.WAIVE_PRIORITY,
+            ConnectionRecordProto.IMPORTANT,
+            ConnectionRecordProto.ADJUST_WITH_ACTIVITY,
+            ConnectionRecordProto.FG_SERVICE_WHILE_AWAKE,
+            ConnectionRecordProto.FG_SERVICE,
+            ConnectionRecordProto.TREAT_LIKE_ACTIVITY,
+            ConnectionRecordProto.VISIBLE,
+            ConnectionRecordProto.SHOWING_UI,
+            ConnectionRecordProto.NOT_VISIBLE,
+    };
+
     void dump(PrintWriter pw, String prefix) {
         pw.println(prefix + "binding=" + binding);
         if (activity != null) {
@@ -46,7 +83,7 @@
         pw.println(prefix + "conn=" + conn.asBinder()
                 + " flags=0x" + Integer.toHexString(flags));
     }
-    
+
     ConnectionRecord(AppBindRecord _binding, ActivityRecord _activity,
                IServiceConnection _conn, int _flags,
                int _clientLabel, PendingIntent _clientIntent) {
@@ -131,51 +168,8 @@
         if (binding.client != null) {
             proto.write(ConnectionRecordProto.USER_ID, binding.client.userId);
         }
-        if ((flags&Context.BIND_AUTO_CREATE) != 0) {
-            proto.write(ConnectionRecordProto.FLAGS, ConnectionRecordProto.AUTO_CREATE);
-        }
-        if ((flags&Context.BIND_DEBUG_UNBIND) != 0) {
-            proto.write(ConnectionRecordProto.FLAGS, ConnectionRecordProto.DEBUG_UNBIND);
-        }
-        if ((flags&Context.BIND_NOT_FOREGROUND) != 0) {
-            proto.write(ConnectionRecordProto.FLAGS, ConnectionRecordProto.NOT_FG);
-        }
-        if ((flags&Context.BIND_IMPORTANT_BACKGROUND) != 0) {
-            proto.write(ConnectionRecordProto.FLAGS, ConnectionRecordProto.IMPORTANT_BG);
-        }
-        if ((flags&Context.BIND_ABOVE_CLIENT) != 0) {
-            proto.write(ConnectionRecordProto.FLAGS, ConnectionRecordProto.ABOVE_CLIENT);
-        }
-        if ((flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
-            proto.write(ConnectionRecordProto.FLAGS, ConnectionRecordProto.ALLOW_OOM_MANAGEMENT);
-        }
-        if ((flags&Context.BIND_WAIVE_PRIORITY) != 0) {
-            proto.write(ConnectionRecordProto.FLAGS, ConnectionRecordProto.WAIVE_PRIORITY);
-        }
-        if ((flags&Context.BIND_IMPORTANT) != 0) {
-            proto.write(ConnectionRecordProto.FLAGS, ConnectionRecordProto.IMPORTANT);
-        }
-        if ((flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
-            proto.write(ConnectionRecordProto.FLAGS, ConnectionRecordProto.ADJUST_WITH_ACTIVITY);
-        }
-        if ((flags&Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE) != 0) {
-            proto.write(ConnectionRecordProto.FLAGS, ConnectionRecordProto.FG_SERVICE_WHILE_WAKE);
-        }
-        if ((flags&Context.BIND_FOREGROUND_SERVICE) != 0) {
-            proto.write(ConnectionRecordProto.FLAGS, ConnectionRecordProto.FG_SERVICE);
-        }
-        if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
-            proto.write(ConnectionRecordProto.FLAGS, ConnectionRecordProto.TREAT_LIKE_ACTIVITY);
-        }
-        if ((flags&Context.BIND_VISIBLE) != 0) {
-            proto.write(ConnectionRecordProto.FLAGS, ConnectionRecordProto.VISIBLE);
-        }
-        if ((flags&Context.BIND_SHOWING_UI) != 0) {
-            proto.write(ConnectionRecordProto.FLAGS, ConnectionRecordProto.SHOWING_UI);
-        }
-        if ((flags&Context.BIND_NOT_VISIBLE) != 0) {
-            proto.write(ConnectionRecordProto.FLAGS, ConnectionRecordProto.NOT_VISIBLE);
-        }
+        ProtoUtils.writeBitWiseFlagsToProtoEnum(proto, ConnectionRecordProto.FLAGS,
+                flags, BIND_ORIG_ENUMS, BIND_PROTO_ENUMS);
         if (serviceDead) {
             proto.write(ConnectionRecordProto.FLAGS, ConnectionRecordProto.DEAD);
         }
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 77f5c16..29bfebe 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -24,6 +24,7 @@
 import java.nio.ByteBuffer;
 
 import android.app.ActivityManager;
+import android.app.ActivityManagerProto;
 import android.os.Build;
 import android.os.SystemClock;
 import com.android.internal.util.MemInfoReader;
@@ -416,6 +417,53 @@
         return procState;
     }
 
+    public static int makeProcStateProtoEnum(int curProcState) {
+        switch (curProcState) {
+            case ActivityManager.PROCESS_STATE_PERSISTENT:
+                return ActivityManagerProto.PROCESS_STATE_PERSISTENT;
+            case ActivityManager.PROCESS_STATE_PERSISTENT_UI:
+                return ActivityManagerProto.PROCESS_STATE_PERSISTENT_UI;
+            case ActivityManager.PROCESS_STATE_TOP:
+                return ActivityManagerProto.PROCESS_STATE_TOP;
+            case ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE:
+                return ActivityManagerProto.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+            case ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE:
+                return ActivityManagerProto.PROCESS_STATE_FOREGROUND_SERVICE;
+            case ActivityManager.PROCESS_STATE_TOP_SLEEPING:
+                return ActivityManagerProto.PROCESS_STATE_TOP_SLEEPING;
+            case ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND:
+                return ActivityManagerProto.PROCESS_STATE_IMPORTANT_FOREGROUND;
+            case ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND:
+                return ActivityManagerProto.PROCESS_STATE_IMPORTANT_BACKGROUND;
+            case ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND:
+                return ActivityManagerProto.PROCESS_STATE_TRANSIENT_BACKGROUND;
+            case ActivityManager.PROCESS_STATE_BACKUP:
+                return ActivityManagerProto.PROCESS_STATE_BACKUP;
+            case ActivityManager.PROCESS_STATE_HEAVY_WEIGHT:
+                return ActivityManagerProto.PROCESS_STATE_HEAVY_WEIGHT;
+            case ActivityManager.PROCESS_STATE_SERVICE:
+                return ActivityManagerProto.PROCESS_STATE_SERVICE;
+            case ActivityManager.PROCESS_STATE_RECEIVER:
+                return ActivityManagerProto.PROCESS_STATE_RECEIVER;
+            case ActivityManager.PROCESS_STATE_HOME:
+                return ActivityManagerProto.PROCESS_STATE_HOME;
+            case ActivityManager.PROCESS_STATE_LAST_ACTIVITY:
+                return ActivityManagerProto.PROCESS_STATE_LAST_ACTIVITY;
+            case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
+                return ActivityManagerProto.PROCESS_STATE_CACHED_ACTIVITY;
+            case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
+                return ActivityManagerProto.PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
+            case ActivityManager.PROCESS_STATE_CACHED_RECENT:
+                return ActivityManagerProto.PROCESS_STATE_CACHED_RECENT;
+            case ActivityManager.PROCESS_STATE_CACHED_EMPTY:
+                return ActivityManagerProto.PROCESS_STATE_CACHED_EMPTY;
+            case ActivityManager.PROCESS_STATE_NONEXISTENT:
+                return ActivityManagerProto.PROCESS_STATE_NONEXISTENT;
+            default:
+                return -1;
+        }
+    }
+
     public static void appendRamKb(StringBuilder sb, long ramKb) {
         for (int j=0, fact=10; j<6; j++, fact*=10) {
             if (ramKb < fact) {
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index a1e5947..03e140d 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -679,6 +679,7 @@
                 proto.write(ProcessRecordProto.ISOLATED_APP_ID, UserHandle.getAppId(uid));
             }
         }
+        proto.write(ProcessRecordProto.PERSISTENT, persistent);
         proto.end(token);
     }
 
diff --git a/services/core/java/com/android/server/am/UidRecord.java b/services/core/java/com/android/server/am/UidRecord.java
index 8efcb4f..3886e5a 100644
--- a/services/core/java/com/android/server/am/UidRecord.java
+++ b/services/core/java/com/android/server/am/UidRecord.java
@@ -18,13 +18,17 @@
 
 import android.Manifest;
 import android.app.ActivityManager;
+import android.app.ActivityManagerProto;
 import android.content.pm.PackageManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
+import android.util.proto.ProtoUtils;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.am.proto.UidRecordProto;
 
 /**
  * Overall information about a uid that has actively running processes.
@@ -86,6 +90,22 @@
     static final int CHANGE_CACHED = 1<<3;
     static final int CHANGE_UNCACHED = 1<<4;
 
+    // Keep the enum lists in sync
+    private static int[] ORIG_ENUMS = new int[] {
+            CHANGE_GONE,
+            CHANGE_IDLE,
+            CHANGE_ACTIVE,
+            CHANGE_CACHED,
+            CHANGE_UNCACHED,
+    };
+    private static int[] PROTO_ENUMS = new int[] {
+            UidRecordProto.CHANGE_GONE,
+            UidRecordProto.CHANGE_IDLE,
+            UidRecordProto.CHANGE_ACTIVE,
+            UidRecordProto.CHANGE_CACHED,
+            UidRecordProto.CHANGE_UNCACHED,
+    };
+
     static final class ChangeItem {
         UidRecord uidRecord;
         int uid;
@@ -125,6 +145,34 @@
         }
     }
 
+
+    void writeToProto(ProtoOutputStream proto, long fieldId) {
+        long token = proto.start(fieldId);
+        proto.write(UidRecordProto.HEX_HASH, Integer.toHexString(System.identityHashCode(this)));
+        proto.write(UidRecordProto.UID, uid);
+        proto.write(UidRecordProto.CURRENT, ProcessList.makeProcStateProtoEnum(curProcState));
+        proto.write(UidRecordProto.EPHEMERAL, ephemeral);
+        proto.write(UidRecordProto.FG_SERVICES, foregroundServices);
+        proto.write(UidRecordProto.WHILELIST, curWhitelist);
+        ProtoUtils.toDuration(proto, UidRecordProto.LAST_BACKGROUND_TIME,
+                lastBackgroundTime, SystemClock.elapsedRealtime());
+        proto.write(UidRecordProto.IDLE, idle);
+        if (lastReportedChange != 0) {
+            ProtoUtils.writeBitWiseFlagsToProtoEnum(proto, UidRecordProto.LAST_REPORTED_CHANGES,
+                    lastReportedChange, ORIG_ENUMS, PROTO_ENUMS);
+        }
+        proto.write(UidRecordProto.NUM_PROCS, numProcs);
+
+        long seqToken = proto.start(UidRecordProto.NETWORK_STATE_UPDATE);
+        proto.write(UidRecordProto.ProcStateSequence.CURURENT, curProcStateSeq);
+        proto.write(UidRecordProto.ProcStateSequence.LAST_NETWORK_UPDATED,
+                lastNetworkUpdatedProcStateSeq);
+        proto.write(UidRecordProto.ProcStateSequence.LAST_DISPATCHED, lastDispatchedProcStateSeq);
+        proto.end(seqToken);
+
+        proto.end(token);
+    }
+
     public String toString() {
         StringBuilder sb = new StringBuilder(128);
         sb.append("UidRecord{");
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 5ada484..7b0c714 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -83,6 +83,7 @@
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 import android.util.TimingsTraceLog;
+import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
@@ -94,6 +95,7 @@
 import com.android.server.FgThread;
 import com.android.server.LocalServices;
 import com.android.server.SystemServiceManager;
+import com.android.server.am.proto.UserControllerProto;
 import com.android.server.pm.UserManagerService;
 import com.android.server.wm.WindowManagerService;
 
@@ -1844,6 +1846,36 @@
         }
     }
 
+    void writeToProto(ProtoOutputStream proto, long fieldId) {
+        synchronized (mLock) {
+            long token = proto.start(fieldId);
+            for (int i = 0; i < mStartedUsers.size(); i++) {
+                UserState uss = mStartedUsers.valueAt(i);
+                final long uToken = proto.start(UserControllerProto.STARTED_USERS);
+                proto.write(UserControllerProto.User.ID, uss.mHandle.getIdentifier());
+                uss.writeToProto(proto, UserControllerProto.User.STATE);
+                proto.end(uToken);
+            }
+            for (int i = 0; i < mStartedUserArray.length; i++) {
+                proto.write(UserControllerProto.STARTED_USER_ARRAY, mStartedUserArray[i]);
+            }
+            for (int i = 0; i < mUserLru.size(); i++) {
+                proto.write(UserControllerProto.USER_LRU, mUserLru.get(i));
+            }
+            if (mUserProfileGroupIds.size() > 0) {
+                for (int i = 0; i < mUserProfileGroupIds.size(); i++) {
+                    final long uToken = proto.start(UserControllerProto.USER_PROFILE_GROUP_IDS);
+                    proto.write(UserControllerProto.UserProfile.USER,
+                            mUserProfileGroupIds.keyAt(i));
+                    proto.write(UserControllerProto.UserProfile.PROFILE,
+                            mUserProfileGroupIds.valueAt(i));
+                    proto.end(uToken);
+                }
+            }
+            proto.end(token);
+        }
+    }
+
     void dump(PrintWriter pw, boolean dumpAll) {
         synchronized (mLock) {
             pw.println("  mStartedUsers:");
@@ -1868,10 +1900,6 @@
                 pw.print(mUserLru.get(i));
             }
             pw.println("]");
-            if (dumpAll) {
-                pw.print("  mStartedUserArray: ");
-                pw.println(Arrays.toString(mStartedUserArray));
-            }
             if (mUserProfileGroupIds.size() > 0) {
                 pw.println("  mUserProfileGroupIds:");
                 for (int i=0; i< mUserProfileGroupIds.size(); i++) {
diff --git a/services/core/java/com/android/server/am/UserState.java b/services/core/java/com/android/server/am/UserState.java
index d36d9cb..00597e2 100644
--- a/services/core/java/com/android/server/am/UserState.java
+++ b/services/core/java/com/android/server/am/UserState.java
@@ -24,8 +24,10 @@
 import android.os.UserHandle;
 import android.util.ArrayMap;
 import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.util.ProgressReporter;
+import com.android.server.am.proto.UserStateProto;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -112,10 +114,29 @@
         }
     }
 
+    public static int stateToProtoEnum(int state) {
+        switch (state) {
+            case STATE_BOOTING: return UserStateProto.STATE_BOOTING;
+            case STATE_RUNNING_LOCKED: return UserStateProto.STATE_RUNNING_LOCKED;
+            case STATE_RUNNING_UNLOCKING: return UserStateProto.STATE_RUNNING_UNLOCKING;
+            case STATE_RUNNING_UNLOCKED: return UserStateProto.STATE_RUNNING_UNLOCKED;
+            case STATE_STOPPING: return UserStateProto.STATE_STOPPING;
+            case STATE_SHUTDOWN: return UserStateProto.STATE_SHUTDOWN;
+            default: return state;
+        }
+    }
+
     void dump(String prefix, PrintWriter pw) {
         pw.print(prefix);
         pw.print("state="); pw.print(stateToString(state));
         if (switching) pw.print(" SWITCHING");
         pw.println();
     }
+
+    void writeToProto(ProtoOutputStream proto, long fieldId) {
+        final long token = proto.start(fieldId);
+        proto.write(UserStateProto.STATE, stateToProtoEnum(state));
+        proto.write(UserStateProto.SWITCHING, switching);
+        proto.end(token);
+    }
 }
diff --git a/services/core/java/com/android/server/am/VrController.java b/services/core/java/com/android/server/am/VrController.java
index feddfe3..d32db7e 100644
--- a/services/core/java/com/android/server/am/VrController.java
+++ b/services/core/java/com/android/server/am/VrController.java
@@ -20,7 +20,11 @@
 import android.os.Process;
 import android.service.vr.IPersistentVrStateCallbacks;
 import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
+import android.util.proto.ProtoUtils;
+
 import com.android.server.LocalServices;
+import com.android.server.am.proto.ProcessesProto.VrControllerProto;
 import com.android.server.vr.VrManagerInternal;
 
 /**
@@ -49,6 +53,18 @@
     private static final int FLAG_VR_MODE = 1;
     private static final int FLAG_PERSISTENT_VR_MODE = 2;
 
+    // Keep the enum lists in sync
+    private static int[] ORIG_ENUMS = new int[] {
+            FLAG_NON_VR_MODE,
+            FLAG_VR_MODE,
+            FLAG_PERSISTENT_VR_MODE,
+    };
+    private static int[] PROTO_ENUMS = new int[] {
+            VrControllerProto.FLAG_NON_VR_MODE,
+            VrControllerProto.FLAG_VR_MODE,
+            VrControllerProto.FLAG_PERSISTENT_VR_MODE,
+    };
+
     // Invariants maintained for mVrState
     //
     //   Always true:
@@ -420,4 +436,12 @@
     public String toString() {
       return String.format("[VrState=0x%x,VrRenderThreadTid=%d]", mVrState, mVrRenderThreadTid);
     }
+
+    void writeToProto(ProtoOutputStream proto, long fieldId) {
+        final long token = proto.start(fieldId);
+        ProtoUtils.writeBitWiseFlagsToProtoEnum(proto, VrControllerProto.VR_MODE,
+                mVrState, ORIG_ENUMS, PROTO_ENUMS);
+        proto.write(VrControllerProto.RENDER_THREAD_ID, mVrRenderThreadTid);
+        proto.end(token);
+    }
 }
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index b97de65..c77ec20 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -1849,7 +1849,6 @@
             if (packageName != null && !validatePackageName(getCallingUid(), packageName)) {
                 packageName = null;
             }
-            Preconditions.checkNotNull(c);
             final long token = Binder.clearCallingIdentity();
             try {
                 setBrightnessConfigurationForUserInternal(c, userId, packageName);
diff --git a/services/core/java/com/android/server/display/PersistentDataStore.java b/services/core/java/com/android/server/display/PersistentDataStore.java
index f1ce5c5..cbf46f8 100644
--- a/services/core/java/com/android/server/display/PersistentDataStore.java
+++ b/services/core/java/com/android/server/display/PersistentDataStore.java
@@ -598,14 +598,20 @@
         private boolean setBrightnessConfigurationForUser(BrightnessConfiguration c,
                 int userSerial, String packageName) {
             BrightnessConfiguration currentConfig = mConfigurations.get(userSerial);
-            if (currentConfig == null || !currentConfig.equals(c)) {
-                if (packageName == null) {
-                    mPackageNames.remove(userSerial);
+            if (currentConfig != c && (currentConfig == null || !currentConfig.equals(c))) {
+                if (c != null) {
+                    if (packageName == null) {
+                        mPackageNames.remove(userSerial);
+                    } else {
+                        mPackageNames.put(userSerial, packageName);
+                    }
+                    mTimeStamps.put(userSerial, System.currentTimeMillis());
+                    mConfigurations.put(userSerial, c);
                 } else {
-                    mPackageNames.put(userSerial, packageName);
+                    mPackageNames.remove(userSerial);
+                    mTimeStamps.delete(userSerial);
+                    mConfigurations.remove(userSerial);
                 }
-                mTimeStamps.put(userSerial, System.currentTimeMillis());
-                mConfigurations.put(userSerial, c);
                 return true;
             }
             return false;
diff --git a/services/core/java/com/android/server/fingerprint/AuthenticationClient.java b/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
index 370e569..d30b13c 100644
--- a/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
+++ b/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
@@ -16,18 +16,22 @@
 
 package com.android.server.fingerprint;
 
-import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
 import android.content.Context;
+import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
 import android.hardware.fingerprint.Fingerprint;
+import android.hardware.fingerprint.FingerprintDialog;
 import android.hardware.fingerprint.FingerprintManager;
+import android.hardware.fingerprint.IFingerprintDialogReceiver;
 import android.hardware.fingerprint.IFingerprintServiceReceiver;
+import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Slog;
 
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.statusbar.IStatusBarService;
+
 /**
  * A class to keep track of the authentication state for a given client.
  */
@@ -41,11 +45,99 @@
     public static final int LOCKOUT_TIMED = 1;
     public static final int LOCKOUT_PERMANENT = 2;
 
+    // Callback mechanism received from the client
+    // (FingerprintDialog -> FingerprintManager -> FingerprintService -> AuthenticationClient)
+    private IFingerprintDialogReceiver mDialogReceiverFromClient;
+    private Bundle mBundle;
+    private IStatusBarService mStatusBarService;
+    private boolean mInLockout;
+    private final FingerprintManager mFingerprintManager;
+    protected boolean mDialogDismissed;
+
+    // Receives events from SystemUI
+    protected IFingerprintDialogReceiver mDialogReceiver = new IFingerprintDialogReceiver.Stub() {
+        @Override // binder call
+        public void onDialogDismissed(int reason) {
+            if (mBundle != null && mDialogReceiverFromClient != null) {
+                try {
+                    mDialogReceiverFromClient.onDialogDismissed(reason);
+                    if (reason == FingerprintDialog.DISMISSED_REASON_USER_CANCEL) {
+                        onError(FingerprintManager.FINGERPRINT_ERROR_USER_CANCELED,
+                                0 /* vendorCode */);
+                    }
+                    mDialogDismissed = true;
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Unable to notify dialog dismissed", e);
+                }
+                stop(true /* initiatedByClient */);
+            }
+        }
+    };
+
     public AuthenticationClient(Context context, long halDeviceId, IBinder token,
             IFingerprintServiceReceiver receiver, int targetUserId, int groupId, long opId,
-            boolean restricted, String owner) {
+            boolean restricted, String owner, Bundle bundle,
+            IFingerprintDialogReceiver dialogReceiver, IStatusBarService statusBarService) {
         super(context, halDeviceId, token, receiver, targetUserId, groupId, restricted, owner);
         mOpId = opId;
+        mBundle = bundle;
+        mDialogReceiverFromClient = dialogReceiver;
+        mStatusBarService = statusBarService;
+        mFingerprintManager = (FingerprintManager) getContext()
+                .getSystemService(Context.FINGERPRINT_SERVICE);
+    }
+
+    @Override
+    public void binderDied() {
+        super.binderDied();
+        // When the binder dies, we should stop the client. This probably belongs in
+        // ClientMonitor's binderDied(), but testing all the cases would be tricky.
+        // AuthenticationClient is the most user-visible case.
+        stop(false /* initiatedByClient */);
+    }
+
+    @Override
+    public boolean onAcquired(int acquiredInfo, int vendorCode) {
+        // If the dialog is showing, the client doesn't need to receive onAcquired messages.
+        if (mBundle != null) {
+            try {
+                if (acquiredInfo != FingerprintManager.FINGERPRINT_ACQUIRED_GOOD) {
+                    mStatusBarService.onFingerprintHelp(
+                            mFingerprintManager.getAcquiredString(acquiredInfo, vendorCode));
+                }
+                return false; // acquisition continues
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Remote exception when sending acquired message", e);
+                return true; // client failed
+            } finally {
+                // Good scans will keep the device awake
+                if (acquiredInfo == FingerprintManager.FINGERPRINT_ACQUIRED_GOOD) {
+                    notifyUserActivity();
+                }
+            }
+        } else {
+            return super.onAcquired(acquiredInfo, vendorCode);
+        }
+    }
+
+    @Override
+    public boolean onError(int error, int vendorCode) {
+        if (mDialogDismissed) {
+            // If user cancels authentication, the application has already received the
+            // FingerprintManager.FINGERPRINT_ERROR_USER_CANCELED message from onDialogDismissed()
+            // and stopped the fingerprint hardware, so there is no need to send a
+            // FingerprintManager.FINGERPRINT_ERROR_CANCELED message.
+            return true;
+        }
+        if (mBundle != null) {
+            try {
+                mStatusBarService.onFingerprintError(
+                        mFingerprintManager.getErrorString(error, vendorCode));
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Remote exception when sending error", e);
+            }
+        }
+        return super.onError(error, vendorCode);
     }
 
     @Override
@@ -53,6 +145,20 @@
         boolean result = false;
         boolean authenticated = fingerId != 0;
 
+        // If the fingerprint dialog is showing, notify authentication succeeded
+        if (mBundle != null) {
+            try {
+                if (authenticated) {
+                    mStatusBarService.onFingerprintAuthenticated();
+                } else {
+                    mStatusBarService.onFingerprintHelp(getContext().getResources().getString(
+                            com.android.internal.R.string.fingerprint_not_recognized));
+                }
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Failed to notify Authenticated:", e);
+            }
+        }
+
         IFingerprintServiceReceiver receiver = getReceiver();
         if (receiver != null) {
             try {
@@ -85,13 +191,24 @@
             int lockoutMode =  handleFailedAttempt();
             if (lockoutMode != LOCKOUT_NONE) {
                 try {
+                    mInLockout = true;
                     Slog.w(TAG, "Forcing lockout (fp driver code should do this!), mode(" +
                             lockoutMode + ")");
                     stop(false);
                     int errorCode = lockoutMode == LOCKOUT_TIMED ?
                             FingerprintManager.FINGERPRINT_ERROR_LOCKOUT :
                             FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT;
+
+                    // TODO: if the dialog is showing, this error should be delayed. On a similar
+                    // note, AuthenticationClient should override onError and delay all other errors
+                    // as well, if the dialog is showing
                     receiver.onError(getHalDeviceId(), errorCode, 0 /* vendorCode */);
+
+                    // Send the lockout message to the system dialog
+                    if (mBundle != null) {
+                        mStatusBarService.onFingerprintError(
+                                mFingerprintManager.getErrorString(errorCode, 0 /* vendorCode */));
+                    }
                 } catch (RemoteException e) {
                     Slog.w(TAG, "Failed to notify lockout:", e);
                 }
@@ -126,6 +243,15 @@
                 return result;
             }
             if (DEBUG) Slog.w(TAG, "client " + getOwnerString() + " is authenticating...");
+
+            // If authenticating with system dialog, show the dialog
+            if (mBundle != null) {
+                try {
+                    mStatusBarService.showFingerprintDialog(mBundle, mDialogReceiver);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Unable to show fingerprint dialog", e);
+                }
+            }
         } catch (RemoteException e) {
             Slog.e(TAG, "startAuthentication failed", e);
             return ERROR_ESRCH;
@@ -139,6 +265,7 @@
             Slog.w(TAG, "stopAuthentication: already cancelled!");
             return 0;
         }
+
         IBiometricsFingerprint daemon = getFingerprintDaemon();
         if (daemon == null) {
             Slog.w(TAG, "stopAuthentication: no fingerprint HAL!");
@@ -154,6 +281,18 @@
         } catch (RemoteException e) {
             Slog.e(TAG, "stopAuthentication failed", e);
             return ERROR_ESRCH;
+        } finally {
+            // If the user already cancelled authentication (via some interaction with the
+            // dialog, we do not need to hide it since it's already hidden.
+            // If the device is in lockout, don't hide the dialog - it will automatically hide
+            // after FingerprintDialog.HIDE_DIALOG_DELAY
+            if (mBundle != null && !mDialogDismissed && !mInLockout) {
+                try {
+                    mStatusBarService.hideFingerprintDialog();
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Unable to hide fingerprint dialog", e);
+                }
+            }
         }
         mAlreadyCancelled = true;
         return 0; // success
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index d0d951b..3e1958d 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -40,6 +40,7 @@
 import android.hardware.fingerprint.Fingerprint;
 import android.hardware.fingerprint.FingerprintManager;
 import android.hardware.fingerprint.IFingerprintClientActiveCallback;
+import android.hardware.fingerprint.IFingerprintDialogReceiver;
 import android.hardware.fingerprint.IFingerprintService;
 import android.hardware.fingerprint.IFingerprintServiceLockoutResetCallback;
 import android.hardware.fingerprint.IFingerprintServiceReceiver;
@@ -55,6 +56,7 @@
 import android.os.PowerManager.WakeLock;
 import android.os.RemoteException;
 import android.os.SELinux;
+import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -66,6 +68,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.util.DumpUtils;
 import com.android.server.SystemServerInitThreadPool;
 import com.android.server.SystemService;
@@ -131,6 +134,7 @@
     private SparseIntArray mFailedAttempts;
     @GuardedBy("this")
     private IBiometricsFingerprint mDaemon;
+    private IStatusBarService mStatusBarService;
     private final PowerManager mPowerManager;
     private final AlarmManager mAlarmManager;
     private final UserManager mUserManager;
@@ -222,6 +226,8 @@
         mUserManager = UserManager.get(mContext);
         mTimedLockoutCleared = new SparseBooleanArray();
         mFailedAttempts = new SparseIntArray();
+        mStatusBarService = IStatusBarService.Stub.asInterface(
+                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
     }
 
     @Override
@@ -808,13 +814,14 @@
 
     private void startAuthentication(IBinder token, long opId, int callingUserId, int groupId,
                 IFingerprintServiceReceiver receiver, int flags, boolean restricted,
-                String opPackageName) {
+                String opPackageName, Bundle bundle, IFingerprintDialogReceiver dialogReceiver) {
         updateActiveGroup(groupId, opPackageName);
 
         if (DEBUG) Slog.v(TAG, "startAuthentication(" + opPackageName + ")");
 
         AuthenticationClient client = new AuthenticationClient(getContext(), mHalDeviceId, token,
-                receiver, mCurrentUserId, groupId, opId, restricted, opPackageName) {
+                receiver, mCurrentUserId, groupId, opId, restricted, opPackageName, bundle,
+                dialogReceiver, mStatusBarService) {
             @Override
             public int handleFailedAttempt() {
                 final int currentUser = ActivityManager.getCurrentUser();
@@ -1037,7 +1044,7 @@
                 final IFingerprintServiceReceiver receiver, final int flags,
                 final String opPackageName) {
             checkPermission(MANAGE_FINGERPRINT);
-            final int limit =  mContext.getResources().getInteger(
+            final int limit = mContext.getResources().getInteger(
                     com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser);
 
             final int enrolled = FingerprintService.this.getEnrolledFingerprints(userId).size();
@@ -1085,7 +1092,8 @@
         @Override // Binder call
         public void authenticate(final IBinder token, final long opId, final int groupId,
                 final IFingerprintServiceReceiver receiver, final int flags,
-                final String opPackageName) {
+                final String opPackageName, final Bundle bundle,
+                final IFingerprintDialogReceiver dialogReceiver) {
             final int callingUid = Binder.getCallingUid();
             final int callingPid = Binder.getCallingPid();
             final int callingUserId = UserHandle.getCallingUserId();
@@ -1113,7 +1121,7 @@
                     mPerformanceStats = stats;
 
                     startAuthentication(token, opId, callingUserId, groupId, receiver,
-                            flags, restricted, opPackageName);
+                            flags, restricted, opPackageName, bundle, dialogReceiver);
                 }
             });
         }
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index fa5fdf5..5da470e 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -21,6 +21,7 @@
 
 import android.app.Activity;
 import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
 import android.app.AppGlobals;
 import android.app.IUidObserver;
 import android.app.job.IJobScheduler;
@@ -73,8 +74,10 @@
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.DumpUtils;
+import com.android.internal.util.Preconditions;
 import com.android.server.DeviceIdleController;
 import com.android.server.FgThread;
+import com.android.server.ForceAppStandbyTracker;
 import com.android.server.LocalServices;
 import com.android.server.job.JobSchedulerServiceDumpProto.ActiveJob;
 import com.android.server.job.JobSchedulerServiceDumpProto.PendingJob;
@@ -102,6 +105,7 @@
 import java.util.Comparator;
 import java.util.Iterator;
 import java.util.List;
+import java.util.function.Predicate;
 
 /**
  * Responsible for taking jobs representing work to be performed by a client app, and determining
@@ -175,8 +179,10 @@
     final JobSchedulerStub mJobSchedulerStub;
 
     PackageManagerInternal mLocalPM;
+    ActivityManagerInternal mActivityManagerInternal;
     IBatteryStats mBatteryStats;
     DeviceIdleController.LocalService mLocalDeviceIdleController;
+    final ForceAppStandbyTracker mForceAppStandbyTracker;
 
     /**
      * Set to true once we are allowed to run third party apps.
@@ -778,6 +784,22 @@
         mStartedUsers = ArrayUtils.removeInt(mStartedUsers, userHandle);
     }
 
+    /**
+     * Return whether an UID is in the foreground or not.
+     */
+    private boolean isUidInForeground(int uid) {
+        synchronized (mLock) {
+            if (mUidPriorityOverride.get(uid, 0) > 0) {
+                return true;
+            }
+        }
+        // Note UID observer may not be called in time, so we always check with the AM.
+        return mActivityManagerInternal.getUidProcessState(uid)
+                <= ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+    }
+
+    private final Predicate<Integer> mIsUidInForegroundPredicate = this::isUidInForeground;
+
     public int scheduleAsPackage(JobInfo job, JobWorkItem work, int uId, String packageName,
             int userId, String tag) {
         try {
@@ -797,12 +819,25 @@
                 // Fast path: we are adding work to an existing job, and the JobInfo is not
                 // changing.  We can just directly enqueue this work in to the job.
                 if (toCancel.getJob().equals(job)) {
+
                     toCancel.enqueueWorkLocked(ActivityManager.getService(), work);
+
+                    // If any of work item is enqueued when the source is in the foreground,
+                    // exempt the entire job.
+                    toCancel.maybeAddForegroundExemption(mIsUidInForegroundPredicate);
+
                     return JobScheduler.RESULT_SUCCESS;
                 }
             }
 
             JobStatus jobStatus = JobStatus.createFromJobInfo(job, uId, packageName, userId, tag);
+
+            // Give exemption if the source is in the foreground just now.
+            // Note if it's a sync job, this method is called on the handler so it's not exactly
+            // the state when requestSync() was called, but that should be fine because of the
+            // 1 minute foreground grace period.
+            jobStatus.maybeAddForegroundExemption(mIsUidInForegroundPredicate);
+
             if (DEBUG) Slog.d(TAG, "SCHEDULE: " + jobStatus.toShortString());
             // Jobs on behalf of others don't apply to the per-app job cap
             if (ENFORCE_MAX_JOBS && packageName == null) {
@@ -1047,6 +1082,8 @@
         super(context);
 
         mLocalPM = LocalServices.getService(PackageManagerInternal.class);
+        mActivityManagerInternal = Preconditions.checkNotNull(
+                LocalServices.getService(ActivityManagerInternal.class));
 
         mHandler = new JobHandler(context.getMainLooper());
         mConstants = new Constants(mHandler);
@@ -1078,6 +1115,8 @@
         mDeviceIdleJobsController = DeviceIdleJobsController.get(this);
         mControllers.add(mDeviceIdleJobsController);
 
+        mForceAppStandbyTracker = ForceAppStandbyTracker.getInstance(context);
+
         // If the job store determined that it can't yet reschedule persisted jobs,
         // we need to start watching the clock.
         if (!mJobs.jobTimesInflatedValid()) {
@@ -1137,6 +1176,9 @@
     public void onBootPhase(int phase) {
         if (PHASE_SYSTEM_SERVICES_READY == phase) {
             mConstants.start(getContext().getContentResolver());
+
+            mForceAppStandbyTracker.start();
+
             // Register br for package removals and user removals.
             final IntentFilter filter = new IntentFilter();
             filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
index 36cacd7a..6da783c 100644
--- a/services/core/java/com/android/server/job/JobStore.java
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -72,6 +72,9 @@
  *      This is important b/c {@link com.android.server.job.JobStore.WriteJobsMapToDiskRunnable}
  *      and {@link com.android.server.job.JobStore.ReadJobMapFromDiskRunnable} lock on that
  *      object.
+ *
+ * Test:
+ * atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
  */
 public final class JobStore {
     private static final String TAG = "JobStore";
@@ -427,6 +430,9 @@
             out.attribute(null, "uid", Integer.toString(jobStatus.getUid()));
             out.attribute(null, "priority", String.valueOf(jobStatus.getPriority()));
             out.attribute(null, "flags", String.valueOf(jobStatus.getFlags()));
+            if (jobStatus.getInternalFlags() != 0) {
+                out.attribute(null, "internalFlags", String.valueOf(jobStatus.getInternalFlags()));
+            }
 
             out.attribute(null, "lastSuccessfulRunTime",
                     String.valueOf(jobStatus.getLastSuccessfulRunTime()));
@@ -689,6 +695,7 @@
             int uid, sourceUserId;
             long lastSuccessfulRunTime;
             long lastFailedRunTime;
+            int internalFlags = 0;
 
             // Read out job identifier attributes and priority.
             try {
@@ -704,6 +711,10 @@
                 if (val != null) {
                     jobBuilder.setFlags(Integer.parseInt(val));
                 }
+                val = parser.getAttributeValue(null, "internalFlags");
+                if (val != null) {
+                    internalFlags = Integer.parseInt(val);
+                }
                 val = parser.getAttributeValue(null, "sourceUserId");
                 sourceUserId = val == null ? -1 : Integer.parseInt(val);
 
@@ -718,7 +729,6 @@
             }
 
             String sourcePackageName = parser.getAttributeValue(null, "sourcePackageName");
-
             final String sourceTag = parser.getAttributeValue(null, "sourceTag");
 
             int eventType;
@@ -857,7 +867,7 @@
                     appBucket, currentHeartbeat, sourceTag,
                     elapsedRuntimes.first, elapsedRuntimes.second,
                     lastSuccessfulRunTime, lastFailedRunTime,
-                    (rtcIsGood) ? null : rtcRuntimes);
+                    (rtcIsGood) ? null : rtcRuntimes, internalFlags);
             return js;
         }
 
diff --git a/services/core/java/com/android/server/job/controllers/BackgroundJobsController.java b/services/core/java/com/android/server/job/controllers/BackgroundJobsController.java
index 1d053a5..2e4567a 100644
--- a/services/core/java/com/android/server/job/controllers/BackgroundJobsController.java
+++ b/services/core/java/com/android/server/job/controllers/BackgroundJobsController.java
@@ -197,7 +197,9 @@
         final int uid = jobStatus.getSourceUid();
         final String packageName = jobStatus.getSourcePackageName();
 
-        final boolean canRun = !mForceAppStandbyTracker.areJobsRestricted(uid, packageName);
+        final boolean canRun = !mForceAppStandbyTracker.areJobsRestricted(uid, packageName,
+                (jobStatus.getInternalFlags() & JobStatus.INTERNAL_FLAG_HAS_FOREGROUND_EXEMPTION)
+                        != 0);
 
         return jobStatus.setBackgroundNotRestrictedConstraintSatisfied(canRun);
     }
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index 0f5cb0a..d9a5ff6 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -46,6 +46,7 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.function.Predicate;
 
 /**
  * Uniquely identifies a job internally.
@@ -184,6 +185,21 @@
      */
     private int trackingControllers;
 
+    /**
+     * Flag for {@link #mInternalFlags}: this job was scheduled when the app that owns the job
+     * service (not necessarily the caller) was in the foreground and the job has no time
+     * constraints, which makes it exempted from the battery saver job restriction.
+     *
+     * @hide
+     */
+    public static final int INTERNAL_FLAG_HAS_FOREGROUND_EXEMPTION = 1 << 0;
+
+    /**
+     * Versatile, persistable flags for a job that's updated within the system server,
+     * as opposed to {@link JobInfo#flags} that's set by callers.
+     */
+    private int mInternalFlags;
+
     // These are filled in by controllers when preparing for execution.
     public ArraySet<Uri> changedUris;
     public ArraySet<String> changedAuthorities;
@@ -248,7 +264,7 @@
     private JobStatus(JobInfo job, int callingUid, int targetSdkVersion, String sourcePackageName,
             int sourceUserId, int standbyBucket, long heartbeat, String tag, int numFailures,
             long earliestRunTimeElapsedMillis, long latestRunTimeElapsedMillis,
-            long lastSuccessfulRunTime, long lastFailedRunTime) {
+            long lastSuccessfulRunTime, long lastFailedRunTime, int internalFlags) {
         this.job = job;
         this.callingUid = callingUid;
         this.targetSdkVersion = targetSdkVersion;
@@ -304,6 +320,8 @@
         mLastSuccessfulRunTime = lastSuccessfulRunTime;
         mLastFailedRunTime = lastFailedRunTime;
 
+        mInternalFlags = internalFlags;
+
         updateEstimatedNetworkBytesLocked();
     }
 
@@ -315,7 +333,8 @@
                 jobStatus.getStandbyBucket(), jobStatus.getBaseHeartbeat(),
                 jobStatus.getSourceTag(), jobStatus.getNumFailures(),
                 jobStatus.getEarliestRunTime(), jobStatus.getLatestRunTimeElapsed(),
-                jobStatus.getLastSuccessfulRunTime(), jobStatus.getLastFailedRunTime());
+                jobStatus.getLastSuccessfulRunTime(), jobStatus.getLastFailedRunTime(),
+                jobStatus.getInternalFlags());
         mPersistedUtcTimes = jobStatus.mPersistedUtcTimes;
         if (jobStatus.mPersistedUtcTimes != null) {
             if (DEBUG) {
@@ -336,12 +355,13 @@
             int standbyBucket, long baseHeartbeat, String sourceTag,
             long earliestRunTimeElapsedMillis, long latestRunTimeElapsedMillis,
             long lastSuccessfulRunTime, long lastFailedRunTime,
-            Pair<Long, Long> persistedExecutionTimesUTC) {
+            Pair<Long, Long> persistedExecutionTimesUTC,
+            int innerFlags) {
         this(job, callingUid, resolveTargetSdkVersion(job), sourcePkgName, sourceUserId,
                 standbyBucket, baseHeartbeat,
                 sourceTag, 0,
                 earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis,
-                lastSuccessfulRunTime, lastFailedRunTime);
+                lastSuccessfulRunTime, lastFailedRunTime, innerFlags);
 
         // Only during initial inflation do we record the UTC-timebase execution bounds
         // read from the persistent store.  If we ever have to recreate the JobStatus on
@@ -365,7 +385,7 @@
                 rescheduling.getStandbyBucket(), newBaseHeartbeat,
                 rescheduling.getSourceTag(), backoffAttempt, newEarliestRuntimeElapsedMillis,
                 newLatestRuntimeElapsedMillis,
-                lastSuccessfulRunTime, lastFailedRunTime);
+                lastSuccessfulRunTime, lastFailedRunTime, rescheduling.getInternalFlags());
     }
 
     /**
@@ -395,10 +415,12 @@
                 sourceUserId, elapsedNow);
         JobSchedulerInternal js = LocalServices.getService(JobSchedulerInternal.class);
         long currentHeartbeat = js != null ? js.currentHeartbeat() : 0;
+
         return new JobStatus(job, callingUid, resolveTargetSdkVersion(job), sourcePkg, sourceUserId,
                 standbyBucket, currentHeartbeat, tag, 0,
                 earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis,
-                0 /* lastSuccessfulRunTime */, 0 /* lastFailedRunTime */);
+                0 /* lastSuccessfulRunTime */, 0 /* lastFailedRunTime */,
+                /*innerFlags=*/ 0);
     }
 
     public void enqueueWorkLocked(IActivityManager am, JobWorkItem work) {
@@ -623,6 +645,28 @@
         return job.getFlags();
     }
 
+    public int getInternalFlags() {
+        return mInternalFlags;
+    }
+
+    public void addInternalFlags(int flags) {
+        mInternalFlags |= flags;
+    }
+
+    public void maybeAddForegroundExemption(Predicate<Integer> uidForegroundChecker) {
+        // Jobs with time constraints shouldn't be exempted.
+        if (job.hasEarlyConstraint() || job.hasLateConstraint()) {
+            return;
+        }
+        // Already exempted, skip the foreground check.
+        if ((mInternalFlags & INTERNAL_FLAG_HAS_FOREGROUND_EXEMPTION) != 0) {
+            return;
+        }
+        if (uidForegroundChecker.test(getSourceUid())) {
+            addInternalFlags(INTERNAL_FLAG_HAS_FOREGROUND_EXEMPTION);
+        }
+    }
+
     private void updateEstimatedNetworkBytesLocked() {
         totalNetworkBytes = computeEstimatedNetworkBytesLocked();
     }
@@ -1054,6 +1098,14 @@
         if ((constraints&CONSTRAINT_DEVICE_NOT_DOZING) != 0) {
             pw.print(" DEVICE_NOT_DOZING");
         }
+        if ((constraints&CONSTRAINT_BACKGROUND_NOT_RESTRICTED) != 0) {
+            pw.print(" BACKGROUND_NOT_RESTRICTED");
+        }
+        if (constraints != 0) {
+            pw.print(" [0x");
+            pw.print(Integer.toHexString(constraints));
+            pw.print("]");
+        }
     }
 
     /** Writes constraints to the given repeating proto field. */
@@ -1162,6 +1214,15 @@
                 pw.print(prefix); pw.print("  Flags: ");
                 pw.println(Integer.toHexString(job.getFlags()));
             }
+            if (getInternalFlags() != 0) {
+                pw.print(prefix); pw.print("  Internal flags: ");
+                pw.print(Integer.toHexString(getInternalFlags()));
+
+                if ((getInternalFlags()&INTERNAL_FLAG_HAS_FOREGROUND_EXEMPTION) != 0) {
+                    pw.print(" HAS_FOREGROUND_EXEMPTION");
+                }
+                pw.println();
+            }
             pw.print(prefix); pw.print("  Requires: charging=");
             pw.print(job.isRequireCharging()); pw.print(" batteryNotLow=");
             pw.print(job.isRequireBatteryNotLow()); pw.print(" deviceIdle=");
@@ -1317,6 +1378,7 @@
         proto.write(JobStatusDumpProto.SOURCE_UID, getSourceUid());
         proto.write(JobStatusDumpProto.SOURCE_USER_ID, getSourceUserId());
         proto.write(JobStatusDumpProto.SOURCE_PACKAGE_NAME, getSourcePackageName());
+        proto.write(JobStatusDumpProto.INTERNAL_FLAGS, getInternalFlags());
 
         if (full) {
             final long jiToken = proto.start(JobStatusDumpProto.JOB_INFO);
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index eb12e1c..31c20cb 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -78,10 +78,10 @@
 import android.security.keystore.AndroidKeyStoreProvider;
 import android.security.keystore.KeyProperties;
 import android.security.keystore.KeyProtection;
-import android.security.keystore.KeychainProtectionParams;
 import android.security.keystore.UserNotAuthenticatedException;
-import android.security.keystore.WrappedApplicationKey;
-import android.security.keystore.KeychainSnapshot;
+import android.security.keystore.recovery.KeyChainProtectionParams;
+import android.security.keystore.recovery.WrappedApplicationKey;
+import android.security.keystore.recovery.KeyChainSnapshot;
 import android.service.gatekeeper.GateKeeperResponse;
 import android.service.gatekeeper.IGateKeeperService;
 import android.text.TextUtils;
@@ -1598,8 +1598,10 @@
                 userId, progressCallback);
         // The user employs synthetic password based credential.
         if (response != null) {
-            mRecoverableKeyStoreManager.lockScreenSecretAvailable(credentialType, credential,
-                    userId);
+            if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
+                mRecoverableKeyStoreManager.lockScreenSecretAvailable(credentialType, credential,
+                        userId);
+            }
             return response;
         }
 
@@ -1980,7 +1982,7 @@
     }
 
     @Override
-    public KeychainSnapshot getRecoveryData(@NonNull byte[] account) throws RemoteException {
+    public KeyChainSnapshot getRecoveryData(@NonNull byte[] account) throws RemoteException {
         return mRecoverableKeyStoreManager.getRecoveryData(account);
     }
 
@@ -2009,7 +2011,7 @@
     }
 
     @Override
-    public void setRecoverySecretTypes(@NonNull @KeychainProtectionParams.UserSecretType
+    public void setRecoverySecretTypes(@NonNull @KeyChainProtectionParams.UserSecretType
             int[] secretTypes) throws RemoteException {
         mRecoverableKeyStoreManager.setRecoverySecretTypes(secretTypes);
     }
@@ -2026,7 +2028,7 @@
     }
 
     @Override
-    public void recoverySecretAvailable(@NonNull KeychainProtectionParams recoverySecret)
+    public void recoverySecretAvailable(@NonNull KeyChainProtectionParams recoverySecret)
             throws RemoteException {
         mRecoverableKeyStoreManager.recoverySecretAvailable(recoverySecret);
     }
@@ -2034,7 +2036,7 @@
     @Override
     public byte[] startRecoverySession(@NonNull String sessionId,
             @NonNull byte[] verifierPublicKey, @NonNull byte[] vaultParams,
-            @NonNull byte[] vaultChallenge, @NonNull List<KeychainProtectionParams> secrets)
+            @NonNull byte[] vaultChallenge, @NonNull List<KeyChainProtectionParams> secrets)
             throws RemoteException {
         return mRecoverableKeyStoreManager.startRecoverySession(sessionId, verifierPublicKey,
                 vaultParams, vaultChallenge, secrets);
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
index 452c9ee..e1e769c 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
@@ -16,14 +16,14 @@
 
 package com.android.server.locksettings.recoverablekeystore;
 
-import static android.security.keystore.KeychainProtectionParams.TYPE_LOCKSCREEN;
+import static android.security.keystore.recovery.KeyChainProtectionParams.TYPE_LOCKSCREEN;
 
 import android.annotation.Nullable;
 import android.content.Context;
-import android.security.keystore.KeyDerivationParams;
-import android.security.keystore.KeychainProtectionParams;
-import android.security.keystore.KeychainSnapshot;
-import android.security.keystore.WrappedApplicationKey;
+import android.security.keystore.recovery.KeyDerivationParams;
+import android.security.keystore.recovery.KeyChainProtectionParams;
+import android.security.keystore.recovery.KeyChainSnapshot;
+import android.security.keystore.recovery.WrappedApplicationKey;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -255,12 +255,12 @@
         }
         // TODO: store raw data in RecoveryServiceMetadataEntry and generate Parcelables later
         // TODO: use Builder.
-        KeychainProtectionParams metadata = new KeychainProtectionParams(
+        KeyChainProtectionParams metadata = new KeyChainProtectionParams(
                 /*userSecretType=*/ TYPE_LOCKSCREEN,
                 /*lockScreenUiFormat=*/ getUiFormat(mCredentialType, mCredential),
                 /*keyDerivationParams=*/ KeyDerivationParams.createSha256Params(salt),
                 /*secret=*/ new byte[0]);
-        ArrayList<KeychainProtectionParams> metadataList = new ArrayList<>();
+        ArrayList<KeyChainProtectionParams> metadataList = new ArrayList<>();
         metadataList.add(metadata);
 
         int snapshotVersion = incrementSnapshotVersion(recoveryAgentUid);
@@ -268,13 +268,13 @@
         // If application keys are not updated, snapshot will not be created on next unlock.
         mRecoverableKeyStoreDb.setShouldCreateSnapshot(mUserId, recoveryAgentUid, false);
 
-        mRecoverySnapshotStorage.put(recoveryAgentUid, new KeychainSnapshot.Builder()
+        mRecoverySnapshotStorage.put(recoveryAgentUid, new KeyChainSnapshot.Builder()
                 .setSnapshotVersion(snapshotVersion)
                 .setMaxAttempts(TRUSTED_HARDWARE_MAX_ATTEMPTS)
                 .setCounterId(counterId)
                 .setTrustedHardwarePublicKey(SecureBox.encodePublicKey(publicKey))
                 .setServerParams(vaultHandle)
-                .setKeychainProtectionParams(metadataList)
+                .setKeyChainProtectionParams(metadataList)
                 .setWrappedApplicationKeys(createApplicationKeyEntries(encryptedApplicationKeys))
                 .setEncryptedRecoveryKeyBlob(encryptedRecoveryKey)
                 .build());
@@ -317,7 +317,7 @@
      */
     private boolean shoudCreateSnapshot(int recoveryAgentUid) {
         int[] types = mRecoverableKeyStoreDb.getRecoverySecretTypes(mUserId, recoveryAgentUid);
-        if (!ArrayUtils.contains(types, KeychainProtectionParams.TYPE_LOCKSCREEN)) {
+        if (!ArrayUtils.contains(types, KeyChainProtectionParams.TYPE_LOCKSCREEN)) {
             // Only lockscreen type is supported.
             // We will need to pass extra argument to KeySyncTask to support custom pass phrase.
             return false;
@@ -340,14 +340,14 @@
      * @return The format - either pattern, pin, or password.
      */
     @VisibleForTesting
-    @KeychainProtectionParams.LockScreenUiFormat static int getUiFormat(
+    @KeyChainProtectionParams.LockScreenUiFormat static int getUiFormat(
             int credentialType, String credential) {
         if (credentialType == LockPatternUtils.CREDENTIAL_TYPE_PATTERN) {
-            return KeychainProtectionParams.TYPE_PATTERN;
+            return KeyChainProtectionParams.UI_FORMAT_PATTERN;
         } else if (isPin(credential)) {
-            return KeychainProtectionParams.TYPE_PIN;
+            return KeyChainProtectionParams.UI_FORMAT_PIN;
         } else {
-            return KeychainProtectionParams.TYPE_PASSWORD;
+            return KeyChainProtectionParams.UI_FORMAT_PASSWORD;
         }
     }
 
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
index 76508d5..b6c3c66 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
@@ -33,10 +33,10 @@
 import android.os.ServiceSpecificException;
 import android.os.UserHandle;
 
-import android.security.keystore.KeychainProtectionParams;
-import android.security.keystore.KeychainSnapshot;
-import android.security.keystore.RecoveryController;
-import android.security.keystore.WrappedApplicationKey;
+import android.security.keystore.recovery.KeyChainProtectionParams;
+import android.security.keystore.recovery.KeyChainSnapshot;
+import android.security.keystore.recovery.RecoveryController;
+import android.security.keystore.recovery.WrappedApplicationKey;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -170,11 +170,11 @@
      * @hide
      */
     public @NonNull
-    KeychainSnapshot getRecoveryData(@NonNull byte[] account)
+    KeyChainSnapshot getRecoveryData(@NonNull byte[] account)
             throws RemoteException {
         checkRecoverKeyStorePermission();
         int uid = Binder.getCallingUid();
-        KeychainSnapshot snapshot = mSnapshotStorage.get(uid);
+        KeyChainSnapshot snapshot = mSnapshotStorage.get(uid);
         if (snapshot == null) {
             throw new ServiceSpecificException(ERROR_NO_SNAPSHOT_PENDING);
         }
@@ -256,7 +256,7 @@
      * @hide
      */
     public void setRecoverySecretTypes(
-            @NonNull @KeychainProtectionParams.UserSecretType int[] secretTypes)
+            @NonNull @KeyChainProtectionParams.UserSecretType int[] secretTypes)
             throws RemoteException {
         checkRecoverKeyStorePermission();
         int userId = UserHandle.getCallingUserId();
@@ -291,9 +291,9 @@
     }
 
     public void recoverySecretAvailable(
-            @NonNull KeychainProtectionParams recoverySecret) throws RemoteException {
+            @NonNull KeyChainProtectionParams recoverySecret) throws RemoteException {
         int uid = Binder.getCallingUid();
-        if (recoverySecret.getLockScreenUiFormat() == KeychainProtectionParams.TYPE_LOCKSCREEN) {
+        if (recoverySecret.getLockScreenUiFormat() == KeyChainProtectionParams.TYPE_LOCKSCREEN) {
             throw new SecurityException(
                     "Caller " + uid + " is not allowed to set lock screen secret");
         }
@@ -319,14 +319,14 @@
             @NonNull byte[] verifierPublicKey,
             @NonNull byte[] vaultParams,
             @NonNull byte[] vaultChallenge,
-            @NonNull List<KeychainProtectionParams> secrets)
+            @NonNull List<KeyChainProtectionParams> secrets)
             throws RemoteException {
         checkRecoverKeyStorePermission();
         int uid = Binder.getCallingUid();
 
         if (secrets.size() != 1) {
             throw new UnsupportedOperationException(
-                    "Only a single KeychainProtectionParams is supported");
+                    "Only a single KeyChainProtectionParams is supported");
         }
 
         PublicKey publicKey;
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java
index 2b1416e..f2e71b3 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java
@@ -404,7 +404,7 @@
     /**
      * Updates the list of user secret types used for end-to-end encryption.
      * If no secret types are set, recovery snapshot will not be created.
-     * See {@code KeychainProtectionParams}
+     * See {@code KeyChainProtectionParams}
      *
      * @param userId The userId of the profile the application is running under.
      * @param uid The uid of the application.
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorage.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorage.java
index 62bb41e..3f93cc6 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorage.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorage.java
@@ -17,7 +17,7 @@
 package com.android.server.locksettings.recoverablekeystore.storage;
 
 import android.annotation.Nullable;
-import android.security.keystore.KeychainSnapshot;
+import android.security.keystore.recovery.KeyChainSnapshot;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
@@ -34,12 +34,12 @@
  */
 public class RecoverySnapshotStorage {
     @GuardedBy("this")
-    private final SparseArray<KeychainSnapshot> mSnapshotByUid = new SparseArray<>();
+    private final SparseArray<KeyChainSnapshot> mSnapshotByUid = new SparseArray<>();
 
     /**
      * Sets the latest {@code snapshot} for the recovery agent {@code uid}.
      */
-    public synchronized void put(int uid, KeychainSnapshot snapshot) {
+    public synchronized void put(int uid, KeyChainSnapshot snapshot) {
         mSnapshotByUid.put(uid, snapshot);
     }
 
@@ -47,7 +47,7 @@
      * Returns the latest snapshot for the recovery agent {@code uid}, or null if none exists.
      */
     @Nullable
-    public synchronized KeychainSnapshot get(int uid) {
+    public synchronized KeyChainSnapshot get(int uid) {
         return mSnapshotByUid.get(uid);
     }
 
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 6812778..c9c7d04 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -38,6 +38,7 @@
 import android.media.IAudioService;
 import android.media.IMediaSession2;
 import android.media.IRemoteVolumeController;
+import android.media.MediaLibraryService2;
 import android.media.MediaSessionService2;
 import android.media.SessionToken;
 import android.media.session.IActiveSessionsListener;
@@ -445,9 +446,18 @@
         }
 
         // TODO(jaewan): Query per users.
-        List<ResolveInfo> services = getContext().getPackageManager().queryIntentServices(
-                new Intent(MediaSessionService2.SERVICE_INTERFACE),
-                PackageManager.GET_META_DATA);
+        List<ResolveInfo> services = new ArrayList<>();
+        // If multiple actions are declared for a service, browser gets higher priority.
+        List<ResolveInfo> libraryServices = getContext().getPackageManager().queryIntentServices(
+                new Intent(MediaLibraryService2.SERVICE_INTERFACE), PackageManager.GET_META_DATA);
+        if (libraryServices != null) {
+            services.addAll(libraryServices);
+        }
+        List<ResolveInfo> sessionServices = getContext().getPackageManager().queryIntentServices(
+                new Intent(MediaSessionService2.SERVICE_INTERFACE), PackageManager.GET_META_DATA);
+        if (sessionServices != null) {
+            services.addAll(sessionServices);
+        }
         synchronized (mLock) {
             mSessions.clear();
             if (services == null) {
@@ -470,10 +480,11 @@
                             + " the same ID=" + id + ". Ignoring "
                             + serviceInfo.packageName + "/" + serviceInfo.name);
                 } else {
+                    int type = (libraryServices.contains(services.get(i)))
+                            ? SessionToken.TYPE_LIBRARY_SERVICE : SessionToken.TYPE_SESSION_SERVICE;
                     MediaSessionService2Record record =
                             new MediaSessionService2Record(getContext(), mSessionDestroyedListener,
-                                    SessionToken.TYPE_SESSION_SERVICE,
-                                    serviceInfo.packageName, serviceInfo.name, id);
+                                    type, serviceInfo.packageName, serviceInfo.name, id);
                     mSessions.add(record);
                 }
             }
diff --git a/services/core/java/com/android/server/net/NetworkPolicyLogger.java b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
index 2bd9cab..b4bc7f5 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyLogger.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
@@ -37,6 +37,7 @@
 import java.text.SimpleDateFormat;
 import java.util.Arrays;
 import java.util.Date;
+import java.util.Set;
 
 public class NetworkPolicyLogger {
     static final String TAG = "NetworkPolicy";
@@ -62,6 +63,7 @@
     private static final int EVENT_TEMP_POWER_SAVE_WL_CHANGED = 10;
     private static final int EVENT_UID_FIREWALL_RULE_CHANGED = 11;
     private static final int EVENT_FIREWALL_CHAIN_ENABLED = 12;
+    private static final int EVENT_UPDATE_METERED_RESTRICTED_PKGS = 13;
 
     static final int NTWK_BLOCKED_POWER = 0;
     static final int NTWK_ALLOWED_NON_METERED = 1;
@@ -179,6 +181,14 @@
         }
     }
 
+    void meteredRestrictedPkgsChanged(Set<Integer> restrictedUids) {
+        synchronized (mLock) {
+            final String log = "Metered restricted uids: " + restrictedUids;
+            if (LOGD) Slog.d(TAG, log);
+            mEventsBuffer.event(log);
+        }
+    }
+
     void dumpLogs(IndentingPrintWriter pw) {
         synchronized (mLock) {
             pw.println();
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
index 971ac8b..6490964 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
@@ -19,6 +19,8 @@
 import android.net.Network;
 import android.telephony.SubscriptionPlan;
 
+import java.util.Set;
+
 /**
  * Network Policy Manager local system service interface.
  *
@@ -71,4 +73,21 @@
      * Informs that admin data is loaded and available.
      */
     public abstract void onAdminDataAvailable();
+
+    /**
+     * Sets a list of packages which are restricted by admin from accessing metered data.
+     *
+     * @param packageNames the list of restricted packages.
+     * @param userId the userId in which {@param packagesNames} are restricted.
+     */
+    public abstract void setMeteredRestrictedPackages(
+            Set<String> packageNames, int userId);
+
+
+    /**
+     * Similar to {@link #setMeteredRestrictedPackages(Set, int)} but updates the restricted
+     * packages list asynchronously.
+     */
+    public abstract void setMeteredRestrictedPackagesAsync(
+            Set<String> packageNames, int userId);
 }
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index e406d51..0e54768 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -232,6 +232,7 @@
 import java.util.Calendar;
 import java.util.List;
 import java.util.Objects;
+import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -349,6 +350,7 @@
     private static final int MSG_POLICIES_CHANGED = 13;
     private static final int MSG_RESET_FIREWALL_RULES_BY_UID = 15;
     private static final int MSG_SUBSCRIPTION_OVERRIDE = 16;
+    private static final int MSG_METERED_RESTRICTED_PACKAGES_CHANGED = 17;
 
     private static final int UID_MSG_STATE_CHANGED = 100;
     private static final int UID_MSG_GONE = 101;
@@ -480,6 +482,13 @@
     @GuardedBy("mNetworkPoliciesSecondLock")
     private final SparseIntArray mNetIdToSubId = new SparseIntArray();
 
+    /**
+     * Indicates the uids restricted by admin from accessing metered data. It's a mapping from
+     * userId to restricted uids which belong to that user.
+     */
+    @GuardedBy("mUidRulesFirstLock")
+    private final SparseArray<Set<Integer>> mMeteredRestrictedUids = new SparseArray<>();
+
     private final RemoteCallbackList<INetworkPolicyListener>
             mListeners = new RemoteCallbackList<>();
 
@@ -898,6 +907,9 @@
                         // Remove any persistable state for the given user; both cleaning up after a
                         // USER_REMOVED, and one last sanity check during USER_ADDED
                         removeUserStateUL(userId, true);
+                        // Removing outside removeUserStateUL since that can also be called when
+                        // user resets app preferences.
+                        mMeteredRestrictedUids.remove(userId);
                         if (action == ACTION_USER_ADDED) {
                             // Add apps that are whitelisted by default.
                             addDefaultRestrictBackgroundWhitelistUidsUL(userId);
@@ -3137,6 +3149,15 @@
                 }
                 fout.decreaseIndent();
 
+                fout.println("Admin restricted uids for metered data:");
+                fout.increaseIndent();
+                size = mMeteredRestrictedUids.size();
+                for (int i = 0; i < size; ++i) {
+                    fout.print("u" + mMeteredRestrictedUids.keyAt(i) + ": ");
+                    fout.println(mMeteredRestrictedUids.valueAt(i));
+                }
+                fout.decreaseIndent();
+
                 mLogger.dumpLogs(fout);
             }
         }
@@ -3705,6 +3726,7 @@
         final int uidPolicy = mUidPolicy.get(uid, POLICY_NONE);
         final int oldUidRules = mUidRules.get(uid, RULE_NONE);
         final boolean isForeground = isUidForegroundOnRestrictBackgroundUL(uid);
+        final boolean isRestrictedByAdmin = isRestrictedByAdminUL(uid);
 
         final boolean isBlacklisted = (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
         final boolean isWhitelisted = (uidPolicy & POLICY_ALLOW_METERED_BACKGROUND) != 0;
@@ -3712,7 +3734,9 @@
         int newRule = RULE_NONE;
 
         // First step: define the new rule based on user restrictions and foreground state.
-        if (isForeground) {
+        if (isRestrictedByAdmin) {
+            newRule = RULE_REJECT_METERED;
+        } else if (isForeground) {
             if (isBlacklisted || (mRestrictBackground && !isWhitelisted)) {
                 newRule = RULE_TEMPORARY_ALLOW_METERED;
             } else if (isWhitelisted) {
@@ -3732,6 +3756,7 @@
                     + ": isForeground=" +isForeground
                     + ", isBlacklisted=" + isBlacklisted
                     + ", isWhitelisted=" + isWhitelisted
+                    + ", isRestrictedByAdmin=" + isRestrictedByAdmin
                     + ", oldRule=" + uidRulesToString(oldRule)
                     + ", newRule=" + uidRulesToString(newRule)
                     + ", newUidRules=" + uidRulesToString(newUidRules)
@@ -3767,13 +3792,13 @@
                 if (!isWhitelisted) {
                     setMeteredNetworkWhitelist(uid, false);
                 }
-                if (isBlacklisted) {
+                if (isBlacklisted || isRestrictedByAdmin) {
                     setMeteredNetworkBlacklist(uid, true);
                 }
             } else if (hasRule(newRule, RULE_REJECT_METERED)
                     || hasRule(oldRule, RULE_REJECT_METERED)) {
                 // Flip state because app was explicitly added or removed to blacklist.
-                setMeteredNetworkBlacklist(uid, isBlacklisted);
+                setMeteredNetworkBlacklist(uid, (isBlacklisted || isRestrictedByAdmin));
                 if (hasRule(oldRule, RULE_REJECT_METERED) && isWhitelisted) {
                     // Since blacklist prevails over whitelist, we need to handle the special case
                     // where app is whitelisted and blacklisted at the same time (although such
@@ -3790,6 +3815,7 @@
                         + ": foreground=" + isForeground
                         + ", whitelisted=" + isWhitelisted
                         + ", blacklisted=" + isBlacklisted
+                        + ", isRestrictedByAdmin=" + isRestrictedByAdmin
                         + ", newRule=" + uidRulesToString(newUidRules)
                         + ", oldRule=" + uidRulesToString(oldUidRules));
             }
@@ -4102,6 +4128,12 @@
                     mListeners.finishBroadcast();
                     return true;
                 }
+                case MSG_METERED_RESTRICTED_PACKAGES_CHANGED: {
+                    final int userId = msg.arg1;
+                    final Set<String> packageNames = (Set<String>) msg.obj;
+                    setMeteredRestrictedPackagesInternal(packageNames, userId);
+                    return true;
+                }
                 default: {
                     return false;
                 }
@@ -4605,6 +4637,42 @@
         public void onAdminDataAvailable() {
             mAdminDataAvailableLatch.countDown();
         }
+
+        @Override
+        public void setMeteredRestrictedPackages(Set<String> packageNames, int userId) {
+            setMeteredRestrictedPackagesInternal(packageNames, userId);
+        }
+
+        @Override
+        public void setMeteredRestrictedPackagesAsync(Set<String> packageNames, int userId) {
+            mHandler.obtainMessage(MSG_METERED_RESTRICTED_PACKAGES_CHANGED,
+                    userId, 0, packageNames).sendToTarget();
+        }
+    }
+
+    private void setMeteredRestrictedPackagesInternal(Set<String> packageNames, int userId) {
+        synchronized (mUidRulesFirstLock) {
+            final Set<Integer> newRestrictedUids = new ArraySet<>();
+            for (String packageName : packageNames) {
+                final int uid = getUidForPackage(packageName, userId);
+                if (uid >= 0) {
+                    newRestrictedUids.add(uid);
+                }
+            }
+            final Set<Integer> oldRestrictedUids = mMeteredRestrictedUids.get(userId);
+            mMeteredRestrictedUids.put(userId, newRestrictedUids);
+            handleRestrictedPackagesChangeUL(oldRestrictedUids, newRestrictedUids);
+            mLogger.meteredRestrictedPkgsChanged(newRestrictedUids);
+        }
+    }
+
+    private int getUidForPackage(String packageName, int userId) {
+        try {
+            return mContext.getPackageManager().getPackageUidAsUser(packageName,
+                    PackageManager.MATCH_KNOWN_PACKAGES, userId);
+        } catch (NameNotFoundException e) {
+            return -1;
+        }
     }
 
     private int parseSubId(NetworkState state) {
@@ -4642,6 +4710,32 @@
         }
     }
 
+    private void handleRestrictedPackagesChangeUL(Set<Integer> oldRestrictedUids,
+            Set<Integer> newRestrictedUids) {
+        if (oldRestrictedUids == null) {
+            for (int uid : newRestrictedUids) {
+                updateRulesForDataUsageRestrictionsUL(uid);
+            }
+            return;
+        }
+        for (int uid : oldRestrictedUids) {
+            if (!newRestrictedUids.contains(uid)) {
+                updateRulesForDataUsageRestrictionsUL(uid);
+            }
+        }
+        for (int uid : newRestrictedUids) {
+            if (!oldRestrictedUids.contains(uid)) {
+                updateRulesForDataUsageRestrictionsUL(uid);
+            }
+        }
+    }
+
+    private boolean isRestrictedByAdminUL(int uid) {
+        final Set<Integer> restrictedUids = mMeteredRestrictedUids.get(
+                UserHandle.getUserId(uid));
+        return restrictedUids != null && restrictedUids.contains(uid);
+    }
+
     private static boolean hasRule(int uidRules, int rule) {
         return (uidRules & rule) != 0;
     }
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 78fd4b4..bfc150e 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -887,17 +887,21 @@
 
     @Override
     public long getUidStats(int uid, int type) {
-        return nativeGetUidStat(uid, type);
+        return nativeGetUidStat(uid, type, checkBpfStatsEnable());
     }
 
     @Override
     public long getIfaceStats(String iface, int type) {
-        return nativeGetIfaceStat(iface, type);
+        return nativeGetIfaceStat(iface, type, checkBpfStatsEnable());
     }
 
     @Override
     public long getTotalStats(int type) {
-        return nativeGetTotalStat(type);
+        return nativeGetTotalStat(type, checkBpfStatsEnable());
+    }
+
+    private boolean checkBpfStatsEnable() {
+        return new File("/sys/fs/bpf/traffic_uid_stats_map").exists();
     }
 
     /**
@@ -1668,7 +1672,7 @@
     private static int TYPE_TCP_RX_PACKETS;
     private static int TYPE_TCP_TX_PACKETS;
 
-    private static native long nativeGetTotalStat(int type);
-    private static native long nativeGetIfaceStat(String iface, int type);
-    private static native long nativeGetUidStat(int uid, int type);
+    private static native long nativeGetTotalStat(int type, boolean useBpfStats);
+    private static native long nativeGetIfaceStat(String iface, int type, boolean useBpfStats);
+    private static native long nativeGetUidStat(int uid, int type, boolean useBpfStats);
 }
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 42093e8..502760a 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -254,13 +254,11 @@
 
         for (ComponentName cmpt : mEnabledServicesForCurrentProfiles) {
             if (filter != null && !filter.matches(cmpt)) continue;
-
             cmpt.writeToProto(proto, ManagedServicesProto.ENABLED);
         }
 
         for (ManagedServiceInfo info : mServices) {
             if (filter != null && !filter.matches(info.component)) continue;
-
             info.writeToProto(proto, ManagedServicesProto.LIVE_SERVICES, this);
         }
 
@@ -1145,13 +1143,11 @@
 
         public void writeToProto(ProtoOutputStream proto, long fieldId, ManagedServices host) {
             final long token = proto.start(fieldId);
-
             component.writeToProto(proto, ManagedServiceInfoProto.COMPONENT);
             proto.write(ManagedServiceInfoProto.USER_ID, userid);
             proto.write(ManagedServiceInfoProto.SERVICE, service.getClass().getName());
             proto.write(ManagedServiceInfoProto.IS_SYSTEM, isSystem);
             proto.write(ManagedServiceInfoProto.IS_GUEST, isGuest(host));
-
             proto.end(token);
         }
 
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 39b7c7c..efe54fa 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -3382,36 +3382,28 @@
     private void dumpProto(FileDescriptor fd, @NonNull DumpFilter filter) {
         final ProtoOutputStream proto = new ProtoOutputStream(fd);
         synchronized (mNotificationLock) {
-            long records = proto.start(NotificationServiceDumpProto.RECORDS);
             int N = mNotificationList.size();
-            if (N > 0) {
-                for (int i = 0; i < N; i++) {
-                    final NotificationRecord nr = mNotificationList.get(i);
-                    if (filter.filtered && !filter.matches(nr.sbn)) continue;
-                    nr.dump(proto, filter.redact);
-                    proto.write(NotificationRecordProto.STATE, NotificationRecordProto.POSTED);
-                }
+            for (int i = 0; i < N; i++) {
+                final NotificationRecord nr = mNotificationList.get(i);
+                if (filter.filtered && !filter.matches(nr.sbn)) continue;
+                nr.dump(proto, NotificationServiceDumpProto.RECORDS, filter.redact,
+                        NotificationRecordProto.POSTED);
             }
             N = mEnqueuedNotifications.size();
-            if (N > 0) {
-                for (int i = 0; i < N; i++) {
-                    final NotificationRecord nr = mEnqueuedNotifications.get(i);
-                    if (filter.filtered && !filter.matches(nr.sbn)) continue;
-                    nr.dump(proto, filter.redact);
-                    proto.write(NotificationRecordProto.STATE, NotificationRecordProto.ENQUEUED);
-                }
+            for (int i = 0; i < N; i++) {
+                final NotificationRecord nr = mEnqueuedNotifications.get(i);
+                if (filter.filtered && !filter.matches(nr.sbn)) continue;
+                nr.dump(proto, NotificationServiceDumpProto.RECORDS, filter.redact,
+                        NotificationRecordProto.ENQUEUED);
             }
             List<NotificationRecord> snoozed = mSnoozeHelper.getSnoozed();
             N = snoozed.size();
-            if (N > 0) {
-                for (int i = 0; i < N; i++) {
-                    final NotificationRecord nr = snoozed.get(i);
-                    if (filter.filtered && !filter.matches(nr.sbn)) continue;
-                    nr.dump(proto, filter.redact);
-                    proto.write(NotificationRecordProto.STATE, NotificationRecordProto.SNOOZED);
-                }
+            for (int i = 0; i < N; i++) {
+                final NotificationRecord nr = snoozed.get(i);
+                if (filter.filtered && !filter.matches(nr.sbn)) continue;
+                nr.dump(proto, NotificationServiceDumpProto.RECORDS, filter.redact,
+                        NotificationRecordProto.SNOOZED);
             }
-            proto.end(records);
 
             long zenLog = proto.start(NotificationServiceDumpProto.ZEN);
             mZenModeHelper.dump(proto);
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index faa300f2..23b9743 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -361,8 +361,11 @@
     /** @deprecated Use {@link #getUser()} instead. */
     public int getUserId() { return sbn.getUserId(); }
 
-    void dump(ProtoOutputStream proto, boolean redact) {
+    void dump(ProtoOutputStream proto, long fieldId, boolean redact, int state) {
+        final long token = proto.start(fieldId);
+
         proto.write(NotificationRecordProto.KEY, sbn.getKey());
+        proto.write(NotificationRecordProto.STATE, state);
         if (getChannel() != null) {
             proto.write(NotificationRecordProto.CHANNEL_ID, getChannel().getId());
         }
@@ -375,8 +378,10 @@
             proto.write(NotificationRecordProto.SOUND, getSound().toString());
         }
         if (getAudioAttributes() != null) {
-            proto.write(NotificationRecordProto.SOUND_USAGE, getAudioAttributes().getUsage());
+            getAudioAttributes().writeToProto(proto, NotificationRecordProto.AUDIO_ATTRIBUTES);
         }
+
+        proto.end(token);
     }
 
     String formatRemoteViews(RemoteViews rv) {
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index c0dccb5..b0e3820 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -973,16 +973,11 @@
                 proto.write(RecordProto.VISIBILITY, r.visibility);
                 proto.write(RecordProto.SHOW_BADGE, r.showBadge);
 
-                long token;
                 for (NotificationChannel channel : r.channels.values()) {
-                    token = proto.start(RecordProto.CHANNELS);
-                    channel.toProto(proto);
-                    proto.end(token);
+                    channel.writeToProto(proto, RecordProto.CHANNELS);
                 }
                 for (NotificationChannelGroup group : r.groups.values()) {
-                    token = proto.start(RecordProto.CHANNEL_GROUPS);
-                    group.toProto(proto);
-                    proto.end(token);
+                    group.writeToProto(proto, RecordProto.CHANNEL_GROUPS);
                 }
 
                 proto.end(fToken);
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 8f672b5..932e4f9 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -565,7 +565,7 @@
                     proto.write(ZenModeProto.ENABLED_ACTIVE_CONDITIONS, rule.toString());
                 }
             }
-            mConfig.toNotificationPolicy().toProto(proto, ZenModeProto.POLICY);
+            mConfig.toNotificationPolicy().writeToProto(proto, ZenModeProto.POLICY);
             proto.write(ZenModeProto.SUPPRESSED_EFFECTS, mSuppressedEffects);
         }
     }
diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
index 253d4f5..321af43 100644
--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
@@ -169,8 +169,9 @@
         }
 
         final PackageInfo targetPackage = mPackageManager.getPackageInfo(packageName, userId);
-        updateAllOverlaysForTarget(packageName, userId, targetPackage);
-        mListener.onOverlaysChanged(packageName, userId);
+        if (updateAllOverlaysForTarget(packageName, userId, targetPackage)) {
+            mListener.onOverlaysChanged(packageName, userId);
+        }
     }
 
     void onTargetPackageChanged(@NonNull final String packageName, final int userId) {
@@ -210,7 +211,9 @@
             Slog.d(TAG, "onTargetPackageRemoved packageName=" + packageName + " userId=" + userId);
         }
 
-        updateAllOverlaysForTarget(packageName, userId, null);
+        if (updateAllOverlaysForTarget(packageName, userId, null)) {
+            mListener.onOverlaysChanged(packageName, userId);
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java
index c059b37..7d00423 100644
--- a/services/core/java/com/android/server/om/OverlayManagerSettings.java
+++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java
@@ -230,7 +230,7 @@
         }
 
         mItems.remove(moveIdx);
-        final int newParentIdx = select(newParentPackageName, userId);
+        final int newParentIdx = select(newParentPackageName, userId) + 1;
         mItems.add(newParentIdx, itemToMove);
         return moveIdx != newParentIdx;
     }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index faf6114..42b6946 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -24,6 +24,8 @@
 import static android.Manifest.permission.REQUEST_DELETE_PACKAGES;
 import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
 import static android.Manifest.permission.WRITE_MEDIA_STORAGE;
+import static android.content.pm.PackageManager.CERT_INPUT_RAW_X509;
+import static android.content.pm.PackageManager.CERT_INPUT_SHA256;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
@@ -108,6 +110,8 @@
 import static com.android.server.pm.PackageManagerServiceUtils.getCompressedFiles;
 import static com.android.server.pm.PackageManagerServiceUtils.getLastModifiedTime;
 import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo;
+import static com.android.server.pm.PackageManagerServiceUtils.signingDetailsHasCertificate;
+import static com.android.server.pm.PackageManagerServiceUtils.signingDetailsHasSha256Certificate;
 import static com.android.server.pm.PackageManagerServiceUtils.verifySignatures;
 import static com.android.server.pm.permission.PermissionsState.PERMISSION_OPERATION_FAILURE;
 import static com.android.server.pm.permission.PermissionsState.PERMISSION_OPERATION_SUCCESS;
@@ -5421,13 +5425,13 @@
                     if (isCallerInstantApp) {
                         return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
                     }
-                    s1 = ((SharedUserSetting)obj).signatures.mSignatures;
+                    s1 = ((SharedUserSetting)obj).signatures.mSigningDetails.signatures;
                 } else if (obj instanceof PackageSetting) {
                     final PackageSetting ps = (PackageSetting) obj;
                     if (filterAppAccessLPr(ps, callingUid, callingUserId)) {
                         return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
                     }
-                    s1 = ps.signatures.mSignatures;
+                    s1 = ps.signatures.mSigningDetails.signatures;
                 } else {
                     return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
                 }
@@ -5440,13 +5444,13 @@
                     if (isCallerInstantApp) {
                         return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
                     }
-                    s2 = ((SharedUserSetting)obj).signatures.mSignatures;
+                    s2 = ((SharedUserSetting)obj).signatures.mSigningDetails.signatures;
                 } else if (obj instanceof PackageSetting) {
                     final PackageSetting ps = (PackageSetting) obj;
                     if (filterAppAccessLPr(ps, callingUid, callingUserId)) {
                         return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
                     }
-                    s2 = ps.signatures.mSignatures;
+                    s2 = ps.signatures.mSigningDetails.signatures;
                 } else {
                     return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
                 }
@@ -5457,6 +5461,73 @@
         }
     }
 
+    @Override
+    public boolean hasSigningCertificate(
+            String packageName, byte[] certificate, @PackageManager.CertificateInputType int type) {
+
+        synchronized (mPackages) {
+            final PackageParser.Package p = mPackages.get(packageName);
+            if (p == null || p.mExtras == null) {
+                return false;
+            }
+            final int callingUid = Binder.getCallingUid();
+            final int callingUserId = UserHandle.getUserId(callingUid);
+            final PackageSetting ps = (PackageSetting) p.mExtras;
+            if (filterAppAccessLPr(ps, callingUid, callingUserId)) {
+                return false;
+            }
+            switch (type) {
+                case CERT_INPUT_RAW_X509:
+                    return signingDetailsHasCertificate(certificate, p.mSigningDetails);
+                case CERT_INPUT_SHA256:
+                    return signingDetailsHasSha256Certificate(certificate, p.mSigningDetails);
+                default:
+                    return false;
+            }
+        }
+    }
+
+    @Override
+    public boolean hasUidSigningCertificate(
+            int uid, byte[] certificate, @PackageManager.CertificateInputType int type) {
+        final int callingUid = Binder.getCallingUid();
+        final int callingUserId = UserHandle.getUserId(callingUid);
+        // Map to base uids.
+        uid = UserHandle.getAppId(uid);
+        // reader
+        synchronized (mPackages) {
+            final PackageParser.SigningDetails signingDetails;
+            final Object obj = mSettings.getUserIdLPr(uid);
+            if (obj != null) {
+                if (obj instanceof SharedUserSetting) {
+                    final boolean isCallerInstantApp = getInstantAppPackageName(callingUid) != null;
+                    if (isCallerInstantApp) {
+                        return false;
+                    }
+                    signingDetails = ((SharedUserSetting)obj).signatures.mSigningDetails;
+                } else if (obj instanceof PackageSetting) {
+                    final PackageSetting ps = (PackageSetting) obj;
+                    if (filterAppAccessLPr(ps, callingUid, callingUserId)) {
+                        return false;
+                    }
+                    signingDetails = ps.signatures.mSigningDetails;
+                } else {
+                    return false;
+                }
+            } else {
+                return false;
+            }
+            switch (type) {
+                case CERT_INPUT_RAW_X509:
+                    return signingDetailsHasCertificate(certificate, signingDetails);
+                case CERT_INPUT_SHA256:
+                    return signingDetailsHasSha256Certificate(certificate, signingDetails);
+                default:
+                    return false;
+            }
+        }
+    }
+
     /**
      * This method should typically only be used when granting or revoking
      * permissions, since the app may immediately restart after this call.
@@ -8233,19 +8304,15 @@
                 && ps.timeStamp == lastModifiedTime
                 && !isCompatSignatureUpdateNeeded(pkg)
                 && !isRecoverSignatureUpdateNeeded(pkg)) {
-            if (ps.signatures.mSignatures != null
-                    && ps.signatures.mSignatures.length != 0
-                    && ps.signatures.mSignatureSchemeVersion != SignatureSchemeVersion.UNKNOWN) {
+            if (ps.signatures.mSigningDetails.signatures != null
+                    && ps.signatures.mSigningDetails.signatures.length != 0
+                    && ps.signatures.mSigningDetails.signatureSchemeVersion
+                            != SignatureSchemeVersion.UNKNOWN) {
                 // Optimization: reuse the existing cached signing data
                 // if the package appears to be unchanged.
-                try {
-                    pkg.mSigningDetails = new PackageParser.SigningDetails(ps.signatures.mSignatures,
-                            ps.signatures.mSignatureSchemeVersion);
-                    return;
-                } catch (CertificateException e) {
-                    Slog.e(TAG, "Attempt to read public keys from persisted signatures failed for "
-                                    + ps.name, e);
-                }
+                pkg.mSigningDetails =
+                        new PackageParser.SigningDetails(ps.signatures.mSigningDetails);
+                return;
             }
 
             Slog.w(TAG, "PackageSetting for " + ps.name
@@ -8573,8 +8640,9 @@
         if (scanSystemPartition && !isSystemPkgUpdated && pkgAlreadyExists
                 && !pkgSetting.isSystem()) {
             // if the signatures don't match, wipe the installed application and its data
-            if (compareSignatures(pkgSetting.signatures.mSignatures, pkg.mSigningDetails.signatures)
-                    != PackageManager.SIGNATURE_MATCH) {
+            if (compareSignatures(pkgSetting.signatures.mSigningDetails.signatures,
+                    pkg.mSigningDetails.signatures)
+                            != PackageManager.SIGNATURE_MATCH) {
                 logCriticalInfo(Log.WARN,
                         "System package signature mismatch;"
                         + " name: " + pkgSetting.name);
@@ -9936,14 +10004,14 @@
             if (ksms.checkUpgradeKeySetLocked(signatureCheckPs, pkg)) {
                 // We just determined the app is signed correctly, so bring
                 // over the latest parsed certs.
-                pkgSetting.signatures.mSignatures = pkg.mSigningDetails.signatures;
+                pkgSetting.signatures.mSigningDetails = pkg.mSigningDetails;
             } else {
                 if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
                     throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
                             "Package " + pkg.packageName + " upgrade keys do not match the "
                                     + "previously installed version");
                 } else {
-                    pkgSetting.signatures.mSignatures = pkg.mSigningDetails.signatures;
+                    pkgSetting.signatures.mSigningDetails = pkg.mSigningDetails;
                     String msg = "System package " + pkg.packageName
                             + " signature changed; retaining data.";
                     reportSettingsProblem(Log.WARN, msg);
@@ -9963,21 +10031,22 @@
                 }
                 // We just determined the app is signed correctly, so bring
                 // over the latest parsed certs.
-                pkgSetting.signatures.mSignatures = pkg.mSigningDetails.signatures;
+                pkgSetting.signatures.mSigningDetails = pkg.mSigningDetails;
             } catch (PackageManagerException e) {
                 if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
                     throw e;
                 }
                 // The signature has changed, but this package is in the system
                 // image...  let's recover!
-                pkgSetting.signatures.mSignatures = pkg.mSigningDetails.signatures;
+                pkgSetting.signatures.mSigningDetails = pkg.mSigningDetails;
                 // However...  if this package is part of a shared user, but it
                 // doesn't match the signature of the shared user, let's fail.
                 // What this means is that you can't change the signatures
                 // associated with an overall shared user, which doesn't seem all
                 // that unreasonable.
                 if (signatureCheckPs.sharedUser != null) {
-                    if (compareSignatures(signatureCheckPs.sharedUser.signatures.mSignatures,
+                    if (compareSignatures(
+                            signatureCheckPs.sharedUser.signatures.mSigningDetails.signatures,
                             pkg.mSigningDetails.signatures) != PackageManager.SIGNATURE_MATCH) {
                         throw new PackageManagerException(
                                 INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
@@ -10804,9 +10873,12 @@
                 if (sharedUserSetting != null && sharedUserSetting.isPrivileged()) {
                     // Exempt SharedUsers signed with the platform key.
                     PackageSetting platformPkgSetting = mSettings.mPackages.get("android");
-                    if ((platformPkgSetting.signatures.mSignatures != null) &&
-                            (compareSignatures(platformPkgSetting.signatures.mSignatures,
-                                pkg.mSigningDetails.signatures) != PackageManager.SIGNATURE_MATCH)) {
+                    if ((platformPkgSetting.signatures.mSigningDetails
+                            != PackageParser.SigningDetails.UNKNOWN)
+                            && (compareSignatures(
+                                    platformPkgSetting.signatures.mSigningDetails.signatures,
+                                    pkg.mSigningDetails.signatures)
+                                            != PackageManager.SIGNATURE_MATCH)) {
                         throw new PackageManagerException("Apps that share a user with a " +
                                 "privileged app must themselves be marked as privileged. " +
                                 pkg.packageName + " shares privileged user " +
@@ -14248,9 +14320,10 @@
             Object obj = mSettings.getUserIdLPr(callingUid);
             if (obj != null) {
                 if (obj instanceof SharedUserSetting) {
-                    callerSignature = ((SharedUserSetting)obj).signatures.mSignatures;
+                    callerSignature =
+                            ((SharedUserSetting)obj).signatures.mSigningDetails.signatures;
                 } else if (obj instanceof PackageSetting) {
-                    callerSignature = ((PackageSetting)obj).signatures.mSignatures;
+                    callerSignature = ((PackageSetting)obj).signatures.mSigningDetails.signatures;
                 } else {
                     throw new SecurityException("Bad object " + obj + " for uid " + callingUid);
                 }
@@ -14262,7 +14335,7 @@
             // not signed with the same cert as the caller.
             if (installerPackageSetting != null) {
                 if (compareSignatures(callerSignature,
-                        installerPackageSetting.signatures.mSignatures)
+                        installerPackageSetting.signatures.mSigningDetails.signatures)
                         != PackageManager.SIGNATURE_MATCH) {
                     throw new SecurityException(
                             "Caller does not have same cert as new installer package "
@@ -14279,7 +14352,7 @@
                 // okay to change it.
                 if (setting != null) {
                     if (compareSignatures(callerSignature,
-                            setting.signatures.mSignatures)
+                            setting.signatures.mSigningDetails.signatures)
                             != PackageManager.SIGNATURE_MATCH) {
                         throw new SecurityException(
                                 "Caller does not have same cert as old installer package "
@@ -16787,7 +16860,8 @@
                                     sourcePackageSetting, scanFlags))) {
                         sigsOk = ksms.checkUpgradeKeySetLocked(sourcePackageSetting, pkg);
                     } else {
-                        sigsOk = compareSignatures(sourcePackageSetting.signatures.mSignatures,
+                        sigsOk = compareSignatures(
+                                sourcePackageSetting.signatures.mSigningDetails.signatures,
                                 pkg.mSigningDetails.signatures) == PackageManager.SIGNATURE_MATCH;
                     }
                     if (!sigsOk) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index 7b96ca6..021c4b8 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -54,6 +54,7 @@
 import android.system.Os;
 import android.util.ArraySet;
 import android.util.Log;
+import android.util.PackageUtils;
 import android.util.Slog;
 import android.util.jar.StrictJarFile;
 import android.util.proto.ProtoOutputStream;
@@ -74,6 +75,8 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.PrintWriter;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
 import java.security.cert.CertificateEncodingException;
 import java.security.cert.CertificateException;
 import java.text.SimpleDateFormat;
@@ -509,7 +512,7 @@
     private static boolean matchSignaturesCompat(String packageName,
             PackageSignatures packageSignatures, PackageParser.SigningDetails parsedSignatures) {
         ArraySet<Signature> existingSet = new ArraySet<Signature>();
-        for (Signature sig : packageSignatures.mSignatures) {
+        for (Signature sig : packageSignatures.mSigningDetails.signatures) {
             existingSet.add(sig);
         }
         ArraySet<Signature> scannedCompatSet = new ArraySet<Signature>();
@@ -526,7 +529,7 @@
         // make sure the expanded scanned set contains all signatures in the existing one
         if (scannedCompatSet.equals(existingSet)) {
             // migrate the old signatures to the new scheme
-            packageSignatures.assignSignatures(parsedSignatures);
+            packageSignatures.mSigningDetails = parsedSignatures;
             return true;
         }
         return false;
@@ -561,8 +564,8 @@
         try {
             PackageParser.collectCertificates(disabledPkgSetting.pkg,
                     PackageParser.PARSE_IS_SYSTEM_DIR);
-            if (compareSignatures(pkgSetting.signatures.mSignatures,
-                        disabledPkgSetting.signatures.mSignatures)
+            if (compareSignatures(pkgSetting.signatures.mSigningDetails.signatures,
+                        disabledPkgSetting.signatures.mSigningDetails.signatures)
                     != PackageManager.SIGNATURE_MATCH) {
                 logCriticalInfo(Log.ERROR, "Updated system app mismatches cert on /system: " +
                         pkgSetting.name);
@@ -576,6 +579,69 @@
         return true;
     }
 
+
+    /**
+     * Checks the signing certificates to see if the provided certificate is a member.  Invalid for
+     * {@code SigningDetails} with multiple signing certificates.
+     * @param certificate certificate to check for membership
+     * @param signingDetails signing certificates record whose members are to be searched
+     * @return true if {@code certificate} is in {@code signingDetails}
+     */
+    public static boolean signingDetailsHasCertificate(
+            byte[] certificate, PackageParser.SigningDetails signingDetails) {
+        if (signingDetails == PackageParser.SigningDetails.UNKNOWN) {
+            return false;
+        }
+        Signature signature = new Signature(certificate);
+        if (signingDetails.hasPastSigningCertificates()) {
+            for (int i = 0; i < signingDetails.pastSigningCertificates.length; i++) {
+                if (signingDetails.pastSigningCertificates[i].equals(signature)) {
+                    return true;
+                }
+            }
+        } else {
+            // no signing history, just check the current signer
+            if (signingDetails.signatures.length == 1
+                    && signingDetails.signatures[0].equals(signature)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Checks the signing certificates to see if the provided certificate is a member.  Invalid for
+     * {@code SigningDetails} with multiple signing certificaes.
+     * @param sha256Certificate certificate to check for membership
+     * @param signingDetails signing certificates record whose members are to be searched
+     * @return true if {@code certificate} is in {@code signingDetails}
+     */
+    public static boolean signingDetailsHasSha256Certificate(
+            byte[] sha256Certificate, PackageParser.SigningDetails signingDetails ) {
+        if (signingDetails == PackageParser.SigningDetails.UNKNOWN) {
+            return false;
+        }
+        if (signingDetails.hasPastSigningCertificates()) {
+            for (int i = 0; i < signingDetails.pastSigningCertificates.length; i++) {
+                byte[] digest = PackageUtils.computeSha256DigestBytes(
+                        signingDetails.pastSigningCertificates[i].toByteArray());
+                if (Arrays.equals(sha256Certificate, digest)) {
+                    return true;
+                }
+            }
+        } else {
+            // no signing history, just check the current signer
+            if (signingDetails.signatures.length == 1) {
+                byte[] digest = PackageUtils.computeSha256DigestBytes(
+                        signingDetails.signatures[0].toByteArray());
+                if (Arrays.equals(sha256Certificate, digest)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
     /** Returns true to force apk verification if the updated package (in /data) is a priv app. */
     static boolean isApkVerificationForced(@Nullable PackageSetting disabledPs) {
         return disabledPs != null && disabledPs.isPrivileged() &&
@@ -593,9 +659,9 @@
             throws PackageManagerException {
         final String packageName = pkgSetting.name;
         boolean compatMatch = false;
-        if (pkgSetting.signatures.mSignatures != null) {
+        if (pkgSetting.signatures.mSigningDetails.signatures != null) {
             // Already existing package. Make sure signatures match
-            boolean match = compareSignatures(pkgSetting.signatures.mSignatures,
+            boolean match = compareSignatures(pkgSetting.signatures.mSigningDetails.signatures,
                     parsedSignatures.signatures)
                     == PackageManager.SIGNATURE_MATCH;
             if (!match && compareCompat) {
@@ -605,7 +671,7 @@
             }
             if (!match && compareRecover) {
                 match = matchSignaturesRecover(
-                        packageName, pkgSetting.signatures.mSignatures,
+                        packageName, pkgSetting.signatures.mSigningDetails.signatures,
                         parsedSignatures.signatures);
             }
 
@@ -620,17 +686,21 @@
             }
         }
         // Check for shared user signatures
-        if (pkgSetting.sharedUser != null && pkgSetting.sharedUser.signatures.mSignatures != null) {
+        if (pkgSetting.sharedUser != null
+                && pkgSetting.sharedUser.signatures.mSigningDetails.signatures != null) {
             // Already existing package. Make sure signatures match
-            boolean match = compareSignatures(pkgSetting.sharedUser.signatures.mSignatures,
-                    parsedSignatures.signatures) == PackageManager.SIGNATURE_MATCH;
+            boolean match =
+                    compareSignatures(
+                            pkgSetting.sharedUser.signatures.mSigningDetails.signatures,
+                            parsedSignatures.signatures) == PackageManager.SIGNATURE_MATCH;
             if (!match && compareCompat) {
                 match = matchSignaturesCompat(
                         packageName, pkgSetting.sharedUser.signatures, parsedSignatures);
             }
             if (!match && compareRecover) {
                 match = matchSignaturesRecover(packageName,
-                        pkgSetting.sharedUser.signatures.mSignatures, parsedSignatures.signatures);
+                        pkgSetting.sharedUser.signatures.mSigningDetails.signatures,
+                        parsedSignatures.signatures);
                 compatMatch |= match;
             }
             if (!match) {
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index e3c4c43..18356c5 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -233,7 +233,7 @@
     }
 
     public Signature[] getSignatures() {
-        return signatures.mSignatures;
+        return signatures.mSigningDetails.signatures;
     }
 
     /**
diff --git a/services/core/java/com/android/server/pm/PackageSignatures.java b/services/core/java/com/android/server/pm/PackageSignatures.java
index d567d5c..d471fc8 100644
--- a/services/core/java/com/android/server/pm/PackageSignatures.java
+++ b/services/core/java/com/android/server/pm/PackageSignatures.java
@@ -22,91 +22,148 @@
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
+import android.annotation.NonNull;
 import android.content.pm.PackageParser;
 import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion;
 import android.content.pm.Signature;
 import android.util.Log;
 
 import java.io.IOException;
+import java.security.cert.CertificateException;
 import java.util.ArrayList;
 
 class PackageSignatures {
-    Signature[] mSignatures;
-    @SignatureSchemeVersion int mSignatureSchemeVersion;
+
+    @NonNull PackageParser.SigningDetails mSigningDetails;
 
     PackageSignatures(PackageSignatures orig) {
-        if (orig != null && orig.mSignatures != null) {
-            mSignatures = orig.mSignatures.clone();
-            mSignatureSchemeVersion = orig.mSignatureSchemeVersion;
+        if (orig != null && orig.mSigningDetails != PackageParser.SigningDetails.UNKNOWN) {
+            mSigningDetails = new PackageParser.SigningDetails(orig.mSigningDetails);
+        } else {
+            mSigningDetails = PackageParser.SigningDetails.UNKNOWN;
         }
     }
 
     PackageSignatures(PackageParser.SigningDetails signingDetails) {
-        assignSignatures(signingDetails);
+        mSigningDetails = signingDetails;
     }
 
     PackageSignatures() {
+        mSigningDetails = PackageParser.SigningDetails.UNKNOWN;
     }
 
     void writeXml(XmlSerializer serializer, String tagName,
-            ArrayList<Signature> pastSignatures) throws IOException {
-        if (mSignatures == null) {
+            ArrayList<Signature> writtenSignatures) throws IOException {
+        if (mSigningDetails.signatures == null) {
             return;
         }
         serializer.startTag(null, tagName);
-        serializer.attribute(null, "count",
-                Integer.toString(mSignatures.length));
-        serializer.attribute(null, "schemeVersion", Integer.toString(mSignatureSchemeVersion));
-        for (int i=0; i<mSignatures.length; i++) {
-            serializer.startTag(null, "cert");
-            final Signature sig = mSignatures[i];
-            final int sigHash = sig.hashCode();
-            final int numPast = pastSignatures.size();
-            int j;
-            for (j=0; j<numPast; j++) {
-                Signature pastSig = pastSignatures.get(j);
-                if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
-                    serializer.attribute(null, "index", Integer.toString(j));
-                    break;
-                }
-            }
-            if (j >= numPast) {
-                pastSignatures.add(sig);
-                serializer.attribute(null, "index", Integer.toString(numPast));
-                serializer.attribute(null, "key", sig.toCharsString());
-            }
-            serializer.endTag(null, "cert");
+        serializer.attribute(null, "count", Integer.toString(mSigningDetails.signatures.length));
+        serializer.attribute(null, "schemeVersion",
+                Integer.toString(mSigningDetails.signatureSchemeVersion));
+        writeCertsListXml(serializer, writtenSignatures, mSigningDetails.signatures, null);
+
+        // if we have past signer certificate information, write it out
+        if (mSigningDetails.pastSigningCertificates != null) {
+            serializer.startTag(null, "pastSigs");
+            serializer.attribute(null, "count",
+                    Integer.toString(mSigningDetails.pastSigningCertificates.length));
+            writeCertsListXml(
+                    serializer, writtenSignatures, mSigningDetails.pastSigningCertificates,
+                    mSigningDetails.pastSigningCertificatesFlags);
+            serializer.endTag(null, "pastSigs");
         }
         serializer.endTag(null, tagName);
     }
 
-    void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures)
+    private void writeCertsListXml(XmlSerializer serializer, ArrayList<Signature> writtenSignatures,
+            Signature[] signatures, int[] flags) throws IOException {
+        for (int i=0; i<signatures.length; i++) {
+            serializer.startTag(null, "cert");
+            final Signature sig = signatures[i];
+            final int sigHash = sig.hashCode();
+            final int numWritten = writtenSignatures.size();
+            int j;
+            for (j=0; j<numWritten; j++) {
+                Signature writtenSig = writtenSignatures.get(j);
+                if (writtenSig.hashCode() == sigHash && writtenSig.equals(sig)) {
+                    serializer.attribute(null, "index", Integer.toString(j));
+                    break;
+                }
+            }
+            if (j >= numWritten) {
+                writtenSignatures.add(sig);
+                serializer.attribute(null, "index", Integer.toString(numWritten));
+                serializer.attribute(null, "key", sig.toCharsString());
+            }
+            if (flags != null) {
+                serializer.attribute(null, "flags", Integer.toString(flags[i]));
+            }
+            serializer.endTag(null, "cert");
+        }
+    }
+
+    void readXml(XmlPullParser parser, ArrayList<Signature> readSignatures)
             throws IOException, XmlPullParserException {
+        PackageParser.SigningDetails.Builder builder =
+                new PackageParser.SigningDetails.Builder();
+
         String countStr = parser.getAttributeValue(null, "count");
         if (countStr == null) {
             PackageManagerService.reportSettingsProblem(Log.WARN,
-                    "Error in package manager settings: <signatures> has"
+                    "Error in package manager settings: <sigs> has"
                        + " no count at " + parser.getPositionDescription());
             XmlUtils.skipCurrentTag(parser);
         }
+        final int count = Integer.parseInt(countStr);
+
         String schemeVersionStr = parser.getAttributeValue(null, "schemeVersion");
+        int signatureSchemeVersion;
         if (schemeVersionStr == null) {
             PackageManagerService.reportSettingsProblem(Log.WARN,
-                    "Error in package manager settings: <signatures> has no schemeVersion at "
+                    "Error in package manager settings: <sigs> has no schemeVersion at "
                         + parser.getPositionDescription());
-            mSignatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
+            signatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
         } else {
-            mSignatureSchemeVersion = Integer.parseInt(countStr);
+            signatureSchemeVersion = Integer.parseInt(schemeVersionStr);
         }
-        final int count = Integer.parseInt(countStr);
-        mSignatures = new Signature[count];
+        builder.setSignatureSchemeVersion(signatureSchemeVersion);
+        Signature[] signatures = new Signature[count];
+        int pos = readCertsListXml(parser, readSignatures, signatures, null, builder);
+        builder.setSignatures(signatures);
+        if (pos < count) {
+            // Should never happen -- there is an error in the written
+            // settings -- but if it does we don't want to generate
+            // a bad array.
+            Signature[] newSigs = new Signature[pos];
+            System.arraycopy(signatures, 0, newSigs, 0, pos);
+            builder = builder.setSignatures(newSigs);
+            PackageManagerService.reportSettingsProblem(Log.WARN,
+                    "Error in package manager settings: <sigs> count does not match number of "
+                            + " <cert> entries" + parser.getPositionDescription());
+        }
+
+        try {
+            mSigningDetails = builder.build();
+        } catch (CertificateException e) {
+            PackageManagerService.reportSettingsProblem(Log.WARN,
+                    "Error in package manager settings: <sigs> "
+                            + "unable to convert certificate(s) to public key(s).");
+            mSigningDetails = PackageParser.SigningDetails.UNKNOWN;
+        }
+    }
+
+    private int readCertsListXml(XmlPullParser parser, ArrayList<Signature> readSignatures,
+            Signature[] signatures, int[] flags, PackageParser.SigningDetails.Builder builder)
+            throws IOException, XmlPullParserException {
+        int count = signatures.length;
         int pos = 0;
 
         int outerDepth = parser.getDepth();
         int type;
         while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
-               && (type != XmlPullParser.END_TAG
-                       || parser.getDepth() > outerDepth)) {
+                && (type != XmlPullParser.END_TAG
+                || parser.getDepth() > outerDepth)) {
             if (type == XmlPullParser.END_TAG
                     || type == XmlPullParser.TEXT) {
                 continue;
@@ -121,83 +178,128 @@
                             int idx = Integer.parseInt(index);
                             String key = parser.getAttributeValue(null, "key");
                             if (key == null) {
-                                if (idx >= 0 && idx < pastSignatures.size()) {
-                                    Signature sig = pastSignatures.get(idx);
+                                if (idx >= 0 && idx < readSignatures.size()) {
+                                    Signature sig = readSignatures.get(idx);
                                     if (sig != null) {
-                                        mSignatures[pos] = pastSignatures.get(idx);
+                                        signatures[pos] = readSignatures.get(idx);
                                         pos++;
                                     } else {
                                         PackageManagerService.reportSettingsProblem(Log.WARN,
                                                 "Error in package manager settings: <cert> "
-                                                   + "index " + index + " is not defined at "
-                                                   + parser.getPositionDescription());
+                                                        + "index " + index + " is not defined at "
+                                                        + parser.getPositionDescription());
                                     }
                                 } else {
                                     PackageManagerService.reportSettingsProblem(Log.WARN,
                                             "Error in package manager settings: <cert> "
-                                               + "index " + index + " is out of bounds at "
-                                               + parser.getPositionDescription());
+                                                    + "index " + index + " is out of bounds at "
+                                                    + parser.getPositionDescription());
                                 }
                             } else {
-                                while (pastSignatures.size() <= idx) {
-                                    pastSignatures.add(null);
+                                while (readSignatures.size() <= idx) {
+                                    readSignatures.add(null);
                                 }
                                 Signature sig = new Signature(key);
-                                pastSignatures.set(idx, sig);
-                                mSignatures[pos] = sig;
+                                readSignatures.set(idx, sig);
+                                signatures[pos] = sig;
                                 pos++;
                             }
                         } catch (NumberFormatException e) {
                             PackageManagerService.reportSettingsProblem(Log.WARN,
                                     "Error in package manager settings: <cert> "
-                                       + "index " + index + " is not a number at "
-                                       + parser.getPositionDescription());
+                                            + "index " + index + " is not a number at "
+                                            + parser.getPositionDescription());
                         } catch (IllegalArgumentException e) {
                             PackageManagerService.reportSettingsProblem(Log.WARN,
                                     "Error in package manager settings: <cert> "
-                                       + "index " + index + " has an invalid signature at "
-                                       + parser.getPositionDescription() + ": "
-                                       + e.getMessage());
+                                            + "index " + index + " has an invalid signature at "
+                                            + parser.getPositionDescription() + ": "
+                                            + e.getMessage());
+                        }
+
+                        if (flags != null) {
+                            String flagsStr = parser.getAttributeValue(null, "flags");
+                            if (flagsStr != null) {
+                                try {
+                                    flags[pos] = Integer.parseInt(flagsStr);
+                                } catch (NumberFormatException e) {
+                                    PackageManagerService.reportSettingsProblem(Log.WARN,
+                                            "Error in package manager settings: <cert> "
+                                                    + "flags " + flagsStr + " is not a number at "
+                                                    + parser.getPositionDescription());
+                                }
+                            } else {
+                                PackageManagerService.reportSettingsProblem(Log.WARN,
+                                        "Error in package manager settings: <cert> has no"
+                                                + " flags at " + parser.getPositionDescription());
+                            }
                         }
                     } else {
                         PackageManagerService.reportSettingsProblem(Log.WARN,
                                 "Error in package manager settings: <cert> has"
-                                   + " no index at " + parser.getPositionDescription());
+                                        + " no index at " + parser.getPositionDescription());
                     }
                 } else {
                     PackageManagerService.reportSettingsProblem(Log.WARN,
                             "Error in package manager settings: too "
-                               + "many <cert> tags, expected " + count
-                               + " at " + parser.getPositionDescription());
+                                    + "many <cert> tags, expected " + count
+                                    + " at " + parser.getPositionDescription());
+                }
+            } else if (tagName.equals("pastSigs")) {
+                if (flags == null) {
+                    // we haven't encountered pastSigs yet, go ahead
+                    String countStr = parser.getAttributeValue(null, "count");
+                    if (countStr == null) {
+                        PackageManagerService.reportSettingsProblem(Log.WARN,
+                                "Error in package manager settings: <pastSigs> has"
+                                        + " no count at " + parser.getPositionDescription());
+                        XmlUtils.skipCurrentTag(parser);
+                    }
+                    try {
+                        final int pastSigsCount = Integer.parseInt(countStr);
+                        Signature[] pastSignatures = new Signature[pastSigsCount];
+                        int[] pastSignaturesFlags = new int[pastSigsCount];
+                        int pastSigsPos = readCertsListXml(parser, readSignatures, pastSignatures,
+                                pastSignaturesFlags, builder);
+                        builder = builder
+                                .setPastSigningCertificates(pastSignatures)
+                                .setPastSigningCertificatesFlags(pastSignaturesFlags);
+
+                        if (pastSigsPos < pastSigsCount) {
+                            // Should never happen -- there is an error in the written
+                            // settings -- but if it does we don't want to generate
+                            // a bad array.
+                            Signature[] newSigs = new Signature[pastSigsPos];
+                            System.arraycopy(pastSignatures, 0, newSigs, 0, pastSigsPos);
+                            int[] newFlags = new int[pastSigsPos];
+                            System.arraycopy(pastSignaturesFlags, 0, newFlags, 0, pastSigsPos);
+                            builder = builder
+                                    .setPastSigningCertificates(newSigs)
+                                    .setPastSigningCertificatesFlags(newFlags);
+                            PackageManagerService.reportSettingsProblem(Log.WARN,
+                                    "Error in package manager settings: <pastSigs> count does not "
+                                    + "match number of <cert> entries "
+                                    + parser.getPositionDescription());
+                        }
+                    } catch (NumberFormatException e) {
+                        PackageManagerService.reportSettingsProblem(Log.WARN,
+                                "Error in package manager settings: <pastSigs> "
+                                        + "count " + countStr + " is not a number at "
+                                        + parser.getPositionDescription());
+                    }
+                } else {
+                    PackageManagerService.reportSettingsProblem(Log.WARN,
+                            "<pastSigs> encountered multiple times under the same <sigs> at "
+                                    + parser.getPositionDescription());
                 }
             } else {
                 PackageManagerService.reportSettingsProblem(Log.WARN,
-                        "Unknown element under <cert>: "
-                        + parser.getName());
+                        "Unknown element under <sigs>: "
+                                + parser.getName());
             }
             XmlUtils.skipCurrentTag(parser);
         }
-
-        if (pos < count) {
-            // Should never happen -- there is an error in the written
-            // settings -- but if it does we don't want to generate
-            // a bad array.
-            Signature[] newSigs = new Signature[pos];
-            System.arraycopy(mSignatures, 0, newSigs, 0, pos);
-            mSignatures = newSigs;
-        }
-    }
-
-    void assignSignatures(PackageParser.SigningDetails signingDetails) {
-        mSignatureSchemeVersion = signingDetails.signatureSchemeVersion;
-        if (!signingDetails.hasSignatures()) {
-            mSignatures = null;
-            return;
-        }
-        mSignatures = new Signature[signingDetails.signatures.length];
-        for (int i=0; i<signingDetails.signatures.length; i++) {
-            mSignatures[i] = signingDetails.signatures[i];
-        }
+        return pos;
     }
 
     @Override
@@ -206,16 +308,26 @@
         buf.append("PackageSignatures{");
         buf.append(Integer.toHexString(System.identityHashCode(this)));
         buf.append(" version:");
-        buf.append(mSignatureSchemeVersion);
+        buf.append(mSigningDetails.signatureSchemeVersion);
         buf.append(", signatures:[");
-        if (mSignatures != null) {
-            for (int i=0; i<mSignatures.length; i++) {
+        if (mSigningDetails.signatures != null) {
+            for (int i = 0; i < mSigningDetails.signatures.length; i++) {
                 if (i > 0) buf.append(", ");
                 buf.append(Integer.toHexString(
-                        mSignatures[i].hashCode()));
+                        mSigningDetails.signatures[i].hashCode()));
             }
         }
         buf.append("]}");
+        buf.append(", past signatures:[");
+        if (mSigningDetails.pastSigningCertificates != null) {
+            for (int i = 0; i < mSigningDetails.pastSigningCertificates.length; i++) {
+                if (i > 0) buf.append(", ");
+                buf.append(Integer.toHexString(
+                        mSigningDetails.pastSigningCertificates[i].hashCode()));
+                buf.append(" flags: ");
+                buf.append(Integer.toHexString(mSigningDetails.pastSigningCertificatesFlags[i]));
+            }
+        }
         return buf.toString();
     }
 }
\ No newline at end of file
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index ecbc452..8ce412e 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -920,13 +920,13 @@
     // by that time.
     void insertPackageSettingLPw(PackageSetting p, PackageParser.Package pkg) {
         // Update signatures if needed.
-        if (p.signatures.mSignatures == null) {
-            p.signatures.assignSignatures(pkg.mSigningDetails);
+        if (p.signatures.mSigningDetails.signatures == null) {
+            p.signatures.mSigningDetails = pkg.mSigningDetails;
         }
         // If this app defines a shared user id initialize
         // the shared user signatures as well.
-        if (p.sharedUser != null && p.sharedUser.signatures.mSignatures == null) {
-            p.sharedUser.signatures.assignSignatures(pkg.mSigningDetails);
+        if (p.sharedUser != null && p.sharedUser.signatures.mSigningDetails.signatures == null) {
+            p.sharedUser.signatures.mSigningDetails = pkg.mSigningDetails;
         }
         addPackageSettingLPw(p, p.sharedUser);
     }
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index c58c208..d67f2d7 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -23,6 +23,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.graphics.Rect;
+import android.hardware.fingerprint.IFingerprintDialogReceiver;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
@@ -514,6 +515,56 @@
     }
 
     @Override
+    public void showFingerprintDialog(Bundle bundle, IFingerprintDialogReceiver receiver) {
+        if (mBar != null) {
+            try {
+                mBar.showFingerprintDialog(bundle, receiver);
+            } catch (RemoteException ex) {
+            }
+        }
+    }
+
+    @Override
+    public void onFingerprintAuthenticated() {
+        if (mBar != null) {
+            try {
+                mBar.onFingerprintAuthenticated();
+            } catch (RemoteException ex) {
+            }
+        }
+    }
+
+    @Override
+    public void onFingerprintHelp(String message) {
+        if (mBar != null) {
+            try {
+                mBar.onFingerprintHelp(message);
+            } catch (RemoteException ex) {
+            }
+        }
+    }
+
+    @Override
+    public void onFingerprintError(String error) {
+        if (mBar != null) {
+            try {
+                mBar.onFingerprintError(error);
+            } catch (RemoteException ex) {
+            }
+        }
+    }
+
+    @Override
+    public void hideFingerprintDialog() {
+        if (mBar != null) {
+            try {
+                mBar.hideFingerprintDialog();
+            } catch (RemoteException ex) {
+            }
+        }
+    }
+
+    @Override
     public void disable(int what, IBinder token, String pkg) {
         disableForUser(what, token, pkg, mCurrentUserId);
     }
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 0bc58e0..7540e26 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -104,6 +104,8 @@
         "libhwbinder",
         "libutils",
         "libhwui",
+        "libbpf",
+        "libnetdutils",
         "android.hardware.audio.common@2.0",
         "android.hardware.broadcastradio@1.0",
         "android.hardware.broadcastradio@1.1",
diff --git a/services/core/jni/com_android_server_net_NetworkStatsService.cpp b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
index 8de24e5..3302dea 100644
--- a/services/core/jni/com_android_server_net_NetworkStatsService.cpp
+++ b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
@@ -29,6 +29,15 @@
 #include <utils/misc.h>
 #include <utils/Log.h>
 
+#include "android-base/unique_fd.h"
+#include "bpf/BpfNetworkStats.h"
+#include "bpf/BpfUtils.h"
+
+using android::bpf::Stats;
+using android::bpf::hasBpfSupport;
+using android::bpf::bpfGetUidStats;
+using android::bpf::bpfGetIfaceStats;
+
 namespace android {
 
 static const char* QTAGUID_IFACE_STATS = "/proc/net/xt_qtaguid/iface_stat_fmt";
@@ -46,15 +55,6 @@
     TCP_TX_PACKETS = 5
 };
 
-struct Stats {
-    uint64_t rxBytes;
-    uint64_t rxPackets;
-    uint64_t txBytes;
-    uint64_t txPackets;
-    uint64_t tcpRxPackets;
-    uint64_t tcpTxPackets;
-};
-
 static uint64_t getStatsType(struct Stats* stats, StatsType type) {
     switch (type) {
         case RX_BYTES:
@@ -150,9 +150,18 @@
     return 0;
 }
 
-static jlong getTotalStat(JNIEnv* env, jclass clazz, jint type) {
+static jlong getTotalStat(JNIEnv* env, jclass clazz, jint type, jboolean useBpfStats) {
     struct Stats stats;
     memset(&stats, 0, sizeof(Stats));
+
+    if (useBpfStats) {
+        if (bpfGetIfaceStats(NULL, &stats) == 0) {
+            return getStatsType(&stats, (StatsType) type);
+        } else {
+            return UNKNOWN;
+        }
+    }
+
     if (parseIfaceStats(NULL, &stats) == 0) {
         return getStatsType(&stats, (StatsType) type);
     } else {
@@ -160,7 +169,8 @@
     }
 }
 
-static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type) {
+static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type,
+                          jboolean useBpfStats) {
     ScopedUtfChars iface8(env, iface);
     if (iface8.c_str() == NULL) {
         return UNKNOWN;
@@ -168,6 +178,15 @@
 
     struct Stats stats;
     memset(&stats, 0, sizeof(Stats));
+
+    if (useBpfStats) {
+        if (bpfGetIfaceStats(iface8.c_str(), &stats) == 0) {
+            return getStatsType(&stats, (StatsType) type);
+        } else {
+            return UNKNOWN;
+        }
+    }
+
     if (parseIfaceStats(iface8.c_str(), &stats) == 0) {
         return getStatsType(&stats, (StatsType) type);
     } else {
@@ -175,9 +194,18 @@
     }
 }
 
-static jlong getUidStat(JNIEnv* env, jclass clazz, jint uid, jint type) {
+static jlong getUidStat(JNIEnv* env, jclass clazz, jint uid, jint type, jboolean useBpfStats) {
     struct Stats stats;
     memset(&stats, 0, sizeof(Stats));
+
+    if (useBpfStats) {
+        if (bpfGetUidStats(uid, &stats) == 0) {
+            return getStatsType(&stats, (StatsType) type);
+        } else {
+            return UNKNOWN;
+        }
+    }
+
     if (parseUidStats(uid, &stats) == 0) {
         return getStatsType(&stats, (StatsType) type);
     } else {
@@ -186,9 +214,9 @@
 }
 
 static const JNINativeMethod gMethods[] = {
-    {"nativeGetTotalStat", "(I)J", (void*) getTotalStat},
-    {"nativeGetIfaceStat", "(Ljava/lang/String;I)J", (void*) getIfaceStat},
-    {"nativeGetUidStat", "(II)J", (void*) getUidStat},
+    {"nativeGetTotalStat", "(IZ)J", (void*) getTotalStat},
+    {"nativeGetIfaceStat", "(Ljava/lang/String;IZ)J", (void*) getIfaceStat},
+    {"nativeGetUidStat", "(IIZ)J", (void*) getUidStat},
 };
 
 int register_android_server_net_NetworkStatsService(JNIEnv* env) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
index 7a0b1bf..886747c 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
@@ -22,10 +22,13 @@
 import android.os.UserHandle;
 import android.security.keymaster.KeymasterCertificateChain;
 import android.security.keystore.ParcelableKeyGenParameterSpec;
+import android.telephony.data.ApnSetting;
 
 import com.android.internal.R;
 import com.android.server.SystemService;
 
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -135,4 +138,42 @@
     public CharSequence getPrintingDisabledReason() {
         return null;
     }
+
+    @Override
+    public List<String> setMeteredDataDisabled(ComponentName admin, List<String> packageNames) {
+        return packageNames;
+    }
+
+    @Override
+    public List<String> getMeteredDataDisabled(ComponentName admin) {
+        return new ArrayList<>();
+    }
+
+    @Override
+    public int addOverrideApn(ComponentName admin, ApnSetting apnSetting) {
+        return -1;
+    }
+
+    @Override
+    public boolean updateOverrideApn(ComponentName admin, int apnId, ApnSetting apnSetting) {
+        return false;
+    }
+
+    @Override
+    public boolean removeOverrideApn(ComponentName admin, int apnId) {
+        return false;
+    }
+
+    @Override
+    public List<ApnSetting> getOverrideApns(ComponentName admin) {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public void setOverrideApnsEnabled(ComponentName admin, boolean enabled) {}
+
+    @Override
+    public boolean isOverrideApnEnabled(ComponentName admin) {
+        return false;
+    }
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 6bee9d6..cb346cc 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -58,8 +58,15 @@
 import static android.app.admin.DevicePolicyManager.WIPE_EXTERNAL_STORAGE;
 import static android.app.admin.DevicePolicyManager.WIPE_RESET_PROTECTION_DATA;
 import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
-import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_ENTRY_POINT_ADB;
-import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
+import static android.provider.Telephony.Carriers.DPC_URI;
+import static android.provider.Telephony.Carriers.ENFORCE_KEY;
+import static android.provider.Telephony.Carriers.ENFORCE_MANAGED_URI;
+
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
+        .PROVISIONING_ENTRY_POINT_ADB;
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker
+        .STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
+
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 import static org.xmlpull.v1.XmlPullParser.END_TAG;
 import static org.xmlpull.v1.XmlPullParser.TEXT;
@@ -99,6 +106,7 @@
 import android.app.usage.UsageStatsManagerInternal;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
+import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -108,8 +116,8 @@
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.PackageManagerInternal;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.PermissionInfo;
 import android.content.pm.ResolveInfo;
@@ -118,6 +126,7 @@
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.database.ContentObserver;
+import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.Color;
 import android.media.AudioManager;
@@ -161,13 +170,14 @@
 import android.security.IKeyChainService;
 import android.security.KeyChain;
 import android.security.KeyChain.KeyChainConnection;
+import android.security.KeyStore;
 import android.security.keymaster.KeymasterCertificateChain;
+import android.security.keystore.AttestationUtils;
 import android.security.keystore.KeyGenParameterSpec;
 import android.security.keystore.ParcelableKeyGenParameterSpec;
-import android.security.KeyStore;
-import android.security.keystore.AttestationUtils;
 import android.service.persistentdata.PersistentDataBlockManager;
 import android.telephony.TelephonyManager;
+import android.telephony.data.ApnSetting;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -217,7 +227,6 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
-import java.lang.IllegalStateException;
 import java.lang.reflect.Constructor;
 import java.nio.charset.StandardCharsets;
 import java.text.DateFormat;
@@ -228,8 +237,8 @@
 import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
-import java.util.Map.Entry;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
@@ -806,6 +815,8 @@
         private static final String TAG_MANDATORY_BACKUP_TRANSPORT = "mandatory_backup_transport";
         private static final String TAG_START_USER_SESSION_MESSAGE = "start_user_session_message";
         private static final String TAG_END_USER_SESSION_MESSAGE = "end_user_session_message";
+        private static final String TAG_METERED_DATA_DISABLED_PACKAGES
+                = "metered_data_disabled_packages";
 
         DeviceAdminInfo info;
 
@@ -872,6 +883,9 @@
             }
         }
 
+        // The list of packages which are not allowed to use metered data.
+        List<String> meteredDisabledPackages;
+
         final Set<String> accountTypesWithManagementDisabled = new ArraySet<>();
 
         // The list of permitted accessibility services package namesas set by a profile
@@ -1153,6 +1167,7 @@
             writePackageListToXml(out, TAG_PERMITTED_NOTIFICATION_LISTENERS,
                     permittedNotificationListeners);
             writePackageListToXml(out, TAG_KEEP_UNINSTALLED_PACKAGES, keepUninstalledPackages);
+            writePackageListToXml(out, TAG_METERED_DATA_DISABLED_PACKAGES, meteredDisabledPackages);
             if (hasUserRestrictions()) {
                 UserRestrictionsUtils.writeRestrictions(
                         out, userRestrictions, TAG_USER_RESTRICTIONS);
@@ -1349,6 +1364,8 @@
                     permittedNotificationListeners = readPackageList(parser, tag);
                 } else if (TAG_KEEP_UNINSTALLED_PACKAGES.equals(tag)) {
                     keepUninstalledPackages = readPackageList(parser, tag);
+                } else if (TAG_METERED_DATA_DISABLED_PACKAGES.equals(tag)) {
+                    meteredDisabledPackages = readPackageList(parser, tag);
                 } else if (TAG_USER_RESTRICTIONS.equals(tag)) {
                     userRestrictions = UserRestrictionsUtils.readRestrictions(parser);
                 } else if (TAG_DEFAULT_ENABLED_USER_RESTRICTIONS.equals(tag)) {
@@ -1647,6 +1664,7 @@
                             policy.mAdminList.remove(i);
                             policy.mAdminMap.remove(aa.info.getComponent());
                             pushActiveAdminPackagesLocked(userHandle);
+                            pushMeteredDisabledPackagesLocked(userHandle);
                         }
                     }
                 } catch (RemoteException re) {
@@ -3502,6 +3520,7 @@
         mInjector.postOnSystemServerInitThreadPool(() -> {
             pushActiveAdminPackages();
             mUsageStatsManagerInternal.onAdminDataAvailable();
+            pushAllMeteredRestrictedPackages();
             mInjector.getNetworkPolicyManagerInternal().onAdminDataAvailable();
         });
     }
@@ -3517,6 +3536,17 @@
         }
     }
 
+    private void pushAllMeteredRestrictedPackages() {
+        synchronized (this) {
+            final List<UserInfo> users = mUserManager.getUsers();
+            for (int i = users.size() - 1; i >= 0; --i) {
+                final int userId = users.get(i).id;
+                mInjector.getNetworkPolicyManagerInternal().setMeteredRestrictedPackagesAsync(
+                        getMeteredDisabledPackagesLocked(userId), userId);
+            }
+        }
+    }
+
     private void pushActiveAdminPackagesLocked(int userId) {
         mUsageStatsManagerInternal.setActiveAdminApps(
                 getActiveAdminPackagesLocked(userId), userId);
@@ -7262,6 +7292,15 @@
         }
     }
 
+    private void clearOverrideApnUnchecked() {
+        // Disable Override APNs and remove them from database.
+        setOverrideApnsEnabledUnchecked(false);
+        final List<ApnSetting> apns = getOverrideApnsUnchecked();
+        for (int i = 0; i < apns.size(); i ++) {
+            removeOverrideApnUnchecked(apns.get(i).getId());
+        }
+    }
+
     private void clearDeviceOwnerLocked(ActiveAdmin admin, int userId) {
         mDeviceAdminServiceController.stopServiceForOwner(userId, "clear-device-owner");
 
@@ -7282,6 +7321,7 @@
         systemPolicyData.mLastNetworkLogsRetrievalTime = -1;
         saveSettingsLocked(UserHandle.USER_SYSTEM);
         clearUserPoliciesLocked(userId);
+        clearOverrideApnUnchecked();
 
         mOwners.clearDeviceOwner();
         mOwners.writeDeviceOwner();
@@ -11031,6 +11071,93 @@
     }
 
     @Override
+    public List<String> setMeteredDataDisabled(ComponentName who, List<String> packageNames) {
+        Preconditions.checkNotNull(who);
+        Preconditions.checkNotNull(packageNames);
+
+        if (!mHasFeature) {
+            return packageNames;
+        }
+        synchronized (this) {
+            final ActiveAdmin admin = getActiveAdminForCallerLocked(who,
+                    DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+            final int callingUserId = mInjector.userHandleGetCallingUserId();
+            final long identity = mInjector.binderClearCallingIdentity();
+            try {
+                final List<String> excludedPkgs
+                        = removeInvalidPkgsForMeteredDataRestriction(callingUserId, packageNames);
+                admin.meteredDisabledPackages = packageNames;
+                pushMeteredDisabledPackagesLocked(callingUserId);
+                saveSettingsLocked(callingUserId);
+                return excludedPkgs;
+            } finally {
+                mInjector.binderRestoreCallingIdentity(identity);
+            }
+        }
+    }
+
+    private List<String> removeInvalidPkgsForMeteredDataRestriction(
+            int userId, List<String> pkgNames) {
+        final Set<String> activeAdmins = getActiveAdminPackagesLocked(userId);
+        final List<String> excludedPkgs = new ArrayList<>();
+        for (int i = pkgNames.size() - 1; i >= 0; --i) {
+            final String pkgName = pkgNames.get(i);
+            // If the package is an active admin, don't restrict it.
+            if (activeAdmins.contains(pkgName)) {
+                excludedPkgs.add(pkgName);
+                continue;
+            }
+            // If the package doesn't exist, don't restrict it.
+            try {
+                if (!mInjector.getIPackageManager().isPackageAvailable(pkgName, userId)) {
+                    excludedPkgs.add(pkgName);
+                }
+            } catch (RemoteException e) {
+                // Should not happen
+            }
+        }
+        pkgNames.removeAll(excludedPkgs);
+        return excludedPkgs;
+    }
+
+    @Override
+    public List<String> getMeteredDataDisabled(ComponentName who) {
+        Preconditions.checkNotNull(who);
+
+        if (!mHasFeature) {
+            return new ArrayList<>();
+        }
+        synchronized (this) {
+            final ActiveAdmin admin = getActiveAdminForCallerLocked(who,
+                    DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+            return admin.meteredDisabledPackages == null
+                    ? new ArrayList<>() : admin.meteredDisabledPackages;
+        }
+    }
+
+    private void pushMeteredDisabledPackagesLocked(int userId) {
+        mInjector.getNetworkPolicyManagerInternal().setMeteredRestrictedPackages(
+                getMeteredDisabledPackagesLocked(userId), userId);
+    }
+
+    private Set<String> getMeteredDisabledPackagesLocked(int userId) {
+        final DevicePolicyData policy = getUserData(userId);
+        final Set<String> restrictedPkgs = new ArraySet<>();
+        for (int i = policy.mAdminList.size() - 1; i >= 0; --i) {
+            final ActiveAdmin admin = policy.mAdminList.get(i);
+            if (!isActiveAdminWithPolicyForUserLocked(admin,
+                    DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, userId)) {
+                // Not a profile or device owner, ignore
+                continue;
+            }
+            if (admin.meteredDisabledPackages != null) {
+                restrictedPkgs.addAll(admin.meteredDisabledPackages);
+            }
+        }
+        return restrictedPkgs;
+    }
+
+    @Override
     public void setAffiliationIds(ComponentName admin, List<String> ids) {
         if (!mHasFeature) {
             return;
@@ -11389,6 +11516,7 @@
                 resetGlobalProxyLocked(policy);
             }
             pushActiveAdminPackagesLocked(userHandle);
+            pushMeteredDisabledPackagesLocked(userHandle);
             saveSettingsLocked(userHandle);
             updateMaximumTimeToLockLocked(userHandle);
             policy.mRemovingAdmins.remove(adminReceiver);
@@ -12400,4 +12528,185 @@
                     .getResources().getString(R.string.printing_disabled_by, appLabel);
         }
     }
+
+    @Override
+    public int addOverrideApn(@NonNull ComponentName who, @NonNull ApnSetting apnSetting) {
+        if (!mHasFeature) {
+            return -1;
+        }
+        Preconditions.checkNotNull(who, "ComponentName is null in addOverrideApn");
+        Preconditions.checkNotNull(apnSetting, "ApnSetting is null in addOverrideApn");
+        synchronized (this) {
+            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+        }
+
+        int operatedId = -1;
+        Uri resultUri;
+        final long id = mInjector.binderClearCallingIdentity();
+        try {
+            resultUri = mContext.getContentResolver().insert(DPC_URI, apnSetting.toContentValues());
+        } finally {
+            mInjector.binderRestoreCallingIdentity(id);
+        }
+        if (resultUri != null) {
+            try {
+                operatedId = Integer.parseInt(resultUri.getLastPathSegment());
+            } catch (NumberFormatException e) {
+                Slog.e(LOG_TAG, "Failed to parse inserted override APN id.", e);
+            }
+        }
+
+        return operatedId;
+    }
+
+    @Override
+    public boolean updateOverrideApn(@NonNull ComponentName who, int apnId,
+            @NonNull ApnSetting apnSetting) {
+        if (!mHasFeature) {
+            return false;
+        }
+        Preconditions.checkNotNull(who, "ComponentName is null in updateOverrideApn");
+        Preconditions.checkNotNull(apnSetting, "ApnSetting is null in updateOverrideApn");
+        synchronized (this) {
+            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+        }
+
+        if (apnId < 0) {
+            return false;
+        }
+        final long id = mInjector.binderClearCallingIdentity();
+        try {
+            return mContext.getContentResolver().update(
+                    Uri.withAppendedPath(DPC_URI, Integer.toString(apnId)),
+                    apnSetting.toContentValues(), null, null) > 0;
+        } finally {
+            mInjector.binderRestoreCallingIdentity(id);
+        }
+    }
+
+    @Override
+    public boolean removeOverrideApn(@NonNull ComponentName who, int apnId) {
+        if (!mHasFeature) {
+            return false;
+        }
+        Preconditions.checkNotNull(who, "ComponentName is null in removeOverrideApn");
+        synchronized (this) {
+            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+        }
+
+        return removeOverrideApnUnchecked(apnId);
+    }
+
+    private boolean removeOverrideApnUnchecked(int apnId) {
+        if(apnId < 0) {
+            return false;
+        }
+        int numDeleted = 0;
+        final long id = mInjector.binderClearCallingIdentity();
+        try {
+            numDeleted = mContext.getContentResolver().delete(
+                    Uri.withAppendedPath(DPC_URI, Integer.toString(apnId)), null, null);
+        } finally {
+            mInjector.binderRestoreCallingIdentity(id);
+        }
+        return numDeleted > 0;
+    }
+
+    @Override
+    public List<ApnSetting> getOverrideApns(@NonNull ComponentName who) {
+        if (!mHasFeature) {
+            return Collections.emptyList();
+        }
+        Preconditions.checkNotNull(who, "ComponentName is null in getOverrideApns");
+        synchronized (this) {
+            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+        }
+
+        return getOverrideApnsUnchecked();
+    }
+
+    private List<ApnSetting> getOverrideApnsUnchecked() {
+        final Cursor cursor;
+        final long id = mInjector.binderClearCallingIdentity();
+        try {
+            cursor = mContext.getContentResolver().query(DPC_URI, null, null, null, null);
+        } finally {
+            mInjector.binderRestoreCallingIdentity(id);
+        }
+
+        if (cursor == null) {
+            return Collections.emptyList();
+        }
+        try {
+            List<ApnSetting> apnList = new ArrayList<ApnSetting>();
+            cursor.moveToPosition(-1);
+            while (cursor.moveToNext()) {
+                ApnSetting apn = ApnSetting.makeApnSetting(cursor);
+                apnList.add(apn);
+            }
+            return apnList;
+        } finally {
+            cursor.close();
+        }
+    }
+
+    @Override
+    public void setOverrideApnsEnabled(@NonNull ComponentName who, boolean enabled) {
+        if (!mHasFeature) {
+            return;
+        }
+        Preconditions.checkNotNull(who, "ComponentName is null in setOverrideApnEnabled");
+        synchronized (this) {
+            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+        }
+
+        setOverrideApnsEnabledUnchecked(enabled);
+    }
+
+    private void setOverrideApnsEnabledUnchecked(boolean enabled) {
+        ContentValues value = new ContentValues();
+        value.put(ENFORCE_KEY, enabled);
+        final long id = mInjector.binderClearCallingIdentity();
+        try {
+            mContext.getContentResolver().update(
+                    ENFORCE_MANAGED_URI, value, null, null);
+        } finally {
+            mInjector.binderRestoreCallingIdentity(id);
+        }
+    }
+
+    @Override
+    public boolean isOverrideApnEnabled(@NonNull ComponentName who) {
+        if (!mHasFeature) {
+            return false;
+        }
+        Preconditions.checkNotNull(who, "ComponentName is null in isOverrideApnEnabled");
+        synchronized (this) {
+            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+        }
+
+        Cursor enforceCursor;
+        final long id = mInjector.binderClearCallingIdentity();
+        try {
+            enforceCursor = mContext.getContentResolver().query(
+                    ENFORCE_MANAGED_URI, null, null, null, null);
+        } finally {
+            mInjector.binderRestoreCallingIdentity(id);
+        }
+
+        if (enforceCursor == null) {
+            return false;
+        }
+        try {
+            if (enforceCursor.moveToFirst()) {
+                return enforceCursor.getInt(enforceCursor.getColumnIndex(ENFORCE_KEY)) == 1;
+            }
+        } catch (IllegalArgumentException e) {
+            Slog.e(LOG_TAG, "Cursor returned from ENFORCE_MANAGED_URI doesn't contain "
+                    + "correct info.", e);
+        } finally {
+            enforceCursor.close();
+        }
+        return false;
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java b/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
index de54e52..a29e169 100644
--- a/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
@@ -15,6 +15,8 @@
  */
 package com.android.server;
 
+import static android.app.ActivityManager.PROCESS_STATE_CACHED_EMPTY;
+
 import static com.android.server.ForceAppStandbyTracker.TARGET_OP;
 
 import static org.junit.Assert.assertEquals;
@@ -33,6 +35,7 @@
 import static org.mockito.Mockito.when;
 
 import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
 import android.app.AppOpsManager;
 import android.app.AppOpsManager.OpEntry;
 import android.app.AppOpsManager.PackageOps;
@@ -259,13 +262,19 @@
     private static final int JOBS_AND_ALARMS = ALARMS_ONLY | JOBS_ONLY;
 
     private void areRestricted(ForceAppStandbyTrackerTestable instance, int uid, String packageName,
-            int restrictionTypes) {
+            int restrictionTypes, boolean exemptFromBatterySaver) {
         assertEquals(((restrictionTypes & JOBS_ONLY) != 0),
-                instance.areJobsRestricted(uid, packageName));
+                instance.areJobsRestricted(uid, packageName, exemptFromBatterySaver));
         assertEquals(((restrictionTypes & ALARMS_ONLY) != 0),
                 instance.areAlarmsRestricted(uid, packageName));
     }
 
+    private void areRestricted(ForceAppStandbyTrackerTestable instance, int uid, String packageName,
+            int restrictionTypes) {
+        areRestricted(instance, uid, packageName, restrictionTypes,
+                /*exemptFromBatterySaver=*/ false);
+    }
+
     @Test
     public void testAll() throws Exception {
         final ForceAppStandbyTrackerTestable instance = newInstance();
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationGestureHandlerTest.java
index 8d5556e..07262e1 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationGestureHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationGestureHandlerTest.java
@@ -23,6 +23,8 @@
 
 import static com.android.server.testutils.TestUtils.strictMock;
 
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
@@ -32,6 +34,7 @@
 
 import android.annotation.NonNull;
 import android.content.Context;
+import android.os.Handler;
 import android.os.Message;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
@@ -46,7 +49,9 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.concurrent.CompletableFuture;
 import java.util.function.IntConsumer;
+import java.util.function.Supplier;
 
 
 /**
@@ -130,7 +135,7 @@
     }
 
     @NonNull
-    public MagnificationGestureHandler newInstance(boolean detectTripleTap,
+    private MagnificationGestureHandler newInstance(boolean detectTripleTap,
             boolean detectShortcutTrigger) {
         MagnificationGestureHandler h = new MagnificationGestureHandler(
                 mContext, mMagnificationController,
@@ -192,6 +197,16 @@
         });
     }
 
+    @Test
+    public void testTransitionToDelegatingStateAndClear_preservesShortcutTriggeredState() {
+        mMgh.mDetectingState.transitionToDelegatingStateAndClear();
+        assertFalse(mMgh.mDetectingState.mShortcutTriggered);
+
+        goFromStateIdleTo(STATE_SHORTCUT_TRIGGERED);
+        mMgh.mDetectingState.transitionToDelegatingStateAndClear();
+        assertTrue(mMgh.mDetectingState.mShortcutTriggered);
+    }
+
     /**
      * Covers edges of the graph not covered by "canonical" transitions specified in
      * {@link #goFromStateIdleTo} and {@link #returnToNormalFrom}
@@ -510,14 +525,20 @@
         fastForward(1);
     }
 
+    private static MotionEvent fromTouchscreen(MotionEvent ev) {
+        ev.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+        return ev;
+    }
+
     private MotionEvent moveEvent(float x, float y) {
-        return MotionEvent.obtain(mLastDownTime, mClock.now(), ACTION_MOVE, x, y, 0);
+        return fromTouchscreen(
+        	    MotionEvent.obtain(mLastDownTime, mClock.now(), ACTION_MOVE, x, y, 0));
     }
 
     private MotionEvent downEvent() {
         mLastDownTime = mClock.now();
-        return MotionEvent.obtain(mLastDownTime, mLastDownTime,
-                ACTION_DOWN, DEFAULT_X, DEFAULT_Y, 0);
+        return fromTouchscreen(MotionEvent.obtain(mLastDownTime, mLastDownTime,
+                ACTION_DOWN, DEFAULT_X, DEFAULT_Y, 0));
     }
 
     private MotionEvent upEvent() {
@@ -525,8 +546,8 @@
     }
 
     private MotionEvent upEvent(long downTime) {
-        return MotionEvent.obtain(downTime, mClock.now(),
-                MotionEvent.ACTION_UP, DEFAULT_X, DEFAULT_Y, 0);
+        return fromTouchscreen(MotionEvent.obtain(downTime, mClock.now(),
+                MotionEvent.ACTION_UP, DEFAULT_X, DEFAULT_Y, 0));
     }
 
     private MotionEvent pointerEvent(int action, float x, float y) {
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 725ede8..5825a8b7 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -78,6 +78,7 @@
 import android.security.KeyChain;
 import android.security.keystore.AttestationUtils;
 import android.telephony.TelephonyManager;
+import android.telephony.data.ApnSetting;
 import android.test.MoreAsserts;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.ArraySet;
@@ -126,6 +127,7 @@
             permission.MANAGE_DEVICE_ADMINS, permission.MANAGE_PROFILE_AND_DEVICE_OWNERS,
             permission.MANAGE_USERS, permission.INTERACT_ACROSS_USERS_FULL);
     public static final String NOT_DEVICE_OWNER_MSG = "does not own the device";
+    public static final String NOT_PROFILE_OWNER_MSG = "does not own the profile";
     public static final String ONGOING_CALL_MSG = "ongoing call on the device";
 
     // TODO replace all instances of this with explicit {@link #mServiceContext}.
@@ -301,10 +303,10 @@
 
         // Verify
         verify(getServices().usageStatsManagerInternal).setActiveAdminApps(
-                MockUtils.checkAdminApps(admin1.getPackageName()),
+                MockUtils.checkApps(admin1.getPackageName()),
                 eq(UserHandle.USER_SYSTEM));
         verify(getServices().usageStatsManagerInternal).setActiveAdminApps(
-                MockUtils.checkAdminApps(admin2.getPackageName(),
+                MockUtils.checkApps(admin2.getPackageName(),
                         adminAnotherPackage.getPackageName()),
                 eq(DpmMockContext.CALLER_USER_HANDLE));
         verify(getServices().usageStatsManagerInternal).onAdminDataAvailable();
@@ -705,7 +707,7 @@
 
         assertFalse(dpm.isAdminActiveAsUser(admin1, DpmMockContext.CALLER_USER_HANDLE));
         verify(getServices().usageStatsManagerInternal).setActiveAdminApps(
-                MockUtils.checkAdminApps(admin2.getPackageName()),
+                MockUtils.checkApps(admin2.getPackageName()),
                 eq(DpmMockContext.CALLER_USER_HANDLE));
 
         // Again broadcast from saveSettingsLocked().
@@ -1360,6 +1362,7 @@
                 eq(packageName),
                 anyInt(),
                 eq(userId));
+        doReturn(true).when(getServices().ipackageManager).isPackageAvailable(packageName, userId);
         // Setup application UID with the PackageManager
         doReturn(uid).when(getServices().packageManager).getPackageUidAsUser(
                 eq(packageName),
@@ -2101,6 +2104,53 @@
         }
     }
 
+    public void testSetGetMeteredDataDisabled() throws Exception {
+        setAsProfileOwner(admin1);
+
+        final ArrayList<String> emptyList = new ArrayList<>();
+        assertEquals(emptyList, dpm.getMeteredDataDisabled(admin1));
+
+        // Setup
+        final ArrayList<String> pkgsToRestrict = new ArrayList<>();
+        final String package1 = "com.example.one";
+        final String package2 = "com.example.two";
+        pkgsToRestrict.add(package1);
+        pkgsToRestrict.add(package2);
+        setupPackageInPackageManager(package1, DpmMockContext.CALLER_USER_HANDLE, 123, 0);
+        setupPackageInPackageManager(package2, DpmMockContext.CALLER_USER_HANDLE, 456, 0);
+        List<String> excludedPkgs = dpm.setMeteredDataDisabled(admin1, pkgsToRestrict);
+
+        // Verify
+        assertEquals(emptyList, excludedPkgs);
+        assertEquals(pkgsToRestrict, dpm.getMeteredDataDisabled(admin1));
+        verify(getServices().networkPolicyManagerInternal).setMeteredRestrictedPackages(
+                MockUtils.checkApps(pkgsToRestrict.toArray(new String[0])),
+                eq(DpmMockContext.CALLER_USER_HANDLE));
+
+        // Setup
+        pkgsToRestrict.remove(package1);
+        excludedPkgs = dpm.setMeteredDataDisabled(admin1, pkgsToRestrict);
+
+        // Verify
+        assertEquals(emptyList, excludedPkgs);
+        assertEquals(pkgsToRestrict, dpm.getMeteredDataDisabled(admin1));
+        verify(getServices().networkPolicyManagerInternal).setMeteredRestrictedPackages(
+                MockUtils.checkApps(pkgsToRestrict.toArray(new String[0])),
+                eq(DpmMockContext.CALLER_USER_HANDLE));
+    }
+
+    public void testSetGetMeteredDataDisabled_deviceAdmin() {
+        mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
+        dpm.setActiveAdmin(admin1, true);
+        assertTrue(dpm.isAdminActive(admin1));
+        mContext.callerPermissions.remove(permission.MANAGE_DEVICE_ADMINS);
+
+        assertExpectException(SecurityException.class,  /* messageRegex= */ NOT_PROFILE_OWNER_MSG,
+                () -> dpm.setMeteredDataDisabled(admin1, new ArrayList<>()));
+        assertExpectException(SecurityException.class,  /* messageRegex= */ NOT_PROFILE_OWNER_MSG,
+                () -> dpm.getMeteredDataDisabled(admin1));
+    }
+
     public void testCreateAdminSupportIntent() throws Exception {
         // Setup device owner.
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
@@ -4561,6 +4611,23 @@
                 MockUtils.checkUserHandle(UserHandle.USER_SYSTEM));
     }
 
+    public void testOverrideApnAPIsFailWithPO() throws Exception {
+        setupProfileOwner();
+        ApnSetting apn = (new ApnSetting.Builder()).build();
+        assertExpectException(SecurityException.class, null, () ->
+                dpm.addOverrideApn(admin1, apn));
+        assertExpectException(SecurityException.class, null, () ->
+                dpm.updateOverrideApn(admin1, 0, apn));
+        assertExpectException(SecurityException.class, null, () ->
+                dpm.removeOverrideApn(admin1, 0));
+        assertExpectException(SecurityException.class, null, () ->
+                dpm.getOverrideApns(admin1));
+        assertExpectException(SecurityException.class, null, () ->
+                dpm.setOverrideApnsEnabled(admin1, false));
+        assertExpectException(SecurityException.class, null, () ->
+                dpm.isOverrideApnEnabled(admin1));
+    }
+
     private void verifyCanGetOwnerInstalledCaCerts(
             final ComponentName caller, final DpmMockContext callerContext) throws Exception {
         final String alias = "cert";
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
index 0343a52..34c69f5 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
@@ -32,6 +32,7 @@
 import android.app.backup.IBackupManager;
 import android.app.usage.UsageStatsManagerInternal;
 import android.content.BroadcastReceiver;
+import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -39,8 +40,10 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.UserInfo;
+import android.database.Cursor;
 import android.media.IAudioService;
 import android.net.IIpConnectivityMetrics;
+import android.net.Uri;
 import android.net.wifi.WifiManager;
 import android.os.Handler;
 import android.os.PowerManager;
@@ -51,6 +54,7 @@
 import android.provider.Settings;
 import android.security.KeyChain;
 import android.telephony.TelephonyManager;
+import android.test.mock.MockContentProvider;
 import android.test.mock.MockContentResolver;
 import android.util.ArrayMap;
 import android.util.Pair;
@@ -144,6 +148,23 @@
         packageManager = spy(realContext.getPackageManager());
 
         contentResolver = new MockContentResolver();
+        contentResolver.addProvider("telephony", new MockContentProvider(realContext) {
+            @Override
+            public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+                return 0;
+            }
+
+            @Override
+            public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+                    String sortOrder) {
+                return null;
+            }
+
+            @Override
+            public int delete(Uri uri, String selection, String[] selectionArgs) {
+                return 0;
+            }
+        });
         contentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
 
         // Add the system user with a fake profile group already set up (this can happen in the real
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
index dec962e..92ea766 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
@@ -119,25 +119,25 @@
         return MockitoHamcrest.argThat(m);
     }
 
-    public static Set<String> checkAdminApps(String... adminApps) {
+    public static Set<String> checkApps(String... adminApps) {
         final Matcher<Set<String>> m = new BaseMatcher<Set<String>>() {
             @Override
             public boolean matches(Object item) {
                 if (item == null) return false;
-                final Set<String> actualAdminApps = (Set<String>) item;
-                if (adminApps.length != actualAdminApps.size()) {
+                final Set<String> actualApps = (Set<String>) item;
+                if (adminApps.length != actualApps.size()) {
                     return false;
                 }
-                final Set<String> copyOfAdmins = new ArraySet<>(actualAdminApps);
+                final Set<String> copyOfApps = new ArraySet<>(actualApps);
                 for (String adminApp : adminApps) {
-                    copyOfAdmins.remove(adminApp);
+                    copyOfApps.remove(adminApp);
                 }
-                return copyOfAdmins.isEmpty();
+                return copyOfApps.isEmpty();
             }
 
             @Override
             public void describeTo(Description description) {
-                description.appendText("Admin apps=" + Arrays.toString(adminApps));
+                description.appendText("Apps=" + Arrays.toString(adminApps));
             }
         };
         return MockitoHamcrest.argThat(m);
diff --git a/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java b/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java
index c5f8c90..675000e 100644
--- a/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java
@@ -171,6 +171,23 @@
                 newDataStore.getBrightnessConfiguration(0 /*userSerial*/));
     }
 
+    @Test
+    public void testNullBrightnessConfiguration() {
+        final float[] lux = { 0f, 10f };
+        final float[] nits = {1f, 100f };
+        final BrightnessConfiguration config = new BrightnessConfiguration.Builder(lux, nits)
+                .setDescription("a description")
+                .build();
+        mDataStore.loadIfNeeded();
+        assertNull(mDataStore.getBrightnessConfiguration(0 /*userSerial*/));
+
+        mDataStore.setBrightnessConfigurationForUser(config, 0, "packagename");
+        assertNotNull(mDataStore.getBrightnessConfiguration(0 /*userSerial*/));
+
+        mDataStore.setBrightnessConfigurationForUser(null, 0, "packagename");
+        assertNull(mDataStore.getBrightnessConfiguration(0 /*userSerial*/));
+    }
+
     public class TestInjector extends PersistentDataStore.Injector {
         private InputStream mReadStream;
         private OutputStream mWriteStream;
diff --git a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
index 43d026d..e2064aa 100644
--- a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
@@ -47,6 +47,8 @@
 
 /**
  * Test reading and writing correctly from file.
+ *
+ * atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
  */
 @RunWith(AndroidJUnit4.class)
 public class JobStoreTest {
@@ -116,6 +118,7 @@
                 .setPersisted(true)
                 .build();
         final JobStatus ts = JobStatus.createFromJobInfo(task, SOME_UID, null, -1, null);
+        ts.addInternalFlags(JobStatus.INTERNAL_FLAG_HAS_FOREGROUND_EXEMPTION);
         mTaskStoreUnderTest.add(ts);
         waitForPendingIo();
 
@@ -128,6 +131,8 @@
         assertTasksEqual(task, loadedTaskStatus.getJob());
         assertTrue("JobStore#contains invalid.", mTaskStoreUnderTest.containsJob(ts));
         assertEquals("Different uids.", SOME_UID, loadedTaskStatus.getUid());
+        assertEquals(JobStatus.INTERNAL_FLAG_HAS_FOREGROUND_EXEMPTION,
+                loadedTaskStatus.getInternalFlags());
         compareTimestampsSubjectToIoLatency("Early run-times not the same after read.",
                 ts.getEarliestRunTime(), loadedTaskStatus.getEarliestRunTime());
         compareTimestampsSubjectToIoLatency("Late run-times not the same after read.",
@@ -272,7 +277,7 @@
                 0 /* sourceUserId */, 0, 0, "someTag",
                 invalidEarlyRuntimeElapsedMillis, invalidLateRuntimeElapsedMillis,
                 0 /* lastSuccessfulRunTime */, 0 /* lastFailedRunTime */,
-                persistedExecutionTimesUTC);
+                persistedExecutionTimesUTC, 0 /* innerFlagg */);
 
         mTaskStoreUnderTest.add(js);
         waitForPendingIo();
diff --git a/services/tests/servicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java b/services/tests/servicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
index f6a749d..35cba18 100644
--- a/services/tests/servicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
@@ -164,6 +164,6 @@
     private static JobStatus createJobStatus(JobInfo.Builder job, long earliestRunTimeElapsedMillis,
             long latestRunTimeElapsedMillis) {
         return new JobStatus(job.build(), 0, null, -1, 0, 0, null, earliestRunTimeElapsedMillis,
-                latestRunTimeElapsedMillis, 0, 0, null);
+                latestRunTimeElapsedMillis, 0, 0, null, 0);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/job/controllers/JobStatusTest.java b/services/tests/servicestests/src/com/android/server/job/controllers/JobStatusTest.java
index 15c24ac..d78af22 100644
--- a/services/tests/servicestests/src/com/android/server/job/controllers/JobStatusTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/controllers/JobStatusTest.java
@@ -71,6 +71,6 @@
         final JobInfo job = new JobInfo.Builder(101, new ComponentName("foo", "bar"))
                 .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY).build();
         return new JobStatus(job, 0, null, -1, 0, 0, null, earliestRunTimeElapsedMillis,
-                latestRunTimeElapsedMillis, 0, 0, null);
+                latestRunTimeElapsedMillis, 0, 0, null, 0);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
index 7eec4fe..6a3a260 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
@@ -16,11 +16,11 @@
 
 package com.android.server.locksettings.recoverablekeystore;
 
-import static android.security.keystore.KeychainProtectionParams.TYPE_LOCKSCREEN;
+import static android.security.keystore.recovery.KeyChainProtectionParams.TYPE_LOCKSCREEN;
 
-import static android.security.keystore.KeychainProtectionParams.TYPE_PASSWORD;
-import static android.security.keystore.KeychainProtectionParams.TYPE_PATTERN;
-import static android.security.keystore.KeychainProtectionParams.TYPE_PIN;
+import static android.security.keystore.recovery.KeyChainProtectionParams.UI_FORMAT_PASSWORD;
+import static android.security.keystore.recovery.KeyChainProtectionParams.UI_FORMAT_PATTERN;
+import static android.security.keystore.recovery.KeyChainProtectionParams.UI_FORMAT_PIN;
 
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
@@ -40,9 +40,9 @@
 import android.security.keystore.AndroidKeyStoreSecretKey;
 import android.security.keystore.KeyGenParameterSpec;
 import android.security.keystore.KeyProperties;
-import android.security.keystore.KeyDerivationParams;
-import android.security.keystore.KeychainSnapshot;
-import android.security.keystore.WrappedApplicationKey;
+import android.security.keystore.recovery.KeyDerivationParams;
+import android.security.keystore.recovery.KeyChainSnapshot;
+import android.security.keystore.recovery.WrappedApplicationKey;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -190,19 +190,19 @@
 
     @Test
     public void getUiFormat_returnsPinIfPin() {
-        assertEquals(TYPE_PIN,
+        assertEquals(UI_FORMAT_PIN,
                 KeySyncTask.getUiFormat(CREDENTIAL_TYPE_PASSWORD, "1234"));
     }
 
     @Test
     public void getUiFormat_returnsPasswordIfPassword() {
-        assertEquals(TYPE_PASSWORD,
+        assertEquals(UI_FORMAT_PASSWORD,
                 KeySyncTask.getUiFormat(CREDENTIAL_TYPE_PASSWORD, "1234a"));
     }
 
     @Test
     public void getUiFormat_returnsPatternIfPattern() {
-        assertEquals(TYPE_PATTERN,
+        assertEquals(UI_FORMAT_PATTERN,
                 KeySyncTask.getUiFormat(CREDENTIAL_TYPE_PATTERN, "1234"));
 
     }
@@ -287,33 +287,33 @@
 
         mKeySyncTask.run();
 
-        KeychainSnapshot keychainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
-        KeyDerivationParams KeyDerivationParams =
-                keychainSnapshot.getKeychainProtectionParams().get(0).getKeyDerivationParams();
-        assertThat(KeyDerivationParams.getAlgorithm()).isEqualTo(
+        KeyChainSnapshot keyChainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+        KeyDerivationParams keyDerivationParams =
+                keyChainSnapshot.getKeyChainProtectionParams().get(0).getKeyDerivationParams();
+        assertThat(keyDerivationParams.getAlgorithm()).isEqualTo(
                 KeyDerivationParams.ALGORITHM_SHA256);
         verify(mSnapshotListenersStorage).recoverySnapshotAvailable(TEST_RECOVERY_AGENT_UID);
         byte[] lockScreenHash = KeySyncTask.hashCredentials(
-                KeyDerivationParams.getSalt(),
+                keyDerivationParams.getSalt(),
                 TEST_CREDENTIAL);
         Long counterId = mRecoverableKeyStoreDb.getCounterId(TEST_USER_ID, TEST_RECOVERY_AGENT_UID);
         counterId = 1L; // TODO: use value from the database.
         assertThat(counterId).isNotNull();
         byte[] recoveryKey = decryptThmEncryptedKey(
                 lockScreenHash,
-                keychainSnapshot.getEncryptedRecoveryKeyBlob(),
+                keyChainSnapshot.getEncryptedRecoveryKeyBlob(),
                 /*vaultParams=*/ KeySyncUtils.packVaultParams(
                         mKeyPair.getPublic(),
                         counterId,
                         /*maxAttempts=*/ 10,
                         TEST_VAULT_HANDLE));
-        List<WrappedApplicationKey> applicationKeys = keychainSnapshot.getWrappedApplicationKeys();
+        List<WrappedApplicationKey> applicationKeys = keyChainSnapshot.getWrappedApplicationKeys();
         assertThat(applicationKeys).hasSize(1);
-        assertThat(keychainSnapshot.getCounterId()).isEqualTo(counterId);
-        assertThat(keychainSnapshot.getMaxAttempts()).isEqualTo(10);
-        assertThat(keychainSnapshot.getTrustedHardwarePublicKey())
+        assertThat(keyChainSnapshot.getCounterId()).isEqualTo(counterId);
+        assertThat(keyChainSnapshot.getMaxAttempts()).isEqualTo(10);
+        assertThat(keyChainSnapshot.getTrustedHardwarePublicKey())
                 .isEqualTo(SecureBox.encodePublicKey(mKeyPair.getPublic()));
-        assertThat(keychainSnapshot.getServerParams()).isEqualTo(TEST_VAULT_HANDLE);
+        assertThat(keyChainSnapshot.getServerParams()).isEqualTo(TEST_VAULT_HANDLE);
         WrappedApplicationKey keyData = applicationKeys.get(0);
         assertEquals(TEST_APP_KEY_ALIAS, keyData.getAlias());
         assertThat(keyData.getAlias()).isEqualTo(keyData.getAlias());
@@ -332,14 +332,14 @@
 
         mKeySyncTask.run();
 
-        KeychainSnapshot keychainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
-        assertThat(keychainSnapshot.getSnapshotVersion()).isEqualTo(1); // default value;
+        KeyChainSnapshot keyChainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+        assertThat(keyChainSnapshot.getSnapshotVersion()).isEqualTo(1); // default value;
         mRecoverableKeyStoreDb.setShouldCreateSnapshot(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, true);
 
         mKeySyncTask.run();
 
-        keychainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
-        assertThat(keychainSnapshot.getSnapshotVersion()).isEqualTo(2); // Updated
+        keyChainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+        assertThat(keyChainSnapshot.getSnapshotVersion()).isEqualTo(2); // Updated
     }
 
     @Test
@@ -362,10 +362,10 @@
 
         mKeySyncTask.run();
 
-        KeychainSnapshot keychainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
-        assertThat(keychainSnapshot.getKeychainProtectionParams()).hasSize(1);
-        assertThat(keychainSnapshot.getKeychainProtectionParams().get(0).getLockScreenUiFormat()).
-                isEqualTo(TYPE_PASSWORD);
+        KeyChainSnapshot keyChainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+        assertThat(keyChainSnapshot.getKeyChainProtectionParams()).hasSize(1);
+        assertThat(keyChainSnapshot.getKeyChainProtectionParams().get(0).getLockScreenUiFormat()).
+                isEqualTo(UI_FORMAT_PASSWORD);
     }
 
    @Test
@@ -388,11 +388,11 @@
 
         mKeySyncTask.run();
 
-        KeychainSnapshot keychainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
-        assertThat(keychainSnapshot.getKeychainProtectionParams()).hasSize(1);
+        KeyChainSnapshot keyChainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+        assertThat(keyChainSnapshot.getKeyChainProtectionParams()).hasSize(1);
         // Password with only digits is changed to pin.
-        assertThat(keychainSnapshot.getKeychainProtectionParams().get(0).getLockScreenUiFormat()).
-                isEqualTo(TYPE_PIN);
+        assertThat(keyChainSnapshot.getKeyChainProtectionParams().get(0).getLockScreenUiFormat()).
+                isEqualTo(UI_FORMAT_PIN);
     }
 
     @Test
@@ -415,10 +415,10 @@
 
         mKeySyncTask.run();
 
-        KeychainSnapshot keychainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
-        assertThat(keychainSnapshot.getKeychainProtectionParams()).hasSize(1);
-        assertThat(keychainSnapshot.getKeychainProtectionParams().get(0).getLockScreenUiFormat()).
-                isEqualTo(TYPE_PATTERN);
+        KeyChainSnapshot keyChainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+        assertThat(keyChainSnapshot.getKeyChainProtectionParams()).hasSize(1);
+        assertThat(keyChainSnapshot.getKeyChainProtectionParams().get(0).getLockScreenUiFormat()).
+                isEqualTo(UI_FORMAT_PATTERN);
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
index 970bc33..c863aab 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
@@ -16,8 +16,8 @@
 
 package com.android.server.locksettings.recoverablekeystore;
 
-import static android.security.keystore.KeychainProtectionParams.TYPE_LOCKSCREEN;
-import static android.security.keystore.KeychainProtectionParams.TYPE_PASSWORD;
+import static android.security.keystore.recovery.KeyChainProtectionParams.TYPE_LOCKSCREEN;
+import static android.security.keystore.recovery.KeyChainProtectionParams.UI_FORMAT_PASSWORD;
 
 import static com.google.common.truth.Truth.assertThat;
 import static org.junit.Assert.assertArrayEquals;
@@ -42,9 +42,9 @@
 import android.security.keystore.AndroidKeyStoreSecretKey;
 import android.security.keystore.KeyGenParameterSpec;
 import android.security.keystore.KeyProperties;
-import android.security.keystore.KeyDerivationParams;
-import android.security.keystore.KeychainProtectionParams;
-import android.security.keystore.WrappedApplicationKey;
+import android.security.keystore.recovery.KeyDerivationParams;
+import android.security.keystore.recovery.KeyChainProtectionParams;
+import android.security.keystore.recovery.WrappedApplicationKey;
 import android.support.test.filters.SmallTest;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
@@ -250,9 +250,9 @@
                 TEST_VAULT_PARAMS,
                 TEST_VAULT_CHALLENGE,
                 ImmutableList.of(
-                        new KeychainProtectionParams(
+                        new KeyChainProtectionParams(
                                 TYPE_LOCKSCREEN,
-                                TYPE_PASSWORD,
+                                UI_FORMAT_PASSWORD,
                                 KeyDerivationParams.createSha256Params(TEST_SALT),
                                 TEST_SECRET)));
 
@@ -269,9 +269,9 @@
                 TEST_VAULT_PARAMS,
                 TEST_VAULT_CHALLENGE,
                 ImmutableList.of(
-                        new KeychainProtectionParams(
+                        new KeyChainProtectionParams(
                                 TYPE_LOCKSCREEN,
-                                TYPE_PASSWORD,
+                                UI_FORMAT_PASSWORD,
                                 KeyDerivationParams.createSha256Params(TEST_SALT),
                                 TEST_SECRET)));
 
@@ -290,9 +290,9 @@
                 TEST_VAULT_PARAMS,
                 TEST_VAULT_CHALLENGE,
                 ImmutableList.of(
-                        new KeychainProtectionParams(
+                        new KeyChainProtectionParams(
                                 TYPE_LOCKSCREEN,
-                                TYPE_PASSWORD,
+                                UI_FORMAT_PASSWORD,
                                 KeyDerivationParams.createSha256Params(TEST_SALT),
                                 TEST_SECRET)));
 
@@ -309,9 +309,9 @@
                 TEST_VAULT_PARAMS,
                 TEST_VAULT_CHALLENGE,
                 ImmutableList.of(
-                        new KeychainProtectionParams(
+                        new KeyChainProtectionParams(
                                 TYPE_LOCKSCREEN,
-                                TYPE_PASSWORD,
+                                UI_FORMAT_PASSWORD,
                                 KeyDerivationParams.createSha256Params(TEST_SALT),
                                 TEST_SECRET)));
 
@@ -332,7 +332,7 @@
             fail("should have thrown");
         } catch (UnsupportedOperationException e) {
             assertThat(e.getMessage()).startsWith(
-                    "Only a single KeychainProtectionParams is supported");
+                    "Only a single KeyChainProtectionParams is supported");
         }
     }
 
@@ -345,9 +345,9 @@
                     TEST_VAULT_PARAMS,
                     TEST_VAULT_CHALLENGE,
                     ImmutableList.of(
-                            new KeychainProtectionParams(
+                            new KeyChainProtectionParams(
                                     TYPE_LOCKSCREEN,
-                                    TYPE_PASSWORD,
+                                    UI_FORMAT_PASSWORD,
                                     KeyDerivationParams.createSha256Params(TEST_SALT),
                                     TEST_SECRET)));
             fail("should have thrown");
@@ -367,9 +367,9 @@
                     vaultParams,
                     TEST_VAULT_CHALLENGE,
                     ImmutableList.of(
-                            new KeychainProtectionParams(
+                            new KeyChainProtectionParams(
                                     TYPE_LOCKSCREEN,
-                                    TYPE_PASSWORD,
+                                    UI_FORMAT_PASSWORD,
                                     KeyDerivationParams.createSha256Params(TEST_SALT),
                                     TEST_SECRET)));
             fail("should have thrown");
@@ -400,9 +400,9 @@
                 TEST_PUBLIC_KEY,
                 TEST_VAULT_PARAMS,
                 TEST_VAULT_CHALLENGE,
-                ImmutableList.of(new KeychainProtectionParams(
+                ImmutableList.of(new KeyChainProtectionParams(
                         TYPE_LOCKSCREEN,
-                        TYPE_PASSWORD,
+                        UI_FORMAT_PASSWORD,
                         KeyDerivationParams.createSha256Params(TEST_SALT),
                         TEST_SECRET)));
 
@@ -424,9 +424,9 @@
                 TEST_PUBLIC_KEY,
                 TEST_VAULT_PARAMS,
                 TEST_VAULT_CHALLENGE,
-                ImmutableList.of(new KeychainProtectionParams(
+                ImmutableList.of(new KeyChainProtectionParams(
                         TYPE_LOCKSCREEN,
-                        TYPE_PASSWORD,
+                        UI_FORMAT_PASSWORD,
                         KeyDerivationParams.createSha256Params(TEST_SALT),
                         TEST_SECRET)));
         byte[] keyClaimant = mRecoverySessionStorage.get(Binder.getCallingUid(), TEST_SESSION_ID)
@@ -456,9 +456,9 @@
                 TEST_PUBLIC_KEY,
                 TEST_VAULT_PARAMS,
                 TEST_VAULT_CHALLENGE,
-                ImmutableList.of(new KeychainProtectionParams(
+                ImmutableList.of(new KeyChainProtectionParams(
                         TYPE_LOCKSCREEN,
-                        TYPE_PASSWORD,
+                        UI_FORMAT_PASSWORD,
                         KeyDerivationParams.createSha256Params(TEST_SALT),
                         TEST_SECRET)));
         byte[] keyClaimant = mRecoverySessionStorage.get(Binder.getCallingUid(), TEST_SESSION_ID)
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorageTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorageTest.java
index 56b44e2..d61a294 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorageTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorageTest.java
@@ -3,7 +3,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 
-import android.security.keystore.KeychainSnapshot;
+import android.security.keystore.recovery.KeyChainSnapshot;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
@@ -26,25 +26,25 @@
     @Test
     public void get_returnsSetSnapshot() {
         int userId = 1000;
-        KeychainSnapshot keychainSnapshot = new KeychainSnapshot(
+        KeyChainSnapshot keyChainSnapshot = new KeyChainSnapshot(
                 /*snapshotVersion=*/ 1,
                 new ArrayList<>(),
                 new ArrayList<>(),
                 new byte[0]);
-        mRecoverySnapshotStorage.put(userId, keychainSnapshot);
+        mRecoverySnapshotStorage.put(userId, keyChainSnapshot);
 
-        assertEquals(keychainSnapshot, mRecoverySnapshotStorage.get(userId));
+        assertEquals(keyChainSnapshot, mRecoverySnapshotStorage.get(userId));
     }
 
     @Test
     public void remove_removesSnapshots() {
         int userId = 1000;
-        KeychainSnapshot keychainSnapshot = new KeychainSnapshot(
+        KeyChainSnapshot keyChainSnapshot = new KeyChainSnapshot(
                 /*snapshotVersion=*/ 1,
                 new ArrayList<>(),
                 new ArrayList<>(),
                 new byte[0]);
-        mRecoverySnapshotStorage.put(userId, keychainSnapshot);
+        mRecoverySnapshotStorage.put(userId, keyChainSnapshot);
 
         mRecoverySnapshotStorage.remove(userId);
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index 49601c3..5c7348c 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -497,7 +497,9 @@
                 new PackageParser.SigningDetails(
                         new Signature[] { new Signature(new byte[16]) },
                         2,
-                        new ArraySet<>());
+                        new ArraySet<>(),
+                        null,
+                        null);
         pkg.mExtras = new Bundle();
         pkg.mRestrictedAccountType = "foo19";
         pkg.mRequiredAccountType = "foo20";
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java b/services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java
index f8db4fa..794d033 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java
@@ -54,7 +54,7 @@
     @Test
     public void testApply_clipNone() {
         Rect windowCrop = new Rect(0, 0, 20, 20);
-        Animation a = new ClipRectAnimation(windowCrop, windowCrop);
+        Animation a = createClipRectAnimation(windowCrop, windowCrop);
         WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null,
                 mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_NONE);
         windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
@@ -99,7 +99,8 @@
     public void testApply_clipBeforeNoStackBounds() {
         // Stack bounds is (0, 0, 0, 0) animation clip is (0, 0, 20, 20)
         Rect windowCrop = new Rect(0, 0, 20, 20);
-        Animation a = new ClipRectAnimation(windowCrop, windowCrop);
+        Animation a = createClipRectAnimation(windowCrop, windowCrop);
+        a.initialize(0, 0, 0, 0);
         WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null,
                 null, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM);
         windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
@@ -110,7 +111,7 @@
     public void testApply_clipBeforeSmallerAnimationClip() {
         // Stack bounds is (0, 0, 10, 10) animation clip is (0, 0, 5, 5)
         Rect windowCrop = new Rect(0, 0, 5, 5);
-        Animation a = new ClipRectAnimation(windowCrop, windowCrop);
+        Animation a = createClipRectAnimation(windowCrop, windowCrop);
         WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null,
                 mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM);
         windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
@@ -122,11 +123,17 @@
     public void testApply_clipBeforeSmallerStackClip() {
         // Stack bounds is (0, 0, 10, 10) animation clip is (0, 0, 20, 20)
         Rect windowCrop = new Rect(0, 0, 20, 20);
-        Animation a = new ClipRectAnimation(windowCrop, windowCrop);
+        Animation a = createClipRectAnimation(windowCrop, windowCrop);
         WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null,
                 mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM);
         windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
         verify(mTransaction).setWindowCrop(eq(mSurfaceControl),
                 argThat(rect -> rect.equals(mStackBounds)));
     }
+
+    private Animation createClipRectAnimation(Rect fromClip, Rect toClip) {
+        Animation a = new ClipRectAnimation(fromClip, toClip);
+        a.initialize(0, 0, 0, 0);
+        return a;
+    }
 }
diff --git a/services/usage/java/com/android/server/usage/IntervalStats.java b/services/usage/java/com/android/server/usage/IntervalStats.java
index cb32d1f..4d458b0 100644
--- a/services/usage/java/com/android/server/usage/IntervalStats.java
+++ b/services/usage/java/com/android/server/usage/IntervalStats.java
@@ -92,6 +92,17 @@
         return false;
     }
 
+    /**
+     * Returns whether the event type is one caused by user visible
+     * interaction. Excludes those that are internally generated.
+     * @param eventType
+     * @return
+     */
+    private boolean isUserVisibleEvent(int eventType) {
+        return eventType != UsageEvents.Event.SYSTEM_INTERACTION
+                && eventType != UsageEvents.Event.STANDBY_BUCKET_CHANGED;
+    }
+
     void update(String packageName, long timeStamp, int eventType) {
         UsageStats usageStats = getOrCreateUsageStats(packageName);
 
@@ -109,7 +120,7 @@
             usageStats.mLastEvent = eventType;
         }
 
-        if (eventType != UsageEvents.Event.SYSTEM_INTERACTION) {
+        if (isUserVisibleEvent(eventType)) {
             usageStats.mLastTimeUsed = timeStamp;
         }
         usageStats.mEndTimeStamp = timeStamp;
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 979feaa..096fdcc 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -115,6 +115,26 @@
 
     AppStandbyController mAppStandby;
 
+    private UsageStatsManagerInternal.AppIdleStateChangeListener mStandbyChangeListener =
+            new UsageStatsManagerInternal.AppIdleStateChangeListener() {
+                @Override
+                public void onAppIdleStateChanged(String packageName, int userId, boolean idle,
+                        int bucket) {
+                    Event event = new Event();
+                    event.mEventType = Event.STANDBY_BUCKET_CHANGED;
+                    event.mBucket = bucket;
+                    event.mPackage = packageName;
+                    // This will later be converted to system time.
+                    event.mTimeStamp = SystemClock.elapsedRealtime();
+                    mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
+                }
+
+                @Override
+                public void onParoleStateChanged(boolean isParoleOn) {
+
+                }
+            };
+
     public UsageStatsService(Context context) {
         super(context);
     }
@@ -129,6 +149,7 @@
 
         mAppStandby = new AppStandbyController(getContext(), BackgroundThread.get().getLooper());
 
+        mAppStandby.addListener(mStandbyChangeListener);
         File systemDataDir = new File(Environment.getDataDirectory(), "system");
         mUsageStatsDir = new File(systemDataDir, "usagestats");
         mUsageStatsDir.mkdirs();
diff --git a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
index cc53a9c..d1ed599 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
@@ -64,6 +64,7 @@
     private static final String LAST_EVENT_ATTR = "lastEvent";
     private static final String TYPE_ATTR = "type";
     private static final String SHORTCUT_ID_ATTR = "shortcutId";
+    private static final String STANDBY_BUCKET_ATTR = "standbyBucket";
 
     // Time attributes stored as an offset of the beginTime.
     private static final String LAST_TIME_ACTIVE_ATTR = "lastTimeActive";
@@ -173,6 +174,9 @@
                 final String id = XmlUtils.readStringAttribute(parser, SHORTCUT_ID_ATTR);
                 event.mShortcutId = (id != null) ? id.intern() : null;
                 break;
+            case UsageEvents.Event.STANDBY_BUCKET_CHANGED:
+                event.mBucket = XmlUtils.readIntAttribute(parser, STANDBY_BUCKET_ATTR, 0);
+                break;
         }
 
         if (statsOut.events == null) {
@@ -276,6 +280,10 @@
                     XmlUtils.writeStringAttribute(xml, SHORTCUT_ID_ATTR, event.mShortcutId);
                 }
                 break;
+            case UsageEvents.Event.STANDBY_BUCKET_CHANGED:
+                if (event.mBucket != 0) {
+                    XmlUtils.writeIntAttribute(xml, STANDBY_BUCKET_ATTR, event.mBucket);
+                }
         }
 
         xml.endTag(null, EVENT_TAG);
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index f02221c..ec12da2 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -599,6 +599,9 @@
             if (event.mShortcutId != null) {
                 pw.printPair("shortcutId", event.mShortcutId);
             }
+            if (event.mEventType == UsageEvents.Event.STANDBY_BUCKET_CHANGED) {
+                pw.printPair("standbyBucket", event.mBucket);
+            }
             pw.printHexPair("flags", event.mFlags);
             pw.println();
         }
@@ -645,6 +648,8 @@
                 return "CHOOSER_ACTION";
             case UsageEvents.Event.NOTIFICATION_SEEN:
                 return "NOTIFICATION_SEEN";
+            case UsageEvents.Event.STANDBY_BUCKET_CHANGED:
+                return "STANDBY_BUCKET_CHANGED";
             default:
                 return "UNKNOWN";
         }
diff --git a/telephony/java/android/telephony/AccessNetworkConstants.java b/telephony/java/android/telephony/AccessNetworkConstants.java
index fc814be..703f96d 100644
--- a/telephony/java/android/telephony/AccessNetworkConstants.java
+++ b/telephony/java/android/telephony/AccessNetworkConstants.java
@@ -16,6 +16,8 @@
 
 package android.telephony;
 
+import android.annotation.SystemApi;
+
 /**
  * Contains access network related constants.
  */
@@ -30,6 +32,18 @@
     }
 
     /**
+     * Wireless transportation type
+     * @hide
+     */
+    @SystemApi
+    public static final class TransportType {
+        /** Wireless Wide Area Networks (i.e. Cellular) */
+        public static final int WWAN = 1;
+        /** Wireless Local Area Networks (i.e. Wifi) */
+        public static final int WLAN = 2;
+    }
+
+    /**
      * Frenquency bands for GERAN.
      * http://www.etsi.org/deliver/etsi_ts/145000_145099/145005/14.00.00_60/ts_145005v140000p.pdf
      */
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 649d478..cbc9428 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -275,7 +275,6 @@
      *
      * @see SubscriptionManager#getSubscriptionPlans(int)
      * @see SubscriptionManager#setSubscriptionPlans(int, java.util.List)
-     * @hide
      */
     @SystemApi
     public static final String KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING =
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index d2134f9..fc2ef27 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -51,12 +51,15 @@
         "none", "poor", "moderate", "good", "great"
     };
 
-    /** @hide */
-    //Use int max, as -1 is a valid value in signal strength
-    public static final int INVALID = 0x7FFFFFFF;
+    /**
+     * Use Integer.MAX_VALUE because -1 is a valid value in signal strength.
+     * @hide
+     */
+    public static final int INVALID = Integer.MAX_VALUE;
 
     private static final int LTE_RSRP_THRESHOLDS_NUM = 6;
 
+    /** Parameters reported by the Radio */
     private int mGsmSignalStrength; // Valid values are (0-31, 99) as defined in TS 27.007 8.5
     private int mGsmBitErrorRate;   // bit error rate (0-7, 99) as defined in TS 27.007 8.5
     private int mCdmaDbm;   // This value is the RSSI value
@@ -69,11 +72,13 @@
     private int mLteRsrq;
     private int mLteRssnr;
     private int mLteCqi;
-    private int mLteRsrpBoost; // offset to be reduced from the rsrp threshold while calculating
-                                // signal strength level
     private int mTdScdmaRscp;
 
-    private boolean isGsm; // This value is set by the ServiceStateTracker onSignalStrengthResult
+    /** Parameters from the framework */
+    private int mLteRsrpBoost; // offset to be reduced from the rsrp threshold while calculating
+                                // signal strength level
+    private boolean mIsGsm; // This value is set by the ServiceStateTracker
+                            // onSignalStrengthResult.
     private boolean mUseOnlyRsrpForLteLevel; // Use only RSRP for the number of LTE signal bar.
 
     // The threshold of LTE RSRP for determining the display level of LTE signal bar.
@@ -103,28 +108,12 @@
      * @hide
      */
     public SignalStrength() {
-        mGsmSignalStrength = 99;
-        mGsmBitErrorRate = -1;
-        mCdmaDbm = -1;
-        mCdmaEcio = -1;
-        mEvdoDbm = -1;
-        mEvdoEcio = -1;
-        mEvdoSnr = -1;
-        mLteSignalStrength = 99;
-        mLteRsrp = INVALID;
-        mLteRsrq = INVALID;
-        mLteRssnr = INVALID;
-        mLteCqi = INVALID;
-        mLteRsrpBoost = 0;
-        mTdScdmaRscp = INVALID;
-        isGsm = true;
-        mUseOnlyRsrpForLteLevel = false;
-        setLteRsrpThresholds(getDefaultLteRsrpThresholds());
+        this(true);
     }
 
     /**
      * This constructor is used to create SignalStrength with default
-     * values and set the isGsmFlag with the value passed in the input
+     * values and set the gsmFlag with the value passed in the input
      *
      * @param gsmFlag true if Gsm Phone,false if Cdma phone
      * @return newly created SignalStrength
@@ -143,134 +132,26 @@
         mLteRsrq = INVALID;
         mLteRssnr = INVALID;
         mLteCqi = INVALID;
-        mLteRsrpBoost = 0;
         mTdScdmaRscp = INVALID;
-        isGsm = gsmFlag;
+        mLteRsrpBoost = 0;
+        mIsGsm = gsmFlag;
         mUseOnlyRsrpForLteLevel = false;
         setLteRsrpThresholds(getDefaultLteRsrpThresholds());
     }
 
     /**
-     * Constructor
+     * Constructor with all fields present
      *
      * @hide
      */
-    public SignalStrength(int gsmSignalStrength, int gsmBitErrorRate,
+    public SignalStrength(
+            int gsmSignalStrength, int gsmBitErrorRate,
             int cdmaDbm, int cdmaEcio,
             int evdoDbm, int evdoEcio, int evdoSnr,
             int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
-            int lteRsrpBoost, int tdScdmaRscp, boolean gsmFlag, boolean lteLevelBaseOnRsrp) {
-        initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
-                evdoDbm, evdoEcio, evdoSnr, lteSignalStrength, lteRsrp,
-                lteRsrq, lteRssnr, lteCqi, lteRsrpBoost, gsmFlag, lteLevelBaseOnRsrp);
-        mTdScdmaRscp = tdScdmaRscp;
-    }
-
-    /**
-     * Constructor
-     *
-     * @hide
-     */
-    public SignalStrength(int gsmSignalStrength, int gsmBitErrorRate,
-            int cdmaDbm, int cdmaEcio,
-            int evdoDbm, int evdoEcio, int evdoSnr,
-            int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
-            int tdScdmaRscp, boolean gsmFlag) {
-        initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
-                evdoDbm, evdoEcio, evdoSnr, lteSignalStrength, lteRsrp,
-                lteRsrq, lteRssnr, lteCqi, 0, gsmFlag, false);
-        mTdScdmaRscp = tdScdmaRscp;
-    }
-
-    /**
-     * Constructor
-     *
-     * @hide
-     */
-    public SignalStrength(int gsmSignalStrength, int gsmBitErrorRate,
-            int cdmaDbm, int cdmaEcio,
-            int evdoDbm, int evdoEcio, int evdoSnr,
-            int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
-            boolean gsmFlag) {
-        initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
-                evdoDbm, evdoEcio, evdoSnr, lteSignalStrength, lteRsrp,
-                lteRsrq, lteRssnr, lteCqi, 0, gsmFlag, false);
-    }
-
-    /**
-     * Constructor
-     *
-     * @hide
-     */
-    public SignalStrength(int gsmSignalStrength, int gsmBitErrorRate,
-            int cdmaDbm, int cdmaEcio,
-            int evdoDbm, int evdoEcio, int evdoSnr,
-            boolean gsmFlag) {
-        initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
-                evdoDbm, evdoEcio, evdoSnr, 99, INVALID,
-                INVALID, INVALID, INVALID, 0, gsmFlag, false);
-    }
-
-    /**
-     * Copy constructors
-     *
-     * @param s Source SignalStrength
-     *
-     * @hide
-     */
-    public SignalStrength(SignalStrength s) {
-        copyFrom(s);
-    }
-
-    /**
-     * Initialize gsm/cdma values, sets lte values to defaults.
-     *
-     * @param gsmSignalStrength
-     * @param gsmBitErrorRate
-     * @param cdmaDbm
-     * @param cdmaEcio
-     * @param evdoDbm
-     * @param evdoEcio
-     * @param evdoSnr
-     * @param gsm
-     *
-     * @hide
-     */
-    public void initialize(int gsmSignalStrength, int gsmBitErrorRate,
-            int cdmaDbm, int cdmaEcio,
-            int evdoDbm, int evdoEcio, int evdoSnr,
-            boolean gsm) {
-        initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
-                evdoDbm, evdoEcio, evdoSnr, 99, INVALID,
-                INVALID, INVALID, INVALID, 0, gsm, false);
-    }
-
-    /**
-     * Initialize all the values
-     *
-     * @param gsmSignalStrength
-     * @param gsmBitErrorRate
-     * @param cdmaDbm
-     * @param cdmaEcio
-     * @param evdoDbm
-     * @param evdoEcio
-     * @param evdoSnr
-     * @param lteSignalStrength
-     * @param lteRsrp
-     * @param lteRsrq
-     * @param lteRssnr
-     * @param lteCqi
-     * @param lteRsrpBoost
-     * @param gsm
-     * @param useOnlyRsrpForLteLevel
-     *
-     * @hide
-     */
-    public void initialize(int gsmSignalStrength, int gsmBitErrorRate,
-            int cdmaDbm, int cdmaEcio,
-            int evdoDbm, int evdoEcio, int evdoSnr,
-            int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
-            int lteRsrpBoost, boolean gsm, boolean useOnlyRsrpForLteLevel) {
+            int tdScdmaRscp,
+            // values Added by config
+            int lteRsrpBoost, boolean gsmFlag, boolean lteLevelBaseOnRsrp) {
         mGsmSignalStrength = gsmSignalStrength;
         mGsmBitErrorRate = gsmBitErrorRate;
         mCdmaDbm = cdmaDbm;
@@ -283,16 +164,41 @@
         mLteRsrq = lteRsrq;
         mLteRssnr = lteRssnr;
         mLteCqi = lteCqi;
-        mLteRsrpBoost = lteRsrpBoost;
         mTdScdmaRscp = INVALID;
-        isGsm = gsm;
-        mUseOnlyRsrpForLteLevel = useOnlyRsrpForLteLevel;
-
+        mLteRsrpBoost = lteRsrpBoost;
+        mIsGsm = gsmFlag;
+        mUseOnlyRsrpForLteLevel = lteLevelBaseOnRsrp;
         setLteRsrpThresholds(getDefaultLteRsrpThresholds());
         if (DBG) log("initialize: " + toString());
     }
 
     /**
+     * Constructor for only values provided by Radio HAL
+     *
+     * @hide
+     */
+    public SignalStrength(int gsmSignalStrength, int gsmBitErrorRate,
+            int cdmaDbm, int cdmaEcio,
+            int evdoDbm, int evdoEcio, int evdoSnr,
+            int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
+            int tdScdmaRscp) {
+        this(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
+                evdoDbm, evdoEcio, evdoSnr, lteSignalStrength, lteRsrp,
+                lteRsrq, lteRssnr, lteCqi, tdScdmaRscp, 0, true, false);
+    }
+
+    /**
+     * Copy constructors
+     *
+     * @param s Source SignalStrength
+     *
+     * @hide
+     */
+    public SignalStrength(SignalStrength s) {
+        copyFrom(s);
+    }
+
+    /**
      * @hide
      */
     protected void copyFrom(SignalStrength s) {
@@ -308,9 +214,9 @@
         mLteRsrq = s.mLteRsrq;
         mLteRssnr = s.mLteRssnr;
         mLteCqi = s.mLteCqi;
-        mLteRsrpBoost = s.mLteRsrpBoost;
         mTdScdmaRscp = s.mTdScdmaRscp;
-        isGsm = s.isGsm;
+        mLteRsrpBoost = s.mLteRsrpBoost;
+        mIsGsm = s.mIsGsm;
         mUseOnlyRsrpForLteLevel = s.mUseOnlyRsrpForLteLevel;
         setLteRsrpThresholds(s.mLteRsrpThresholds);
     }
@@ -335,40 +241,11 @@
         mLteRsrq = in.readInt();
         mLteRssnr = in.readInt();
         mLteCqi = in.readInt();
-        mLteRsrpBoost = in.readInt();
         mTdScdmaRscp = in.readInt();
-        isGsm = (in.readInt() != 0);
-        mUseOnlyRsrpForLteLevel = (in.readInt() != 0);
-        for (int i = 0; i < LTE_RSRP_THRESHOLDS_NUM; i++) {
-            mLteRsrpThresholds[i] = in.readInt();
-        }
-    }
-
-    /**
-     * Make a SignalStrength object from the given parcel as passed up by
-     * the ril which does not have isGsm. isGsm will be changed by ServiceStateTracker
-     * so the default is a don't care.
-     *
-     * @hide
-     */
-    public static SignalStrength makeSignalStrengthFromRilParcel(Parcel in) {
-        if (DBG) log("Size of signalstrength parcel:" + in.dataSize());
-
-        SignalStrength ss = new SignalStrength();
-        ss.mGsmSignalStrength = in.readInt();
-        ss.mGsmBitErrorRate = in.readInt();
-        ss.mCdmaDbm = in.readInt();
-        ss.mCdmaEcio = in.readInt();
-        ss.mEvdoDbm = in.readInt();
-        ss.mEvdoEcio = in.readInt();
-        ss.mEvdoSnr = in.readInt();
-        ss.mLteSignalStrength = in.readInt();
-        ss.mLteRsrp = in.readInt();
-        ss.mLteRsrq = in.readInt();
-        ss.mLteRssnr = in.readInt();
-        ss.mLteCqi = in.readInt();
-        ss.mTdScdmaRscp = in.readInt();
-        return ss;
+        mLteRsrpBoost = in.readInt();
+        mIsGsm = in.readBoolean();
+        mUseOnlyRsrpForLteLevel = in.readBoolean();
+        in.readIntArray(mLteRsrpThresholds);
     }
 
     /**
@@ -387,13 +264,11 @@
         out.writeInt(mLteRsrq);
         out.writeInt(mLteRssnr);
         out.writeInt(mLteCqi);
-        out.writeInt(mLteRsrpBoost);
         out.writeInt(mTdScdmaRscp);
-        out.writeInt(isGsm ? 1 : 0);
-        out.writeInt(mUseOnlyRsrpForLteLevel ? 1 : 0);
-        for (int i = 0; i < LTE_RSRP_THRESHOLDS_NUM; i++) {
-            out.writeInt(mLteRsrpThresholds[i]);
-        }
+        out.writeInt(mLteRsrpBoost);
+        out.writeBoolean(mIsGsm);
+        out.writeBoolean(mUseOnlyRsrpForLteLevel);
+        out.writeIntArray(mLteRsrpThresholds);
     }
 
     /**
@@ -456,24 +331,24 @@
     }
 
     /**
-     * Fix {@link #isGsm} based on the signal strength data.
+     * Fix {@link #mIsGsm} based on the signal strength data.
      *
      * @hide
      */
     public void fixType() {
-        isGsm = getCdmaRelatedSignalStrength() == SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+        mIsGsm = getCdmaRelatedSignalStrength() == SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
     }
 
     /**
      * @param true - Gsm, Lte phones
      *        false - Cdma phones
      *
-     * Used by voice phone to set the isGsm
+     * Used by voice phone to set the mIsGsm
      *        flag
      * @hide
      */
     public void setGsm(boolean gsmFlag) {
-        isGsm = gsmFlag;
+        mIsGsm = gsmFlag;
     }
 
     /**
@@ -604,7 +479,7 @@
      *     while 4 represents a very strong signal strength.
      */
     public int getLevel() {
-        int level = isGsm ? getGsmRelatedSignalStrength() : getCdmaRelatedSignalStrength();
+        int level = mIsGsm ? getGsmRelatedSignalStrength() : getCdmaRelatedSignalStrength();
         if (DBG) log("getLevel=" + level);
         return level;
     }
@@ -616,15 +491,13 @@
      */
     public int getAsuLevel() {
         int asuLevel = 0;
-        if (isGsm) {
-            if (getLteLevel() == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
-                if (getTdScdmaLevel() == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
-                    asuLevel = getGsmAsuLevel();
-                } else {
-                    asuLevel = getTdScdmaAsuLevel();
-                }
-            } else {
+        if (mIsGsm) {
+            if (mLteRsrp != SignalStrength.INVALID) {
                 asuLevel = getLteAsuLevel();
+            } else if (mTdScdmaRscp != SignalStrength.INVALID) {
+                asuLevel = getTdScdmaAsuLevel();
+            } else {
+                asuLevel = getGsmAsuLevel();
             }
         } else {
             int cdmaAsuLevel = getCdmaAsuLevel();
@@ -966,7 +839,7 @@
      * @return true if this is for GSM
      */
     public boolean isGsm() {
-        return this.isGsm;
+        return this.mIsGsm;
     }
 
     /**
@@ -1038,7 +911,7 @@
                 + (mEvdoDbm * primeNum) + (mEvdoEcio * primeNum) + (mEvdoSnr * primeNum)
                 + (mLteSignalStrength * primeNum) + (mLteRsrp * primeNum)
                 + (mLteRsrq * primeNum) + (mLteRssnr * primeNum) + (mLteCqi * primeNum)
-                + (mLteRsrpBoost * primeNum) + (mTdScdmaRscp * primeNum) + (isGsm ? 1 : 0)
+                + (mLteRsrpBoost * primeNum) + (mTdScdmaRscp * primeNum) + (mIsGsm ? 1 : 0)
                 + (mUseOnlyRsrpForLteLevel ? 1 : 0) + (Arrays.hashCode(mLteRsrpThresholds)));
     }
 
@@ -1073,7 +946,7 @@
                 && mLteCqi == s.mLteCqi
                 && mLteRsrpBoost == s.mLteRsrpBoost
                 && mTdScdmaRscp == s.mTdScdmaRscp
-                && isGsm == s.isGsm
+                && mIsGsm == s.mIsGsm
                 && mUseOnlyRsrpForLteLevel == s.mUseOnlyRsrpForLteLevel
                 && Arrays.equals(mLteRsrpThresholds, s.mLteRsrpThresholds));
     }
@@ -1098,7 +971,7 @@
                 + " " + mLteCqi
                 + " " + mLteRsrpBoost
                 + " " + mTdScdmaRscp
-                + " " + (isGsm ? "gsm|lte" : "cdma")
+                + " " + (mIsGsm ? "gsm|lte" : "cdma")
                 + " " + (mUseOnlyRsrpForLteLevel ? "use_only_rsrp_for_lte_level" :
                          "use_rsrp_and_rssnr_for_lte_level")
                 + " " + (Arrays.toString(mLteRsrpThresholds)));
@@ -1153,10 +1026,10 @@
         mLteRsrq = m.getInt("LteRsrq");
         mLteRssnr = m.getInt("LteRssnr");
         mLteCqi = m.getInt("LteCqi");
-        mLteRsrpBoost = m.getInt("lteRsrpBoost");
+        mLteRsrpBoost = m.getInt("LteRsrpBoost");
         mTdScdmaRscp = m.getInt("TdScdma");
-        isGsm = m.getBoolean("isGsm");
-        mUseOnlyRsrpForLteLevel = m.getBoolean("useOnlyRsrpForLteLevel");
+        mIsGsm = m.getBoolean("IsGsm");
+        mUseOnlyRsrpForLteLevel = m.getBoolean("UseOnlyRsrpForLteLevel");
         ArrayList<Integer> lteRsrpThresholds = m.getIntegerArrayList("lteRsrpThresholds");
         for (int i = 0; i < lteRsrpThresholds.size(); i++) {
             mLteRsrpThresholds[i] = lteRsrpThresholds.get(i);
@@ -1182,10 +1055,10 @@
         m.putInt("LteRsrq", mLteRsrq);
         m.putInt("LteRssnr", mLteRssnr);
         m.putInt("LteCqi", mLteCqi);
-        m.putInt("lteRsrpBoost", mLteRsrpBoost);
+        m.putInt("LteRsrpBoost", mLteRsrpBoost);
         m.putInt("TdScdma", mTdScdmaRscp);
-        m.putBoolean("isGsm", isGsm);
-        m.putBoolean("useOnlyRsrpForLteLevel", mUseOnlyRsrpForLteLevel);
+        m.putBoolean("IsGsm", mIsGsm);
+        m.putBoolean("UseOnlyRsrpForLteLevel", mUseOnlyRsrpForLteLevel);
         ArrayList<Integer> lteRsrpThresholds = new ArrayList<Integer>();
         for (int value : mLteRsrpThresholds) {
             lteRsrpThresholds.add(value);
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 57f4cf2..debf43d 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -462,8 +462,6 @@
      * <p>
      * Contains {@link #EXTRA_SUBSCRIPTION_INDEX} to indicate which subscription
      * the user is interested in.
-     *
-     * @hide
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     @SystemApi
@@ -481,8 +479,6 @@
      * <p>
      * Contains {@link #EXTRA_SUBSCRIPTION_INDEX} to indicate which subscription
      * the user is interested in.
-     *
-     * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     @SystemApi
@@ -1698,7 +1694,6 @@
      * </ul>
      *
      * @param subId the subscriber this relationship applies to
-     * @hide
      */
     @SystemApi
     public @NonNull List<SubscriptionPlan> getSubscriptionPlans(int subId) {
@@ -1728,7 +1723,6 @@
      * @param plans the list of plans. The first plan is always the primary and
      *            most important plan. Any additional plans are secondary and
      *            may not be displayed or used by decision making logic.
-     * @hide
      */
     @SystemApi
     public void setSubscriptionPlans(int subId, @NonNull List<SubscriptionPlan> plans) {
@@ -1769,7 +1763,6 @@
      *            be automatically cleared, or {@code 0} to leave in the
      *            requested state until explicitly cleared, or the next reboot,
      *            whichever happens first.
-     * @hide
      */
     @SystemApi
     public void setSubscriptionOverrideUnmetered(int subId, boolean overrideUnmetered,
@@ -1804,7 +1797,6 @@
      *            be automatically cleared, or {@code 0} to leave in the
      *            requested state until explicitly cleared, or the next reboot,
      *            whichever happens first.
-     * @hide
      */
     @SystemApi
     public void setSubscriptionOverrideCongested(int subId, boolean overrideCongested,
diff --git a/telephony/java/android/telephony/SubscriptionPlan.java b/telephony/java/android/telephony/SubscriptionPlan.java
index 265e3e7..9411652 100644
--- a/telephony/java/android/telephony/SubscriptionPlan.java
+++ b/telephony/java/android/telephony/SubscriptionPlan.java
@@ -43,7 +43,6 @@
  *
  * @see SubscriptionManager#setSubscriptionPlans(int, java.util.List)
  * @see SubscriptionManager#getSubscriptionPlans(int)
- * @hide
  */
 @SystemApi
 public final class SubscriptionPlan implements Parcelable {
diff --git a/telephony/java/android/telephony/data/DataService.java b/telephony/java/android/telephony/data/DataService.java
index ea08175..fa19ea0 100644
--- a/telephony/java/android/telephony/data/DataService.java
+++ b/telephony/java/android/telephony/data/DataService.java
@@ -17,6 +17,7 @@
 package android.telephony.data;
 
 import android.annotation.CallSuper;
+import android.annotation.IntDef;
 import android.annotation.SystemApi;
 import android.app.Service;
 import android.content.Intent;
@@ -32,6 +33,8 @@
 import android.telephony.SubscriptionManager;
 import android.util.SparseArray;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -56,6 +59,33 @@
     public static final String DATA_SERVICE_INTERFACE = "android.telephony.data.DataService";
     public static final String DATA_SERVICE_EXTRA_SLOT_ID = "android.telephony.data.extra.SLOT_ID";
 
+    /** {@hide} */
+    @IntDef(prefix = "REQUEST_REASON_", value = {
+            REQUEST_REASON_NORMAL,
+            REQUEST_REASON_HANDOVER,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SetupDataReason {}
+
+    /** {@hide} */
+    @IntDef(prefix = "REQUEST_REASON_", value = {
+            REQUEST_REASON_NORMAL,
+            REQUEST_REASON_SHUTDOWN,
+            REQUEST_REASON_HANDOVER,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface DeactivateDataReason {}
+
+
+    /** The reason of the data request is normal */
+    public static final int REQUEST_REASON_NORMAL = 1;
+
+    /** The reason of the data request is device shutdown */
+    public static final int REQUEST_REASON_SHUTDOWN = 2;
+
+    /** The reason of the data request is IWLAN handover */
+    public static final int REQUEST_REASON_HANDOVER = 3;
+
     private static final int DATA_SERVICE_INTERNAL_REQUEST_INITIALIZE_SERVICE          = 1;
     private static final int DATA_SERVICE_REQUEST_SETUP_DATA_CALL                      = 2;
     private static final int DATA_SERVICE_REQUEST_DEACTIVATE_DATA_CALL                 = 3;
@@ -110,13 +140,14 @@
          * @param dataProfile Data profile used for data call setup. See {@link DataProfile}
          * @param isRoaming True if the device is data roaming.
          * @param allowRoaming True if data roaming is allowed by the user.
-         * @param isHandover True if the request is for IWLAN handover.
-         * @param linkProperties If {@code isHandover} is true, this is the link properties of the
-         * existing data connection, otherwise null.
+         * @param reason The reason for data setup. Must be {@link #REQUEST_REASON_NORMAL} or
+         * {@link #REQUEST_REASON_HANDOVER}.
+         * @param linkProperties If {@code reason} is {@link #REQUEST_REASON_HANDOVER}, this is the
+         * link properties of the existing data connection, otherwise null.
          * @param callback The result callback for this request.
          */
         public void setupDataCall(int accessNetworkType, DataProfile dataProfile, boolean isRoaming,
-                                  boolean allowRoaming, boolean isHandover,
+                                  boolean allowRoaming, @SetupDataReason int reason,
                                   LinkProperties linkProperties, DataServiceCallback callback) {
             // The default implementation is to return unsupported.
             callback.onSetupDataCallComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED, null);
@@ -128,12 +159,12 @@
          * provided callback to notify the platform.
          *
          * @param cid Call id returned in the callback of {@link DataServiceProvider#setupDataCall(
-         * int, DataProfile, boolean, boolean, boolean, LinkProperties, DataServiceCallback)}.
-         * @param reasonRadioShutDown True if the deactivate request reason is device shut down.
-         * @param isHandover True if the request is for IWLAN handover.
+         * int, DataProfile, boolean, boolean, int, LinkProperties, DataServiceCallback)}.
+         * @param reason The reason for data deactivation. Must be {@link #REQUEST_REASON_NORMAL},
+         * {@link #REQUEST_REASON_SHUTDOWN} or {@link #REQUEST_REASON_HANDOVER}.
          * @param callback The result callback for this request.
          */
-        public void deactivateDataCall(int cid, boolean reasonRadioShutDown, boolean isHandover,
+        public void deactivateDataCall(int cid, @DeactivateDataReason int reason,
                                        DataServiceCallback callback) {
             // The default implementation is to return unsupported.
             callback.onDeactivateDataCallComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED);
@@ -219,32 +250,29 @@
         public final DataProfile dataProfile;
         public final boolean isRoaming;
         public final boolean allowRoaming;
-        public final boolean isHandover;
+        public final int reason;
         public final LinkProperties linkProperties;
         public final IDataServiceCallback callback;
         SetupDataCallRequest(int accessNetworkType, DataProfile dataProfile, boolean isRoaming,
-                             boolean allowRoaming, boolean isHandover,
-                             LinkProperties linkProperties, IDataServiceCallback callback) {
+                             boolean allowRoaming, int reason, LinkProperties linkProperties,
+                             IDataServiceCallback callback) {
             this.accessNetworkType = accessNetworkType;
             this.dataProfile = dataProfile;
             this.isRoaming = isRoaming;
             this.allowRoaming = allowRoaming;
             this.linkProperties = linkProperties;
-            this.isHandover = isHandover;
+            this.reason = reason;
             this.callback = callback;
         }
     }
 
     private static final class DeactivateDataCallRequest {
         public final int cid;
-        public final boolean reasonRadioShutDown;
-        public final boolean isHandover;
+        public final int reason;
         public final IDataServiceCallback callback;
-        DeactivateDataCallRequest(int cid, boolean reasonRadioShutDown, boolean isHandover,
-                                  IDataServiceCallback callback) {
+        DeactivateDataCallRequest(int cid, int reason, IDataServiceCallback callback) {
             this.cid = cid;
-            this.reasonRadioShutDown = reasonRadioShutDown;
-            this.isHandover = isHandover;
+            this.reason = reason;
             this.callback = callback;
         }
     }
@@ -311,7 +339,7 @@
                     SetupDataCallRequest setupDataCallRequest = (SetupDataCallRequest) message.obj;
                     service.setupDataCall(setupDataCallRequest.accessNetworkType,
                             setupDataCallRequest.dataProfile, setupDataCallRequest.isRoaming,
-                            setupDataCallRequest.allowRoaming, setupDataCallRequest.isHandover,
+                            setupDataCallRequest.allowRoaming, setupDataCallRequest.reason,
                             setupDataCallRequest.linkProperties,
                             new DataServiceCallback(setupDataCallRequest.callback));
 
@@ -321,8 +349,7 @@
                     DeactivateDataCallRequest deactivateDataCallRequest =
                             (DeactivateDataCallRequest) message.obj;
                     service.deactivateDataCall(deactivateDataCallRequest.cid,
-                            deactivateDataCallRequest.reasonRadioShutDown,
-                            deactivateDataCallRequest.isHandover,
+                            deactivateDataCallRequest.reason,
                             new DataServiceCallback(deactivateDataCallRequest.callback));
                     break;
                 case DATA_SERVICE_REQUEST_SET_INITIAL_ATTACH_APN:
@@ -370,7 +397,8 @@
         }
     }
 
-    private DataService() {
+    /** @hide */
+    protected DataService() {
         mHandlerThread = new HandlerThread(TAG);
         mHandlerThread.start();
 
@@ -472,19 +500,18 @@
 
         @Override
         public void setupDataCall(int accessNetworkType, DataProfile dataProfile,
-                                  boolean isRoaming, boolean allowRoaming, boolean isHandover,
+                                  boolean isRoaming, boolean allowRoaming, int reason,
                                   LinkProperties linkProperties, IDataServiceCallback callback) {
             mHandler.obtainMessage(DATA_SERVICE_REQUEST_SETUP_DATA_CALL, mSlotId, 0,
                     new SetupDataCallRequest(accessNetworkType, dataProfile, isRoaming,
-                            allowRoaming, isHandover, linkProperties, callback))
+                            allowRoaming, reason, linkProperties, callback))
                     .sendToTarget();
         }
 
         @Override
-        public void deactivateDataCall(int cid, boolean reasonRadioShutDown, boolean isHandover,
-                                       IDataServiceCallback callback) {
+        public void deactivateDataCall(int cid, int reason, IDataServiceCallback callback) {
             mHandler.obtainMessage(DATA_SERVICE_REQUEST_DEACTIVATE_DATA_CALL, mSlotId, 0,
-                    new DeactivateDataCallRequest(cid, reasonRadioShutDown, isHandover, callback))
+                    new DeactivateDataCallRequest(cid, reason, callback))
                     .sendToTarget();
         }
 
diff --git a/telephony/java/android/telephony/data/IDataService.aidl b/telephony/java/android/telephony/data/IDataService.aidl
index 4eaaa252..07720b6 100644
--- a/telephony/java/android/telephony/data/IDataService.aidl
+++ b/telephony/java/android/telephony/data/IDataService.aidl
@@ -26,10 +26,9 @@
 oneway interface IDataService
 {
     void setupDataCall(int accessNetwork, in DataProfile dataProfile, boolean isRoaming,
-                       boolean allowRoaming, boolean isHandover, in LinkProperties linkProperties,
+                       boolean allowRoaming, int reason, in LinkProperties linkProperties,
                        IDataServiceCallback callback);
-    void deactivateDataCall(int cid, boolean reasonRadioShutDown, boolean isHandover,
-                            IDataServiceCallback callback);
+    void deactivateDataCall(int cid, int reason, IDataServiceCallback callback);
     void setInitialAttachApn(in DataProfile dataProfile, boolean isRoaming,
                              IDataServiceCallback callback);
     void setDataProfile(in List<DataProfile> dps, boolean isRoaming, IDataServiceCallback callback);
diff --git a/telephony/java/android/telephony/euicc/EuiccCardManager.java b/telephony/java/android/telephony/euicc/EuiccCardManager.java
index b9ed005..88bae33 100644
--- a/telephony/java/android/telephony/euicc/EuiccCardManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccCardManager.java
@@ -142,11 +142,12 @@
     /**
      * Gets all the profiles on eUicc.
      *
+     * @param cardId The Id of the eUICC.
      * @param callback The callback to get the result code and all the profiles.
      */
-    public void getAllProfiles(ResultCallback<EuiccProfileInfo[]> callback) {
+    public void getAllProfiles(String cardId, ResultCallback<EuiccProfileInfo[]> callback) {
         try {
-            getIEuiccCardController().getAllProfiles(mContext.getOpPackageName(),
+            getIEuiccCardController().getAllProfiles(mContext.getOpPackageName(), cardId,
                     new IGetAllProfilesCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode, EuiccProfileInfo[] profiles) {
@@ -162,12 +163,13 @@
     /**
      * Gets the profile of the given iccid.
      *
+     * @param cardId The Id of the eUICC.
      * @param iccid The iccid of the profile.
      * @param callback The callback to get the result code and profile.
      */
-    public void getProfile(String iccid, ResultCallback<EuiccProfileInfo> callback) {
+    public void getProfile(String cardId, String iccid, ResultCallback<EuiccProfileInfo> callback) {
         try {
-            getIEuiccCardController().getProfile(mContext.getOpPackageName(), iccid,
+            getIEuiccCardController().getProfile(mContext.getOpPackageName(), cardId, iccid,
                     new IGetProfileCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode, EuiccProfileInfo profile) {
@@ -183,14 +185,16 @@
     /**
      * Disables the profile of the given iccid.
      *
+     * @param cardId The Id of the eUICC.
      * @param iccid The iccid of the profile.
      * @param refresh Whether sending the REFRESH command to modem.
      * @param callback The callback to get the result code.
      */
-    public void disableProfile(String iccid, boolean refresh, ResultCallback<Void> callback) {
+    public void disableProfile(String cardId, String iccid, boolean refresh,
+            ResultCallback<Void> callback) {
         try {
-            getIEuiccCardController().disableProfile(mContext.getOpPackageName(), iccid, refresh,
-                    new IDisableProfileCallback.Stub() {
+            getIEuiccCardController().disableProfile(mContext.getOpPackageName(), cardId, iccid,
+                    refresh, new IDisableProfileCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode) {
                             callback.onComplete(resultCode, null);
@@ -206,15 +210,16 @@
      * Switches from the current profile to another profile. The current profile will be disabled
      * and the specified profile will be enabled.
      *
+     * @param cardId The Id of the eUICC.
      * @param iccid The iccid of the profile to switch to.
      * @param refresh Whether sending the REFRESH command to modem.
      * @param callback The callback to get the result code and the EuiccProfileInfo enabled.
      */
-    public void switchToProfile(String iccid, boolean refresh,
+    public void switchToProfile(String cardId, String iccid, boolean refresh,
             ResultCallback<EuiccProfileInfo> callback) {
         try {
-            getIEuiccCardController().switchToProfile(mContext.getOpPackageName(), iccid, refresh,
-                    new ISwitchToProfileCallback.Stub() {
+            getIEuiccCardController().switchToProfile(mContext.getOpPackageName(), cardId, iccid,
+                    refresh, new ISwitchToProfileCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode, EuiccProfileInfo profile) {
                             callback.onComplete(resultCode, profile);
@@ -227,30 +232,18 @@
     }
 
     /**
-     * Gets the EID of the eUICC.
-     *
-     * @return The EID.
-     */
-    public String getEid() {
-        try {
-            return getIEuiccCardController().getEid();
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error calling getEid", e);
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
      * Sets the nickname of the profile of the given iccid.
      *
+     * @param cardId The Id of the eUICC.
      * @param iccid The iccid of the profile.
      * @param nickname The nickname of the profile.
      * @param callback The callback to get the result code.
      */
-    public void setNickname(String iccid, String nickname, ResultCallback<Void> callback) {
+    public void setNickname(String cardId, String iccid, String nickname,
+            ResultCallback<Void> callback) {
         try {
-            getIEuiccCardController().setNickname(mContext.getOpPackageName(), iccid, nickname,
-                    new ISetNicknameCallback.Stub() {
+            getIEuiccCardController().setNickname(mContext.getOpPackageName(), cardId, iccid,
+                    nickname, new ISetNicknameCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode) {
                             callback.onComplete(resultCode, null);
@@ -265,12 +258,13 @@
     /**
      * Deletes the profile of the given iccid from eUICC.
      *
+     * @param cardId The Id of the eUICC.
      * @param iccid The iccid of the profile.
      * @param callback The callback to get the result code.
      */
-    public void deleteProfile(String iccid, ResultCallback<Void> callback) {
+    public void deleteProfile(String cardId, String iccid, ResultCallback<Void> callback) {
         try {
-            getIEuiccCardController().deleteProfile(mContext.getOpPackageName(), iccid,
+            getIEuiccCardController().deleteProfile(mContext.getOpPackageName(), cardId, iccid,
                     new IDeleteProfileCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode) {
@@ -286,13 +280,14 @@
     /**
      * Resets the eUICC memory.
      *
+     * @param cardId The Id of the eUICC.
      * @param options Bits of the options of resetting which parts of the eUICC memory. See
      *     EuiccCard for details.
      * @param callback The callback to get the result code.
      */
-    public void resetMemory(@ResetOption int options, ResultCallback<Void> callback) {
+    public void resetMemory(String cardId, @ResetOption int options, ResultCallback<Void> callback) {
         try {
-            getIEuiccCardController().resetMemory(mContext.getOpPackageName(), options,
+            getIEuiccCardController().resetMemory(mContext.getOpPackageName(), cardId, options,
                     new IResetMemoryCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode) {
@@ -308,11 +303,12 @@
     /**
      * Gets the default SM-DP+ address from eUICC.
      *
+     * @param cardId The Id of the eUICC.
      * @param callback The callback to get the result code and the default SM-DP+ address.
      */
-    public void getDefaultSmdpAddress(ResultCallback<String> callback) {
+    public void getDefaultSmdpAddress(String cardId, ResultCallback<String> callback) {
         try {
-            getIEuiccCardController().getDefaultSmdpAddress(mContext.getOpPackageName(),
+            getIEuiccCardController().getDefaultSmdpAddress(mContext.getOpPackageName(), cardId,
                     new IGetDefaultSmdpAddressCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode, String address) {
@@ -328,11 +324,12 @@
     /**
      * Gets the SM-DS address from eUICC.
      *
+     * @param cardId The Id of the eUICC.
      * @param callback The callback to get the result code and the SM-DS address.
      */
-    public void getSmdsAddress(ResultCallback<String> callback) {
+    public void getSmdsAddress(String cardId, ResultCallback<String> callback) {
         try {
-            getIEuiccCardController().getSmdsAddress(mContext.getOpPackageName(),
+            getIEuiccCardController().getSmdsAddress(mContext.getOpPackageName(), cardId,
                     new IGetSmdsAddressCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode, String address) {
@@ -348,12 +345,13 @@
     /**
      * Sets the default SM-DP+ address of eUICC.
      *
+     * @param cardId The Id of the eUICC.
      * @param defaultSmdpAddress The default SM-DP+ address to set.
      * @param callback The callback to get the result code.
      */
-    public void setDefaultSmdpAddress(String defaultSmdpAddress, ResultCallback<Void> callback) {
+    public void setDefaultSmdpAddress(String cardId, String defaultSmdpAddress, ResultCallback<Void> callback) {
         try {
-            getIEuiccCardController().setDefaultSmdpAddress(mContext.getOpPackageName(),
+            getIEuiccCardController().setDefaultSmdpAddress(mContext.getOpPackageName(), cardId,
                     defaultSmdpAddress,
                     new ISetDefaultSmdpAddressCallback.Stub() {
                         @Override
@@ -370,11 +368,12 @@
     /**
      * Gets Rules Authorisation Table.
      *
+     * @param cardId The Id of the eUICC.
      * @param callback the callback to get the result code and the rule authorisation table.
      */
-    public void getRulesAuthTable(ResultCallback<EuiccRulesAuthTable> callback) {
+    public void getRulesAuthTable(String cardId, ResultCallback<EuiccRulesAuthTable> callback) {
         try {
-            getIEuiccCardController().getRulesAuthTable(mContext.getOpPackageName(),
+            getIEuiccCardController().getRulesAuthTable(mContext.getOpPackageName(), cardId,
                     new IGetRulesAuthTableCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode, EuiccRulesAuthTable rat) {
@@ -390,11 +389,12 @@
     /**
      * Gets the eUICC challenge for new profile downloading.
      *
+     * @param cardId The Id of the eUICC.
      * @param callback the callback to get the result code and the challenge.
      */
-    public void getEuiccChallenge(ResultCallback<byte[]> callback) {
+    public void getEuiccChallenge(String cardId, ResultCallback<byte[]> callback) {
         try {
-            getIEuiccCardController().getEuiccChallenge(mContext.getOpPackageName(),
+            getIEuiccCardController().getEuiccChallenge(mContext.getOpPackageName(), cardId,
                     new IGetEuiccChallengeCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode, byte[] challenge) {
@@ -410,11 +410,12 @@
     /**
      * Gets the eUICC info1 defined in GSMA RSP v2.0+ for new profile downloading.
      *
+     * @param cardId The Id of the eUICC.
      * @param callback the callback to get the result code and the info1.
      */
-    public void getEuiccInfo1(ResultCallback<byte[]> callback) {
+    public void getEuiccInfo1(String cardId, ResultCallback<byte[]> callback) {
         try {
-            getIEuiccCardController().getEuiccInfo1(mContext.getOpPackageName(),
+            getIEuiccCardController().getEuiccInfo1(mContext.getOpPackageName(), cardId,
                     new IGetEuiccInfo1Callback.Stub() {
                         @Override
                         public void onComplete(int resultCode, byte[] info) {
@@ -430,11 +431,12 @@
     /**
      * Gets the eUICC info2 defined in GSMA RSP v2.0+ for new profile downloading.
      *
+     * @param cardId The Id of the eUICC.
      * @param callback the callback to get the result code and the info2.
      */
-    public void getEuiccInfo2(ResultCallback<byte[]> callback) {
+    public void getEuiccInfo2(String cardId, ResultCallback<byte[]> callback) {
         try {
-            getIEuiccCardController().getEuiccInfo2(mContext.getOpPackageName(),
+            getIEuiccCardController().getEuiccInfo2(mContext.getOpPackageName(), cardId,
                     new IGetEuiccInfo2Callback.Stub() {
                         @Override
                         public void onComplete(int resultCode, byte[] info) {
@@ -450,6 +452,7 @@
     /**
      * Authenticates the SM-DP+ server by the eUICC.
      *
+     * @param cardId The Id of the eUICC.
      * @param matchingId the activation code token defined in GSMA RSP v2.0+ or empty when it is not
      *     required.
      * @param serverSigned1 ASN.1 data in byte array signed and returned by the SM-DP+ server.
@@ -463,12 +466,13 @@
      * @param callback the callback to get the result code and a byte array which represents a
      *     {@code AuthenticateServerResponse} defined in GSMA RSP v2.0+.
      */
-    public void authenticateServer(String matchingId, byte[] serverSigned1,
+    public void authenticateServer(String cardId, String matchingId, byte[] serverSigned1,
             byte[] serverSignature1, byte[] euiccCiPkIdToBeUsed, byte[] serverCertificate,
             ResultCallback<byte[]> callback) {
         try {
             getIEuiccCardController().authenticateServer(
                     mContext.getOpPackageName(),
+                    cardId,
                     matchingId,
                     serverSigned1,
                     serverSignature1,
@@ -489,6 +493,7 @@
     /**
      * Prepares the profile download request sent to SM-DP+.
      *
+     * @param cardId The Id of the eUICC.
      * @param hashCc the hash of confirmation code. It can be null if there is no confirmation code
      *     required.
      * @param smdpSigned2 ASN.1 data in byte array indicating the data to be signed by the SM-DP+
@@ -500,11 +505,12 @@
      * @param callback the callback to get the result code and a byte array which represents a
      *     {@code PrepareDownloadResponse} defined in GSMA RSP v2.0+
      */
-    public void prepareDownload(@Nullable byte[] hashCc, byte[] smdpSigned2,
+    public void prepareDownload(String cardId, @Nullable byte[] hashCc, byte[] smdpSigned2,
             byte[] smdpSignature2, byte[] smdpCertificate, ResultCallback<byte[]> callback) {
         try {
             getIEuiccCardController().prepareDownload(
                     mContext.getOpPackageName(),
+                    cardId,
                     hashCc,
                     smdpSigned2,
                     smdpSignature2,
@@ -524,15 +530,17 @@
     /**
      * Loads a downloaded bound profile package onto the eUICC.
      *
+     * @param cardId The Id of the eUICC.
      * @param boundProfilePackage the Bound Profile Package data returned by SM-DP+ server.
      * @param callback the callback to get the result code and a byte array which represents a
      *     {@code LoadBoundProfilePackageResponse} defined in GSMA RSP v2.0+.
      */
-    public void loadBoundProfilePackage(byte[] boundProfilePackage,
+    public void loadBoundProfilePackage(String cardId, byte[] boundProfilePackage,
             ResultCallback<byte[]> callback) {
         try {
             getIEuiccCardController().loadBoundProfilePackage(
                     mContext.getOpPackageName(),
+                    cardId,
                     boundProfilePackage,
                     new ILoadBoundProfilePackageCallback.Stub() {
                         @Override
@@ -549,16 +557,18 @@
     /**
      * Cancels the current profile download session.
      *
+     * @param cardId The Id of the eUICC.
      * @param transactionId the transaction ID returned by SM-DP+ server.
      * @param reason the cancel reason.
      * @param callback the callback to get the result code and an byte[] which represents a
      *     {@code CancelSessionResponse} defined in GSMA RSP v2.0+.
      */
-    public void cancelSession(byte[] transactionId, @CancelReason int reason,
+    public void cancelSession(String cardId, byte[] transactionId, @CancelReason int reason,
             ResultCallback<byte[]> callback) {
         try {
             getIEuiccCardController().cancelSession(
                     mContext.getOpPackageName(),
+                    cardId,
                     transactionId,
                     reason,
                     new ICancelSessionCallback.Stub() {
@@ -576,13 +586,14 @@
     /**
      * Lists all notifications of the given {@code notificationEvents}.
      *
+     * @param cardId The Id of the eUICC.
      * @param events bits of the event types ({@link EuiccNotification.Event}) to list.
      * @param callback the callback to get the result code and the list of notifications.
      */
-    public void listNotifications(@EuiccNotification.Event int events,
+    public void listNotifications(String cardId, @EuiccNotification.Event int events,
             ResultCallback<EuiccNotification[]> callback) {
         try {
-            getIEuiccCardController().listNotifications(mContext.getOpPackageName(), events,
+            getIEuiccCardController().listNotifications(mContext.getOpPackageName(), cardId, events,
                     new IListNotificationsCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode, EuiccNotification[] notifications) {
@@ -598,14 +609,15 @@
     /**
      * Retrieves contents of all notification of the given {@code events}.
      *
+     * @param cardId The Id of the eUICC.
      * @param events bits of the event types ({@link EuiccNotification.Event}) to list.
      * @param callback the callback to get the result code and the list of notifications.
      */
-    public void retrieveNotificationList(@EuiccNotification.Event int events,
+    public void retrieveNotificationList(String cardId, @EuiccNotification.Event int events,
             ResultCallback<EuiccNotification[]> callback) {
         try {
-            getIEuiccCardController().retrieveNotificationList(mContext.getOpPackageName(), events,
-                    new IRetrieveNotificationListCallback.Stub() {
+            getIEuiccCardController().retrieveNotificationList(mContext.getOpPackageName(), cardId,
+                    events, new IRetrieveNotificationListCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode, EuiccNotification[] notifications) {
                             callback.onComplete(resultCode, notifications);
@@ -620,13 +632,15 @@
     /**
      * Retrieves the content of a notification of the given {@code seqNumber}.
      *
+     * @param cardId The Id of the eUICC.
      * @param seqNumber the sequence number of the notification.
      * @param callback the callback to get the result code and the notification.
      */
-    public void retrieveNotification(int seqNumber, ResultCallback<EuiccNotification> callback) {
+    public void retrieveNotification(String cardId, int seqNumber,
+            ResultCallback<EuiccNotification> callback) {
         try {
-            getIEuiccCardController().retrieveNotification(mContext.getOpPackageName(), seqNumber,
-                    new IRetrieveNotificationCallback.Stub() {
+            getIEuiccCardController().retrieveNotification(mContext.getOpPackageName(), cardId,
+                    seqNumber, new IRetrieveNotificationCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode, EuiccNotification notification) {
                             callback.onComplete(resultCode, notification);
@@ -641,13 +655,16 @@
     /**
      * Removes a notification from eUICC.
      *
+     * @param cardId The Id of the eUICC.
      * @param seqNumber the sequence number of the notification.
      * @param callback the callback to get the result code.
      */
-    public void removeNotificationFromList(int seqNumber, ResultCallback<Void> callback) {
+    public void removeNotificationFromList(String cardId, int seqNumber,
+            ResultCallback<Void> callback) {
         try {
             getIEuiccCardController().removeNotificationFromList(
                     mContext.getOpPackageName(),
+                    cardId,
                     seqNumber,
                     new IRemoveNotificationFromListCallback.Stub() {
                         @Override
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index d146707..7f913ce 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -19,6 +19,7 @@
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.app.Activity;
 import android.app.PendingIntent;
 import android.content.Context;
@@ -598,7 +599,11 @@
         }
     }
 
-    private static IEuiccController getIEuiccController() {
+    /**
+     * @hide
+     */
+    @TestApi
+    protected IEuiccController getIEuiccController() {
         return IEuiccController.Stub.asInterface(ServiceManager.getService("econtroller"));
     }
 }
diff --git a/telephony/java/com/android/internal/telephony/euicc/IEuiccCardController.aidl b/telephony/java/com/android/internal/telephony/euicc/IEuiccCardController.aidl
index abc55c7..e33f44c 100644
--- a/telephony/java/com/android/internal/telephony/euicc/IEuiccCardController.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IEuiccCardController.aidl
@@ -41,42 +41,49 @@
 
 /** @hide */
 interface IEuiccCardController {
-    oneway void getAllProfiles(String callingPackage, in IGetAllProfilesCallback callback);
-    oneway void getProfile(String callingPackage, String iccid, in IGetProfileCallback callback);
-    oneway void disableProfile(String callingPackage, String iccid, boolean refresh,
+    oneway void getAllProfiles(String callingPackage, String cardId,
+        in IGetAllProfilesCallback callback);
+    oneway void getProfile(String callingPackage, String cardId, String iccid,
+        in IGetProfileCallback callback);
+    oneway void disableProfile(String callingPackage, String cardId, String iccid, boolean refresh,
         in IDisableProfileCallback callback);
-    oneway void switchToProfile(String callingPackage, String iccid, boolean refresh,
+    oneway void switchToProfile(String callingPackage, String cardId, String iccid, boolean refresh,
         in ISwitchToProfileCallback callback);
-    String getEid();
-    oneway void setNickname(String callingPackage, String iccid, String nickname,
+    oneway void setNickname(String callingPackage, String cardId, String iccid, String nickname,
         in ISetNicknameCallback callback);
-    oneway void deleteProfile(String callingPackage, String iccid,
+    oneway void deleteProfile(String callingPackage, String cardId, String iccid,
         in IDeleteProfileCallback callback);
-    oneway void resetMemory(String callingPackage, int options, in IResetMemoryCallback callback);
-    oneway void getDefaultSmdpAddress(String callingPackage,
+    oneway void resetMemory(String callingPackage, String cardId, int options, in IResetMemoryCallback callback);
+    oneway void getDefaultSmdpAddress(String callingPackage, String cardId,
         in IGetDefaultSmdpAddressCallback callback);
-    oneway void getSmdsAddress(String callingPackage, in IGetSmdsAddressCallback callback);
-    oneway void setDefaultSmdpAddress(String callingPackage, String address,
+    oneway void getSmdsAddress(String callingPackage, String cardId,
+        in IGetSmdsAddressCallback callback);
+    oneway void setDefaultSmdpAddress(String callingPackage, String cardId, String address,
         in ISetDefaultSmdpAddressCallback callback);
-    oneway void getRulesAuthTable(String callingPackage, in IGetRulesAuthTableCallback callback);
-    oneway void getEuiccChallenge(String callingPackage, in IGetEuiccChallengeCallback callback);
-    oneway void getEuiccInfo1(String callingPackage, in IGetEuiccInfo1Callback callback);
-    oneway void getEuiccInfo2(String callingPackage, in IGetEuiccInfo2Callback callback);
-    oneway void authenticateServer(String callingPackage, String matchingId,
+    oneway void getRulesAuthTable(String callingPackage, String cardId,
+        in IGetRulesAuthTableCallback callback);
+    oneway void getEuiccChallenge(String callingPackage, String cardId,
+        in IGetEuiccChallengeCallback callback);
+    oneway void getEuiccInfo1(String callingPackage, String cardId,
+        in IGetEuiccInfo1Callback callback);
+    oneway void getEuiccInfo2(String callingPackage, String cardId,
+        in IGetEuiccInfo2Callback callback);
+    oneway void authenticateServer(String callingPackage, String cardId, String matchingId,
         in byte[] serverSigned1, in byte[] serverSignature1, in byte[] euiccCiPkIdToBeUsed,
         in byte[] serverCertificatein, in IAuthenticateServerCallback callback);
-    oneway void prepareDownload(String callingPackage, in byte[] hashCc, in byte[] smdpSigned2,
-        in byte[] smdpSignature2, in byte[] smdpCertificate, in IPrepareDownloadCallback callback);
-    oneway void loadBoundProfilePackage(String callingPackage, in byte[] boundProfilePackage,
-        in ILoadBoundProfilePackageCallback callback);
-    oneway void cancelSession(String callingPackage, in byte[] transactionId, int reason,
-        in ICancelSessionCallback callback);
-    oneway void listNotifications(String callingPackage, int events,
+    oneway void prepareDownload(String callingPackage, String cardId, in byte[] hashCc,
+        in byte[] smdpSigned2, in byte[] smdpSignature2, in byte[] smdpCertificate,
+        in IPrepareDownloadCallback callback);
+    oneway void loadBoundProfilePackage(String callingPackage, String cardId,
+        in byte[] boundProfilePackage, in ILoadBoundProfilePackageCallback callback);
+    oneway void cancelSession(String callingPackage, String cardId, in byte[] transactionId,
+        int reason, in ICancelSessionCallback callback);
+    oneway void listNotifications(String callingPackage, String cardId, int events,
         in IListNotificationsCallback callback);
-    oneway void retrieveNotificationList(String callingPackage, int events,
+    oneway void retrieveNotificationList(String callingPackage, String cardId, int events,
         in IRetrieveNotificationListCallback callback);
-    oneway void retrieveNotification(String callingPackage, int seqNumber,
+    oneway void retrieveNotification(String callingPackage, String cardId, int seqNumber,
         in IRetrieveNotificationCallback callback);
-    oneway void removeNotificationFromList(String callingPackage, int seqNumber,
+    oneway void removeNotificationFromList(String callingPackage, String cardId, int seqNumber,
             in IRemoveNotificationFromListCallback callback);
 }
diff --git a/test-mock/src/android/test/mock/MockPackageManager.java b/test-mock/src/android/test/mock/MockPackageManager.java
index 41cde17..1ddc52c 100644
--- a/test-mock/src/android/test/mock/MockPackageManager.java
+++ b/test-mock/src/android/test/mock/MockPackageManager.java
@@ -1196,4 +1196,17 @@
     public CharSequence getHarmfulAppWarning(String packageName) {
         throw new UnsupportedOperationException();
     }
+
+    @Override
+    public boolean hasSigningCertificate(
+            String packageName, byte[] certificate, @PackageManager.CertificateInputType int type) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean hasSigningCertificate(
+            int uid, byte[] certificate, @PackageManager.CertificateInputType int type) {
+        throw new UnsupportedOperationException();
+    }
+
 }
diff --git a/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java b/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
index 56b8e60..b14f550 100644
--- a/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
+++ b/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
@@ -67,7 +67,7 @@
             IoUtils.deleteContents(mTestProc);
         }
 
-        mFactory = new NetworkStatsFactory(mTestProc);
+        mFactory = new NetworkStatsFactory(mTestProc, false);
     }
 
     @After
@@ -116,6 +116,20 @@
     }
 
     @Test
+    public void testNetworkStatsSummary() throws Exception {
+        stageFile(R.raw.net_dev_typical, file("net/dev"));
+
+        final NetworkStats stats = mFactory.readNetworkStatsIfaceDev();
+        assertEquals(6, stats.size());
+        assertStatsEntry(stats, "lo", UID_ALL, SET_ALL, TAG_NONE, 8308L, 8308L);
+        assertStatsEntry(stats, "rmnet0", UID_ALL, SET_ALL, TAG_NONE, 1507570L, 489339L);
+        assertStatsEntry(stats, "ifb0", UID_ALL, SET_ALL, TAG_NONE, 52454L, 0L);
+        assertStatsEntry(stats, "ifb1", UID_ALL, SET_ALL, TAG_NONE, 52454L, 0L);
+        assertStatsEntry(stats, "sit0", UID_ALL, SET_ALL, TAG_NONE, 0L, 0L);
+        assertStatsEntry(stats, "ip6tnl0", UID_ALL, SET_ALL, TAG_NONE, 0L, 0L);
+    }
+
+    @Test
     public void testNetworkStatsSingle() throws Exception {
         stageFile(R.raw.xt_qtaguid_iface_typical, file("net/xt_qtaguid/iface_stat_all"));
 
diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
index d9d4eeb..1618e07 100644
--- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
@@ -268,6 +268,31 @@
                         anyInt());
     }
 
+    public void testCreateTwoTransformsWithSameSpis() throws Exception {
+        IpSecConfig ipSecConfig = new IpSecConfig();
+        addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
+        addAuthAndCryptToIpSecConfig(ipSecConfig);
+
+        IpSecTransformResponse createTransformResp =
+                mIpSecService.createTransform(ipSecConfig, new Binder());
+        assertEquals(IpSecManager.Status.OK, createTransformResp.status);
+
+        // Attempting to create transform a second time with the same SPIs should throw an error...
+        try {
+                mIpSecService.createTransform(ipSecConfig, new Binder());
+                fail("IpSecService should have thrown an error for reuse of SPI");
+        } catch (IllegalStateException expected) {
+        }
+
+        // ... even if the transform is deleted
+        mIpSecService.deleteTransform(createTransformResp.resourceId);
+        try {
+                mIpSecService.createTransform(ipSecConfig, new Binder());
+                fail("IpSecService should have thrown an error for reuse of SPI");
+        } catch (IllegalStateException expected) {
+        }
+    }
+
     @Test
     public void testDeleteTransform() throws Exception {
         IpSecConfig ipSecConfig = new IpSecConfig();
diff --git a/tests/net/res/raw/net_dev_typical b/tests/net/res/raw/net_dev_typical
new file mode 100644
index 0000000..290bf03
--- /dev/null
+++ b/tests/net/res/raw/net_dev_typical
@@ -0,0 +1,8 @@
+Inter-|   Receive                                                |  Transmit
+ face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed
+    lo:    8308     116    0    0    0     0          0         0     8308     116    0    0    0     0       0          0
+rmnet0: 1507570    2205    0    0    0     0          0         0   489339    2237    0    0    0     0       0          0
+  ifb0:   52454     151    0  151    0     0          0         0        0       0    0    0    0     0       0          0
+  ifb1:   52454     151    0  151    0     0          0         0        0       0    0    0    0     0       0          0
+  sit0:       0       0    0    0    0     0          0         0        0       0  148    0    0     0       0          0
+ip6tnl0:       0       0    0    0    0     0          0         0        0       0  151  151    0     0       0          0
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index eaad137..c46789c 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -294,18 +294,6 @@
     }
 
     /**
-     * num IP configuration failures
-     * @hide
-     */
-    public int numIpConfigFailures;
-
-    /**
-     * @hide
-     * Last time we blacklisted the ScanResult
-     */
-    public long blackListTimestamp;
-
-    /**
      * Status indicating the scan result does not correspond to a user's saved configuration
      * @hide
      * @removed
@@ -314,12 +302,6 @@
     public boolean untrusted;
 
     /**
-     * Number of time we connected to it
-     * @hide
-     */
-    public int numConnection;
-
-    /**
      * Number of time autojoin used it
      * @hide
      */
@@ -432,12 +414,6 @@
      */
     public List<String> anqpLines;
 
-    /**
-     *  @hide
-     * storing the raw bytes of full result IEs
-     **/
-    public byte[] bytes;
-
     /** information elements from beacon
      * @hide
      */
@@ -612,9 +588,7 @@
             distanceSdCm = source.distanceSdCm;
             seen = source.seen;
             untrusted = source.untrusted;
-            numConnection = source.numConnection;
             numUsage = source.numUsage;
-            numIpConfigFailures = source.numIpConfigFailures;
             venueName = source.venueName;
             operatorFriendlyName = source.operatorFriendlyName;
             flags = source.flags;
@@ -697,9 +671,7 @@
         dest.writeInt(centerFreq1);
         dest.writeLong(seen);
         dest.writeInt(untrusted ? 1 : 0);
-        dest.writeInt(numConnection);
         dest.writeInt(numUsage);
-        dest.writeInt(numIpConfigFailures);
         dest.writeString((venueName != null) ? venueName.toString() : "");
         dest.writeString((operatorFriendlyName != null) ? operatorFriendlyName.toString() : "");
         dest.writeLong(this.flags);
@@ -779,9 +751,7 @@
 
                 sr.seen = in.readLong();
                 sr.untrusted = in.readInt() != 0;
-                sr.numConnection = in.readInt();
                 sr.numUsage = in.readInt();
-                sr.numIpConfigFailures = in.readInt();
                 sr.venueName = in.readString();
                 sr.operatorFriendlyName = in.readString();
                 sr.flags = in.readLong();