Merge "Add padlock to the top of the bouncer"
diff --git a/Android.bp b/Android.bp
index 4e7aa5f..4219d36 100644
--- a/Android.bp
+++ b/Android.bp
@@ -225,6 +225,7 @@
         "core/java/android/net/INetworkScoreService.aidl",
         "core/java/android/net/INetworkStatsService.aidl",
         "core/java/android/net/INetworkStatsSession.aidl",
+        "core/java/android/net/ISocketKeepaliveCallback.aidl",
         "core/java/android/net/ITestNetworkManager.aidl",
         "core/java/android/net/ITetheringEventCallback.aidl",
         "core/java/android/net/ITetheringStatsProvider.aidl",
@@ -636,7 +637,7 @@
         "wifi/java/android/net/wifi/ISoftApCallback.aidl",
         "wifi/java/android/net/wifi/ITrafficStateCallback.aidl",
         "wifi/java/android/net/wifi/IWifiManager.aidl",
-        "wifi/java/android/net/wifi/IWifiUsabilityStatsListener.aidl",
+        "wifi/java/android/net/wifi/IOnWifiUsabilityStatsListener.aidl",
         "wifi/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl",
         "wifi/java/android/net/wifi/aware/IWifiAwareEventCallback.aidl",
         "wifi/java/android/net/wifi/aware/IWifiAwareMacAddressProvider.aidl",
@@ -736,7 +737,7 @@
         "updatable_media_stubs",
     ],
 
-    jarjar_rules: "jarjar_rules_hidl.txt",
+    jarjar_rules: ":framework-jarjar-rules",
 
     static_libs: [
         "apex_aidl_interface-java",
@@ -789,6 +790,11 @@
 }
 
 filegroup {
+    name: "framework-jarjar-rules",
+    srcs: ["jarjar_rules_hidl.txt"],
+}
+
+filegroup {
     name: "libincident_aidl",
     srcs: [
         "core/java/android/os/IIncidentManager.aidl",
@@ -897,14 +903,8 @@
         "core/java/android/net/INetworkStackConnector.aidl",
         "core/java/android/net/INetworkStackStatusCallback.aidl",
         "core/java/android/net/InitialConfigurationParcelable.aidl",
-        "core/java/android/net/IpPrefixParcelable.aidl",
-        "core/java/android/net/LinkAddressParcelable.aidl",
-        "core/java/android/net/LinkPropertiesParcelable.aidl",
-        "core/java/android/net/NetworkParcelable.aidl",
         "core/java/android/net/PrivateDnsConfigParcel.aidl",
         "core/java/android/net/ProvisioningConfigurationParcelable.aidl",
-        "core/java/android/net/ProxyInfoParcelable.aidl",
-        "core/java/android/net/RouteInfoParcelable.aidl",
         "core/java/android/net/StaticIpConfigurationParcelable.aidl",
         "core/java/android/net/TcpKeepalivePacketDataParcelable.aidl",
         "core/java/android/net/dhcp/DhcpServingParamsParcel.aidl",
@@ -913,6 +913,14 @@
         "core/java/android/net/ip/IIpClient.aidl",
         "core/java/android/net/ip/IIpClientCallbacks.aidl",
     ],
+    backend: {
+        ndk: {
+            enabled: false,
+        },
+        cpp: {
+            enabled: false,
+        },
+    },
     api_dir: "aidl/networkstack",
 }
 
@@ -925,6 +933,11 @@
         "core/java/android/net/ipmemorystore/**/*.aidl",
     ],
     api_dir: "aidl/networkstack",
+    backend: {
+        java: {
+            sdk_version: "28",
+        },
+    },
 }
 
 filegroup {
@@ -1126,6 +1139,7 @@
         "core/java/android/annotation/Nullable.java",
         "core/java/android/annotation/SystemApi.java",
         "core/java/android/annotation/TestApi.java",
+        "core/java/android/annotation/UnsupportedAppUsage.java",
         "core/java/android/os/HwBinder.java",
         "core/java/android/os/HwBlob.java",
         "core/java/android/os/HwParcel.java",
diff --git a/api/current.txt b/api/current.txt
index fb588dc..9190a13 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4263,24 +4263,24 @@
   }
 
   public class AppOpsManager {
-    method @Deprecated public int checkOp(String, int, String);
-    method @Deprecated public int checkOpNoThrow(String, int, String);
-    method public void checkPackage(int, String);
-    method public void finishOp(String, int, String);
-    method public int noteOp(String, int, String);
-    method public int noteOpNoThrow(String, int, String);
-    method public int noteProxyOp(String, String);
-    method public int noteProxyOpNoThrow(String, String);
+    method @Deprecated public int checkOp(@NonNull String, int, @NonNull String);
+    method @Deprecated public int checkOpNoThrow(@NonNull String, int, @NonNull String);
+    method public void checkPackage(int, @NonNull String);
+    method public void finishOp(@NonNull String, int, @NonNull String);
+    method public int noteOp(@NonNull String, int, @NonNull String);
+    method public int noteOpNoThrow(@NonNull String, int, @NonNull String);
+    method public int noteProxyOp(@NonNull String, @NonNull String);
+    method public int noteProxyOpNoThrow(@NonNull String, @NonNull String);
     method public int noteProxyOpNoThrow(@NonNull String, @Nullable String, int);
     method public static String permissionToOp(String);
-    method public int startOp(String, int, String);
-    method public int startOpNoThrow(String, int, String);
-    method public void startWatchingMode(String, String, android.app.AppOpsManager.OnOpChangedListener);
-    method public void startWatchingMode(String, String, int, android.app.AppOpsManager.OnOpChangedListener);
-    method public void stopWatchingMode(android.app.AppOpsManager.OnOpChangedListener);
-    method public int unsafeCheckOp(String, int, String);
-    method public int unsafeCheckOpNoThrow(String, int, String);
-    method public int unsafeCheckOpRaw(@NonNull String, int, String);
+    method public int startOp(@NonNull String, int, @NonNull String);
+    method public int startOpNoThrow(@NonNull String, int, @NonNull String);
+    method public void startWatchingMode(@NonNull String, @Nullable String, @NonNull android.app.AppOpsManager.OnOpChangedListener);
+    method public void startWatchingMode(@NonNull String, @Nullable String, int, @NonNull android.app.AppOpsManager.OnOpChangedListener);
+    method public void stopWatchingMode(@NonNull android.app.AppOpsManager.OnOpChangedListener);
+    method public int unsafeCheckOp(@NonNull String, int, @NonNull String);
+    method public int unsafeCheckOpNoThrow(@NonNull String, int, @NonNull String);
+    method public int unsafeCheckOpRaw(@NonNull String, int, @NonNull String);
     method public int unsafeCheckOpRawNoThrow(@NonNull String, int, @NonNull String);
     field public static final int MODE_ALLOWED = 0; // 0x0
     field public static final int MODE_DEFAULT = 3; // 0x3
@@ -6509,9 +6509,9 @@
 
   public class DelegatedAdminReceiver extends android.content.BroadcastReceiver {
     ctor public DelegatedAdminReceiver();
-    method public String onChoosePrivateKeyAlias(android.content.Context, android.content.Intent, int, android.net.Uri, String);
-    method public void onNetworkLogsAvailable(android.content.Context, android.content.Intent, long, int);
-    method public void onReceive(android.content.Context, android.content.Intent);
+    method @Nullable public String onChoosePrivateKeyAlias(@NonNull android.content.Context, @NonNull android.content.Intent, int, @Nullable android.net.Uri, @Nullable String);
+    method public void onNetworkLogsAvailable(@NonNull android.content.Context, @NonNull android.content.Intent, long, @IntRange(from=1) int);
+    method public final void onReceive(@NonNull android.content.Context, @NonNull android.content.Intent);
   }
 
   public final class DeviceAdminInfo implements android.os.Parcelable {
@@ -6544,38 +6544,38 @@
 
   public class DeviceAdminReceiver extends android.content.BroadcastReceiver {
     ctor public DeviceAdminReceiver();
-    method public android.app.admin.DevicePolicyManager getManager(android.content.Context);
-    method public android.content.ComponentName getWho(android.content.Context);
-    method public void onBugreportFailed(android.content.Context, android.content.Intent, int);
-    method public void onBugreportShared(android.content.Context, android.content.Intent, String);
-    method public void onBugreportSharingDeclined(android.content.Context, android.content.Intent);
-    method public String onChoosePrivateKeyAlias(android.content.Context, android.content.Intent, int, android.net.Uri, String);
-    method public CharSequence onDisableRequested(android.content.Context, android.content.Intent);
-    method public void onDisabled(android.content.Context, android.content.Intent);
-    method public void onEnabled(android.content.Context, android.content.Intent);
-    method public void onLockTaskModeEntering(android.content.Context, android.content.Intent, String);
-    method public void onLockTaskModeExiting(android.content.Context, android.content.Intent);
-    method public void onNetworkLogsAvailable(android.content.Context, android.content.Intent, long, int);
-    method @Deprecated public void onPasswordChanged(android.content.Context, android.content.Intent);
-    method public void onPasswordChanged(android.content.Context, android.content.Intent, android.os.UserHandle);
-    method @Deprecated public void onPasswordExpiring(android.content.Context, android.content.Intent);
-    method public void onPasswordExpiring(android.content.Context, android.content.Intent, android.os.UserHandle);
-    method @Deprecated public void onPasswordFailed(android.content.Context, android.content.Intent);
-    method public void onPasswordFailed(android.content.Context, android.content.Intent, android.os.UserHandle);
-    method @Deprecated public void onPasswordSucceeded(android.content.Context, android.content.Intent);
-    method public void onPasswordSucceeded(android.content.Context, android.content.Intent, android.os.UserHandle);
-    method public void onProfileProvisioningComplete(android.content.Context, android.content.Intent);
-    method @Deprecated public void onReadyForUserInitialization(android.content.Context, android.content.Intent);
-    method public void onReceive(android.content.Context, android.content.Intent);
-    method public void onSecurityLogsAvailable(android.content.Context, android.content.Intent);
-    method public void onSystemUpdatePending(android.content.Context, android.content.Intent, long);
-    method public void onTransferAffiliatedProfileOwnershipComplete(android.content.Context, android.os.UserHandle);
+    method @NonNull public android.app.admin.DevicePolicyManager getManager(@NonNull android.content.Context);
+    method @NonNull public android.content.ComponentName getWho(@NonNull android.content.Context);
+    method public void onBugreportFailed(@NonNull android.content.Context, @NonNull android.content.Intent, int);
+    method public void onBugreportShared(@NonNull android.content.Context, @NonNull android.content.Intent, @NonNull String);
+    method public void onBugreportSharingDeclined(@NonNull android.content.Context, @NonNull android.content.Intent);
+    method @Nullable public String onChoosePrivateKeyAlias(@NonNull android.content.Context, @NonNull android.content.Intent, int, @Nullable android.net.Uri, @Nullable String);
+    method @Nullable public CharSequence onDisableRequested(@NonNull android.content.Context, @NonNull android.content.Intent);
+    method public void onDisabled(@NonNull android.content.Context, @NonNull android.content.Intent);
+    method public void onEnabled(@NonNull android.content.Context, @NonNull android.content.Intent);
+    method public void onLockTaskModeEntering(@NonNull android.content.Context, @NonNull android.content.Intent, @NonNull String);
+    method public void onLockTaskModeExiting(@NonNull android.content.Context, @NonNull android.content.Intent);
+    method public void onNetworkLogsAvailable(@NonNull android.content.Context, @NonNull android.content.Intent, long, @IntRange(from=1) int);
+    method @Deprecated public void onPasswordChanged(@NonNull android.content.Context, @NonNull android.content.Intent);
+    method public void onPasswordChanged(@NonNull android.content.Context, @NonNull android.content.Intent, @NonNull android.os.UserHandle);
+    method @Deprecated public void onPasswordExpiring(@NonNull android.content.Context, @NonNull android.content.Intent);
+    method public void onPasswordExpiring(@NonNull android.content.Context, @NonNull android.content.Intent, @NonNull android.os.UserHandle);
+    method @Deprecated public void onPasswordFailed(@NonNull android.content.Context, @NonNull android.content.Intent);
+    method public void onPasswordFailed(@NonNull android.content.Context, @NonNull android.content.Intent, @NonNull android.os.UserHandle);
+    method @Deprecated public void onPasswordSucceeded(@NonNull android.content.Context, @NonNull android.content.Intent);
+    method public void onPasswordSucceeded(@NonNull android.content.Context, @NonNull android.content.Intent, @NonNull android.os.UserHandle);
+    method public void onProfileProvisioningComplete(@NonNull android.content.Context, @NonNull android.content.Intent);
+    method @Deprecated public void onReadyForUserInitialization(@NonNull android.content.Context, @NonNull android.content.Intent);
+    method public void onReceive(@NonNull android.content.Context, @NonNull android.content.Intent);
+    method public void onSecurityLogsAvailable(@NonNull android.content.Context, @NonNull android.content.Intent);
+    method public void onSystemUpdatePending(@NonNull android.content.Context, @NonNull android.content.Intent, long);
+    method public void onTransferAffiliatedProfileOwnershipComplete(@NonNull android.content.Context, @NonNull android.os.UserHandle);
     method public void onTransferOwnershipComplete(@NonNull android.content.Context, @Nullable android.os.PersistableBundle);
-    method public void onUserAdded(android.content.Context, android.content.Intent, @NonNull android.os.UserHandle);
-    method public void onUserRemoved(android.content.Context, android.content.Intent, @NonNull android.os.UserHandle);
-    method public void onUserStarted(android.content.Context, android.content.Intent, @NonNull android.os.UserHandle);
-    method public void onUserStopped(android.content.Context, android.content.Intent, @NonNull android.os.UserHandle);
-    method public void onUserSwitched(android.content.Context, android.content.Intent, @NonNull android.os.UserHandle);
+    method public void onUserAdded(@NonNull android.content.Context, @NonNull android.content.Intent, @NonNull android.os.UserHandle);
+    method public void onUserRemoved(@NonNull android.content.Context, @NonNull android.content.Intent, @NonNull android.os.UserHandle);
+    method public void onUserStarted(@NonNull android.content.Context, @NonNull android.content.Intent, @NonNull android.os.UserHandle);
+    method public void onUserStopped(@NonNull android.content.Context, @NonNull android.content.Intent, @NonNull android.os.UserHandle);
+    method public void onUserSwitched(@NonNull android.content.Context, @NonNull android.content.Intent, @NonNull android.os.UserHandle);
     field public static final String ACTION_CHOOSE_PRIVATE_KEY_ALIAS = "android.app.action.CHOOSE_PRIVATE_KEY_ALIAS";
     field public static final String ACTION_DEVICE_ADMIN_DISABLED = "android.app.action.DEVICE_ADMIN_DISABLED";
     field public static final String ACTION_DEVICE_ADMIN_DISABLE_REQUESTED = "android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED";
@@ -6623,7 +6623,7 @@
     method @Nullable public String[] getAccountTypesWithManagementDisabled();
     method @Nullable public java.util.List<android.content.ComponentName> getActiveAdmins();
     method @NonNull public java.util.Set<java.lang.String> getAffiliationIds(@NonNull android.content.ComponentName);
-    method @Nullable public java.util.List<java.lang.String> getAlwaysOnVpnLockdownWhitelist(@NonNull android.content.ComponentName);
+    method @Nullable public java.util.Set<java.lang.String> getAlwaysOnVpnLockdownWhitelist(@NonNull android.content.ComponentName);
     method @Nullable public String getAlwaysOnVpnPackage(@NonNull android.content.ComponentName);
     method @WorkerThread @NonNull public android.os.Bundle getApplicationRestrictions(@Nullable android.content.ComponentName, String);
     method @Deprecated @Nullable public String getApplicationRestrictionsManagingPackage(@NonNull android.content.ComponentName);
@@ -6641,7 +6641,7 @@
     method @NonNull public java.util.List<java.lang.String> getDelegatedScopes(@Nullable android.content.ComponentName, @NonNull String);
     method public CharSequence getDeviceOwnerLockScreenInfo();
     method public CharSequence getEndUserSessionMessage(@NonNull android.content.ComponentName);
-    method public String getGlobalPrivateDnsHost(@NonNull android.content.ComponentName);
+    method @Nullable public String getGlobalPrivateDnsHost(@NonNull android.content.ComponentName);
     method public int getGlobalPrivateDnsMode(@NonNull android.content.ComponentName);
     method @NonNull public java.util.List<byte[]> getInstalledCaCerts(@Nullable android.content.ComponentName);
     method @Nullable public java.util.List<java.lang.String> getKeepUninstalledPackages(@Nullable android.content.ComponentName);
@@ -6736,7 +6736,7 @@
     method public void setAccountManagementDisabled(@NonNull android.content.ComponentName, String, boolean);
     method public void setAffiliationIds(@NonNull android.content.ComponentName, @NonNull java.util.Set<java.lang.String>);
     method public void setAlwaysOnVpnPackage(@NonNull android.content.ComponentName, @Nullable String, boolean) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public void setAlwaysOnVpnPackage(@NonNull android.content.ComponentName, @Nullable String, boolean, @Nullable java.util.List<java.lang.String>) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public void setAlwaysOnVpnPackage(@NonNull android.content.ComponentName, @Nullable String, boolean, @Nullable java.util.Set<java.lang.String>) throws android.content.pm.PackageManager.NameNotFoundException;
     method public boolean setApplicationHidden(@NonNull android.content.ComponentName, String, boolean);
     method @WorkerThread public void setApplicationRestrictions(@Nullable android.content.ComponentName, String, android.os.Bundle);
     method @Deprecated public void setApplicationRestrictionsManagingPackage(@NonNull android.content.ComponentName, @Nullable String) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -7966,9 +7966,9 @@
     method public boolean isMultipleAdvertisementSupported();
     method public boolean isOffloadedFilteringSupported();
     method public boolean isOffloadedScanBatchingSupported();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothServerSocket listenUsingInsecureL2capChannel() throws java.io.IOException;
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) @NonNull public android.bluetooth.BluetoothServerSocket listenUsingInsecureL2capChannel() throws java.io.IOException;
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String, java.util.UUID) throws java.io.IOException;
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothServerSocket listenUsingL2capChannel() throws java.io.IOException;
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) @NonNull public android.bluetooth.BluetoothServerSocket listenUsingL2capChannel() throws java.io.IOException;
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothServerSocket listenUsingRfcommWithServiceRecord(String, java.util.UUID) throws java.io.IOException;
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setName(String);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean startDiscovery();
@@ -8336,9 +8336,9 @@
     method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int);
     method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int, android.os.Handler);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean createBond();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothSocket createInsecureL2capChannel(int) throws java.io.IOException;
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) @NonNull public android.bluetooth.BluetoothSocket createInsecureL2capChannel(int) throws java.io.IOException;
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothSocket createL2capChannel(int) throws java.io.IOException;
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) @NonNull public android.bluetooth.BluetoothSocket createL2capChannel(int) throws java.io.IOException;
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
     method public int describeContents();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean fetchUuidsWithSdp();
@@ -14431,6 +14431,7 @@
     method @ColorInt public int getColor();
     method public android.graphics.ColorFilter getColorFilter();
     method @ColorLong public long getColorLong();
+    method public int getEndHyphenEdit();
     method public boolean getFillPath(android.graphics.Path, android.graphics.Path);
     method public int getFlags();
     method public String getFontFeatureSettings();
@@ -14441,7 +14442,6 @@
     method public float getFontSpacing();
     method public String getFontVariationSettings();
     method public int getHinting();
-    method public int getHyphenEdit();
     method public float getLetterSpacing();
     method public android.graphics.MaskFilter getMaskFilter();
     method public int getOffsetForAdvance(char[], int, int, int, int, boolean, float);
@@ -14455,6 +14455,7 @@
     method public float getShadowLayerDx();
     method public float getShadowLayerDy();
     method public float getShadowLayerRadius();
+    method public int getStartHyphenEdit();
     method @Px public float getStrikeThruPosition();
     method @Px public float getStrikeThruThickness();
     method public android.graphics.Paint.Cap getStrokeCap();
@@ -14510,13 +14511,13 @@
     method public android.graphics.ColorFilter setColorFilter(android.graphics.ColorFilter);
     method public void setDither(boolean);
     method public void setElegantTextHeight(boolean);
+    method public void setEndHyphenEdit(int);
     method public void setFakeBoldText(boolean);
     method public void setFilterBitmap(boolean);
     method public void setFlags(int);
     method public void setFontFeatureSettings(String);
     method public boolean setFontVariationSettings(String);
     method public void setHinting(int);
-    method public void setHyphenEdit(int);
     method public void setLetterSpacing(float);
     method public void setLinearText(boolean);
     method public android.graphics.MaskFilter setMaskFilter(android.graphics.MaskFilter);
@@ -14524,6 +14525,7 @@
     method public android.graphics.Shader setShader(android.graphics.Shader);
     method public void setShadowLayer(float, float, float, @ColorInt int);
     method public void setShadowLayer(float, float, float, @ColorLong long);
+    method public void setStartHyphenEdit(int);
     method public void setStrikeThruText(boolean);
     method public void setStrokeCap(android.graphics.Paint.Cap);
     method public void setStrokeJoin(android.graphics.Paint.Join);
@@ -14550,11 +14552,21 @@
     field public static final int DEV_KERN_TEXT_FLAG = 256; // 0x100
     field public static final int DITHER_FLAG = 4; // 0x4
     field public static final int EMBEDDED_BITMAP_TEXT_FLAG = 1024; // 0x400
+    field public static final int END_HYPHEN_EDIT_INSERT_ARMENIAN_HYPHEN = 3; // 0x3
+    field public static final int END_HYPHEN_EDIT_INSERT_HYPHEN = 2; // 0x2
+    field public static final int END_HYPHEN_EDIT_INSERT_MAQAF = 4; // 0x4
+    field public static final int END_HYPHEN_EDIT_INSERT_UCAS_HYPHEN = 5; // 0x5
+    field public static final int END_HYPHEN_EDIT_INSERT_ZWJ_AND_HYPHEN = 6; // 0x6
+    field public static final int END_HYPHEN_EDIT_NO_EDIT = 0; // 0x0
+    field public static final int END_HYPHEN_EDIT_REPLACE_WITH_HYPHEN = 1; // 0x1
     field public static final int FAKE_BOLD_TEXT_FLAG = 32; // 0x20
     field public static final int FILTER_BITMAP_FLAG = 2; // 0x2
     field public static final int HINTING_OFF = 0; // 0x0
     field public static final int HINTING_ON = 1; // 0x1
     field public static final int LINEAR_TEXT_FLAG = 64; // 0x40
+    field public static final int START_HYPHEN_EDIT_INSERT_HYPHEN = 1; // 0x1
+    field public static final int START_HYPHEN_EDIT_INSERT_ZWJ = 2; // 0x2
+    field public static final int START_HYPHEN_EDIT_NO_EDIT = 0; // 0x0
     field public static final int STRIKE_THRU_TEXT_FLAG = 16; // 0x10
     field public static final int SUBPIXEL_TEXT_FLAG = 128; // 0x80
     field public static final int UNDERLINE_TEXT_FLAG = 8; // 0x8
@@ -15790,7 +15802,7 @@
     ctor public Font.Builder(@NonNull android.os.ParcelFileDescriptor, @IntRange(from=0) long, @IntRange(from=0xffffffff) long);
     ctor public Font.Builder(@NonNull android.content.res.AssetManager, @NonNull String);
     ctor public Font.Builder(@NonNull android.content.res.Resources, int);
-    method @Nullable public android.graphics.fonts.Font build() throws java.io.IOException;
+    method @NonNull public android.graphics.fonts.Font build() throws java.io.IOException;
     method @NonNull public android.graphics.fonts.Font.Builder setFontVariationSettings(@Nullable String);
     method @NonNull public android.graphics.fonts.Font.Builder setFontVariationSettings(@Nullable android.graphics.fonts.FontVariationAxis[]);
     method @NonNull public android.graphics.fonts.Font.Builder setSlant(int);
@@ -15917,30 +15929,30 @@
 
   public static class LineBreaker.ParagraphConstraints {
     ctor public LineBreaker.ParagraphConstraints();
-    method @Px @IntRange(from=0) public int getDefaultTabStop();
+    method @Px @FloatRange(from=0) public float getDefaultTabStop();
     method @Px @FloatRange(from=0.0f) public float getFirstWidth();
     method @Px @IntRange(from=0) public int getFirstWidthLineCount();
-    method @Nullable public int[] getTabStops();
+    method @Nullable public float[] getTabStops();
     method @Px @FloatRange(from=0.0f) public float getWidth();
     method public void setIndent(@Px @FloatRange(from=0.0f) float, @Px @IntRange(from=0) int);
-    method public void setTabStops(@Nullable int[], @Px @IntRange(from=0) int);
+    method public void setTabStops(@Nullable float[], @Px @FloatRange(from=0) float);
     method public void setWidth(@Px @FloatRange(from=0.0f) float);
   }
 
   public static class LineBreaker.Result {
+    method public int getEndLineHyphenEdit(int);
     method @Px public float getLineAscent(@IntRange(from=0) int);
     method @IntRange(from=0) public int getLineBreakOffset(@IntRange(from=0) int);
     method @IntRange(from=0) public int getLineCount();
     method @Px public float getLineDescent(@IntRange(from=0) int);
-    method public int getLineHyphenEdit(int);
     method @Px public float getLineWidth(@IntRange(from=0) int);
+    method public int getStartLineHyphenEdit(int);
     method public boolean hasLineTab(int);
   }
 
   public class MeasuredText {
     method public void getBounds(@IntRange(from=0) int, @IntRange(from=0) int, @NonNull android.graphics.Rect);
     method @FloatRange(from=0.0f) @Px public float getCharWidthAt(@IntRange(from=0) int);
-    method @NonNull public char[] getChars();
     method @FloatRange(from=0.0) @Px public float getWidth(@IntRange(from=0) int, @IntRange(from=0) int);
   }
 
@@ -17354,15 +17366,16 @@
     method @Nullable public java.util.Set<android.util.Size> getInputSizes(int);
     method @NonNull public java.util.Set<java.lang.Integer> getOutputFormats();
     method @IntRange(from=0) public long getOutputMinFrameDuration(int, @NonNull android.util.Size);
-    method public <T> long getOutputMinFrameDuration(@NonNull Class<T>, @NonNull android.util.Size);
+    method @IntRange(from=0) public <T> long getOutputMinFrameDuration(@NonNull Class<T>, @NonNull android.util.Size);
     method @Nullable public java.util.Set<android.util.Size> getOutputSizes(int);
-    method public <T> java.util.Set<android.util.Size> getOutputSizes(@NonNull Class<T>);
+    method @Nullable public <T> java.util.Set<android.util.Size> getOutputSizes(@NonNull Class<T>);
     method @IntRange(from=0) public long getOutputStallDuration(int, @NonNull android.util.Size);
-    method public <T> long getOutputStallDuration(@NonNull Class<T>, @NonNull android.util.Size);
+    method @IntRange(from=0) public <T> long getOutputStallDuration(@NonNull Class<T>, @NonNull android.util.Size);
     method public int getRecommendedUseCase();
     method @Nullable public java.util.Set<java.lang.Integer> getValidOutputFormatsForInput(int);
     method public boolean isOutputSupportedFor(int);
     method public boolean isOutputSupportedFor(@NonNull android.view.Surface);
+    field public static final int USECASE_LOW_LATENCY_SNAPSHOT = 6; // 0x6
     field public static final int USECASE_PREVIEW = 0; // 0x0
     field public static final int USECASE_RAW = 5; // 0x5
     field public static final int USECASE_RECORD = 1; // 0x1
@@ -22680,10 +22693,9 @@
     method @Deprecated public double getCarrierPhase();
     method @Deprecated public double getCarrierPhaseUncertainty();
     method public double getCn0DbHz();
-    method public int getCodeType();
+    method @NonNull public String getCodeType();
     method public int getConstellationType();
     method public int getMultipathIndicator();
-    method @NonNull public String getOtherCodeTypeName();
     method public double getPseudorangeRateMetersPerSecond();
     method public double getPseudorangeRateUncertaintyMetersPerSecond();
     method public long getReceivedSvTimeNanos();
@@ -22706,22 +22718,6 @@
     field public static final int ADR_STATE_RESET = 2; // 0x2
     field public static final int ADR_STATE_UNKNOWN = 0; // 0x0
     field public static final int ADR_STATE_VALID = 1; // 0x1
-    field public static final int CODE_TYPE_A = 0; // 0x0
-    field public static final int CODE_TYPE_B = 1; // 0x1
-    field public static final int CODE_TYPE_C = 2; // 0x2
-    field public static final int CODE_TYPE_I = 3; // 0x3
-    field public static final int CODE_TYPE_L = 4; // 0x4
-    field public static final int CODE_TYPE_M = 5; // 0x5
-    field public static final int CODE_TYPE_N = 13; // 0xd
-    field public static final int CODE_TYPE_OTHER = 255; // 0xff
-    field public static final int CODE_TYPE_P = 6; // 0x6
-    field public static final int CODE_TYPE_Q = 7; // 0x7
-    field public static final int CODE_TYPE_S = 8; // 0x8
-    field public static final int CODE_TYPE_UNKNOWN = -1; // 0xffffffff
-    field public static final int CODE_TYPE_W = 9; // 0x9
-    field public static final int CODE_TYPE_X = 10; // 0xa
-    field public static final int CODE_TYPE_Y = 11; // 0xb
-    field public static final int CODE_TYPE_Z = 12; // 0xc
     field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssMeasurement> CREATOR;
     field public static final int MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
     field public static final int MULTIPATH_INDICATOR_NOT_DETECTED = 2; // 0x2
@@ -22837,6 +22833,24 @@
     method @Deprecated public boolean usedInFix();
   }
 
+  @Deprecated public final class GpsStatus {
+    method @Deprecated public int getMaxSatellites();
+    method @Deprecated public Iterable<android.location.GpsSatellite> getSatellites();
+    method @Deprecated public int getTimeToFirstFix();
+    field @Deprecated public static final int GPS_EVENT_FIRST_FIX = 3; // 0x3
+    field @Deprecated public static final int GPS_EVENT_SATELLITE_STATUS = 4; // 0x4
+    field @Deprecated public static final int GPS_EVENT_STARTED = 1; // 0x1
+    field @Deprecated public static final int GPS_EVENT_STOPPED = 2; // 0x2
+  }
+
+  @Deprecated public static interface GpsStatus.Listener {
+    method @Deprecated public void onGpsStatusChanged(int);
+  }
+
+  @Deprecated public static interface GpsStatus.NmeaListener {
+    method @Deprecated public void onNmeaReceived(long, String);
+  }
+
   public class Location implements android.os.Parcelable {
     ctor public Location(String);
     ctor public Location(android.location.Location);
@@ -22905,6 +22919,7 @@
   }
 
   public class LocationManager {
+    method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addGpsStatusListener(android.location.GpsStatus.Listener);
     method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(@NonNull android.location.OnNmeaMessageListener);
     method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(@NonNull android.location.OnNmeaMessageListener, @Nullable android.os.Handler);
     method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void addProximityAlert(double, double, float, long, @NonNull android.app.PendingIntent);
@@ -22916,6 +22931,7 @@
     method @Nullable public String getBestProvider(@NonNull android.location.Criteria, boolean);
     method @Nullable public String getGnssHardwareModelName();
     method public int getGnssYearOfHardware();
+    method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public android.location.GpsStatus getGpsStatus(@Nullable android.location.GpsStatus);
     method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) @Nullable public android.location.Location getLastKnownLocation(@NonNull String);
     method @Nullable public android.location.LocationProvider getProvider(@NonNull String);
     method @NonNull public java.util.List<java.lang.String> getProviders(boolean);
@@ -22928,6 +22944,7 @@
     method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback, @Nullable android.os.Handler);
     method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssStatusCallback(@NonNull android.location.GnssStatus.Callback);
     method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssStatusCallback(@NonNull android.location.GnssStatus.Callback, @Nullable android.os.Handler);
+    method @Deprecated public void removeGpsStatusListener(android.location.GpsStatus.Listener);
     method public void removeNmeaListener(@NonNull android.location.OnNmeaMessageListener);
     method @RequiresPermission(anyOf={"android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"}, apis="..22") public void removeProximityAlert(@NonNull android.app.PendingIntent);
     method public void removeTestProvider(@NonNull String);
@@ -22949,6 +22966,7 @@
     method public void unregisterGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback);
     method public void unregisterGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback);
     method public void unregisterGnssStatusCallback(@NonNull android.location.GnssStatus.Callback);
+    field public static final String EXTRA_PROVIDER_NAME = "android.location.extra.PROVIDER_NAME";
     field public static final String GPS_PROVIDER = "gps";
     field public static final String KEY_LOCATION_CHANGED = "location";
     field public static final String KEY_PROVIDER_ENABLED = "providerEnabled";
@@ -22988,7 +23006,7 @@
     method protected abstract String onGetSummary();
     method public final void onStart(android.content.Intent, int);
     method public final int onStartCommand(android.content.Intent, int, int);
-    method public static final void refreshSettings(android.content.Context);
+    method public static final void refreshSettings(@NonNull android.content.Context);
     field public static final String ACTION_INJECTED_SETTING_CHANGED = "android.location.InjectedSettingChanged";
     field public static final String ACTION_SERVICE_INTENT = "android.location.SettingInjectorService";
     field public static final String ATTRIBUTES_NAME = "injected-location-setting";
@@ -24740,6 +24758,10 @@
 
   public final class MediaDrm implements java.lang.AutoCloseable {
     ctor public MediaDrm(@NonNull java.util.UUID) throws android.media.UnsupportedSchemeException;
+    method public void clearOnEventListener();
+    method public void clearOnExpirationUpdateListener();
+    method public void clearOnKeyStatusChangeListener();
+    method public void clearOnSessionLostStateListener();
     method public void close();
     method public void closeSession(@NonNull byte[]);
     method @android.media.MediaDrm.HdcpLevel public int getConnectedHdcpLevel();
@@ -24776,9 +24798,14 @@
     method public void removeSecureStop(@NonNull byte[]);
     method public void restoreKeys(@NonNull byte[], @NonNull byte[]);
     method public void setOnEventListener(@Nullable android.media.MediaDrm.OnEventListener);
+    method public void setOnEventListener(@Nullable android.media.MediaDrm.OnEventListener, @Nullable android.os.Handler);
+    method public void setOnEventListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.MediaDrm.OnEventListener);
     method public void setOnExpirationUpdateListener(@Nullable android.media.MediaDrm.OnExpirationUpdateListener, @Nullable android.os.Handler);
+    method public void setOnExpirationUpdateListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.MediaDrm.OnExpirationUpdateListener);
     method public void setOnKeyStatusChangeListener(@Nullable android.media.MediaDrm.OnKeyStatusChangeListener, @Nullable android.os.Handler);
+    method public void setOnKeyStatusChangeListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.MediaDrm.OnKeyStatusChangeListener);
     method public void setOnSessionLostStateListener(@Nullable android.media.MediaDrm.OnSessionLostStateListener, @Nullable android.os.Handler);
+    method public void setOnSessionLostStateListener(@NonNull java.util.concurrent.Executor, @Nullable android.media.MediaDrm.OnSessionLostStateListener);
     method public void setPropertyByteArray(@NonNull String, @NonNull byte[]);
     method public void setPropertyString(@NonNull String, @NonNull String);
     field @Deprecated public static final int EVENT_KEY_EXPIRED = 3; // 0x3
@@ -24820,7 +24847,7 @@
     method public boolean verify(@NonNull byte[], @NonNull byte[], @NonNull byte[]);
   }
 
-  @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef({android.media.MediaDrm.HDCP_LEVEL_UNKNOWN, android.media.MediaDrm.HDCP_NONE, android.media.MediaDrm.HDCP_V1, android.media.MediaDrm.HDCP_V2, android.media.MediaDrm.HDCP_V2_1, android.media.MediaDrm.HDCP_V2_2, android.media.MediaDrm.HDCP_V2_3, android.media.MediaDrm.HDCP_NO_DIGITAL_OUTPUT}) public static @interface MediaDrm.HdcpLevel {
+  @Deprecated @IntDef({android.media.MediaDrm.HDCP_LEVEL_UNKNOWN, android.media.MediaDrm.HDCP_NONE, android.media.MediaDrm.HDCP_V1, android.media.MediaDrm.HDCP_V2, android.media.MediaDrm.HDCP_V2_1, android.media.MediaDrm.HDCP_V2_2, android.media.MediaDrm.HDCP_V2_3, android.media.MediaDrm.HDCP_NO_DIGITAL_OUTPUT}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface MediaDrm.HdcpLevel {
   }
 
   public static final class MediaDrm.KeyRequest {
@@ -24907,7 +24934,7 @@
     method @NonNull public String getDefaultUrl();
   }
 
-  @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef({android.media.MediaDrm.SECURITY_LEVEL_UNKNOWN, android.media.MediaDrm.SECURITY_LEVEL_SW_SECURE_CRYPTO, android.media.MediaDrm.SECURITY_LEVEL_SW_SECURE_DECODE, android.media.MediaDrm.SECURITY_LEVEL_HW_SECURE_CRYPTO, android.media.MediaDrm.SECURITY_LEVEL_HW_SECURE_DECODE, android.media.MediaDrm.SECURITY_LEVEL_HW_SECURE_ALL}) public static @interface MediaDrm.SecurityLevel {
+  @Deprecated @IntDef({android.media.MediaDrm.SECURITY_LEVEL_UNKNOWN, android.media.MediaDrm.SECURITY_LEVEL_SW_SECURE_CRYPTO, android.media.MediaDrm.SECURITY_LEVEL_SW_SECURE_DECODE, android.media.MediaDrm.SECURITY_LEVEL_HW_SECURE_CRYPTO, android.media.MediaDrm.SECURITY_LEVEL_HW_SECURE_DECODE, android.media.MediaDrm.SECURITY_LEVEL_HW_SECURE_ALL}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface MediaDrm.SecurityLevel {
   }
 
   public static final class MediaDrm.SessionException extends java.lang.RuntimeException {
@@ -26399,7 +26426,7 @@
   public final class Session2Token implements android.os.Parcelable {
     ctor public Session2Token(@NonNull android.content.Context, @NonNull android.content.ComponentName);
     method public int describeContents();
-    method @Nullable public android.os.Bundle getExtras();
+    method @NonNull public android.os.Bundle getExtras();
     method @NonNull public String getPackageName();
     method @Nullable public String getServiceName();
     method public int getType();
@@ -30098,8 +30125,8 @@
     method @NonNull public android.net.wifi.WifiNetworkSpecifier build();
     method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setBssid(@NonNull android.net.MacAddress);
     method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setBssidPattern(@NonNull android.net.MacAddress, @NonNull android.net.MacAddress);
-    method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setIsEnhancedOpen();
-    method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setIsHiddenSsid();
+    method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setIsEnhancedOpen(boolean);
+    method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setIsHiddenSsid(boolean);
     method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setSsid(@NonNull String);
     method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setSsidPattern(@NonNull android.os.PatternMatcher);
     method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setWpa2EnterpriseConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
@@ -30118,12 +30145,12 @@
     ctor public WifiNetworkSuggestion.Builder();
     method @NonNull public android.net.wifi.WifiNetworkSuggestion build();
     method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setBssid(@NonNull android.net.MacAddress);
-    method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsAppInteractionRequired();
-    method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsEnhancedOpen();
-    method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsHiddenSsid();
-    method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsMetered();
-    method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsUserInteractionRequired();
-    method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setPriority(int);
+    method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsAppInteractionRequired(boolean);
+    method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsEnhancedOpen(boolean);
+    method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsHiddenSsid(boolean);
+    method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsMetered(boolean);
+    method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsUserInteractionRequired(boolean);
+    method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setPriority(@IntRange(from=0) int);
     method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setSsid(@NonNull String);
     method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setWpa2EnterpriseConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
     method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setWpa2Passphrase(@NonNull String);
@@ -43165,6 +43192,7 @@
     method public void unregisterCallback(android.telecom.Call.Callback);
     field @Deprecated public static final String AVAILABLE_PHONE_ACCOUNTS = "selectPhoneAccountAccounts";
     field public static final String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS = "android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS";
+    field public static final String EXTRA_SILENT_RINGING_REQUESTED = "android.telecom.extra.SILENT_RINGING_REQUESTED";
     field public static final String EXTRA_SUGGESTED_PHONE_ACCOUNTS = "android.telecom.extra.SUGGESTED_PHONE_ACCOUNTS";
     field public static final int STATE_ACTIVE = 4; // 0x4
     field public static final int STATE_CONNECTING = 9; // 0x9
@@ -43323,9 +43351,9 @@
   public abstract class CallRedirectionService extends android.app.Service {
     ctor public CallRedirectionService();
     method public final void cancelCall();
-    method public final android.os.IBinder onBind(android.content.Intent);
+    method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
     method public abstract void onPlaceCall(@NonNull android.net.Uri, @NonNull android.telecom.PhoneAccountHandle, boolean);
-    method public final boolean onUnbind(android.content.Intent);
+    method public final boolean onUnbind(@NonNull android.content.Intent);
     method public final void placeCallUnmodified();
     method public final void redirectCall(@NonNull android.net.Uri, @NonNull android.telecom.PhoneAccountHandle, boolean);
     field public static final String SERVICE_INTERFACE = "android.telecom.CallRedirectionService";
@@ -43352,6 +43380,7 @@
   public static class CallScreeningService.CallResponse {
     method public boolean getDisallowCall();
     method public boolean getRejectCall();
+    method public boolean getSilenceCall();
     method public boolean getSkipCallLog();
     method public boolean getSkipNotification();
   }
@@ -43361,6 +43390,7 @@
     method public android.telecom.CallScreeningService.CallResponse build();
     method public android.telecom.CallScreeningService.CallResponse.Builder setDisallowCall(boolean);
     method public android.telecom.CallScreeningService.CallResponse.Builder setRejectCall(boolean);
+    method @NonNull public android.telecom.CallScreeningService.CallResponse.Builder setSilenceCall(boolean);
     method public android.telecom.CallScreeningService.CallResponse.Builder setSkipCallLog(boolean);
     method public android.telecom.CallScreeningService.CallResponse.Builder setSkipNotification(boolean);
   }
@@ -44388,12 +44418,12 @@
   }
 
   public final class CellIdentityNr extends android.telephony.CellIdentity {
-    method public String getMccString();
-    method public String getMncString();
+    method @Nullable public String getMccString();
+    method @Nullable public String getMncString();
     method public long getNci();
-    method public int getNrarfcn();
-    method public int getPci();
-    method public int getTac();
+    method @IntRange(from=0, to=3279165) public int getNrarfcn();
+    method @IntRange(from=0, to=1007) public int getPci();
+    method @IntRange(from=0, to=65535) public int getTac();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellIdentityNr> CREATOR;
   }
@@ -44460,8 +44490,8 @@
   }
 
   public final class CellInfoNr extends android.telephony.CellInfo {
-    method public android.telephony.CellIdentity getCellIdentity();
-    method public android.telephony.CellSignalStrength getCellSignalStrength();
+    method @NonNull public android.telephony.CellIdentity getCellIdentity();
+    method @NonNull public android.telephony.CellSignalStrength getCellSignalStrength();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellInfoNr> CREATOR;
   }
@@ -45218,7 +45248,7 @@
     field public static final String EXTRA_CARRIER_ID = "android.telephony.extra.CARRIER_ID";
     field public static final String EXTRA_CARRIER_NAME = "android.telephony.extra.CARRIER_NAME";
     field public static final String EXTRA_HIDE_PUBLIC_SETTINGS = "android.telephony.extra.HIDE_PUBLIC_SETTINGS";
-    field public static final String EXTRA_INCOMING_NUMBER = "incoming_number";
+    field @Deprecated public static final String EXTRA_INCOMING_NUMBER = "incoming_number";
     field public static final String EXTRA_IS_REFRESH = "android.telephony.extra.IS_REFRESH";
     field public static final String EXTRA_LAUNCH_VOICEMAIL_SETTINGS_INTENT = "android.telephony.extra.LAUNCH_VOICEMAIL_SETTINGS_INTENT";
     field public static final String EXTRA_NETWORK_COUNTRY = "android.telephony.extra.NETWORK_COUNTRY";
@@ -45442,26 +45472,26 @@
   public static class ApnSetting.Builder {
     ctor public ApnSetting.Builder();
     method public android.telephony.data.ApnSetting build();
-    method public android.telephony.data.ApnSetting.Builder setApnName(String);
-    method public android.telephony.data.ApnSetting.Builder setApnTypeBitmask(int);
-    method public android.telephony.data.ApnSetting.Builder setAuthType(int);
-    method public android.telephony.data.ApnSetting.Builder setCarrierEnabled(boolean);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setApnName(String);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setApnTypeBitmask(int);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setAuthType(int);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setCarrierEnabled(boolean);
     method @NonNull public android.telephony.data.ApnSetting.Builder setCarrierId(int);
-    method public android.telephony.data.ApnSetting.Builder setEntryName(String);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setEntryName(String);
     method @Deprecated public android.telephony.data.ApnSetting.Builder setMmsProxyAddress(java.net.InetAddress);
-    method public android.telephony.data.ApnSetting.Builder setMmsProxyAddress(String);
-    method public android.telephony.data.ApnSetting.Builder setMmsProxyPort(int);
-    method public android.telephony.data.ApnSetting.Builder setMmsc(android.net.Uri);
-    method public android.telephony.data.ApnSetting.Builder setMvnoType(int);
-    method public android.telephony.data.ApnSetting.Builder setNetworkTypeBitmask(int);
-    method public android.telephony.data.ApnSetting.Builder setOperatorNumeric(String);
-    method public android.telephony.data.ApnSetting.Builder setPassword(String);
-    method public android.telephony.data.ApnSetting.Builder setProtocol(int);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setMmsProxyAddress(String);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setMmsProxyPort(int);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setMmsc(android.net.Uri);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setMvnoType(int);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setNetworkTypeBitmask(int);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setOperatorNumeric(String);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setPassword(String);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setProtocol(int);
     method @Deprecated public android.telephony.data.ApnSetting.Builder setProxyAddress(java.net.InetAddress);
-    method public android.telephony.data.ApnSetting.Builder setProxyAddress(String);
-    method public android.telephony.data.ApnSetting.Builder setProxyPort(int);
-    method public android.telephony.data.ApnSetting.Builder setRoamingProtocol(int);
-    method public android.telephony.data.ApnSetting.Builder setUser(String);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setProxyAddress(String);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setProxyPort(int);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setRoamingProtocol(int);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setUser(String);
   }
 
 }
@@ -45530,7 +45560,7 @@
     method public boolean isEnabled();
     method public void startResolutionActivity(android.app.Activity, int, android.content.Intent, android.app.PendingIntent) throws android.content.IntentSender.SendIntentException;
     method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void switchToSubscription(int, android.app.PendingIntent);
-    method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void updateSubscriptionNickname(int, String, android.app.PendingIntent);
+    method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void updateSubscriptionNickname(int, @Nullable String, @NonNull android.app.PendingIntent);
     field public static final String ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS = "android.telephony.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS";
     field public static final String ACTION_NOTIFY_CARRIER_SETUP_INCOMPLETE = "android.telephony.euicc.action.NOTIFY_CARRIER_SETUP_INCOMPLETE";
     field public static final int EMBEDDED_SUBSCRIPTION_RESULT_ERROR = 2; // 0x2
@@ -46004,22 +46034,6 @@
     method public void handleTag(boolean, String, android.text.Editable, org.xml.sax.XMLReader);
   }
 
-  public class Hyphenator {
-    method public static int packHyphenEdit(int, int);
-    method public static int unpackEndHyphenEdit(int);
-    method public static int unpackStartHyphenEdit(int);
-    field public static final int END_HYPHEN_EDIT_INSERT_ARMENIAN_HYPHEN = 3; // 0x3
-    field public static final int END_HYPHEN_EDIT_INSERT_HYPHEN = 2; // 0x2
-    field public static final int END_HYPHEN_EDIT_INSERT_MAQAF = 4; // 0x4
-    field public static final int END_HYPHEN_EDIT_INSERT_UCAS_HYPHEN = 5; // 0x5
-    field public static final int END_HYPHEN_EDIT_INSERT_ZWJ_AND_HYPHEN = 6; // 0x6
-    field public static final int END_HYPHEN_EDIT_NO_EDIT = 0; // 0x0
-    field public static final int END_HYPHEN_EDIT_REPLACE_WITH_HYPHEN = 1; // 0x1
-    field public static final int START_HYPHEN_EDIT_INSERT_HYPHEN = 1; // 0x1
-    field public static final int START_HYPHEN_EDIT_INSERT_ZWJ = 2; // 0x2
-    field public static final int START_HYPHEN_EDIT_NO_EDIT = 0; // 0x0
-  }
-
   public interface InputFilter {
     method public CharSequence filter(CharSequence, int, int, android.text.Spanned, int, int);
   }
@@ -50349,6 +50363,7 @@
     method @IdRes public int getAccessibilityTraversalBefore();
     method @android.view.ViewDebug.ExportedProperty(category="drawing") public float getAlpha();
     method public android.view.animation.Animation getAnimation();
+    method @Nullable public android.graphics.Matrix getAnimationMatrix();
     method public android.os.IBinder getApplicationWindowToken();
     method @NonNull public int[] getAttributeResolutionStack(@AttrRes int);
     method @NonNull public java.util.Map<java.lang.Integer,java.lang.Integer> getAttributeSourceResourceMap();
@@ -53482,27 +53497,12 @@
     method @Nullable public <T> android.view.inspector.InspectionCompanion<T> provide(@NonNull Class<T>);
   }
 
-  public final class IntEnumMapping {
-    method @Nullable public String get(int);
-  }
-
-  public static final class IntEnumMapping.Builder {
-    ctor public IntEnumMapping.Builder();
-    method @NonNull public android.view.inspector.IntEnumMapping.Builder addValue(@NonNull String, int);
-    method @NonNull public android.view.inspector.IntEnumMapping build();
-  }
-
   public final class IntFlagMapping {
+    ctor public IntFlagMapping();
+    method public void add(int, int, @NonNull String);
     method @NonNull public java.util.Set<java.lang.String> get(int);
   }
 
-  public static final class IntFlagMapping.Builder {
-    ctor public IntFlagMapping.Builder();
-    method @NonNull public android.view.inspector.IntFlagMapping.Builder addFlag(@NonNull String, int);
-    method @NonNull public android.view.inspector.IntFlagMapping.Builder addFlag(@NonNull String, int, int);
-    method @NonNull public android.view.inspector.IntFlagMapping build();
-  }
-
   public interface PropertyMapper {
     method public int mapBoolean(@NonNull String, @AttrRes int);
     method public int mapByte(@NonNull String, @AttrRes int);
@@ -53512,8 +53512,8 @@
     method public int mapFloat(@NonNull String, @AttrRes int);
     method public int mapGravity(@NonNull String, @AttrRes int);
     method public int mapInt(@NonNull String, @AttrRes int);
-    method public int mapIntEnum(@NonNull String, @AttrRes int, @NonNull android.view.inspector.IntEnumMapping);
-    method public int mapIntFlag(@NonNull String, @AttrRes int, @NonNull android.view.inspector.IntFlagMapping);
+    method public int mapIntEnum(@NonNull String, @AttrRes int, @NonNull java.util.function.IntFunction<java.lang.String>);
+    method public int mapIntFlag(@NonNull String, @AttrRes int, @NonNull java.util.function.IntFunction<java.util.Set<java.lang.String>>);
     method public int mapLong(@NonNull String, @AttrRes int);
     method public int mapObject(@NonNull String, @AttrRes int);
     method public int mapResourceId(@NonNull String, @AttrRes int);
@@ -56388,10 +56388,12 @@
     method public int getWindowLayoutType();
     method public boolean isAboveAnchor();
     method public boolean isAttachedInDecor();
-    method public boolean isClipToScreenEnabled();
+    method @Deprecated public boolean isClipToScreenEnabled();
+    method public boolean isClippedToScreen();
     method public boolean isClippingEnabled();
     method public boolean isFocusable();
-    method public boolean isLayoutInScreenEnabled();
+    method public boolean isLaidOutInScreen();
+    method @Deprecated public boolean isLayoutInScreenEnabled();
     method public boolean isOutsideTouchable();
     method public boolean isShowing();
     method public boolean isSplitTouchEnabled();
@@ -56400,7 +56402,7 @@
     method public void setAnimationStyle(int);
     method public void setAttachedInDecor(boolean);
     method public void setBackgroundDrawable(android.graphics.drawable.Drawable);
-    method public void setClipToScreenEnabled(boolean);
+    method @Deprecated public void setClipToScreenEnabled(boolean);
     method public void setClippingEnabled(boolean);
     method public void setContentView(android.view.View);
     method public void setElevation(float);
@@ -56411,7 +56413,9 @@
     method public void setHeight(int);
     method public void setIgnoreCheekPress();
     method public void setInputMethodMode(int);
-    method public void setLayoutInScreenEnabled(boolean);
+    method public void setIsClippedToScreen(boolean);
+    method public void setIsLaidOutInScreen(boolean);
+    method @Deprecated public void setLayoutInScreenEnabled(boolean);
     method public void setOnDismissListener(android.widget.PopupWindow.OnDismissListener);
     method public void setOutsideTouchable(boolean);
     method public void setOverlapAnchor(boolean);
diff --git a/api/removed.txt b/api/removed.txt
index 93d06928..fa07094 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -282,24 +282,6 @@
 
 package android.location {
 
-  @Deprecated public final class GpsStatus {
-    method public int getMaxSatellites();
-    method public Iterable<android.location.GpsSatellite> getSatellites();
-    method public int getTimeToFirstFix();
-    field public static final int GPS_EVENT_FIRST_FIX = 3; // 0x3
-    field public static final int GPS_EVENT_SATELLITE_STATUS = 4; // 0x4
-    field public static final int GPS_EVENT_STARTED = 1; // 0x1
-    field public static final int GPS_EVENT_STOPPED = 2; // 0x2
-  }
-
-  @Deprecated public static interface GpsStatus.Listener {
-    method public void onGpsStatusChanged(int);
-  }
-
-  @Deprecated public static interface GpsStatus.NmeaListener {
-    method public void onNmeaReceived(long, String);
-  }
-
   public class Location implements android.os.Parcelable {
     method @Deprecated public void removeBearingAccuracy();
     method @Deprecated public void removeSpeedAccuracy();
@@ -307,10 +289,7 @@
   }
 
   public class LocationManager {
-    method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addGpsStatusListener(android.location.GpsStatus.Listener);
     method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(android.location.GpsStatus.NmeaListener);
-    method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public android.location.GpsStatus getGpsStatus(@Nullable android.location.GpsStatus);
-    method @Deprecated public void removeGpsStatusListener(android.location.GpsStatus.Listener);
     method @Deprecated public void removeNmeaListener(android.location.GpsStatus.NmeaListener);
   }
 
@@ -335,17 +314,11 @@
 package android.net {
 
   public class ConnectivityManager {
-    method @Deprecated public void getLatestTetheringEntitlementValue(int, boolean, @NonNull android.net.ConnectivityManager.TetheringEntitlementValueListener, @Nullable android.os.Handler);
     method @Deprecated public boolean requestRouteToHost(int, int);
     method @Deprecated public int startUsingNetworkFeature(int, String);
     method @Deprecated public int stopUsingNetworkFeature(int, String);
   }
 
-  @Deprecated public abstract static class ConnectivityManager.TetheringEntitlementValueListener {
-    ctor public ConnectivityManager.TetheringEntitlementValueListener();
-    method public void onEntitlementResult(int);
-  }
-
   @Deprecated public class NetworkBadging {
     method @NonNull public static android.graphics.drawable.Drawable getWifiIcon(@IntRange(from=0, to=4) int, int, @Nullable android.content.res.Resources.Theme);
     field public static final int BADGING_4K = 30; // 0x1e
diff --git a/api/system-current.txt b/api/system-current.txt
index 96c9c752..2724133 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -312,7 +312,7 @@
   public class AppOpsManager {
     method @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public void getHistoricalOps(@NonNull android.app.AppOpsManager.HistoricalOpsRequest, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.AppOpsManager.HistoricalOps>);
     method public static String[] getOpStrs();
-    method @Deprecated @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getOpsForPackage(int, String, int[]);
+    method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getOpsForPackage(int, @NonNull String, @Nullable int[]);
     method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getOpsForPackage(int, @NonNull String, @Nullable java.lang.String...);
     method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getPackagesForOps(@Nullable String[]);
     method public static int opToDefaultMode(@NonNull String);
@@ -465,7 +465,7 @@
 
   public static final class AppOpsManager.PackageOps implements android.os.Parcelable {
     method public int describeContents();
-    method public java.util.List<android.app.AppOpsManager.OpEntry> getOps();
+    method @NonNull public java.util.List<android.app.AppOpsManager.OpEntry> getOps();
     method @NonNull public String getPackageName();
     method public int getUid();
     method public void writeToParcel(android.os.Parcel, int);
@@ -546,10 +546,8 @@
 
   public class NotificationManager {
     method @Nullable public android.content.ComponentName getAllowedNotificationAssistant();
-    method @Nullable public android.content.ComponentName getAllowedNotificationAssistantForUser(@NonNull android.os.UserHandle);
     method public boolean isNotificationAssistantAccessGranted(@NonNull android.content.ComponentName);
     method public void setNotificationAssistantAccessGranted(@Nullable android.content.ComponentName, boolean);
-    method public void setNotificationAssistantAccessGrantedForUser(@Nullable android.content.ComponentName, @NonNull android.os.UserHandle, boolean);
   }
 
   public final class StatsManager {
@@ -680,7 +678,7 @@
     method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public boolean packageHasActiveAdmins(String);
     method @Deprecated @RequiresPermission("android.permission.MANAGE_DEVICE_ADMINS") public boolean setActiveProfileOwner(@NonNull android.content.ComponentName, String) throws java.lang.IllegalArgumentException;
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setDeviceProvisioningConfigApplied();
-    method @RequiresPermission(value=android.Manifest.permission.GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS, conditional=true) public void setProfileOwnerCanAccessDeviceIdsForUser(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle);
+    method @RequiresPermission(value=android.Manifest.permission.GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS, conditional=true) public void setProfileOwnerCanAccessDeviceIds(@NonNull android.content.ComponentName);
     field public static final String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_ALLOWED = "android.account.DEVICE_OR_PROFILE_OWNER_ALLOWED";
     field public static final String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_DISALLOWED = "android.account.DEVICE_OR_PROFILE_OWNER_DISALLOWED";
     field public static final String ACTION_PROVISION_FINALIZATION = "android.app.action.PROVISION_FINALIZATION";
@@ -926,8 +924,10 @@
     method public int restoreAll(long, android.app.backup.RestoreObserver);
     method public int restorePackage(String, android.app.backup.RestoreObserver, android.app.backup.BackupManagerMonitor);
     method public int restorePackage(String, android.app.backup.RestoreObserver);
-    method public int restoreSome(long, android.app.backup.RestoreObserver, android.app.backup.BackupManagerMonitor, String[]);
-    method public int restoreSome(long, android.app.backup.RestoreObserver, String[]);
+    method public int restorePackages(long, @Nullable android.app.backup.RestoreObserver, @NonNull java.util.Set<java.lang.String>, @Nullable android.app.backup.BackupManagerMonitor);
+    method public int restorePackages(long, @Nullable android.app.backup.RestoreObserver, @NonNull java.util.Set<java.lang.String>);
+    method @Deprecated public int restoreSome(long, android.app.backup.RestoreObserver, android.app.backup.BackupManagerMonitor, String[]);
+    method @Deprecated public int restoreSome(long, android.app.backup.RestoreObserver, String[]);
   }
 
   public class RestoreSet implements android.os.Parcelable {
@@ -985,6 +985,7 @@
 
   public final class ContentSuggestionsManager {
     method public void classifyContentSelections(@NonNull android.app.contentsuggestions.ClassificationsRequest, @NonNull java.util.concurrent.Executor, @NonNull android.app.contentsuggestions.ContentSuggestionsManager.ClassificationsCallback);
+    method public boolean isEnabled();
     method public void notifyInteraction(@NonNull String, @NonNull android.os.Bundle);
     method public void provideContextImage(int, @NonNull android.os.Bundle);
     method public void suggestContentSelections(@NonNull android.app.contentsuggestions.SelectionsRequest, @NonNull java.util.concurrent.Executor, @NonNull android.app.contentsuggestions.ContentSuggestionsManager.SelectionsCallback);
@@ -1030,22 +1031,22 @@
     method public int describeContents();
     method @Nullable public android.os.Bundle getExtras();
     method @NonNull public String getPackageName();
-    method public int getPredictedTargetCount();
-    method public String getUiSurface();
-    method public void writeToParcel(android.os.Parcel, int);
+    method @IntRange(from=0) public int getPredictedTargetCount();
+    method @NonNull public String getUiSurface();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.app.prediction.AppPredictionContext> CREATOR;
   }
 
   public static final class AppPredictionContext.Builder {
     ctor public AppPredictionContext.Builder(@NonNull android.content.Context);
-    method public android.app.prediction.AppPredictionContext build();
-    method public android.app.prediction.AppPredictionContext.Builder setExtras(@Nullable android.os.Bundle);
-    method public android.app.prediction.AppPredictionContext.Builder setPredictedTargetCount(int);
-    method public android.app.prediction.AppPredictionContext.Builder setUiSurface(@Nullable String);
+    method @NonNull public android.app.prediction.AppPredictionContext build();
+    method @NonNull public android.app.prediction.AppPredictionContext.Builder setExtras(@Nullable android.os.Bundle);
+    method @NonNull public android.app.prediction.AppPredictionContext.Builder setPredictedTargetCount(@IntRange(from=0) int);
+    method @NonNull public android.app.prediction.AppPredictionContext.Builder setUiSurface(@NonNull String);
   }
 
   public final class AppPredictionManager {
-    method public android.app.prediction.AppPredictor createAppPredictionSession(@NonNull android.app.prediction.AppPredictionContext);
+    method @NonNull public android.app.prediction.AppPredictor createAppPredictionSession(@NonNull android.app.prediction.AppPredictionContext);
   }
 
   public final class AppPredictionSessionId implements android.os.Parcelable {
@@ -1075,7 +1076,7 @@
     method @Nullable public String getClassName();
     method @NonNull public android.app.prediction.AppTargetId getId();
     method @NonNull public String getPackageName();
-    method public int getRank();
+    method @IntRange(from=0) public int getRank();
     method @Nullable public android.content.pm.ShortcutInfo getShortcutInfo();
     method @NonNull public android.os.UserHandle getUser();
     method public void writeToParcel(android.os.Parcel, int);
@@ -1084,8 +1085,8 @@
 
   public final class AppTargetEvent implements android.os.Parcelable {
     method public int describeContents();
-    method @NonNull public int getAction();
-    method @NonNull public String getLaunchLocation();
+    method public int getAction();
+    method @Nullable public String getLaunchLocation();
     method @Nullable public android.app.prediction.AppTarget getTarget();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int ACTION_DISMISS = 2; // 0x2
@@ -1096,8 +1097,8 @@
 
   public static final class AppTargetEvent.Builder {
     ctor public AppTargetEvent.Builder(@Nullable android.app.prediction.AppTarget, int);
-    method public android.app.prediction.AppTargetEvent build();
-    method public android.app.prediction.AppTargetEvent.Builder setLaunchLocation(String);
+    method @NonNull public android.app.prediction.AppTargetEvent build();
+    method @NonNull public android.app.prediction.AppTargetEvent.Builder setLaunchLocation(@Nullable String);
   }
 
   public final class AppTargetId implements android.os.Parcelable {
@@ -1198,7 +1199,8 @@
     method public int getUsageSource();
     method @RequiresPermission(allOf={android.Manifest.permission.SUSPEND_APPS, android.Manifest.permission.OBSERVE_APP_USAGE}) public void registerAppUsageLimitObserver(int, @NonNull String[], @NonNull java.time.Duration, @NonNull java.time.Duration, @Nullable android.app.PendingIntent);
     method @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) public void registerAppUsageObserver(int, @NonNull String[], long, @NonNull java.util.concurrent.TimeUnit, @NonNull android.app.PendingIntent);
-    method @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) public void registerUsageSessionObserver(int, @NonNull String[], long, @NonNull java.util.concurrent.TimeUnit, long, @NonNull java.util.concurrent.TimeUnit, @NonNull android.app.PendingIntent, @Nullable android.app.PendingIntent);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) public void registerUsageSessionObserver(int, @NonNull String[], long, @NonNull java.util.concurrent.TimeUnit, long, @NonNull java.util.concurrent.TimeUnit, @NonNull android.app.PendingIntent, @Nullable android.app.PendingIntent);
+    method @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) public void registerUsageSessionObserver(int, @NonNull String[], @NonNull java.time.Duration, @NonNull java.time.Duration, @NonNull android.app.PendingIntent, @Nullable android.app.PendingIntent);
     method public void reportUsageStart(@NonNull android.app.Activity, @NonNull String);
     method public void reportUsageStart(@NonNull android.app.Activity, @NonNull String, long);
     method public void reportUsageStop(@NonNull android.app.Activity, @NonNull String);
@@ -1603,7 +1605,6 @@
     method @RequiresPermission("android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS") public abstract void addOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener);
     method public abstract boolean arePermissionsIndividuallyControlled();
     method public abstract java.util.List<android.content.IntentFilter> getAllIntentFilters(String);
-    method public boolean getAppDetailsActivityEnabled(@NonNull String);
     method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.pm.ApplicationInfo getApplicationInfoAsUser(@NonNull String, int, @NonNull android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException;
     method @NonNull public android.content.pm.dex.ArtManager getArtManager();
     method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public abstract String getDefaultBrowserPackageNameAsUser(int);
@@ -1617,6 +1618,7 @@
     method public abstract java.util.List<android.content.pm.IntentFilterVerificationInfo> getIntentFilterVerifications(String);
     method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public abstract int getIntentVerificationStatusAsUser(String, int);
     method @android.content.pm.PackageManager.PermissionFlags @RequiresPermission(anyOf={android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, android.Manifest.permission.GET_RUNTIME_PERMISSIONS}) public abstract int getPermissionFlags(String, String, @NonNull android.os.UserHandle);
+    method public boolean getSyntheticAppDetailsActivityEnabled(@NonNull String);
     method @NonNull @RequiresPermission(android.Manifest.permission.SUSPEND_APPS) public String[] getUnsuspendablePackages(@NonNull String[]);
     method @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) public abstract void grantRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
     method @Deprecated public abstract int installExistingPackage(String) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -1630,12 +1632,12 @@
     method @Deprecated public void replacePreferredActivity(@NonNull android.content.IntentFilter, int, @NonNull java.util.List<android.content.ComponentName>, @NonNull android.content.ComponentName);
     method @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS) public abstract void revokeRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
     method public void sendDeviceCustomizationReadyBroadcast();
-    method @RequiresPermission(value=android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE, conditional=true) public void setAppDetailsActivityEnabled(@NonNull String, boolean);
     method @RequiresPermission(allOf={android.Manifest.permission.SET_PREFERRED_APPLICATIONS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public abstract boolean setDefaultBrowserPackageNameAsUser(String, int);
     method @NonNull @RequiresPermission(android.Manifest.permission.SUSPEND_APPS) public String[] setDistractingPackageRestrictions(@NonNull String[], int);
     method @RequiresPermission(android.Manifest.permission.SET_HARMFUL_APP_WARNINGS) public void setHarmfulAppWarning(@NonNull String, @Nullable CharSequence);
     method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.SUSPEND_APPS) public String[] setPackagesSuspended(@Nullable String[], boolean, @Nullable android.os.PersistableBundle, @Nullable android.os.PersistableBundle, @Nullable String);
     method @Nullable @RequiresPermission(android.Manifest.permission.SUSPEND_APPS) public String[] setPackagesSuspended(@Nullable String[], boolean, @Nullable android.os.PersistableBundle, @Nullable android.os.PersistableBundle, @Nullable android.content.pm.SuspendDialogInfo);
+    method @RequiresPermission(value=android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE, conditional=true) public void setSyntheticAppDetailsActivityEnabled(@NonNull String, boolean);
     method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public abstract void setUpdateAvailable(String, boolean);
     method @RequiresPermission(android.Manifest.permission.SET_PREFERRED_APPLICATIONS) public abstract boolean updateIntentVerificationStatusAsUser(String, int, int);
     method @RequiresPermission(anyOf={android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS}) public abstract void updatePermissionFlags(String, String, @android.content.pm.PackageManager.PermissionFlags int, @android.content.pm.PackageManager.PermissionFlags int, @NonNull android.os.UserHandle);
@@ -1754,9 +1756,9 @@
 
   public static final class ShortcutManager.ShareShortcutInfo implements android.os.Parcelable {
     method public int describeContents();
-    method public android.content.pm.ShortcutInfo getShortcutInfo();
-    method public android.content.ComponentName getTargetComponent();
-    method public void writeToParcel(android.os.Parcel, int);
+    method @NonNull public android.content.pm.ShortcutInfo getShortcutInfo();
+    method @NonNull public android.content.ComponentName getTargetComponent();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.ShortcutManager.ShareShortcutInfo> CREATOR;
   }
 
@@ -3487,6 +3489,7 @@
     method public void setAudioServerStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.AudioServerStateCallback);
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setFocusRequestResult(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setVolumeIndexForAttributes(@NonNull android.media.AudioAttributes, int, int);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void unregisterAudioPolicy(@NonNull android.media.audiopolicy.AudioPolicy);
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void unregisterAudioPolicyAsync(@NonNull android.media.audiopolicy.AudioPolicy);
     method public void unregisterVolumeGroupCallback(@NonNull android.media.AudioManager.VolumeGroupCallback);
     field public static final int AUDIOFOCUS_FLAG_DELAY_OK = 1; // 0x1
@@ -3720,10 +3723,6 @@
 
 package android.media.session {
 
-  public static final class MediaController.PlaybackInfo implements android.os.Parcelable {
-    ctor public MediaController.PlaybackInfo(int, int, int, int, android.media.AudioAttributes);
-  }
-
   public final class MediaSessionManager {
     method @RequiresPermission(android.Manifest.permission.SET_MEDIA_KEY_LISTENER) public void setOnMediaKeyListener(android.media.session.MediaSessionManager.OnMediaKeyListener, @Nullable android.os.Handler);
     method @RequiresPermission(android.Manifest.permission.SET_VOLUME_KEY_LONG_PRESS_LISTENER) public void setOnVolumeKeyLongPressListener(android.media.session.MediaSessionManager.OnVolumeKeyLongPressListener, @Nullable android.os.Handler);
@@ -4068,7 +4067,7 @@
   }
 
   public static interface ConnectivityManager.OnTetheringEntitlementResultListener {
-    method public void onEntitlementResult(int);
+    method public void onTetheringEntitlementResult(int);
   }
 
   public abstract static class ConnectivityManager.OnTetheringEventCallback {
@@ -4739,13 +4738,13 @@
   }
 
   public class WifiManager {
-    method @RequiresPermission("android.permission.WIFI_UPDATE_USABILITY_STATS_SCORE") public void addWifiUsabilityStatsListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.WifiUsabilityStatsListener);
+    method @RequiresPermission("android.permission.WIFI_UPDATE_USABILITY_STATS_SCORE") public void addOnWifiUsabilityStatsListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.OnWifiUsabilityStatsListener);
     method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void connect(@NonNull android.net.wifi.WifiConfiguration, @Nullable android.net.wifi.WifiManager.ActionListener);
     method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void connect(int, @Nullable android.net.wifi.WifiManager.ActionListener);
     method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void disable(int, @Nullable android.net.wifi.WifiManager.ActionListener);
     method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void forget(int, @Nullable android.net.wifi.WifiManager.ActionListener);
     method @NonNull @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.List<android.util.Pair<android.net.wifi.WifiConfiguration,java.util.Map<java.lang.Integer,java.util.List<android.net.wifi.ScanResult>>>> getAllMatchingWifiConfigs(@NonNull java.util.List<android.net.wifi.ScanResult>);
-    method @NonNull @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.Map<android.net.wifi.hotspot2.OsuProvider,java.util.List<android.net.wifi.ScanResult>> getMatchingOsuProviders(java.util.List<android.net.wifi.ScanResult>);
+    method @NonNull @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.Map<android.net.wifi.hotspot2.OsuProvider,java.util.List<android.net.wifi.ScanResult>> getMatchingOsuProviders(@Nullable java.util.List<android.net.wifi.ScanResult>);
     method @NonNull @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.Map<android.net.wifi.hotspot2.OsuProvider,android.net.wifi.hotspot2.PasspointConfiguration> getMatchingPasspointConfigsForOsuProviders(@NonNull java.util.Set<android.net.wifi.hotspot2.OsuProvider>);
     method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_WIFI_STATE, android.Manifest.permission.READ_WIFI_CREDENTIAL}) public java.util.List<android.net.wifi.WifiConfiguration> getPrivilegedConfiguredNetworks();
     method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public android.net.wifi.WifiConfiguration getWifiApConfiguration();
@@ -4754,7 +4753,7 @@
     method public boolean isPortableHotspotSupported();
     method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public boolean isWifiApEnabled();
     method public boolean isWifiScannerSupported();
-    method @RequiresPermission("android.permission.WIFI_UPDATE_USABILITY_STATS_SCORE") public void removeWifiUsabilityStatsListener(@NonNull android.net.wifi.WifiManager.WifiUsabilityStatsListener);
+    method @RequiresPermission("android.permission.WIFI_UPDATE_USABILITY_STATS_SCORE") public void removeOnWifiUsabilityStatsListener(@NonNull android.net.wifi.WifiManager.OnWifiUsabilityStatsListener);
     method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void save(@NonNull android.net.wifi.WifiConfiguration, @Nullable android.net.wifi.WifiManager.ActionListener);
     method @RequiresPermission("android.permission.WIFI_SET_DEVICE_MOBILITY_STATE") public void setDeviceMobilityState(int);
     method @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public boolean setWifiApConfiguration(android.net.wifi.WifiConfiguration);
@@ -4799,8 +4798,8 @@
     method public void onSuccess();
   }
 
-  public static interface WifiManager.WifiUsabilityStatsListener {
-    method public void onStatsUpdated(int, boolean, android.net.wifi.WifiUsabilityStatsEntry);
+  public static interface WifiManager.OnWifiUsabilityStatsListener {
+    method public void onWifiUsabilityStats(int, boolean, @NonNull android.net.wifi.WifiUsabilityStatsEntry);
   }
 
   public class WifiNetworkConnectionStatistics implements android.os.Parcelable {
@@ -4935,35 +4934,35 @@
 
   public final class WifiUsabilityStatsEntry implements android.os.Parcelable {
     method public int describeContents();
+    method public int getLinkSpeedMbps();
+    method public int getProbeElapsedTimeSinceLastUpdateMillis();
+    method public int getProbeMcsRateSinceLastUpdate();
+    method public int getProbeStatusSinceLastUpdate();
+    method public int getRssi();
+    method public int getRxLinkSpeedMbps();
+    method public long getTimeStampMillis();
+    method public long getTotalBackgroundScanTimeMillis();
+    method public long getTotalBeaconRx();
+    method public long getTotalCcaBusyFreqTimeMillis();
+    method public long getTotalHotspot2ScanTimeMillis();
+    method public long getTotalNanScanTimeMillis();
+    method public long getTotalPnoScanTimeMillis();
+    method public long getTotalRadioOnFreqTimeMillis();
+    method public long getTotalRadioOnTimeMillis();
+    method public long getTotalRadioRxTimeMillis();
+    method public long getTotalRadioTxTimeMillis();
+    method public long getTotalRoamScanTimeMillis();
+    method public long getTotalRxSuccess();
+    method public long getTotalScanTimeMillis();
+    method public long getTotalTxBad();
+    method public long getTotalTxRetries();
+    method public long getTotalTxSuccess();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.WifiUsabilityStatsEntry> CREATOR;
     field public static final int PROBE_STATUS_FAILURE = 3; // 0x3
     field public static final int PROBE_STATUS_NO_PROBE = 1; // 0x1
     field public static final int PROBE_STATUS_SUCCESS = 2; // 0x2
     field public static final int PROBE_STATUS_UNKNOWN = 0; // 0x0
-    field public final int linkSpeedMbps;
-    field public final int probeElapsedTimeMsSinceLastUpdate;
-    field public final int probeMcsRateSinceLastUpdate;
-    field public final int probeStatusSinceLastUpdate;
-    field public final int rssi;
-    field public final int rxLinkSpeedMbps;
-    field public final long timeStampMs;
-    field public final long totalBackgroundScanTimeMs;
-    field public final long totalBeaconRx;
-    field public final long totalCcaBusyFreqTimeMs;
-    field public final long totalHotspot2ScanTimeMs;
-    field public final long totalNanScanTimeMs;
-    field public final long totalPnoScanTimeMs;
-    field public final long totalRadioOnFreqTimeMs;
-    field public final long totalRadioOnTimeMs;
-    field public final long totalRadioRxTimeMs;
-    field public final long totalRadioTxTimeMs;
-    field public final long totalRoamScanTimeMs;
-    field public final long totalRxSuccess;
-    field public final long totalScanTimeMs;
-    field public final long totalTxBad;
-    field public final long totalTxRetries;
-    field public final long totalTxSuccess;
   }
 
 }
@@ -5451,7 +5450,7 @@
     method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setAdaptivePowerSaveEnabled(boolean);
     method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setAdaptivePowerSavePolicy(@NonNull android.os.BatterySaverPolicyConfig);
     method @RequiresPermission(android.Manifest.permission.POWER_SAVER) public boolean setDynamicPowerSavings(boolean, int);
-    method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setPowerSaveMode(boolean);
+    method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setPowerSaveModeEnabled(boolean);
     method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.USER_ACTIVITY}) public void userActivity(long, int, int);
     field public static final int POWER_SAVER_MODE_DYNAMIC = 1; // 0x1
     field public static final int POWER_SAVER_MODE_PERCENTAGE = 0; // 0x0
@@ -5606,7 +5605,7 @@
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.os.PersistableBundle getSeedAccountOptions();
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getSeedAccountType();
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public long[] getSerialNumbersOfUsers(boolean);
-    method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.graphics.Bitmap getUserIcon();
+    method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.GET_ACCOUNTS_PRIVILEGED}) public android.graphics.Bitmap getUserIcon();
     method @Deprecated @android.os.UserManager.UserRestrictionSource @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public int getUserRestrictionSource(String, android.os.UserHandle);
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public java.util.List<android.os.UserManager.EnforcingUser> getUserRestrictionSources(String, android.os.UserHandle);
     method @RequiresPermission(allOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public int getUserSwitchability();
@@ -5849,54 +5848,41 @@
   public final class DeviceConfig {
     method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static void addOnPropertiesChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertiesChangedListener);
     method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static void addOnPropertyChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
-    method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static boolean getBoolean(String, String, boolean);
-    method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static float getFloat(String, String, float);
-    method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static int getInt(String, String, int);
-    method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static long getLong(String, String, long);
-    method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static String getProperty(String, String);
-    method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static String getString(String, String, String);
+    method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static boolean getBoolean(@NonNull String, @NonNull String, boolean);
+    method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static float getFloat(@NonNull String, @NonNull String, float);
+    method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static int getInt(@NonNull String, @NonNull String, int);
+    method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static long getLong(@NonNull String, @NonNull String, long);
+    method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static String getProperty(@NonNull String, @NonNull String);
+    method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static String getString(@NonNull String, @NonNull String, @Nullable String);
     method public static void removeOnPropertiesChangedListener(@NonNull android.provider.DeviceConfig.OnPropertiesChangedListener);
     method public static void removeOnPropertyChangedListener(@NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
     method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static void resetToDefaults(int, @Nullable String);
-    method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean setProperty(String, String, String, boolean);
+    method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean setProperty(@NonNull String, @NonNull String, @Nullable String, boolean);
     field public static final String NAMESPACE_ACTIVITY_MANAGER = "activity_manager";
     field public static final String NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT = "activity_manager_native_boot";
+    field public static final String NAMESPACE_ATTENTION_MANAGER_SERVICE = "attention_manager_service";
     field public static final String NAMESPACE_AUTOFILL = "autofill";
     field public static final String NAMESPACE_CONNECTIVITY = "connectivity";
     field public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture";
+    field public static final String NAMESPACE_DEX_BOOT = "dex_boot";
     field public static final String NAMESPACE_GAME_DRIVER = "game_driver";
     field public static final String NAMESPACE_INPUT_NATIVE_BOOT = "input_native_boot";
+    field public static final String NAMESPACE_INTELLIGENCE_ATTENTION = "intelligence_attention";
     field public static final String NAMESPACE_MEDIA_NATIVE = "media_native";
     field public static final String NAMESPACE_NETD_NATIVE = "netd_native";
+    field public static final String NAMESPACE_RUNTIME = "runtime";
+    field public static final String NAMESPACE_RUNTIME_NATIVE = "runtime_native";
     field public static final String NAMESPACE_RUNTIME_NATIVE_BOOT = "runtime_native_boot";
     field public static final String NAMESPACE_SYSTEMUI = "systemui";
     field public static final String NAMESPACE_TEXTCLASSIFIER = "textclassifier";
   }
 
-  public static interface DeviceConfig.AttentionManagerService {
-    field public static final String COMPONENT_NAME = "component_name";
-    field public static final String NAMESPACE = "attention_manager_service";
-    field public static final String SERVICE_ENABLED = "service_enabled";
-  }
-
-  public static interface DeviceConfig.DexBoot {
-    field public static final String NAMESPACE = "dex_boot";
-    field public static final String PRIV_APPS_OOB_ENABLED = "priv_apps_oob_enabled";
-    field public static final String PRIV_APPS_OOB_WHITELIST = "priv_apps_oob_whitelist";
-  }
-
-  public static interface DeviceConfig.IntelligenceAttention {
-    field public static final String ATTENTION_ENABLED = "attention_enabled";
-    field public static final String ATTENTION_SETTINGS = "attention_settings";
-    field public static final String NAMESPACE = "intelligence_attention";
-  }
-
   public static interface DeviceConfig.OnPropertiesChangedListener {
     method public void onPropertiesChanged(@NonNull android.provider.DeviceConfig.Properties);
   }
 
   public static interface DeviceConfig.OnPropertyChangedListener {
-    method public void onPropertyChanged(String, String, String);
+    method public void onPropertyChanged(@NonNull String, @NonNull String, @Nullable String);
   }
 
   public static interface DeviceConfig.Privacy {
@@ -5922,15 +5908,6 @@
     field public static final String ROLLBACK_LIFETIME_IN_MILLIS = "rollback_lifetime_in_millis";
   }
 
-  public static interface DeviceConfig.Runtime {
-    field public static final String NAMESPACE = "runtime";
-    field public static final String USE_PRECOMPILED_LAYOUT = "view.precompiled_layout_enabled";
-  }
-
-  public static interface DeviceConfig.RuntimeNative {
-    field public static final String NAMESPACE = "runtime_native";
-  }
-
   public static interface DeviceConfig.Scheduler {
     field public static final String ENABLE_FAST_METRICS_COLLECTION = "enable_fast_metrics_collection";
     field public static final String NAMESPACE = "scheduler";
@@ -6141,7 +6118,6 @@
     field public static final String LOCATION_PERMISSIONS_UPGRADE_TO_Q_MODE = "location_permissions_upgrade_to_q_mode";
     field public static final String LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS = "lock_screen_allow_private_notifications";
     field public static final String LOCK_SCREEN_SHOW_NOTIFICATIONS = "lock_screen_show_notifications";
-    field public static final String MANUAL_RINGER_TOGGLE_COUNT = "manual_ringer_toggle_count";
     field public static final String THEME_CUSTOMIZATION_OVERLAY_PACKAGES = "theme_customization_overlay_packages";
     field public static final String USER_SETUP_COMPLETE = "user_setup_complete";
     field public static final int USER_SETUP_PERSONALIZATION_COMPLETE = 10; // 0xa
@@ -6150,6 +6126,9 @@
     field public static final int USER_SETUP_PERSONALIZATION_STARTED = 1; // 0x1
     field public static final String USER_SETUP_PERSONALIZATION_STATE = "user_setup_personalization_state";
     field public static final String VOLUME_HUSH_GESTURE = "volume_hush_gesture";
+    field public static final int VOLUME_HUSH_MUTE = 2; // 0x2
+    field public static final int VOLUME_HUSH_OFF = 0; // 0x0
+    field public static final int VOLUME_HUSH_VIBRATE = 1; // 0x1
   }
 
   public static final class Telephony.Carriers implements android.provider.BaseColumns {
@@ -6328,7 +6307,7 @@
   public abstract class AppPredictionService extends android.app.Service {
     ctor public AppPredictionService();
     method @MainThread public abstract void onAppTargetEvent(@NonNull android.app.prediction.AppPredictionSessionId, @NonNull android.app.prediction.AppTargetEvent);
-    method public final android.os.IBinder onBind(android.content.Intent);
+    method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent);
     method public void onCreatePredictionSession(@NonNull android.app.prediction.AppPredictionContext, @NonNull android.app.prediction.AppPredictionSessionId);
     method @MainThread public void onDestroyPredictionSession(@NonNull android.app.prediction.AppPredictionSessionId);
     method @MainThread public abstract void onLocationShown(@NonNull android.app.prediction.AppPredictionSessionId, @NonNull String, @NonNull java.util.List<android.app.prediction.AppTargetId>);
@@ -6345,7 +6324,7 @@
 
   public abstract class AttentionService extends android.app.Service {
     ctor public AttentionService();
-    method public final android.os.IBinder onBind(android.content.Intent);
+    method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
     method public abstract void onCancelAttentionCheck(int);
     method public abstract void onCheckAttention(int, @NonNull android.service.attention.AttentionService.AttentionCallback);
     field public static final int ATTENTION_FAILURE_PREEMPTED = 2; // 0x2
@@ -6451,6 +6430,7 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.service.contentcapture.ActivityEvent> CREATOR;
     field public static final int TYPE_ACTIVITY_PAUSED = 2; // 0x2
     field public static final int TYPE_ACTIVITY_RESUMED = 1; // 0x1
+    field public static final int TYPE_ACTIVITY_STOPPED = 23; // 0x17
   }
 
   public abstract class ContentCaptureService extends android.app.Service {
@@ -7178,9 +7158,10 @@
 
 package android.telephony {
 
-  public static final class AccessNetworkConstants.TransportType {
-    field public static final int WLAN = 2; // 0x2
-    field public static final int WWAN = 1; // 0x1
+  public final class AccessNetworkConstants {
+    field public static final int TRANSPORT_TYPE_INVALID = -1; // 0xffffffff
+    field public static final int TRANSPORT_TYPE_WLAN = 2; // 0x2
+    field public static final int TRANSPORT_TYPE_WWAN = 1; // 0x1
   }
 
   public final class CallAttributes implements android.os.Parcelable {
@@ -7255,6 +7236,7 @@
     field public static final int ACCESS_BLOCK_ALL = 2088; // 0x828
     field public static final int ACCESS_CLASS_DSAC_REJECTION = 2108; // 0x83c
     field public static final int ACCESS_CONTROL_LIST_CHECK_FAILURE = 2128; // 0x850
+    field public static final int ACCESS_PROBE_LIMIT_REACHED = 2079; // 0x81f
     field public static final int ACTIVATION_REJECTED_BCM_VIOLATION = 48; // 0x30
     field public static final int ACTIVATION_REJECT_GGSN = 30; // 0x1e
     field public static final int ACTIVATION_REJECT_UNSPECIFIED = 31; // 0x1f
@@ -7369,7 +7351,9 @@
     field public static final int INVALID_PRIMARY_NSAPI = 2158; // 0x86e
     field public static final int INVALID_SIM_STATE = 2224; // 0x8b0
     field public static final int INVALID_TRANSACTION_ID = 81; // 0x51
+    field public static final int IPV4_CONNECTIONS_LIMIT_REACHED = 2052; // 0x804
     field public static final int IPV6_ADDRESS_TRANSFER_FAILED = 2047; // 0x7ff
+    field public static final int IPV6_CONNECTIONS_LIMIT_REACHED = 2053; // 0x805
     field public static final int IPV6_PREFIX_UNAVAILABLE = 2250; // 0x8ca
     field public static final int IP_ADDRESS_MISMATCH = 119; // 0x77
     field public static final int IP_VERSION_MISMATCH = 2055; // 0x807
@@ -7388,10 +7372,6 @@
     field public static final int MAC_FAILURE = 2183; // 0x887
     field public static final int MAXIMIUM_NSAPIS_EXCEEDED = 2157; // 0x86d
     field public static final int MAXINUM_SIZE_OF_L2_MESSAGE_EXCEEDED = 2166; // 0x876
-    field public static final int MAX_ACCESS_PROBE = 2079; // 0x81f
-    field public static final int MAX_IPV4_CONNECTIONS = 2052; // 0x804
-    field public static final int MAX_IPV6_CONNECTIONS = 2053; // 0x805
-    field public static final int MAX_PPP_INACTIVITY_TIMER_EXPIRED = 2046; // 0x7fe
     field public static final int MESSAGE_INCORRECT_SEMANTIC = 95; // 0x5f
     field public static final int MESSAGE_TYPE_UNSUPPORTED = 97; // 0x61
     field public static final int MIP_CONFIG_FAILURE = 2050; // 0x802
@@ -7500,6 +7480,7 @@
     field public static final int PPP_AUTH_FAILURE = 2229; // 0x8b5
     field public static final int PPP_CHAP_FAILURE = 2232; // 0x8b8
     field public static final int PPP_CLOSE_IN_PROGRESS = 2233; // 0x8b9
+    field public static final int PPP_INACTIVITY_TIMER_EXPIRED = 2046; // 0x7fe
     field public static final int PPP_OPTION_MISMATCH = 2230; // 0x8b6
     field public static final int PPP_PAP_FAILURE = 2231; // 0x8b7
     field public static final int PPP_TIMEOUT = 2228; // 0x8b4
@@ -7700,8 +7681,8 @@
     field public static final String MBMS_STREAMING_SERVICE_ACTION = "android.telephony.action.EmbmsStreaming";
   }
 
-  public class NetworkRegistrationState implements android.os.Parcelable {
-    ctor public NetworkRegistrationState(int, int, int, int, int, boolean, @NonNull int[], @Nullable android.telephony.CellIdentity);
+  public class NetworkRegistrationInfo implements android.os.Parcelable {
+    ctor public NetworkRegistrationInfo(int, int, int, int, int, boolean, @NonNull int[], @Nullable android.telephony.CellIdentity);
     method public int describeContents();
     method public int getAccessNetworkTechnology();
     method @NonNull public int[] getAvailableServices();
@@ -7715,7 +7696,7 @@
     method public boolean isEmergencyEnabled();
     method public boolean isRoaming();
     method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.NetworkRegistrationState> CREATOR;
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.NetworkRegistrationInfo> CREATOR;
     field public static final int DOMAIN_CS = 1; // 0x1
     field public static final int DOMAIN_PS = 2; // 0x2
     field public static final int REG_STATE_DENIED = 3; // 0x3
@@ -7731,19 +7712,19 @@
     field public static final int SERVICE_TYPE_VOICE = 1; // 0x1
   }
 
-  public static class NetworkRegistrationState.Builder {
-    ctor public NetworkRegistrationState.Builder();
-    method @NonNull public android.telephony.NetworkRegistrationState build();
-    method @NonNull public android.telephony.NetworkRegistrationState.Builder setAccessNetworkTechnology(int);
-    method @NonNull public android.telephony.NetworkRegistrationState.Builder setAvailableServices(@NonNull int[]);
-    method @NonNull public android.telephony.NetworkRegistrationState.Builder setCellIdentity(@Nullable android.telephony.CellIdentity);
-    method @NonNull public android.telephony.NetworkRegistrationState.Builder setDomain(int);
-    method @NonNull public android.telephony.NetworkRegistrationState.Builder setEmergencyOnly(boolean);
-    method @NonNull public android.telephony.NetworkRegistrationState.Builder setNrStatus(int);
-    method @NonNull public android.telephony.NetworkRegistrationState.Builder setRegState(int);
-    method @NonNull public android.telephony.NetworkRegistrationState.Builder setRejectCause(int);
-    method @NonNull public android.telephony.NetworkRegistrationState.Builder setRoamingType(int);
-    method @NonNull public android.telephony.NetworkRegistrationState.Builder setTransportType(int);
+  public static class NetworkRegistrationInfo.Builder {
+    ctor public NetworkRegistrationInfo.Builder();
+    method @NonNull public android.telephony.NetworkRegistrationInfo build();
+    method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setAccessNetworkTechnology(int);
+    method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setAvailableServices(@NonNull int[]);
+    method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setCellIdentity(@Nullable android.telephony.CellIdentity);
+    method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setDomain(int);
+    method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setEmergencyOnly(boolean);
+    method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setNrStatus(int);
+    method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRegState(int);
+    method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRejectCause(int);
+    method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRoamingType(int);
+    method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setTransportType(int);
   }
 
   public abstract class NetworkService extends android.app.Service {
@@ -7756,13 +7737,13 @@
   public abstract class NetworkService.NetworkServiceProvider implements java.lang.AutoCloseable {
     ctor public NetworkService.NetworkServiceProvider(int);
     method public abstract void close();
-    method public void getNetworkRegistrationState(int, @NonNull android.telephony.NetworkServiceCallback);
+    method public void getNetworkRegistrationInfo(int, @NonNull android.telephony.NetworkServiceCallback);
     method public final int getSlotIndex();
-    method public final void notifyNetworkRegistrationStateChanged();
+    method public final void notifyNetworkRegistrationInfoChanged();
   }
 
   public class NetworkServiceCallback {
-    method public void onGetNetworkRegistrationStateComplete(int, @Nullable android.telephony.NetworkRegistrationState);
+    method public void onGetNetworkRegistrationInfoComplete(int, @Nullable android.telephony.NetworkRegistrationInfo);
     field public static final int RESULT_ERROR_BUSY = 3; // 0x3
     field public static final int RESULT_ERROR_FAILED = 5; // 0x5
     field public static final int RESULT_ERROR_ILLEGAL_STATE = 4; // 0x4
@@ -7937,12 +7918,10 @@
   }
 
   public class ServiceState implements android.os.Parcelable {
-    method @Nullable public android.telephony.NetworkRegistrationState getNetworkRegistrationState(int, int);
-    method @NonNull public java.util.List<android.telephony.NetworkRegistrationState> getNetworkRegistrationStates();
-    method @Deprecated @NonNull public java.util.List<android.telephony.NetworkRegistrationState> getNetworkRegistrationStates(int);
-    method @Deprecated @Nullable public android.telephony.NetworkRegistrationState getNetworkRegistrationStates(int, int);
-    method @NonNull public java.util.List<android.telephony.NetworkRegistrationState> getNetworkRegistrationStatesForDomain(int);
-    method @NonNull public java.util.List<android.telephony.NetworkRegistrationState> getNetworkRegistrationStatesForTransportType(int);
+    method @Nullable public android.telephony.NetworkRegistrationInfo getNetworkRegistrationInfo(int, int);
+    method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoList();
+    method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoListForDomain(int);
+    method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoListForTransportType(int);
     field public static final int ROAMING_TYPE_DOMESTIC = 2; // 0x2
     field public static final int ROAMING_TYPE_INTERNATIONAL = 3; // 0x3
     field public static final int ROAMING_TYPE_NOT_ROAMING = 0; // 0x0
@@ -8052,9 +8031,9 @@
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getEmergencyCallbackMode();
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimDomain();
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimIst();
-    method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.util.Pair<java.lang.Integer,java.lang.Integer>> getLogicalToPhysicalSlotMapping();
+    method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Map<java.lang.Integer,java.lang.Integer> getLogicalToPhysicalSlotMapping();
     method public static long getMaxNumberVerificationTimeoutMillis();
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getPreferredNetworkTypeBitmap();
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getPreferredNetworkTypeBitmask();
     method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public int getRadioPowerState();
     method public int getSimApplicationState();
     method public int getSimCardState();
@@ -8066,6 +8045,10 @@
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoiceActivationState();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handlePinMmi(String);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handlePinMmiForSubscriber(int, String);
+    method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean iccCloseLogicalChannelBySlot(int, int);
+    method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannelBySlot(int, @Nullable String, int);
+    method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduBasicChannelBySlot(int, int, int, int, int, int, @Nullable String);
+    method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduLogicalChannelBySlot(int, int, int, int, int, int, int, @Nullable String);
     method public boolean isDataConnectivityPossible();
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isIdle();
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isOffhook();
@@ -8087,7 +8070,7 @@
     method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(int, boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataRoamingEnabled(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMultisimCarrierRestriction(boolean);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setPreferredNetworkTypeBitmap(long);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setPreferredNetworkTypeBitmask(long);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadio(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadioPower(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerState(int);
@@ -8101,7 +8084,7 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean switchSlots(int[]);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void toggleRadioOnOff();
     method public void updateServiceLocation();
-    field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_DEBUG_EVENT = "android.telephony.action.DEBUG_EVENT";
+    field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_ANOMALY_REPORTED = "android.telephony.action.ANOMALY_REPORTED";
     field public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.telephony.action.SIM_APPLICATION_STATE_CHANGED";
     field public static final String ACTION_SIM_CARD_STATE_CHANGED = "android.telephony.action.SIM_CARD_STATE_CHANGED";
     field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED";
@@ -8109,8 +8092,8 @@
     field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1
     field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0
     field public static final int CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED = -1; // 0xffffffff
-    field public static final String EXTRA_DEBUG_EVENT_DESCRIPTION = "android.telephony.extra.DEBUG_EVENT_DESCRIPTION";
-    field public static final String EXTRA_DEBUG_EVENT_ID = "android.telephony.extra.DEBUG_EVENT_ID";
+    field public static final String EXTRA_ANOMALY_DESCRIPTION = "android.telephony.extra.ANOMALY_DESCRIPTION";
+    field public static final String EXTRA_ANOMALY_ID = "android.telephony.extra.ANOMALY_ID";
     field public static final String EXTRA_SIM_STATE = "android.telephony.extra.SIM_STATE";
     field public static final String EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL = "android.telephony.extra.VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL";
     field public static final String EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING = "android.telephony.extra.VOICEMAIL_SCRAMBLED_PIN_STRING";
@@ -9539,6 +9522,7 @@
     method public int getTaskId();
     field public static final int FLAG_DISABLED_BY_APP = 1; // 0x1
     field public static final int FLAG_DISABLED_BY_FLAG_SECURE = 2; // 0x2
+    field public static final int FLAG_RECONNECTED = 4; // 0x4
   }
 
   public final class ContentCaptureEvent implements android.os.Parcelable {
diff --git a/api/test-current.txt b/api/test-current.txt
index 2913743..5cb918f 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -146,7 +146,7 @@
     method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setUidMode(String, int, int);
     method public void startWatchingActive(@NonNull int[], @NonNull android.app.AppOpsManager.OnOpActiveChangedListener);
     method public void stopWatchingActive(@NonNull android.app.AppOpsManager.OnOpActiveChangedListener);
-    method public static int strOpToOp(String);
+    method public static int strOpToOp(@NonNull String);
     field public static final int HISTORICAL_MODE_DISABLED = 0; // 0x0
     field public static final int HISTORICAL_MODE_ENABLED_ACTIVE = 1; // 0x1
     field public static final int HISTORICAL_MODE_ENABLED_PASSIVE = 2; // 0x2
@@ -427,22 +427,22 @@
     method public int describeContents();
     method @Nullable public android.os.Bundle getExtras();
     method @NonNull public String getPackageName();
-    method public int getPredictedTargetCount();
-    method public String getUiSurface();
-    method public void writeToParcel(android.os.Parcel, int);
+    method @IntRange(from=0) public int getPredictedTargetCount();
+    method @NonNull public String getUiSurface();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.app.prediction.AppPredictionContext> CREATOR;
   }
 
   public static final class AppPredictionContext.Builder {
     ctor public AppPredictionContext.Builder(@NonNull android.content.Context);
-    method public android.app.prediction.AppPredictionContext build();
-    method public android.app.prediction.AppPredictionContext.Builder setExtras(@Nullable android.os.Bundle);
-    method public android.app.prediction.AppPredictionContext.Builder setPredictedTargetCount(int);
-    method public android.app.prediction.AppPredictionContext.Builder setUiSurface(@Nullable String);
+    method @NonNull public android.app.prediction.AppPredictionContext build();
+    method @NonNull public android.app.prediction.AppPredictionContext.Builder setExtras(@Nullable android.os.Bundle);
+    method @NonNull public android.app.prediction.AppPredictionContext.Builder setPredictedTargetCount(@IntRange(from=0) int);
+    method @NonNull public android.app.prediction.AppPredictionContext.Builder setUiSurface(@NonNull String);
   }
 
   public final class AppPredictionManager {
-    method public android.app.prediction.AppPredictor createAppPredictionSession(@NonNull android.app.prediction.AppPredictionContext);
+    method @NonNull public android.app.prediction.AppPredictor createAppPredictionSession(@NonNull android.app.prediction.AppPredictionContext);
   }
 
   public final class AppPredictionSessionId implements android.os.Parcelable {
@@ -472,7 +472,7 @@
     method @Nullable public String getClassName();
     method @NonNull public android.app.prediction.AppTargetId getId();
     method @NonNull public String getPackageName();
-    method public int getRank();
+    method @IntRange(from=0) public int getRank();
     method @Nullable public android.content.pm.ShortcutInfo getShortcutInfo();
     method @NonNull public android.os.UserHandle getUser();
     method public void writeToParcel(android.os.Parcel, int);
@@ -481,8 +481,8 @@
 
   public final class AppTargetEvent implements android.os.Parcelable {
     method public int describeContents();
-    method @NonNull public int getAction();
-    method @NonNull public String getLaunchLocation();
+    method public int getAction();
+    method @Nullable public String getLaunchLocation();
     method @Nullable public android.app.prediction.AppTarget getTarget();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int ACTION_DISMISS = 2; // 0x2
@@ -493,8 +493,8 @@
 
   public static final class AppTargetEvent.Builder {
     ctor public AppTargetEvent.Builder(@Nullable android.app.prediction.AppTarget, int);
-    method public android.app.prediction.AppTargetEvent build();
-    method public android.app.prediction.AppTargetEvent.Builder setLaunchLocation(String);
+    method @NonNull public android.app.prediction.AppTargetEvent build();
+    method @NonNull public android.app.prediction.AppTargetEvent.Builder setLaunchLocation(@Nullable String);
   }
 
   public final class AppTargetId implements android.os.Parcelable {
@@ -599,6 +599,7 @@
     method public void setAutofillOptions(@Nullable android.content.AutofillOptions);
     method public void setContentCaptureOptions(@Nullable android.content.ContentCaptureOptions);
     field public static final String ROLLBACK_SERVICE = "rollback";
+    field public static final String TEST_NETWORK_SERVICE = "test_network";
   }
 
   public class ContextWrapper extends android.content.Context {
@@ -945,10 +946,9 @@
     method @Deprecated public void setCarrierPhase(double);
     method @Deprecated public void setCarrierPhaseUncertainty(double);
     method public void setCn0DbHz(double);
-    method public void setCodeType(int);
+    method public void setCodeType(@NonNull String);
     method public void setConstellationType(int);
     method public void setMultipathIndicator(int);
-    method public void setOtherCodeTypeName(@NonNull String);
     method public void setPseudorangeRateMetersPerSecond(double);
     method public void setPseudorangeRateUncertaintyMetersPerSecond(double);
     method public void setReceivedSvTimeNanos(long);
@@ -1762,7 +1762,7 @@
   public final class PowerManager {
     method @RequiresPermission("android.permission.POWER_SAVER") public int getPowerSaveMode();
     method @RequiresPermission("android.permission.POWER_SAVER") public boolean setDynamicPowerSavings(boolean, int);
-    method @RequiresPermission(anyOf={"android.permission.DEVICE_POWER", "android.permission.POWER_SAVER"}) public boolean setPowerSaveMode(boolean);
+    method @RequiresPermission(anyOf={"android.permission.DEVICE_POWER", "android.permission.POWER_SAVER"}) public boolean setPowerSaveModeEnabled(boolean);
     field public static final int POWER_SAVER_MODE_DYNAMIC = 1; // 0x1
     field public static final int POWER_SAVER_MODE_PERCENTAGE = 0; // 0x0
   }
@@ -2055,16 +2055,16 @@
   public final class DeviceConfig {
     method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static void addOnPropertiesChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertiesChangedListener);
     method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static void addOnPropertyChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
-    method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static boolean getBoolean(String, String, boolean);
-    method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static float getFloat(String, String, float);
-    method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static int getInt(String, String, int);
-    method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static long getLong(String, String, long);
-    method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static String getProperty(String, String);
-    method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static String getString(String, String, String);
+    method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static boolean getBoolean(@NonNull String, @NonNull String, boolean);
+    method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static float getFloat(@NonNull String, @NonNull String, float);
+    method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static int getInt(@NonNull String, @NonNull String, int);
+    method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static long getLong(@NonNull String, @NonNull String, long);
+    method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static String getProperty(@NonNull String, @NonNull String);
+    method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static String getString(@NonNull String, @NonNull String, @Nullable String);
     method public static void removeOnPropertiesChangedListener(@NonNull android.provider.DeviceConfig.OnPropertiesChangedListener);
     method public static void removeOnPropertyChangedListener(@NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
     method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static void resetToDefaults(int, @Nullable String);
-    method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean setProperty(String, String, String, boolean);
+    method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean setProperty(@NonNull String, @NonNull String, @Nullable String, boolean);
     field public static final String NAMESPACE_AUTOFILL = "autofill";
     field public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture";
   }
@@ -2074,7 +2074,7 @@
   }
 
   public static interface DeviceConfig.OnPropertyChangedListener {
-    method public void onPropertyChanged(String, String, String);
+    method public void onPropertyChanged(@NonNull String, @NonNull String, @Nullable String);
   }
 
   public static interface DeviceConfig.Privacy {
@@ -2224,7 +2224,7 @@
   public abstract class AppPredictionService extends android.app.Service {
     ctor public AppPredictionService();
     method @MainThread public abstract void onAppTargetEvent(@NonNull android.app.prediction.AppPredictionSessionId, @NonNull android.app.prediction.AppTargetEvent);
-    method public final android.os.IBinder onBind(android.content.Intent);
+    method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent);
     method public void onCreatePredictionSession(@NonNull android.app.prediction.AppPredictionContext, @NonNull android.app.prediction.AppPredictionSessionId);
     method @MainThread public void onDestroyPredictionSession(@NonNull android.app.prediction.AppPredictionSessionId);
     method @MainThread public abstract void onLocationShown(@NonNull android.app.prediction.AppPredictionSessionId, @NonNull String, @NonNull java.util.List<android.app.prediction.AppTargetId>);
@@ -2396,6 +2396,7 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.service.contentcapture.ActivityEvent> CREATOR;
     field public static final int TYPE_ACTIVITY_PAUSED = 2; // 0x2
     field public static final int TYPE_ACTIVITY_RESUMED = 1; // 0x1
+    field public static final int TYPE_ACTIVITY_STOPPED = 23; // 0x17
   }
 
   public abstract class ContentCaptureService extends android.app.Service {
@@ -2547,7 +2548,8 @@
     method public int getCarrierIdListVersion();
     method public android.util.Pair<java.lang.Integer,java.lang.Integer> getRadioHalVersion();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void refreshUiccProfile();
-    method public void setCarrierTestOverride(String, String, String, String, String, String, String);
+    method @Deprecated public void setCarrierTestOverride(String, String, String, String, String, String, String);
+    method public void setCarrierTestOverride(String, String, String, String, String, String, String, String, String);
     field public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2; // 0xfffffffe
     field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1
     field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0
@@ -3055,6 +3057,7 @@
     method public int getTaskId();
     field public static final int FLAG_DISABLED_BY_APP = 1; // 0x1
     field public static final int FLAG_DISABLED_BY_FLAG_SECURE = 2; // 0x2
+    field public static final int FLAG_RECONNECTED = 4; // 0x4
   }
 
   public final class ContentCaptureEvent implements android.os.Parcelable {
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
index 062ba65..98ab666 100644
--- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
+++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
@@ -803,8 +803,8 @@
                             } else {
                                 String[] names = new String[filter.size()];
                                 filter.toArray(names);
-                                didRestore = (mRestore.restoreSome(token, observer,
-                                        null, names) == 0);
+                                didRestore = (mRestore.restorePackages(token, observer, names,
+                                        null) == 0);
                             }
                             break;
                         }
diff --git a/cmds/bootanimation/bootanim.rc b/cmds/bootanimation/bootanim.rc
index 3666d6a..469c964 100644
--- a/cmds/bootanimation/bootanim.rc
+++ b/cmds/bootanimation/bootanim.rc
@@ -2,9 +2,6 @@
     class core animation
     user graphics
     group graphics audio
-    # bootanimation depends on libandroidicu in the Runtime APEX.
-    # TODO(b/124939955): Remove this dependency on libandroidicu
-    updatable
     disabled
     oneshot
     writepid /dev/stune/top-app/tasks
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index 7298da6..ce07d6d 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -219,6 +219,7 @@
         "tests/anomaly/AnomalyTracker_test.cpp",
         "tests/ConfigManager_test.cpp",
         "tests/external/puller_util_test.cpp",
+        "tests/external/GpuStatsPuller_test.cpp",
         "tests/external/IncidentReportArgs_test.cpp",
         "tests/external/StatsPuller_test.cpp",
         "tests/indexed_priority_queue_test.cpp",
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 1526d66..f78ae38 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -1198,30 +1198,48 @@
     }
     // TODO: add verifier permission
 
-    userid_t userId = multiuser_get_user_id(uid);
+    bool readTrainInfoSuccess = false;
+    InstallTrainInfo trainInfo;
+    if (trainVersionCode == -1 || experimentIds.empty() || trainName.size() == 0) {
+        readTrainInfoSuccess = StorageManager::readTrainInfo(trainInfo);
+    }
 
-    bool requiresStaging = options & IStatsManager::FLAG_REQUIRE_STAGING;
-    bool rollbackEnabled = options & IStatsManager::FLAG_ROLLBACK_ENABLED;
-    bool requiresLowLatencyMonitor = options & IStatsManager::FLAG_REQUIRE_LOW_LATENCY_MONITOR;
-
-    ProtoOutputStream proto;
-    for (const auto& expId : experimentIds) {
-        proto.write(FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED | FIELD_ID_EXPERIMENT_ID,
-                    (long long)expId);
+    if (trainVersionCode == -1 && readTrainInfoSuccess) {
+        trainVersionCode = trainInfo.trainVersionCode;
     }
 
     vector<uint8_t> experimentIdsProtoBuffer;
-    experimentIdsProtoBuffer.resize(proto.size());
-    size_t pos = 0;
-    auto iter = proto.data();
-    while (iter.readBuffer() != NULL) {
-        size_t toRead = iter.currentToRead();
-        std::memcpy(&(experimentIdsProtoBuffer[pos]), iter.readBuffer(), toRead);
-        pos += toRead;
-        iter.rp()->move(toRead);
+    if (readTrainInfoSuccess && experimentIds.empty()) {
+        experimentIdsProtoBuffer = trainInfo.experimentIds;
+    } else {
+        ProtoOutputStream proto;
+        for (const auto& expId : experimentIds) {
+            proto.write(FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED | FIELD_ID_EXPERIMENT_ID,
+                        (long long)expId);
+        }
+
+        experimentIdsProtoBuffer.resize(proto.size());
+        size_t pos = 0;
+        auto iter = proto.data();
+        while (iter.readBuffer() != NULL) {
+            size_t toRead = iter.currentToRead();
+            std::memcpy(&(experimentIdsProtoBuffer[pos]), iter.readBuffer(), toRead);
+            pos += toRead;
+            iter.rp()->move(toRead);
+        }
     }
 
-    std::string trainNameUtf8 = std::string(String8(trainName).string());
+    std::string trainNameUtf8;
+    if (readTrainInfoSuccess && trainName.size() == 0) {
+        trainNameUtf8 = trainInfo.trainName;
+    } else {
+        trainNameUtf8 = std::string(String8(trainName).string());
+    }
+
+    userid_t userId = multiuser_get_user_id(uid);
+    bool requiresStaging = options & IStatsManager::FLAG_REQUIRE_STAGING;
+    bool rollbackEnabled = options & IStatsManager::FLAG_ROLLBACK_ENABLED;
+    bool requiresLowLatencyMonitor = options & IStatsManager::FLAG_REQUIRE_LOW_LATENCY_MONITOR;
     LogEvent event(trainNameUtf8, trainVersionCode, requiresStaging, rollbackEnabled,
                    requiresLowLatencyMonitor, state, experimentIdsProtoBuffer, userId);
     mProcessor->OnLogEvent(&event);
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 4856f77..7a753aec 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -45,6 +45,7 @@
 import "frameworks/base/core/proto/android/stats/devicepolicy/device_policy.proto";
 import "frameworks/base/core/proto/android/stats/devicepolicy/device_policy_enums.proto";
 import "frameworks/base/core/proto/android/stats/launcher/launcher.proto";
+import "frameworks/base/core/proto/android/stats/storage/storage_enums.proto";
 import "frameworks/base/core/proto/android/stats/style/style_enums.proto";
 import "frameworks/base/core/proto/android/telecomm/enums.proto";
 import "frameworks/base/core/proto/android/telephony/enums.proto";
@@ -250,10 +251,11 @@
         HiddenApiUsed hidden_api_used = 178 [(allow_from_any_uid) = true];
         StyleUIChanged style_ui_changed = 179;
         PrivacyIndicatorsInteracted privacy_indicators_interacted = 180;
+        AppInstallOnExternalStorageReported app_install_on_external_storage_reported = 181;
     }
 
     // Pulled events will start at field 10000.
-    // Next: 10056
+    // Next: 10057
     oneof pulled {
         WifiBytesTransfer wifi_bytes_transfer = 10000;
         WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001;
@@ -311,6 +313,7 @@
         SDCardInfo sdcard_info = 10053;
         GpuStatsGlobalInfo gpu_stats_global_info = 10054;
         GpuStatsAppInfo gpu_stats_app_info = 10055;
+        SystemIonHeapSize system_ion_heap_size = 10056;
     }
 
     // DO NOT USE field numbers above 100,000 in AOSP.
@@ -2557,6 +2560,18 @@
 }
 
 /**
+ * Logs whenever an app is installed on external storage.
+ * Logged from:
+        frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
+ */
+message AppInstallOnExternalStorageReported {
+    // The type of external storage.
+    optional android.stats.storage.ExternalStorageType storage_type = 1;
+    // The name of the package that is installed on the sd card.
+    optional string package_name = 2;
+}
+
+/**
  * Logs when an app crashes.
  * Logged from:
  *      frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -4912,7 +4927,7 @@
   // since boot, not including sleep (see SystemClock.uptimeMillis()).
   optional int64 last_compact_timestamp_ms_since_boot = 14;
 
-  // The oom_score_adj at the time of compaction.
+  // The "setAdj" (i.e. previous) oom_score_adj at the time of compaction.
   optional int32 oom_score_adj = 15;
 
   // The process state at the time of compaction.
@@ -5759,7 +5774,7 @@
     optional string tzdb_version = 1;
 }
 
-/*
+/**
  * Logs the GPU stats global health information.
  *
  * Logged from:
@@ -5791,22 +5806,44 @@
     optional int64 vk_loading_failure_count = 8;
 }
 
-/*
+/**
+ * GPU driver loading time info.
+ */
+message GpuDriverLoadingTime {
+    // List of all the driver loading times for this app. The list size is
+    // capped at 50.
+    repeated int64 driver_loading_time = 1;
+}
+
+/**
  * Logs the GPU stats per app health information.
  *
  * Logged from:
  *   frameworks/native/services/gpuservice/gpustats/
  */
 message GpuStatsAppInfo {
-    // Package name of the application that loads the gpu driver.
+    // Package name of the application that loads the gpu driver. Total number
+    // of different packages is capped at 100.
     optional string app_package_name = 1;
 
     // Version code of the gpu driver this app loads.
     optional int64 driver_version_code = 2;
 
-    // List of all the gl driver loading times for this app.
-    repeated int64 gl_driver_loading_time = 3;
+    // gl driver loading time info.
+    optional GpuDriverLoadingTime gl_driver_loading_time = 3
+            [(android.os.statsd.log_mode) = MODE_BYTES];
 
-    // List of all the Vulkan driver laoding times for this app.
-    repeated int64 vk_driver_loading_time = 4;
+    // Vulkan driver loading time info.
+    optional GpuDriverLoadingTime vk_driver_loading_time = 4
+            [(android.os.statsd.log_mode) = MODE_BYTES];
+}
+
+/*
+ * Logs the size of the system ion heap.
+ *
+ * Pulled from StatsCompanionService.
+ */
+message SystemIonHeapSize {
+    // Size of the system ion heap in bytes.
+    optional int64 size_in_bytes = 1;
 }
diff --git a/cmds/statsd/src/external/GpuStatsPuller.cpp b/cmds/statsd/src/external/GpuStatsPuller.cpp
index 8445803..130bd85 100644
--- a/cmds/statsd/src/external/GpuStatsPuller.cpp
+++ b/cmds/statsd/src/external/GpuStatsPuller.cpp
@@ -70,6 +70,30 @@
     return true;
 }
 
+static bool pullGpuStatsAppInfo(const sp<IGpuService>& gpuService,
+                                std::vector<std::shared_ptr<LogEvent>>* data) {
+    std::vector<GpuStatsAppInfo> stats;
+    status_t status = gpuService->getGpuStatsAppInfo(&stats);
+    if (status != OK) {
+        return false;
+    }
+
+    data->clear();
+    data->reserve(stats.size());
+    for (const auto& info : stats) {
+        std::shared_ptr<LogEvent> event = make_shared<LogEvent>(
+                android::util::GPU_STATS_APP_INFO, getWallClockNs(), getElapsedRealtimeNs());
+        if (!event->write(info.appPackageName)) return false;
+        if (!event->write((int64_t)info.driverVersionCode)) return false;
+        if (!event->write(int64VectorToProtoByteString(info.glDriverLoadingTime))) return false;
+        if (!event->write(int64VectorToProtoByteString(info.vkDriverLoadingTime))) return false;
+        event->init();
+        data->emplace_back(event);
+    }
+
+    return true;
+}
+
 bool GpuStatsPuller::PullInternal(std::vector<std::shared_ptr<LogEvent>>* data) {
     const sp<IGpuService> gpuService = getGpuService();
     if (!gpuService) {
@@ -79,6 +103,8 @@
     switch (mTagId) {
         case android::util::GPU_STATS_GLOBAL_INFO:
             return pullGpuStatsGlobalInfo(gpuService, data);
+        case android::util::GPU_STATS_APP_INFO:
+            return pullGpuStatsAppInfo(gpuService, data);
         default:
             break;
     }
@@ -86,6 +112,35 @@
     return false;
 }
 
+static std::string protoOutputStreamToByteString(ProtoOutputStream& proto) {
+    if (!proto.size()) return "";
+
+    std::string byteString;
+    auto iter = proto.data();
+    while (iter.readBuffer() != nullptr) {
+        const size_t toRead = iter.currentToRead();
+        byteString.append((char*)iter.readBuffer(), toRead);
+        iter.rp()->move(toRead);
+    }
+
+    if (byteString.size() != proto.size()) return "";
+
+    return byteString;
+}
+
+std::string int64VectorToProtoByteString(const std::vector<int64_t>& value) {
+    if (value.empty()) return "";
+
+    ProtoOutputStream proto;
+    for (const auto& ele : value) {
+        proto.write(android::util::FIELD_TYPE_INT64 | android::util::FIELD_COUNT_REPEATED |
+                            1 /* field id */,
+                    (long long)ele);
+    }
+
+    return protoOutputStreamToByteString(proto);
+}
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/statsd/src/external/GpuStatsPuller.h b/cmds/statsd/src/external/GpuStatsPuller.h
index 4c7a4d6..2da199c 100644
--- a/cmds/statsd/src/external/GpuStatsPuller.h
+++ b/cmds/statsd/src/external/GpuStatsPuller.h
@@ -31,6 +31,12 @@
     bool PullInternal(std::vector<std::shared_ptr<LogEvent>>* data) override;
 };
 
+// convert a int64_t vector into a byte string for proto message like:
+// message RepeatedInt64Wrapper {
+//   repeated int64 value = 1;
+// }
+std::string int64VectorToProtoByteString(const std::vector<int64_t>& value);
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 924704b..c7ae656 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -148,10 +148,14 @@
         {android::util::NATIVE_PROCESS_MEMORY_STATE,
          {.additiveFields = {3, 4, 5, 6},
           .puller = new StatsCompanionServicePuller(android::util::NATIVE_PROCESS_MEMORY_STATE)}},
+        // process_memory_high_water_mark
         {android::util::PROCESS_MEMORY_HIGH_WATER_MARK,
          {.additiveFields = {3},
           .puller =
                   new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_HIGH_WATER_MARK)}},
+        // system_ion_heap_size
+        {android::util::SYSTEM_ION_HEAP_SIZE,
+         {.puller = new StatsCompanionServicePuller(android::util::SYSTEM_ION_HEAP_SIZE)}},
         // temperature
         {android::util::TEMPERATURE,
          {.puller = new StatsCompanionServicePuller(android::util::TEMPERATURE)}},
@@ -244,6 +248,9 @@
         // GpuStatsGlobalInfo
         {android::util::GPU_STATS_GLOBAL_INFO,
          {.puller = new GpuStatsPuller(android::util::GPU_STATS_GLOBAL_INFO)}},
+        // GpuStatsAppInfo
+        {android::util::GPU_STATS_APP_INFO,
+         {.puller = new GpuStatsPuller(android::util::GPU_STATS_APP_INFO)}},
 };
 
 StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) {
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index 254d7d5..c023e6f 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -319,10 +319,11 @@
         return;
     }
 
-    flushCurrentBucketLocked(eventTimeNs, eventTimeNs);
     // Setup the bucket start time and number.
     int64_t numBucketsForward = 1 + (eventTimeNs - currentBucketEndTimeNs) / mBucketSizeNs;
-    mCurrentBucketStartTimeNs = currentBucketEndTimeNs + (numBucketsForward - 1) * mBucketSizeNs;
+    int64_t nextBucketNs = currentBucketEndTimeNs + (numBucketsForward - 1) * mBucketSizeNs;
+    flushCurrentBucketLocked(eventTimeNs, nextBucketNs);
+
     mCurrentBucketNum += numBucketsForward;
     VLOG("metric %lld: new bucket start time: %lld", (long long)mMetricId,
          (long long)mCurrentBucketStartTimeNs);
@@ -375,6 +376,7 @@
     // Only resets the counters, but doesn't setup the times nor numbers.
     // (Do not clear since the old one is still referenced in mAnomalyTrackers).
     mCurrentSlicedCounter = std::make_shared<DimToValMap>();
+    mCurrentBucketStartTimeNs = nextBucketStartTimeNs;
 }
 
 // Rough estimate of CountMetricProducer buffer stored. This number will be
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index 7dc4e2d..615c7f2 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -559,26 +559,10 @@
         return;
     }
     VLOG("flushing...........");
-    for (auto whatIt = mCurrentSlicedDurationTrackerMap.begin();
-            whatIt != mCurrentSlicedDurationTrackerMap.end();) {
-        for (auto it = whatIt->second.begin(); it != whatIt->second.end();) {
-            if (it->second->flushIfNeeded(eventTimeNs, &mPastBuckets)) {
-                VLOG("erase bucket for key %s %s",
-                     whatIt->first.toString().c_str(), it->first.toString().c_str());
-                it = whatIt->second.erase(it);
-            } else {
-                ++it;
-            }
-        }
-        if (whatIt->second.empty()) {
-            whatIt = mCurrentSlicedDurationTrackerMap.erase(whatIt);
-        } else {
-            whatIt++;
-        }
-    }
-
     int numBucketsForward = 1 + (eventTimeNs - currentBucketEndTimeNs) / mBucketSizeNs;
-    mCurrentBucketStartTimeNs = currentBucketEndTimeNs + (numBucketsForward - 1) * mBucketSizeNs;
+    int64_t nextBucketNs = currentBucketEndTimeNs + (numBucketsForward - 1) * mBucketSizeNs;
+    flushCurrentBucketLocked(eventTimeNs, nextBucketNs);
+
     mCurrentBucketNum += numBucketsForward;
 }
 
@@ -602,6 +586,7 @@
         }
     }
     StatsdStats::getInstance().noteBucketCount(mMetricId);
+    mCurrentBucketStartTimeNs = nextBucketStartTimeNs;
 }
 
 void DurationMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const {
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 2b6cac8..2f9afa5 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -529,11 +529,11 @@
         return;
     }
 
-    flushCurrentBucketLocked(eventTimeNs, eventTimeNs);
-
     // Adjusts the bucket start and end times.
     int64_t numBucketsForward = 1 + (eventTimeNs - currentBucketEndTimeNs) / mBucketSizeNs;
-    mCurrentBucketStartTimeNs = currentBucketEndTimeNs + (numBucketsForward - 1) * mBucketSizeNs;
+    int64_t nextBucketNs = currentBucketEndTimeNs + (numBucketsForward - 1) * mBucketSizeNs;
+    flushCurrentBucketLocked(eventTimeNs, nextBucketNs);
+
     mCurrentBucketNum += numBucketsForward;
     VLOG("Gauge metric %lld: new bucket start time: %lld", (long long)mMetricId,
          (long long)mCurrentBucketStartTimeNs);
@@ -578,6 +578,7 @@
 
     StatsdStats::getInstance().noteBucketCount(mMetricId);
     mCurrentSlicedBucket = std::make_shared<DimToGaugeAtomsMap>();
+    mCurrentBucketStartTimeNs = nextBucketStartTimeNs;
 }
 
 size_t GaugeMetricProducer::byteSizeLocked() const {
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index 27ee570..18bfdfc 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -787,7 +787,6 @@
     }
 
     int64_t numBucketsForward = calcBucketsForwardCount(eventTimeNs);
-    mCurrentBucketNum += numBucketsForward;
     if (numBucketsForward > 1) {
         VLOG("Skipping forward %lld buckets", (long long)numBucketsForward);
         StatsdStats::getInstance().noteSkippedForwardBuckets(mMetricId);
@@ -816,10 +815,9 @@
         mSkippedBuckets.emplace_back(mCurrentBucketStartTimeNs, bucketEndTime);
     }
 
-    if (!mCurrentBucketIsInvalid) {
-        appendToFullBucket(eventTimeNs, fullBucketEndTimeNs);
-    }
+    appendToFullBucket(eventTimeNs, fullBucketEndTimeNs);
     initCurrentSlicedBucket(nextBucketStartTimeNs);
+    mCurrentBucketNum += numBucketsForward;
 }
 
 ValueBucket ValueMetricProducer::buildPartialBucket(int64_t bucketEndTime,
@@ -879,7 +877,17 @@
 }
 
 void ValueMetricProducer::appendToFullBucket(int64_t eventTimeNs, int64_t fullBucketEndTimeNs) {
-    if (eventTimeNs > fullBucketEndTimeNs) {  // If full bucket, send to anomaly tracker.
+    bool isFullBucketReached = eventTimeNs > fullBucketEndTimeNs;
+    if (mCurrentBucketIsInvalid) {
+        if (isFullBucketReached) {
+            // If the bucket is invalid, we ignore the full bucket since it contains invalid data.
+            mCurrentFullBucket.clear();
+        }
+        // Current bucket is invalid, we do not add it to the full bucket.
+        return;
+    }
+
+    if (isFullBucketReached) {  // If full bucket, send to anomaly tracker.
         // Accumulate partial buckets with current value and then send to anomaly tracker.
         if (mCurrentFullBucket.size() > 0) {
             for (const auto& slice : mCurrentSlicedBucket) {
@@ -887,7 +895,10 @@
                     continue;
                 }
                 // TODO: fix this when anomaly can accept double values
-                mCurrentFullBucket[slice.first] += slice.second[0].value.long_value;
+                auto& interval = slice.second[0];
+                if (interval.hasValue) {
+                    mCurrentFullBucket[slice.first] += interval.value.long_value;
+                }
             }
             for (const auto& slice : mCurrentFullBucket) {
                 for (auto& tracker : mAnomalyTrackers) {
@@ -903,8 +914,11 @@
                 for (auto& tracker : mAnomalyTrackers) {
                     if (tracker != nullptr) {
                         // TODO: fix this when anomaly can accept double values
-                        tracker->addPastBucket(slice.first, slice.second[0].value.long_value,
-                                               mCurrentBucketNum);
+                        auto& interval = slice.second[0];
+                        if (interval.hasValue) {
+                            tracker->addPastBucket(slice.first, interval.value.long_value,
+                                                   mCurrentBucketNum);
+                        }
                     }
                 }
             }
@@ -913,7 +927,10 @@
         // Accumulate partial bucket.
         for (const auto& slice : mCurrentSlicedBucket) {
             // TODO: fix this when anomaly can accept double values
-            mCurrentFullBucket[slice.first] += slice.second[0].value.long_value;
+            auto& interval = slice.second[0];
+            if (interval.hasValue) {
+                mCurrentFullBucket[slice.first] += interval.value.long_value;
+            }
         }
     }
 }
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index f317c37..12cec5d 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -178,7 +178,7 @@
 
     void pullAndMatchEventsLocked(const int64_t timestampNs, ConditionState condition);
 
-    void accumulateEvents(const std::vector<std::shared_ptr<LogEvent>>& allData, 
+    void accumulateEvents(const std::vector<std::shared_ptr<LogEvent>>& allData,
                           int64_t originalPullTimeNs, int64_t eventElapsedTimeNs,
                           ConditionState condition);
 
@@ -244,6 +244,7 @@
     FRIEND_TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled);
     FRIEND_TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition);
     FRIEND_TEST(ValueMetricProducerTest, TestFirstBucket);
+    FRIEND_TEST(ValueMetricProducerTest, TestFullBucketResetWhenLastBucketInvalid);
     FRIEND_TEST(ValueMetricProducerTest, TestInvalidBucketWhenGuardRailHit);
     FRIEND_TEST(ValueMetricProducerTest, TestInvalidBucketWhenInitialPullFailed);
     FRIEND_TEST(ValueMetricProducerTest, TestInvalidBucketWhenLastPullFailed);
diff --git a/cmds/statsd/src/shell/ShellSubscriber.cpp b/cmds/statsd/src/shell/ShellSubscriber.cpp
index 52d5ffc..f7e32d4 100644
--- a/cmds/statsd/src/shell/ShellSubscriber.cpp
+++ b/cmds/statsd/src/shell/ShellSubscriber.cpp
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#define DEBUG true  // STOPSHIP if true
+#define DEBUG false  // STOPSHIP if true
 #include "Log.h"
 
 #include "ShellSubscriber.h"
diff --git a/cmds/statsd/src/storage/StorageManager.cpp b/cmds/statsd/src/storage/StorageManager.cpp
index 5df8fb5..65b183c 100644
--- a/cmds/statsd/src/storage/StorageManager.cpp
+++ b/cmds/statsd/src/storage/StorageManager.cpp
@@ -116,14 +116,16 @@
     const size_t trainNameSizeByteCount = sizeof(trainNameSize);
     result = write(fd, (uint8_t*)&trainNameSize, trainNameSizeByteCount);
     if (result != trainNameSizeByteCount) {
-        VLOG("Failed to write %s", file_name.c_str());
+        VLOG("Failed to write train name size for %s", file_name.c_str());
+        close(fd);
         return false;
     }
 
     // Write trainName to file
     result = write(fd, trainName.c_str(), trainNameSize);
     if (result != trainNameSize) {
-        VLOG("Failed to write %s", file_name.c_str());
+        VLOG("Failed to write train name for%s", file_name.c_str());
+        close(fd);
         return false;
     }
 
@@ -131,7 +133,18 @@
     const size_t statusByteCount = sizeof(status);
     result = write(fd, (uint8_t*)&status, statusByteCount);
     if (result != statusByteCount) {
-        VLOG("Failed to write %s", file_name.c_str());
+        VLOG("Failed to write status for %s", file_name.c_str());
+        close(fd);
+        return false;
+    }
+
+    // Write experiment id size to file.
+    const size_t experimentIdSize = experimentIds.size();
+    const size_t experimentIdsSizeByteCount = sizeof(experimentIdSize);
+    result = write(fd, (uint8_t*) &experimentIdSize, experimentIdsSizeByteCount);
+    if (result != experimentIdsSizeByteCount) {
+        VLOG("Failed to write experiment id size for %s", file_name.c_str());
+        close(fd);
         return false;
     }
 
@@ -140,13 +153,15 @@
     if (result == experimentIds.size()) {
         VLOG("Successfully wrote %s", file_name.c_str());
     } else {
-        VLOG("Failed to write %s", file_name.c_str());
+        VLOG("Failed to write experiment ids for %s", file_name.c_str());
+        close(fd);
         return false;
     }
 
     result = fchown(fd, AID_STATSD, AID_STATSD);
     if (result) {
         VLOG("Failed to chown %s to statsd", file_name.c_str());
+        close(fd);
         return false;
     }
 
@@ -170,39 +185,73 @@
         if (name[0] == '.') {
             continue;
         }
+
+        size_t result;
+
         trainInfo.trainVersionCode = StrToInt64(name);
         string fullPath = StringPrintf("%s/%s", TRAIN_INFO_DIR, name);
         int fd = open(fullPath.c_str(), O_RDONLY | O_CLOEXEC);
-        if (fd != -1) {
-            string str;
-            if (android::base::ReadFdToString(fd, &str)) {
-                close(fd);
-
-                auto it = str.begin();
-
-                // Read # of bytes taken by trainName in the file
-                size_t trainNameSize;
-                const size_t trainNameSizeByteCount = sizeof(trainNameSize);
-                std::copy_n(it, trainNameSizeByteCount, &trainNameSize);
-                it += trainNameSizeByteCount;
-
-                // Read trainName
-                std::copy_n(it, trainNameSize, std::back_inserter(trainInfo.trainName));
-                it += trainNameSize;
-
-                // Read status
-                const size_t statusByteCount = sizeof(trainInfo.status);
-                std::copy_n(it, statusByteCount, &trainInfo.status);
-                it += statusByteCount;
-
-                // Read experimentIds
-                std::copy(it, str.end(), std::back_inserter(trainInfo.experimentIds));
-
-                VLOG("Read train info file successful: %s", fullPath.c_str());
-                return true;
-            }
+        if (fd == -1) {
+            return false;
         }
+
+        // Read # of bytes taken by trainName in the file.
+        size_t trainNameSize;
+        result = read(fd, &trainNameSize, sizeof(size_t));
+        if (result != sizeof(size_t)) {
+            VLOG("Failed to read train name size from file %s", fullPath.c_str());
+            close(fd);
+            return false;
+        }
+
+        // Read trainName
+        trainInfo.trainName.resize(trainNameSize);
+        result = read(fd, trainInfo.trainName.data(), trainNameSize);
+        if (result != trainNameSize) {
+            VLOG("Failed to read train name from file %s", fullPath.c_str());
+            close(fd);
+            return false;
+        }
+
+        // Read status
+        const size_t statusByteCount = sizeof(trainInfo.status);
+        result = read(fd, &trainInfo.status, statusByteCount);
+        if (result != statusByteCount) {
+            VLOG("Failed to read train status from file %s", fullPath.c_str());
+            close(fd);
+            return false;
+        }
+
+        // Read experiment ids size.
+        size_t experimentIdSize;
+        result = read(fd, &experimentIdSize, sizeof(size_t));
+        if (result != sizeof(size_t)) {
+            VLOG("Failed to read train experiment id size from file %s", fullPath.c_str());
+            close(fd);
+            return false;
+        }
+
+        // Read experimentIds
+        trainInfo.experimentIds.resize(experimentIdSize);
+        result = read(fd, trainInfo.experimentIds.data(), experimentIdSize);
+        if (result != experimentIdSize) {
+            VLOG("Failed to read train experiment ids from file %s", fullPath.c_str());
+            close(fd);
+            return false;
+        }
+
+        // Expect to be at EOF.
+        char c;
+        result = read(fd, &c, 1);
+        if (result != 0) {
+            VLOG("Failed to read train info from file %s. Did not get expected EOF.", fullPath.c_str());
+            close(fd);
+            return false;
+        }
+
+        VLOG("Read train info file successful: %s", fullPath.c_str());
         close(fd);
+        return true;
     }
     return false;
 }
diff --git a/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp b/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
index ef3643f..3dff7f5 100644
--- a/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
@@ -46,7 +46,7 @@
     IPCThreadState* ipc = IPCThreadState::self();
     ConfigKey configKey(ipc->getCallingUid(), kConfigKey);
     processor->onDumpReport(configKey, timestamp, include_current /* include_current_bucket*/,
-                            true /* erase_data */, ADB_DUMP, FAST, &output);
+                            true /* erase_data */, ADB_DUMP, NO_TIME_CONSTRAINTS, &output);
     ConfigMetricsReportList reports;
     reports.ParseFromArray(output.data(), output.size());
     EXPECT_EQ(1, reports.reports_size());
diff --git a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
index cdb5a78..b316562 100644
--- a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
@@ -75,7 +75,7 @@
             mAllMetricProducers[0]->getCurrentBucketNum();
     EXPECT_GT(startBucketNum, (int64_t)0);
 
-    // When creating the config, the gauge metric producer should register the alarm at the
+    // When creating the config, the value metric producer should register the alarm at the
     // end of the current bucket.
     EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
     EXPECT_EQ(bucketSizeNs,
@@ -140,32 +140,30 @@
     EXPECT_EQ(1 /* subsystem name field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
-    EXPECT_EQ(5, data.bucket_info_size());
+    // We have 4 buckets, the first one was incomplete since the condition was unknown.
+    EXPECT_EQ(4, data.bucket_info_size());
 
-    EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+    EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
     EXPECT_EQ(1, data.bucket_info(0).values_size());
 
-    EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
+    EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
+    EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
     EXPECT_EQ(1, data.bucket_info(1).values_size());
 
-    EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
+    EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
+    EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
     EXPECT_EQ(1, data.bucket_info(2).values_size());
 
-    EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
+    EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
+    EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
     EXPECT_EQ(1, data.bucket_info(3).values_size());
-
-    EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(4).start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(4).end_bucket_elapsed_nanos());
-    EXPECT_EQ(1, data.bucket_info(4).values_size());
 }
 
 TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm) {
     auto config = CreateStatsdConfig();
     int64_t baseTimeNs = getElapsedRealtimeNs();
+    // 10 mins == 2 bucket durations.
     int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
     int64_t bucketSizeNs =
         TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
@@ -181,7 +179,7 @@
             mAllMetricProducers[0]->getCurrentBucketNum();
     EXPECT_GT(startBucketNum, (int64_t)0);
 
-    // When creating the config, the gauge metric producer should register the alarm at the
+    // When creating the config, the value metric producer should register the alarm at the
     // end of the current bucket.
     EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
     EXPECT_EQ(bucketSizeNs,
@@ -203,15 +201,18 @@
                                                    configAddedTimeNs + 75);
     processor->OnLogEvent(screenOffEvent.get());
 
-    // Pulling alarm arrives late by 2 buckets and 1 ns.
+    // Pulling alarm arrives late by 2 buckets and 1 ns. 2 buckets late is too far away in the
+    // future, data will be skipped.
     processor->informPullAlarmFired(expectedPullTimeNs + 2 * bucketSizeNs + 1);
     EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, expectedPullTimeNs);
 
+    // This screen state change will start a new bucket.
     screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
                                                        configAddedTimeNs + 4 * bucketSizeNs + 65);
     processor->OnLogEvent(screenOnEvent.get());
 
-    // Pulling alarm arrives late by one bucket size + 21ns.
+    // The alarm is delayed but we already created a bucket thanks to the screen state condition.
+    // This bucket does not have to be skipped since the alarm arrives in time for the next bucket.
     processor->informPullAlarmFired(expectedPullTimeNs + bucketSizeNs + 21);
     EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, expectedPullTimeNs);
 
@@ -249,8 +250,8 @@
     EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
     EXPECT_EQ(3, data.bucket_info_size());
 
-    EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+    EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
     EXPECT_EQ(1, data.bucket_info(0).values_size());
 
     EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
diff --git a/cmds/statsd/tests/external/GpuStatsPuller_test.cpp b/cmds/statsd/tests/external/GpuStatsPuller_test.cpp
new file mode 100644
index 0000000..8625487
--- /dev/null
+++ b/cmds/statsd/tests/external/GpuStatsPuller_test.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2019 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.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "GpuStatsPuller_test"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <graphicsenv/GpuStatsInfo.h>
+#include <log/log.h>
+
+#include "src/external/GpuStatsPuller.h"
+
+#ifdef __ANDROID__
+
+namespace android {
+namespace os {
+namespace statsd {
+
+// clang-format off
+static const std::string DRIVER_PACKAGE_NAME    = "TEST_DRIVER";
+static const std::string DRIVER_VERSION_NAME    = "TEST_DRIVER_VERSION";
+static const std::string APP_PACKAGE_NAME       = "TEST_APP";
+static const int64_t TIMESTAMP_WALLCLOCK        = 111;
+static const int64_t TIMESTAMP_ELAPSED          = 222;
+static const int64_t DRIVER_VERSION_CODE        = 333;
+static const int64_t DRIVER_BUILD_TIME          = 444;
+static const int64_t GL_LOADING_COUNT           = 3;
+static const int64_t GL_LOADING_FAILURE_COUNT   = 1;
+static const int64_t VK_LOADING_COUNT           = 4;
+static const int64_t VK_LOADING_FAILURE_COUNT   = 0;
+static const int64_t GL_DRIVER_LOADING_TIME_0   = 555;
+static const int64_t GL_DRIVER_LOADING_TIME_1   = 666;
+static const int64_t VK_DRIVER_LOADING_TIME_0   = 777;
+static const int64_t VK_DRIVER_LOADING_TIME_1   = 888;
+static const int64_t VK_DRIVER_LOADING_TIME_2   = 999;
+static const size_t NUMBER_OF_VALUES_GLOBAL     = 8;
+static const size_t NUMBER_OF_VALUES_APP        = 4;
+// clang-format on
+
+class MockGpuStatsPuller : public GpuStatsPuller {
+public:
+    MockGpuStatsPuller(const int tagId, vector<std::shared_ptr<LogEvent>>* data)
+        : GpuStatsPuller(tagId), mData(data){};
+
+private:
+    bool PullInternal(vector<std::shared_ptr<LogEvent>>* data) override {
+        *data = *mData;
+        return true;
+    }
+
+    vector<std::shared_ptr<LogEvent>>* mData;
+};
+
+class GpuStatsPuller_test : public ::testing::Test {
+public:
+    GpuStatsPuller_test() {
+        const ::testing::TestInfo* const test_info =
+                ::testing::UnitTest::GetInstance()->current_test_info();
+        ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
+    }
+
+    ~GpuStatsPuller_test() {
+        const ::testing::TestInfo* const test_info =
+                ::testing::UnitTest::GetInstance()->current_test_info();
+        ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
+    }
+};
+
+TEST_F(GpuStatsPuller_test, PullGpuStatsGlobalInfo) {
+    vector<std::shared_ptr<LogEvent>> inData, outData;
+    std::shared_ptr<LogEvent> event = make_shared<LogEvent>(android::util::GPU_STATS_GLOBAL_INFO,
+                                                            TIMESTAMP_WALLCLOCK, TIMESTAMP_ELAPSED);
+    EXPECT_TRUE(event->write(DRIVER_PACKAGE_NAME));
+    EXPECT_TRUE(event->write(DRIVER_VERSION_NAME));
+    EXPECT_TRUE(event->write(DRIVER_VERSION_CODE));
+    EXPECT_TRUE(event->write(DRIVER_BUILD_TIME));
+    EXPECT_TRUE(event->write(GL_LOADING_COUNT));
+    EXPECT_TRUE(event->write(GL_LOADING_FAILURE_COUNT));
+    EXPECT_TRUE(event->write(VK_LOADING_COUNT));
+    EXPECT_TRUE(event->write(VK_LOADING_FAILURE_COUNT));
+    event->init();
+    inData.emplace_back(event);
+    MockGpuStatsPuller mockPuller(android::util::GPU_STATS_GLOBAL_INFO, &inData);
+    mockPuller.ForceClearCache();
+    mockPuller.Pull(&outData);
+
+    ASSERT_EQ(1, outData.size());
+    EXPECT_EQ(android::util::GPU_STATS_GLOBAL_INFO, outData[0]->GetTagId());
+    ASSERT_EQ(NUMBER_OF_VALUES_GLOBAL, outData[0]->size());
+    EXPECT_EQ(DRIVER_PACKAGE_NAME, outData[0]->getValues()[0].mValue.str_value);
+    EXPECT_EQ(DRIVER_VERSION_NAME, outData[0]->getValues()[1].mValue.str_value);
+    EXPECT_EQ(DRIVER_VERSION_CODE, outData[0]->getValues()[2].mValue.long_value);
+    EXPECT_EQ(DRIVER_BUILD_TIME, outData[0]->getValues()[3].mValue.long_value);
+    EXPECT_EQ(GL_LOADING_COUNT, outData[0]->getValues()[4].mValue.long_value);
+    EXPECT_EQ(GL_LOADING_FAILURE_COUNT, outData[0]->getValues()[5].mValue.long_value);
+    EXPECT_EQ(VK_LOADING_COUNT, outData[0]->getValues()[6].mValue.long_value);
+    EXPECT_EQ(VK_LOADING_FAILURE_COUNT, outData[0]->getValues()[7].mValue.long_value);
+}
+
+TEST_F(GpuStatsPuller_test, PullGpuStatsAppInfo) {
+    vector<std::shared_ptr<LogEvent>> inData, outData;
+    std::shared_ptr<LogEvent> event = make_shared<LogEvent>(android::util::GPU_STATS_APP_INFO,
+                                                            TIMESTAMP_WALLCLOCK, TIMESTAMP_ELAPSED);
+    EXPECT_TRUE(event->write(APP_PACKAGE_NAME));
+    EXPECT_TRUE(event->write(DRIVER_VERSION_CODE));
+    std::vector<int64_t> glDriverLoadingTime;
+    glDriverLoadingTime.emplace_back(GL_DRIVER_LOADING_TIME_0);
+    glDriverLoadingTime.emplace_back(GL_DRIVER_LOADING_TIME_1);
+    std::vector<int64_t> vkDriverLoadingTime;
+    vkDriverLoadingTime.emplace_back(VK_DRIVER_LOADING_TIME_0);
+    vkDriverLoadingTime.emplace_back(VK_DRIVER_LOADING_TIME_1);
+    vkDriverLoadingTime.emplace_back(VK_DRIVER_LOADING_TIME_2);
+    EXPECT_TRUE(event->write(int64VectorToProtoByteString(glDriverLoadingTime)));
+    EXPECT_TRUE(event->write(int64VectorToProtoByteString(vkDriverLoadingTime)));
+    event->init();
+    inData.emplace_back(event);
+    MockGpuStatsPuller mockPuller(android::util::GPU_STATS_APP_INFO, &inData);
+    mockPuller.ForceClearCache();
+    mockPuller.Pull(&outData);
+
+    ASSERT_EQ(1, outData.size());
+    EXPECT_EQ(android::util::GPU_STATS_APP_INFO, outData[0]->GetTagId());
+    ASSERT_EQ(NUMBER_OF_VALUES_APP, outData[0]->size());
+    EXPECT_EQ(APP_PACKAGE_NAME, outData[0]->getValues()[0].mValue.str_value);
+    EXPECT_EQ(DRIVER_VERSION_CODE, outData[0]->getValues()[1].mValue.long_value);
+    EXPECT_EQ(int64VectorToProtoByteString(glDriverLoadingTime),
+              outData[0]->getValues()[2].mValue.str_value);
+    EXPECT_EQ(int64VectorToProtoByteString(vkDriverLoadingTime),
+              outData[0]->getValues()[3].mValue.str_value);
+}
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
+#else
+GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index e5e4534..90b9e81 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -2500,6 +2500,37 @@
     EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
 }
 
+TEST(ValueMetricProducerTest, TestFullBucketResetWhenLastBucketInvalid) {
+    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+
+    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+            // Initialization.
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
+                return true;
+            }))
+            // notifyAppUpgrade.
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                data->push_back(ValueMetricProducerTestHelper::createEvent(
+                        bucketStartTimeNs + bucketSizeNs / 2, 10));
+                return true;
+            }));
+    sp<ValueMetricProducer> valueProducer =
+            ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+    ASSERT_EQ(0UL, valueProducer->mCurrentFullBucket.size());
+
+    valueProducer->notifyAppUpgrade(bucketStartTimeNs + bucketSizeNs / 2, "com.foo", 10000, 1);
+    ASSERT_EQ(1UL, valueProducer->mCurrentFullBucket.size());
+
+    vector<shared_ptr<LogEvent>> allData;
+    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs + 1, 4));
+    valueProducer->onDataPulled(allData, /** fails */ false, bucket3StartTimeNs + 1);
+    ASSERT_EQ(0UL, valueProducer->mCurrentFullBucket.size());
+}
+
 TEST(ValueMetricProducerTest, TestBucketBoundariesOnConditionChange) {
     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index ff8dec1..b3f0037 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -278,227 +278,16 @@
 Landroid/net/wifi/IWifiScanner$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/wifi/IWifiScanner;
 Landroid/net/wifi/p2p/IWifiP2pManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/wifi/p2p/IWifiP2pManager;
 Landroid/nfc/INfcAdapter$Stub;->TRANSACTION_enable:I
-Landroid/os/AsyncResult;-><init>(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Throwable;)V
-Landroid/os/AsyncResult;->exception:Ljava/lang/Throwable;
-Landroid/os/AsyncResult;->forMessage(Landroid/os/Message;)Landroid/os/AsyncResult;
-Landroid/os/AsyncResult;->forMessage(Landroid/os/Message;Ljava/lang/Object;Ljava/lang/Throwable;)Landroid/os/AsyncResult;
-Landroid/os/AsyncResult;->result:Ljava/lang/Object;
-Landroid/os/AsyncResult;->userObj:Ljava/lang/Object;
-Landroid/os/AsyncTask;->mFuture:Ljava/util/concurrent/FutureTask;
-Landroid/os/AsyncTask;->mStatus:Landroid/os/AsyncTask$Status;
-Landroid/os/AsyncTask;->mTaskInvoked:Ljava/util/concurrent/atomic/AtomicBoolean;
-Landroid/os/AsyncTask;->mWorker:Landroid/os/AsyncTask$WorkerRunnable;
-Landroid/os/AsyncTask;->sDefaultExecutor:Ljava/util/concurrent/Executor;
-Landroid/os/AsyncTask;->setDefaultExecutor(Ljava/util/concurrent/Executor;)V
-Landroid/os/BaseBundle;->isParcelled()Z
-Landroid/os/BaseBundle;->mMap:Landroid/util/ArrayMap;
-Landroid/os/BaseBundle;->mParcelledData:Landroid/os/Parcel;
-Landroid/os/BaseBundle;->unparcel()V
-Landroid/os/BatteryManager;->EXTRA_CHARGE_COUNTER:Ljava/lang/String;
-Landroid/os/BatteryManager;->EXTRA_INVALID_CHARGER:Ljava/lang/String;
-Landroid/os/BatteryManager;->EXTRA_MAX_CHARGING_CURRENT:Ljava/lang/String;
-Landroid/os/BatteryManager;->EXTRA_MAX_CHARGING_VOLTAGE:Ljava/lang/String;
-Landroid/os/BatteryStats$Counter;->getCountLocked(I)I
-Landroid/os/BatteryStats$HistoryItem;-><init>()V
-Landroid/os/BatteryStats$HistoryItem;->batteryHealth:B
-Landroid/os/BatteryStats$HistoryItem;->batteryLevel:B
-Landroid/os/BatteryStats$HistoryItem;->batteryPlugType:B
-Landroid/os/BatteryStats$HistoryItem;->batteryStatus:B
-Landroid/os/BatteryStats$HistoryItem;->batteryVoltage:C
-Landroid/os/BatteryStats$HistoryItem;->cmd:B
-Landroid/os/BatteryStats$HistoryItem;->CMD_UPDATE:B
-Landroid/os/BatteryStats$HistoryItem;->states2:I
-Landroid/os/BatteryStats$HistoryItem;->states:I
-Landroid/os/BatteryStats$HistoryItem;->time:J
-Landroid/os/BatteryStats$Timer;->getCountLocked(I)I
-Landroid/os/BatteryStats$Timer;->getTotalTimeLocked(JI)J
-Landroid/os/BatteryStats$Uid$Pkg$Serv;->getLaunches(I)I
-Landroid/os/BatteryStats$Uid$Pkg$Serv;->getStarts(I)I
-Landroid/os/BatteryStats$Uid$Pkg$Serv;->getStartTime(JI)J
-Landroid/os/BatteryStats$Uid$Pkg;->getServiceStats()Landroid/util/ArrayMap;
-Landroid/os/BatteryStats$Uid$Pkg;->getWakeupAlarmStats()Landroid/util/ArrayMap;
 Landroid/os/BatteryStats$Uid$Proc$ExcessivePower;-><init>()V
-Landroid/os/BatteryStats$Uid$Proc$ExcessivePower;->overTime:J
-Landroid/os/BatteryStats$Uid$Proc$ExcessivePower;->type:I
-Landroid/os/BatteryStats$Uid$Proc$ExcessivePower;->usedTime:J
-Landroid/os/BatteryStats$Uid$Proc;->countExcessivePowers()I
-Landroid/os/BatteryStats$Uid$Proc;->getExcessivePower(I)Landroid/os/BatteryStats$Uid$Proc$ExcessivePower;
-Landroid/os/BatteryStats$Uid$Proc;->getForegroundTime(I)J
-Landroid/os/BatteryStats$Uid$Proc;->getStarts(I)I
-Landroid/os/BatteryStats$Uid$Proc;->getSystemTime(I)J
-Landroid/os/BatteryStats$Uid$Proc;->getUserTime(I)J
-Landroid/os/BatteryStats$Uid$Sensor;->getHandle()I
-Landroid/os/BatteryStats$Uid$Sensor;->getSensorTime()Landroid/os/BatteryStats$Timer;
-Landroid/os/BatteryStats$Uid$Sensor;->GPS:I
-Landroid/os/BatteryStats$Uid$Wakelock;->getWakeTime(I)Landroid/os/BatteryStats$Timer;
 Landroid/os/BatteryStats$Uid;-><init>()V
-Landroid/os/BatteryStats$Uid;->getAudioTurnedOnTimer()Landroid/os/BatteryStats$Timer;
-Landroid/os/BatteryStats$Uid;->getFullWifiLockTime(JI)J
-Landroid/os/BatteryStats$Uid;->getMobileRadioActiveTime(I)J
-Landroid/os/BatteryStats$Uid;->getNetworkActivityBytes(II)J
-Landroid/os/BatteryStats$Uid;->getPackageStats()Landroid/util/ArrayMap;
-Landroid/os/BatteryStats$Uid;->getProcessStats()Landroid/util/ArrayMap;
-Landroid/os/BatteryStats$Uid;->getSensorStats()Landroid/util/SparseArray;
-Landroid/os/BatteryStats$Uid;->getUid()I
-Landroid/os/BatteryStats$Uid;->getVideoTurnedOnTimer()Landroid/os/BatteryStats$Timer;
-Landroid/os/BatteryStats$Uid;->getWakelockStats()Landroid/util/ArrayMap;
-Landroid/os/BatteryStats$Uid;->getWifiBatchedScanTime(IJI)J
-Landroid/os/BatteryStats$Uid;->getWifiMulticastTime(JI)J
-Landroid/os/BatteryStats$Uid;->getWifiRunningTime(JI)J
-Landroid/os/BatteryStats$Uid;->getWifiScanTime(JI)J
-Landroid/os/BatteryStats;->computeBatteryRealtime(JI)J
-Landroid/os/BatteryStats;->computeBatteryTimeRemaining(J)J
-Landroid/os/BatteryStats;->computeBatteryUptime(JI)J
-Landroid/os/BatteryStats;->computeChargeTimeRemaining(J)J
-Landroid/os/BatteryStats;->dumpLine(Ljava/io/PrintWriter;ILjava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V
-Landroid/os/BatteryStats;->getBatteryUptime(J)J
-Landroid/os/BatteryStats;->getGlobalWifiRunningTime(JI)J
-Landroid/os/BatteryStats;->getNextHistoryLocked(Landroid/os/BatteryStats$HistoryItem;)Z
-Landroid/os/BatteryStats;->getPhoneOnTime(JI)J
-Landroid/os/BatteryStats;->getPhoneSignalStrengthTime(IJI)J
-Landroid/os/BatteryStats;->getScreenBrightnessTime(IJI)J
-Landroid/os/BatteryStats;->getScreenOnTime(JI)J
-Landroid/os/BatteryStats;->getUidStats()Landroid/util/SparseArray;
-Landroid/os/BatteryStats;->getWifiOnTime(JI)J
-Landroid/os/BatteryStats;->NUM_DATA_CONNECTION_TYPES:I
-Landroid/os/BatteryStats;->NUM_SCREEN_BRIGHTNESS_BINS:I
-Landroid/os/BatteryStats;->startIteratingHistoryLocked()Z
-Landroid/os/BatteryStats;->STATS_CURRENT:I
-Landroid/os/BatteryStats;->WAKE_TYPE_PARTIAL:I
-Landroid/os/Binder;->execTransact(IJJI)Z
-Landroid/os/Binder;->mObject:J
-Landroid/os/Broadcaster;-><init>()V
-Landroid/os/Broadcaster;->broadcast(Landroid/os/Message;)V
-Landroid/os/Broadcaster;->cancelRequest(ILandroid/os/Handler;I)V
-Landroid/os/Broadcaster;->request(ILandroid/os/Handler;I)V
-Landroid/os/Build$VERSION;->ACTIVE_CODENAMES:[Ljava/lang/String;
-Landroid/os/Build;->getLong(Ljava/lang/String;)J
-Landroid/os/Build;->getString(Ljava/lang/String;)Ljava/lang/String;
-Landroid/os/Build;->IS_DEBUGGABLE:Z
-Landroid/os/Bundle;->filterValues()Landroid/os/Bundle;
-Landroid/os/Bundle;->forPair(Ljava/lang/String;Ljava/lang/String;)Landroid/os/Bundle;
-Landroid/os/Bundle;->getIBinder(Ljava/lang/String;)Landroid/os/IBinder;
-Landroid/os/Bundle;->getSize()I
-Landroid/os/Bundle;->putIBinder(Ljava/lang/String;Landroid/os/IBinder;)V
-Landroid/os/Bundle;->putParcelableList(Ljava/lang/String;Ljava/util/List;)V
-Landroid/os/Bundle;->setDefusable(Landroid/os/Bundle;Z)Landroid/os/Bundle;
-Landroid/os/Debug$MemoryInfo;->dalvikPrivateClean:I
-Landroid/os/Debug$MemoryInfo;->dalvikRss:I
-Landroid/os/Debug$MemoryInfo;->dalvikSharedClean:I
-Landroid/os/Debug$MemoryInfo;->dalvikSwappablePss:I
-Landroid/os/Debug$MemoryInfo;->dalvikSwappedOut:I
-Landroid/os/Debug$MemoryInfo;->dalvikSwappedOutPss:I
-Landroid/os/Debug$MemoryInfo;->getOtherLabel(I)Ljava/lang/String;
-Landroid/os/Debug$MemoryInfo;->getOtherPrivate(I)I
-Landroid/os/Debug$MemoryInfo;->getOtherPrivateDirty(I)I
-Landroid/os/Debug$MemoryInfo;->getOtherPss(I)I
-Landroid/os/Debug$MemoryInfo;->getOtherSharedDirty(I)I
-Landroid/os/Debug$MemoryInfo;->getSummaryCode()I
-Landroid/os/Debug$MemoryInfo;->getSummaryGraphics()I
-Landroid/os/Debug$MemoryInfo;->getSummaryJavaHeap()I
-Landroid/os/Debug$MemoryInfo;->getSummaryNativeHeap()I
-Landroid/os/Debug$MemoryInfo;->getSummaryPrivateOther()I
-Landroid/os/Debug$MemoryInfo;->getSummaryStack()I
-Landroid/os/Debug$MemoryInfo;->getSummarySystem()I
-Landroid/os/Debug$MemoryInfo;->getTotalUss()I
-Landroid/os/Debug$MemoryInfo;->hasSwappedOutPss:Z
-Landroid/os/Debug$MemoryInfo;->nativePrivateClean:I
-Landroid/os/Debug$MemoryInfo;->nativeRss:I
-Landroid/os/Debug$MemoryInfo;->nativeSharedClean:I
-Landroid/os/Debug$MemoryInfo;->nativeSwappablePss:I
-Landroid/os/Debug$MemoryInfo;->nativeSwappedOut:I
-Landroid/os/Debug$MemoryInfo;->nativeSwappedOutPss:I
-Landroid/os/Debug$MemoryInfo;->NUM_DVK_STATS:I
-Landroid/os/Debug$MemoryInfo;->NUM_OTHER_STATS:I
-Landroid/os/Debug$MemoryInfo;->otherPrivateClean:I
-Landroid/os/Debug$MemoryInfo;->otherRss:I
-Landroid/os/Debug$MemoryInfo;->otherSharedClean:I
-Landroid/os/Debug$MemoryInfo;->otherStats:[I
-Landroid/os/Debug$MemoryInfo;->otherSwappablePss:I
-Landroid/os/Debug$MemoryInfo;->otherSwappedOut:I
-Landroid/os/Debug$MemoryInfo;->otherSwappedOutPss:I
-Landroid/os/Debug;-><init>()V
-Landroid/os/Debug;->countInstancesOfClass(Ljava/lang/Class;)J
-Landroid/os/Debug;->dumpNativeHeap(Ljava/io/FileDescriptor;)V
-Landroid/os/Debug;->dumpReferenceTables()V
-Landroid/os/Debug;->getCaller()Ljava/lang/String;
-Landroid/os/Debug;->getCallers(I)Ljava/lang/String;
-Landroid/os/Debug;->getMemInfo([J)V
-Landroid/os/Debug;->getMemoryInfo(ILandroid/os/Debug$MemoryInfo;)V
-Landroid/os/DropBoxManager;->mService:Lcom/android/internal/os/IDropBoxManagerService;
-Landroid/os/Environment$UserEnvironment;-><init>(I)V
-Landroid/os/Environment$UserEnvironment;->getExternalDirs()[Ljava/io/File;
-Landroid/os/Environment$UserEnvironment;->getExternalStorageDirectory()Ljava/io/File;
-Landroid/os/Environment$UserEnvironment;->getExternalStoragePublicDirectory(Ljava/lang/String;)Ljava/io/File;
-Landroid/os/Environment;->buildExternalStorageAndroidDataDirs()[Ljava/io/File;
-Landroid/os/Environment;->buildExternalStorageAppCacheDirs(Ljava/lang/String;)[Ljava/io/File;
-Landroid/os/Environment;->buildExternalStorageAppDataDirs(Ljava/lang/String;)[Ljava/io/File;
-Landroid/os/Environment;->buildExternalStorageAppFilesDirs(Ljava/lang/String;)[Ljava/io/File;
-Landroid/os/Environment;->buildExternalStorageAppMediaDirs(Ljava/lang/String;)[Ljava/io/File;
-Landroid/os/Environment;->buildExternalStorageAppObbDirs(Ljava/lang/String;)[Ljava/io/File;
-Landroid/os/Environment;->buildPaths([Ljava/io/File;[Ljava/lang/String;)[Ljava/io/File;
-Landroid/os/Environment;->getDataSystemDirectory()Ljava/io/File;
-Landroid/os/Environment;->getLegacyExternalStorageDirectory()Ljava/io/File;
-Landroid/os/Environment;->getLegacyExternalStorageObbDirectory()Ljava/io/File;
-Landroid/os/Environment;->initForCurrentUser()V
-Landroid/os/Environment;->maybeTranslateEmulatedPathToInternal(Ljava/io/File;)Ljava/io/File;
-Landroid/os/Environment;->sCurrentUser:Landroid/os/Environment$UserEnvironment;
-Landroid/os/FileObserver$ObserverThread;->onEvent(IILjava/lang/String;)V
-Landroid/os/FileObserver;->s_observerThread:Landroid/os/FileObserver$ObserverThread;
-Landroid/os/FileUtils;-><init>()V
-Landroid/os/FileUtils;->checksumCrc32(Ljava/io/File;)J
-Landroid/os/FileUtils;->copyFile(Ljava/io/File;Ljava/io/File;)Z
-Landroid/os/FileUtils;->copyToFile(Ljava/io/InputStream;Ljava/io/File;)Z
-Landroid/os/FileUtils;->deleteContents(Ljava/io/File;)Z
-Landroid/os/FileUtils;->deleteOlderFiles(Ljava/io/File;IJ)Z
-Landroid/os/FileUtils;->isFilenameSafe(Ljava/io/File;)Z
-Landroid/os/FileUtils;->readTextFile(Ljava/io/File;ILjava/lang/String;)Ljava/lang/String;
-Landroid/os/FileUtils;->setPermissions(Ljava/io/File;III)I
-Landroid/os/FileUtils;->setPermissions(Ljava/io/FileDescriptor;III)I
-Landroid/os/FileUtils;->setPermissions(Ljava/lang/String;III)I
-Landroid/os/FileUtils;->stringToFile(Ljava/io/File;Ljava/lang/String;)V
-Landroid/os/FileUtils;->stringToFile(Ljava/lang/String;Ljava/lang/String;)V
-Landroid/os/FileUtils;->sync(Ljava/io/FileOutputStream;)Z
-Landroid/os/Handler;-><init>(Landroid/os/Looper;Landroid/os/Handler$Callback;Z)V
-Landroid/os/Handler;-><init>(Z)V
-Landroid/os/Handler;->getIMessenger()Landroid/os/IMessenger;
-Landroid/os/Handler;->getMain()Landroid/os/Handler;
-Landroid/os/Handler;->getPostMessage(Ljava/lang/Runnable;Ljava/lang/Object;)Landroid/os/Message;
-Landroid/os/Handler;->mCallback:Landroid/os/Handler$Callback;
-Landroid/os/Handler;->mLooper:Landroid/os/Looper;
-Landroid/os/Handler;->mMessenger:Landroid/os/IMessenger;
-Landroid/os/HwBinder;->reportSyspropChanged()V
-Landroid/os/HwParcel;-><init>(Z)V
-Landroid/os/HwRemoteBinder;-><init>()V
 Landroid/os/IBatteryPropertiesRegistrar$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/os/IBinder;->SYSPROPS_TRANSACTION:I
 Landroid/os/IDeviceIdentifiersPolicyService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IDeviceIdentifiersPolicyService;
 Landroid/os/IDeviceIdleController$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IDeviceIdleController;
-Landroid/os/IDeviceIdleController;->addPowerSaveTempWhitelistApp(Ljava/lang/String;JILjava/lang/String;)V
 Landroid/os/IDeviceIdleController;->getAppIdTempWhitelist()[I
 Landroid/os/IDeviceIdleController;->getFullPowerWhitelistExceptIdle()[Ljava/lang/String;
 Landroid/os/INetworkManagementService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/os/INetworkManagementService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/INetworkManagementService;
-Landroid/os/INetworkManagementService;->clearInterfaceAddresses(Ljava/lang/String;)V
-Landroid/os/INetworkManagementService;->disableIpv6(Ljava/lang/String;)V
-Landroid/os/INetworkManagementService;->disableNat(Ljava/lang/String;Ljava/lang/String;)V
-Landroid/os/INetworkManagementService;->enableIpv6(Ljava/lang/String;)V
-Landroid/os/INetworkManagementService;->enableNat(Ljava/lang/String;Ljava/lang/String;)V
-Landroid/os/INetworkManagementService;->getInterfaceConfig(Ljava/lang/String;)Landroid/net/InterfaceConfiguration;
-Landroid/os/INetworkManagementService;->getIpForwardingEnabled()Z
-Landroid/os/INetworkManagementService;->isBandwidthControlEnabled()Z
-Landroid/os/INetworkManagementService;->isTetheringStarted()Z
 Landroid/os/INetworkManagementService;->listTetheredInterfaces()[Ljava/lang/String;
-Landroid/os/INetworkManagementService;->registerObserver(Landroid/net/INetworkManagementEventObserver;)V
-Landroid/os/INetworkManagementService;->setInterfaceConfig(Ljava/lang/String;Landroid/net/InterfaceConfiguration;)V
-Landroid/os/INetworkManagementService;->setInterfaceIpv6PrivacyExtensions(Ljava/lang/String;Z)V
-Landroid/os/INetworkManagementService;->setIpForwardingEnabled(Z)V
-Landroid/os/INetworkManagementService;->setIPv6AddrGenMode(Ljava/lang/String;I)V
-Landroid/os/INetworkManagementService;->startTethering([Ljava/lang/String;)V
-Landroid/os/INetworkManagementService;->stopTethering()V
-Landroid/os/INetworkManagementService;->tetherInterface(Ljava/lang/String;)V
-Landroid/os/INetworkManagementService;->unregisterObserver(Landroid/net/INetworkManagementEventObserver;)V
-Landroid/os/INetworkManagementService;->untetherInterface(Ljava/lang/String;)V
 Landroid/os/IPermissionController$Stub$Proxy;->checkPermission(Ljava/lang/String;II)Z
 Landroid/os/IPermissionController$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IPermissionController;
 Landroid/os/IPowerManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
@@ -506,282 +295,21 @@
 Landroid/os/IPowerManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IPowerManager;
 Landroid/os/IPowerManager$Stub;->TRANSACTION_acquireWakeLock:I
 Landroid/os/IPowerManager$Stub;->TRANSACTION_goToSleep:I
-Landroid/os/IPowerManager;->goToSleep(JII)V
-Landroid/os/IPowerManager;->isInteractive()Z
-Landroid/os/IPowerManager;->reboot(ZLjava/lang/String;Z)V
 Landroid/os/IPowerManager;->releaseWakeLock(Landroid/os/IBinder;I)V
-Landroid/os/IPowerManager;->userActivity(JII)V
 Landroid/os/IRecoverySystem$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IRecoverySystem;
 Landroid/os/IRemoteCallback$Stub;-><init>()V
-Landroid/os/IRemoteCallback;->sendResult(Landroid/os/Bundle;)V
-Landroid/os/IServiceManager;->checkService(Ljava/lang/String;)Landroid/os/IBinder;
-Landroid/os/IServiceManager;->getService(Ljava/lang/String;)Landroid/os/IBinder;
 Landroid/os/IUpdateEngine$Stub;-><init>()V
 Landroid/os/IUpdateEngineCallback;->onStatusUpdate(IF)V
 Landroid/os/IUserManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/os/IUserManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IUserManager;
-Landroid/os/IUserManager;->getUserInfo(I)Landroid/content/pm/UserInfo;
 Landroid/os/IVibratorService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IVibratorService;
-Landroid/os/LocaleList;->setDefault(Landroid/os/LocaleList;I)V
-Landroid/os/Looper;->mLogging:Landroid/util/Printer;
-Landroid/os/Looper;->mQueue:Landroid/os/MessageQueue;
-Landroid/os/Looper;->setTraceTag(J)V
-Landroid/os/Looper;->sMainLooper:Landroid/os/Looper;
-Landroid/os/Looper;->sThreadLocal:Ljava/lang/ThreadLocal;
-Landroid/os/MemoryFile;->deactivate()V
-Landroid/os/MemoryFile;->getFileDescriptor()Ljava/io/FileDescriptor;
-Landroid/os/MemoryFile;->getSize(Ljava/io/FileDescriptor;)I
-Landroid/os/MemoryFile;->native_get_size(Ljava/io/FileDescriptor;)I
-Landroid/os/MemoryFile;->native_pin(Ljava/io/FileDescriptor;Z)Z
-Landroid/os/Message;->callback:Ljava/lang/Runnable;
-Landroid/os/Message;->flags:I
-Landroid/os/Message;->markInUse()V
-Landroid/os/Message;->next:Landroid/os/Message;
-Landroid/os/Message;->recycleUnchecked()V
-Landroid/os/Message;->setCallback(Ljava/lang/Runnable;)Landroid/os/Message;
-Landroid/os/Message;->target:Landroid/os/Handler;
-Landroid/os/Message;->toString(J)Ljava/lang/String;
-Landroid/os/Message;->when:J
-Landroid/os/MessageQueue;->dispatchEvents(II)I
-Landroid/os/MessageQueue;->hasMessages(Landroid/os/Handler;Ljava/lang/Runnable;Ljava/lang/Object;)Z
-Landroid/os/MessageQueue;->mIdleHandlers:Ljava/util/ArrayList;
-Landroid/os/MessageQueue;->mMessages:Landroid/os/Message;
-Landroid/os/MessageQueue;->mNextBarrierToken:I
-Landroid/os/MessageQueue;->mPtr:J
-Landroid/os/MessageQueue;->mQuitAllowed:Z
-Landroid/os/MessageQueue;->nativePollOnce(JI)V
-Landroid/os/MessageQueue;->next()Landroid/os/Message;
 Landroid/os/Parcel$ReadWriteHelper;-><init>()V
-Landroid/os/Parcel;->getGlobalAllocCount()J
-Landroid/os/Parcel;->getGlobalAllocSize()J
-Landroid/os/Parcel;->mNativePtr:J
-Landroid/os/Parcel;->readArrayMap(Landroid/util/ArrayMap;Ljava/lang/ClassLoader;)V
-Landroid/os/Parcel;->readArraySet(Ljava/lang/ClassLoader;)Landroid/util/ArraySet;
-Landroid/os/Parcel;->readBlob()[B
-Landroid/os/Parcel;->readCharSequence()Ljava/lang/CharSequence;
-Landroid/os/Parcel;->readCreator(Landroid/os/Parcelable$Creator;Ljava/lang/ClassLoader;)Landroid/os/Parcelable;
-Landroid/os/Parcel;->readExceptionCode()I
-Landroid/os/Parcel;->readParcelableCreator(Ljava/lang/ClassLoader;)Landroid/os/Parcelable$Creator;
-Landroid/os/Parcel;->readRawFileDescriptor()Ljava/io/FileDescriptor;
-Landroid/os/Parcel;->readStringArray()[Ljava/lang/String;
-Landroid/os/Parcel;->writeArrayMap(Landroid/util/ArrayMap;)V
-Landroid/os/Parcel;->writeArraySet(Landroid/util/ArraySet;)V
-Landroid/os/Parcel;->writeBlob([B)V
-Landroid/os/Parcel;->writeCharSequence(Ljava/lang/CharSequence;)V
-Landroid/os/Parcel;->writeParcelableCreator(Landroid/os/Parcelable;)V
-Landroid/os/ParcelableParcel;-><init>(Ljava/lang/ClassLoader;)V
-Landroid/os/ParcelableParcel;->CREATOR:Landroid/os/Parcelable$ClassLoaderCreator;
-Landroid/os/ParcelableParcel;->getClassLoader()Ljava/lang/ClassLoader;
-Landroid/os/ParcelableParcel;->getParcel()Landroid/os/Parcel;
-Landroid/os/ParcelFileDescriptor;-><init>(Ljava/io/FileDescriptor;)V
-Landroid/os/ParcelFileDescriptor;->fromData([BLjava/lang/String;)Landroid/os/ParcelFileDescriptor;
-Landroid/os/ParcelFileDescriptor;->seekTo(J)J
-Landroid/os/PerformanceCollector;-><init>()V
-Landroid/os/PerformanceCollector;->beginSnapshot(Ljava/lang/String;)V
-Landroid/os/PerformanceCollector;->endSnapshot()Landroid/os/Bundle;
-Landroid/os/PerformanceCollector;->startTiming(Ljava/lang/String;)V
-Landroid/os/PerformanceCollector;->stopTiming(Ljava/lang/String;)Landroid/os/Bundle;
-Landroid/os/PowerManager$WakeLock;->mFlags:I
-Landroid/os/PowerManager$WakeLock;->mTag:Ljava/lang/String;
-Landroid/os/PowerManager;->ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED:Ljava/lang/String;
-Landroid/os/PowerManager;->ACTION_POWER_SAVE_MODE_CHANGING:Ljava/lang/String;
-Landroid/os/PowerManager;->BRIGHTNESS_ON:I
-Landroid/os/PowerManager;->EXTRA_POWER_SAVE_MODE:Ljava/lang/String;
-Landroid/os/PowerManager;->getDefaultScreenBrightnessSetting()I
-Landroid/os/PowerManager;->getMaximumScreenBrightnessSetting()I
-Landroid/os/PowerManager;->getMinimumScreenBrightnessSetting()I
-Landroid/os/PowerManager;->goToSleep(JII)V
-Landroid/os/PowerManager;->GO_TO_SLEEP_REASON_TIMEOUT:I
-Landroid/os/PowerManager;->isLightDeviceIdleMode()Z
-Landroid/os/PowerManager;->mService:Landroid/os/IPowerManager;
-Landroid/os/PowerManager;->validateWakeLockParameters(ILjava/lang/String;)V
-Landroid/os/PowerManager;->wakeUp(JLjava/lang/String;)V
-Landroid/os/Process;->DRM_UID:I
-Landroid/os/Process;->getFreeMemory()J
-Landroid/os/Process;->getParentPid(I)I
-Landroid/os/Process;->getPids(Ljava/lang/String;[I)[I
-Landroid/os/Process;->getPidsForCommands([Ljava/lang/String;)[I
-Landroid/os/Process;->getPss(I)J
-Landroid/os/Process;->getTotalMemory()J
-Landroid/os/Process;->getUidForPid(I)I
-Landroid/os/Process;->isIsolated(I)Z
-Landroid/os/Process;->LOG_UID:I
-Landroid/os/Process;->MEDIA_UID:I
-Landroid/os/Process;->myPpid()I
-Landroid/os/Process;->NFC_UID:I
-Landroid/os/Process;->parseProcLine([BII[I[Ljava/lang/String;[J[F)Z
-Landroid/os/Process;->PROC_COMBINE:I
-Landroid/os/Process;->PROC_OUT_FLOAT:I
-Landroid/os/Process;->PROC_OUT_LONG:I
-Landroid/os/Process;->PROC_OUT_STRING:I
-Landroid/os/Process;->PROC_PARENS:I
-Landroid/os/Process;->PROC_QUOTES:I
-Landroid/os/Process;->PROC_SPACE_TERM:I
-Landroid/os/Process;->PROC_TAB_TERM:I
-Landroid/os/Process;->PROC_TERM_MASK:I
-Landroid/os/Process;->PROC_ZERO_TERM:I
-Landroid/os/Process;->readProcFile(Ljava/lang/String;[I[Ljava/lang/String;[J[F)Z
-Landroid/os/Process;->readProcLines(Ljava/lang/String;[Ljava/lang/String;[J)V
-Landroid/os/Process;->setArgV0(Ljava/lang/String;)V
-Landroid/os/Process;->setProcessGroup(II)V
-Landroid/os/Process;->VPN_UID:I
-Landroid/os/Process;->WIFI_UID:I
-Landroid/os/RecoverySystem;->verifyPackageCompatibility(Ljava/io/InputStream;)Z
-Landroid/os/Registrant;-><init>(Landroid/os/Handler;ILjava/lang/Object;)V
-Landroid/os/Registrant;->clear()V
-Landroid/os/Registrant;->messageForRegistrant()Landroid/os/Message;
-Landroid/os/Registrant;->notifyRegistrant()V
-Landroid/os/Registrant;->notifyRegistrant(Landroid/os/AsyncResult;)V
-Landroid/os/Registrant;->notifyResult(Ljava/lang/Object;)V
 Landroid/os/RegistrantList;-><init>()V
-Landroid/os/RegistrantList;->add(Landroid/os/Handler;ILjava/lang/Object;)V
-Landroid/os/RegistrantList;->add(Landroid/os/Registrant;)V
-Landroid/os/RegistrantList;->addUnique(Landroid/os/Handler;ILjava/lang/Object;)V
-Landroid/os/RegistrantList;->notifyRegistrants()V
-Landroid/os/RegistrantList;->notifyRegistrants(Landroid/os/AsyncResult;)V
-Landroid/os/RegistrantList;->notifyResult(Ljava/lang/Object;)V
-Landroid/os/RegistrantList;->remove(Landroid/os/Handler;)V
-Landroid/os/RegistrantList;->removeCleared()V
-Landroid/os/RegistrantList;->size()I
-Landroid/os/RemoteCallbackList;->mCallbacks:Landroid/util/ArrayMap;
-Landroid/os/RemoteException;->rethrowFromSystemServer()Ljava/lang/RuntimeException;
-Landroid/os/SELinux;->checkSELinuxAccess(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z
-Landroid/os/SELinux;->getContext()Ljava/lang/String;
-Landroid/os/SELinux;->getFileContext(Ljava/lang/String;)Ljava/lang/String;
-Landroid/os/SELinux;->getPidContext(I)Ljava/lang/String;
-Landroid/os/SELinux;->isSELinuxEnabled()Z
-Landroid/os/SELinux;->isSELinuxEnforced()Z
-Landroid/os/SELinux;->restoreconRecursive(Ljava/io/File;)Z
 Landroid/os/ServiceManager;-><init>()V
-Landroid/os/ServiceManager;->addService(Ljava/lang/String;Landroid/os/IBinder;)V
-Landroid/os/ServiceManager;->addService(Ljava/lang/String;Landroid/os/IBinder;Z)V
-Landroid/os/ServiceManager;->addService(Ljava/lang/String;Landroid/os/IBinder;ZI)V
-Landroid/os/ServiceManager;->checkService(Ljava/lang/String;)Landroid/os/IBinder;
-Landroid/os/ServiceManager;->getIServiceManager()Landroid/os/IServiceManager;
-Landroid/os/ServiceManager;->getService(Ljava/lang/String;)Landroid/os/IBinder;
-Landroid/os/ServiceManager;->listServices()[Ljava/lang/String;
-Landroid/os/ServiceManager;->sCache:Ljava/util/Map;
-Landroid/os/ServiceManager;->sServiceManager:Landroid/os/IServiceManager;
-Landroid/os/ServiceManagerNative;->asInterface(Landroid/os/IBinder;)Landroid/os/IServiceManager;
-Landroid/os/ServiceManagerProxy;->getService(Ljava/lang/String;)Landroid/os/IBinder;
-Landroid/os/ServiceManagerProxy;->mRemote:Landroid/os/IBinder;
-Landroid/os/SharedMemory;->getFd()I
-Landroid/os/ShellCommand;->peekNextArg()Ljava/lang/String;
-Landroid/os/StatFs;->mStat:Landroid/system/StructStatVfs;
 Landroid/os/storage/IObbActionListener$Stub;-><init>()V
 Landroid/os/storage/IStorageManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/os/storage/IStorageManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/storage/IStorageManager;
 Landroid/os/storage/StorageEventListener;-><init>()V
-Landroid/os/StrictMode$Span;->finish()V
-Landroid/os/StrictMode$ThreadPolicy;->mask:I
-Landroid/os/StrictMode$VmPolicy$Builder;->mMask:I
-Landroid/os/StrictMode$VmPolicy;->mask:I
-Landroid/os/StrictMode;->disableDeathOnFileUriExposure()V
-Landroid/os/StrictMode;->enableDeathOnFileUriExposure()V
-Landroid/os/StrictMode;->enterCriticalSpan(Ljava/lang/String;)Landroid/os/StrictMode$Span;
-Landroid/os/StrictMode;->getThreadPolicyMask()I
-Landroid/os/StrictMode;->incrementExpectedActivityCount(Ljava/lang/Class;)V
-Landroid/os/StrictMode;->onBinderStrictModePolicyChange(I)V
-Landroid/os/StrictMode;->onWebViewMethodCalledOnWrongThread(Ljava/lang/Throwable;)V
-Landroid/os/StrictMode;->sLastVmViolationTime:Ljava/util/HashMap;
-Landroid/os/StrictMode;->sWindowManager:Landroid/util/Singleton;
-Landroid/os/StrictMode;->violationsBeingTimed:Ljava/lang/ThreadLocal;
-Landroid/os/SystemClock;-><init>()V
-Landroid/os/SystemClock;->currentThreadTimeMicro()J
-Landroid/os/SystemClock;->currentTimeMicro()J
-Landroid/os/SystemProperties;-><init>()V
-Landroid/os/SystemProperties;->addChangeCallback(Ljava/lang/Runnable;)V
-Landroid/os/SystemProperties;->native_get(Ljava/lang/String;)Ljava/lang/String;
-Landroid/os/SystemProperties;->native_get_long(Ljava/lang/String;J)J
-Landroid/os/SystemProperties;->PROP_NAME_MAX:I
-Landroid/os/SystemProperties;->reportSyspropChanged()V
-Landroid/os/SystemProperties;->sChangeCallbacks:Ljava/util/ArrayList;
-Landroid/os/SystemProperties;->set(Ljava/lang/String;Ljava/lang/String;)V
-Landroid/os/SystemService;->start(Ljava/lang/String;)V
-Landroid/os/SystemService;->stop(Ljava/lang/String;)V
-Landroid/os/SystemVibrator;-><init>()V
-Landroid/os/SystemVibrator;-><init>(Landroid/content/Context;)V
-Landroid/os/Trace;->asyncTraceBegin(JLjava/lang/String;I)V
-Landroid/os/Trace;->asyncTraceEnd(JLjava/lang/String;I)V
-Landroid/os/Trace;->isTagEnabled(J)Z
-Landroid/os/Trace;->nativeGetEnabledTags()J
-Landroid/os/Trace;->sEnabledTags:J
-Landroid/os/Trace;->setAppTracingAllowed(Z)V
-Landroid/os/Trace;->traceBegin(JLjava/lang/String;)V
-Landroid/os/Trace;->traceCounter(JLjava/lang/String;I)V
-Landroid/os/Trace;->traceEnd(J)V
-Landroid/os/Trace;->TRACE_TAG_APP:J
-Landroid/os/Trace;->TRACE_TAG_VIEW:J
-Landroid/os/UEventObserver$UEvent;->get(Ljava/lang/String;)Ljava/lang/String;
-Landroid/os/UEventObserver$UEvent;->get(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
-Landroid/os/UEventObserver;-><init>()V
-Landroid/os/UEventObserver;->onUEvent(Landroid/os/UEventObserver$UEvent;)V
-Landroid/os/UEventObserver;->startObserving(Ljava/lang/String;)V
-Landroid/os/UEventObserver;->stopObserving()V
-Landroid/os/UpdateLock;->acquire()V
-Landroid/os/UpdateLock;->isHeld()Z
-Landroid/os/UpdateLock;->NOW_IS_CONVENIENT:Ljava/lang/String;
-Landroid/os/UpdateLock;->release()V
-Landroid/os/UpdateLock;->TIMESTAMP:Ljava/lang/String;
-Landroid/os/UpdateLock;->UPDATE_LOCK_CHANGED:Ljava/lang/String;
-Landroid/os/UserHandle;-><init>(I)V
-Landroid/os/UserHandle;->AID_APP_END:I
-Landroid/os/UserHandle;->AID_APP_START:I
-Landroid/os/UserHandle;->AID_CACHE_GID_START:I
-Landroid/os/UserHandle;->AID_ROOT:I
-Landroid/os/UserHandle;->AID_SHARED_GID_START:I
-Landroid/os/UserHandle;->CURRENT_OR_SELF:Landroid/os/UserHandle;
-Landroid/os/UserHandle;->ERR_GID:I
-Landroid/os/UserHandle;->getAppIdFromSharedAppGid(I)I
-Landroid/os/UserHandle;->getCallingUserId()I
-Landroid/os/UserHandle;->getUid(II)I
-Landroid/os/UserHandle;->getUserId(I)I
-Landroid/os/UserHandle;->isIsolated(I)Z
-Landroid/os/UserHandle;->isSameApp(II)Z
-Landroid/os/UserHandle;->mHandle:I
-Landroid/os/UserHandle;->MU_ENABLED:Z
-Landroid/os/UserHandle;->OWNER:Landroid/os/UserHandle;
-Landroid/os/UserHandle;->PER_USER_RANGE:I
-Landroid/os/UserHandle;->USER_ALL:I
-Landroid/os/UserHandle;->USER_CURRENT:I
-Landroid/os/UserHandle;->USER_CURRENT_OR_SELF:I
-Landroid/os/UserHandle;->USER_OWNER:I
-Landroid/os/UserHandle;->USER_SERIAL_SYSTEM:I
-Landroid/os/UserHandle;->USER_SYSTEM:I
-Landroid/os/UserManager;->createProfileForUser(Ljava/lang/String;II)Landroid/content/pm/UserInfo;
-Landroid/os/UserManager;->createUser(Ljava/lang/String;I)Landroid/content/pm/UserInfo;
-Landroid/os/UserManager;->DISALLOW_RECORD_AUDIO:Ljava/lang/String;
-Landroid/os/UserManager;->get(Landroid/content/Context;)Landroid/os/UserManager;
-Landroid/os/UserManager;->getEnabledProfiles(I)Ljava/util/List;
-Landroid/os/UserManager;->getMaxSupportedUsers()I
-Landroid/os/UserManager;->getProfileIdsWithDisabled(I)[I
-Landroid/os/UserManager;->getProfileParent(I)Landroid/content/pm/UserInfo;
-Landroid/os/UserManager;->getProfiles(I)Ljava/util/List;
-Landroid/os/UserManager;->getUserHandle()I
-Landroid/os/UserManager;->getUserHandle(I)I
-Landroid/os/UserManager;->getUserIcon(I)Landroid/graphics/Bitmap;
-Landroid/os/UserManager;->getUserInfo(I)Landroid/content/pm/UserInfo;
-Landroid/os/UserManager;->getUsers()Ljava/util/List;
-Landroid/os/UserManager;->getUsers(Z)Ljava/util/List;
-Landroid/os/UserManager;->getUserSerialNumber(I)I
-Landroid/os/UserManager;->getUserStartRealtime()J
-Landroid/os/UserManager;->getUserUnlockRealtime()J
-Landroid/os/UserManager;->hasBaseUserRestriction(Ljava/lang/String;Landroid/os/UserHandle;)Z
-Landroid/os/UserManager;->hasUserRestriction(Ljava/lang/String;Landroid/os/UserHandle;)Z
-Landroid/os/UserManager;->isDeviceInDemoMode(Landroid/content/Context;)Z
-Landroid/os/UserManager;->isGuestUser(I)Z
-Landroid/os/UserManager;->isLinkedUser()Z
-Landroid/os/UserManager;->isUserAdmin(I)Z
-Landroid/os/UserManager;->isUserUnlocked(I)Z
-Landroid/os/UserManager;->mService:Landroid/os/IUserManager;
-Landroid/os/UserManager;->removeUser(I)Z
-Landroid/os/Vibrator;-><init>()V
-Landroid/os/WorkSource;-><init>(Landroid/os/Parcel;)V
-Landroid/os/WorkSource;->mNames:[Ljava/lang/String;
-Landroid/os/WorkSource;->mNum:I
-Landroid/os/WorkSource;->mUids:[I
-Landroid/os/ZygoteStartFailedEx;-><init>(Ljava/lang/String;)V
-Landroid/os/ZygoteStartFailedEx;-><init>(Ljava/lang/Throwable;)V
 Landroid/preference/PreferenceGroupAdapter;->getItem(I)Landroid/preference/Preference;
 Landroid/R$styleable;->ActionBar:[I
 Landroid/R$styleable;->ActionBar_background:I
@@ -1756,48 +1284,6 @@
 Lcom/android/internal/statusbar/IStatusBarService$Stub;-><init>()V
 Lcom/android/internal/statusbar/IStatusBarService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/statusbar/IStatusBarService;
 Lcom/android/internal/telecom/ITelecomService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telecom/ITelecomService;
-Lcom/android/internal/telephony/BaseCommands;->mCallStateRegistrants:Landroid/os/RegistrantList;
-Lcom/android/internal/telephony/BaseCommands;->mCallWaitingInfoRegistrants:Landroid/os/RegistrantList;
-Lcom/android/internal/telephony/BaseCommands;->mCatCallSetUpRegistrant:Landroid/os/Registrant;
-Lcom/android/internal/telephony/BaseCommands;->mCatCcAlphaRegistrant:Landroid/os/Registrant;
-Lcom/android/internal/telephony/BaseCommands;->mCatEventRegistrant:Landroid/os/Registrant;
-Lcom/android/internal/telephony/BaseCommands;->mCatProCmdRegistrant:Landroid/os/Registrant;
-Lcom/android/internal/telephony/BaseCommands;->mCatSessionEndRegistrant:Landroid/os/Registrant;
-Lcom/android/internal/telephony/BaseCommands;->mCdmaPrlChangedRegistrants:Landroid/os/RegistrantList;
-Lcom/android/internal/telephony/BaseCommands;->mCdmaSmsRegistrant:Landroid/os/Registrant;
-Lcom/android/internal/telephony/BaseCommands;->mCdmaSubscriptionChangedRegistrants:Landroid/os/RegistrantList;
-Lcom/android/internal/telephony/BaseCommands;->mContext:Landroid/content/Context;
-Lcom/android/internal/telephony/BaseCommands;->mEmergencyCallbackModeRegistrant:Landroid/os/Registrant;
-Lcom/android/internal/telephony/BaseCommands;->mExitEmergencyCallbackModeRegistrants:Landroid/os/RegistrantList;
-Lcom/android/internal/telephony/BaseCommands;->mGsmBroadcastSmsRegistrant:Landroid/os/Registrant;
-Lcom/android/internal/telephony/BaseCommands;->mGsmSmsRegistrant:Landroid/os/Registrant;
-Lcom/android/internal/telephony/BaseCommands;->mHardwareConfigChangeRegistrants:Landroid/os/RegistrantList;
-Lcom/android/internal/telephony/BaseCommands;->mIccRefreshRegistrants:Landroid/os/RegistrantList;
-Lcom/android/internal/telephony/BaseCommands;->mIccSmsFullRegistrant:Landroid/os/Registrant;
-Lcom/android/internal/telephony/BaseCommands;->mIccStatusChangedRegistrants:Landroid/os/RegistrantList;
-Lcom/android/internal/telephony/BaseCommands;->mImsNetworkStateChangedRegistrants:Landroid/os/RegistrantList;
-Lcom/android/internal/telephony/BaseCommands;->mNITZTimeRegistrant:Landroid/os/Registrant;
-Lcom/android/internal/telephony/BaseCommands;->mOtaProvisionRegistrants:Landroid/os/RegistrantList;
-Lcom/android/internal/telephony/BaseCommands;->mPhoneRadioCapabilityChangedRegistrants:Landroid/os/RegistrantList;
-Lcom/android/internal/telephony/BaseCommands;->mPhoneType:I
-Lcom/android/internal/telephony/BaseCommands;->mPreferredNetworkType:I
-Lcom/android/internal/telephony/BaseCommands;->mResendIncallMuteRegistrants:Landroid/os/RegistrantList;
-Lcom/android/internal/telephony/BaseCommands;->mRestrictedStateRegistrant:Landroid/os/Registrant;
-Lcom/android/internal/telephony/BaseCommands;->mRilCellInfoListRegistrants:Landroid/os/RegistrantList;
-Lcom/android/internal/telephony/BaseCommands;->mRingbackToneRegistrants:Landroid/os/RegistrantList;
-Lcom/android/internal/telephony/BaseCommands;->mRingRegistrant:Landroid/os/Registrant;
-Lcom/android/internal/telephony/BaseCommands;->mSignalStrengthRegistrant:Landroid/os/Registrant;
-Lcom/android/internal/telephony/BaseCommands;->mSmsOnSimRegistrant:Landroid/os/Registrant;
-Lcom/android/internal/telephony/BaseCommands;->mSmsStatusRegistrant:Landroid/os/Registrant;
-Lcom/android/internal/telephony/BaseCommands;->mSrvccStateRegistrants:Landroid/os/RegistrantList;
-Lcom/android/internal/telephony/BaseCommands;->mSsnRegistrant:Landroid/os/Registrant;
-Lcom/android/internal/telephony/BaseCommands;->mSsRegistrant:Landroid/os/Registrant;
-Lcom/android/internal/telephony/BaseCommands;->mStateMonitor:Ljava/lang/Object;
-Lcom/android/internal/telephony/BaseCommands;->mSubscriptionStatusRegistrants:Landroid/os/RegistrantList;
-Lcom/android/internal/telephony/BaseCommands;->mUnsolOemHookRawRegistrant:Landroid/os/Registrant;
-Lcom/android/internal/telephony/BaseCommands;->mUSSDRegistrant:Landroid/os/Registrant;
-Lcom/android/internal/telephony/BaseCommands;->mVoiceRadioTechChangedRegistrants:Landroid/os/RegistrantList;
-Lcom/android/internal/telephony/Call$State;->ACTIVE:Lcom/android/internal/telephony/Call$State;
 Lcom/android/internal/telephony/Call$State;->ALERTING:Lcom/android/internal/telephony/Call$State;
 Lcom/android/internal/telephony/Call$State;->DIALING:Lcom/android/internal/telephony/Call$State;
 Lcom/android/internal/telephony/Call$State;->DISCONNECTED:Lcom/android/internal/telephony/Call$State;
@@ -1805,232 +1291,22 @@
 Lcom/android/internal/telephony/Call$State;->HOLDING:Lcom/android/internal/telephony/Call$State;
 Lcom/android/internal/telephony/Call$State;->IDLE:Lcom/android/internal/telephony/Call$State;
 Lcom/android/internal/telephony/Call$State;->INCOMING:Lcom/android/internal/telephony/Call$State;
-Lcom/android/internal/telephony/Call$State;->isAlive()Z
-Lcom/android/internal/telephony/Call$State;->isRinging()Z
 Lcom/android/internal/telephony/Call$State;->values()[Lcom/android/internal/telephony/Call$State;
 Lcom/android/internal/telephony/Call$State;->WAITING:Lcom/android/internal/telephony/Call$State;
 Lcom/android/internal/telephony/Call;-><init>()V
-Lcom/android/internal/telephony/Call;->getConnections()Ljava/util/List;
-Lcom/android/internal/telephony/Call;->getEarliestConnection()Lcom/android/internal/telephony/Connection;
-Lcom/android/internal/telephony/Call;->getLatestConnection()Lcom/android/internal/telephony/Connection;
-Lcom/android/internal/telephony/Call;->getPhone()Lcom/android/internal/telephony/Phone;
-Lcom/android/internal/telephony/Call;->getState()Lcom/android/internal/telephony/Call$State;
-Lcom/android/internal/telephony/Call;->hangup()V
-Lcom/android/internal/telephony/Call;->isIdle()Z
-Lcom/android/internal/telephony/Call;->isMultiparty()Z
-Lcom/android/internal/telephony/Call;->mConnections:Ljava/util/ArrayList;
-Lcom/android/internal/telephony/Call;->mState:Lcom/android/internal/telephony/Call$State;
 Lcom/android/internal/telephony/CallerInfoAsyncQuery$CallerInfoAsyncQueryHandler;-><init>(Lcom/android/internal/telephony/CallerInfoAsyncQuery;Landroid/content/Context;)V
 Lcom/android/internal/telephony/CallerInfoAsyncQuery$CookieWrapper;-><init>()V
 Lcom/android/internal/telephony/CallerInfoAsyncQuery;->release()V
 Lcom/android/internal/telephony/CallForwardInfo;-><init>()V
-Lcom/android/internal/telephony/CallForwardInfo;->number:Ljava/lang/String;
-Lcom/android/internal/telephony/CallForwardInfo;->reason:I
-Lcom/android/internal/telephony/CallForwardInfo;->serviceClass:I
-Lcom/android/internal/telephony/CallForwardInfo;->status:I
-Lcom/android/internal/telephony/CallForwardInfo;->timeSeconds:I
-Lcom/android/internal/telephony/CallForwardInfo;->toa:I
-Lcom/android/internal/telephony/CallManager;->canConference(Lcom/android/internal/telephony/Call;I)Z
-Lcom/android/internal/telephony/CallManager;->canDial(Lcom/android/internal/telephony/Phone;)Z
-Lcom/android/internal/telephony/CallManager;->conference(Lcom/android/internal/telephony/Call;)V
-Lcom/android/internal/telephony/CallManager;->getActiveFgCall(I)Lcom/android/internal/telephony/Call;
-Lcom/android/internal/telephony/CallManager;->getActiveFgCallState(I)Lcom/android/internal/telephony/Call$State;
-Lcom/android/internal/telephony/CallManager;->getBackgroundCalls()Ljava/util/List;
-Lcom/android/internal/telephony/CallManager;->getBgCallConnections()Ljava/util/List;
-Lcom/android/internal/telephony/CallManager;->getBgPhone()Lcom/android/internal/telephony/Phone;
-Lcom/android/internal/telephony/CallManager;->getContext()Landroid/content/Context;
-Lcom/android/internal/telephony/CallManager;->getDefaultPhone()Lcom/android/internal/telephony/Phone;
-Lcom/android/internal/telephony/CallManager;->getFgCallConnections()Ljava/util/List;
-Lcom/android/internal/telephony/CallManager;->getFgPhone()Lcom/android/internal/telephony/Phone;
-Lcom/android/internal/telephony/CallManager;->getFgPhone(I)Lcom/android/internal/telephony/Phone;
-Lcom/android/internal/telephony/CallManager;->getFirstActiveBgCall()Lcom/android/internal/telephony/Call;
-Lcom/android/internal/telephony/CallManager;->getFirstActiveBgCall(I)Lcom/android/internal/telephony/Call;
-Lcom/android/internal/telephony/CallManager;->getFirstActiveRingingCall()Lcom/android/internal/telephony/Call;
-Lcom/android/internal/telephony/CallManager;->getFirstActiveRingingCall(I)Lcom/android/internal/telephony/Call;
-Lcom/android/internal/telephony/CallManager;->getInstance()Lcom/android/internal/telephony/CallManager;
-Lcom/android/internal/telephony/CallManager;->getPhoneInCall()Lcom/android/internal/telephony/Phone;
-Lcom/android/internal/telephony/CallManager;->getRingingCalls()Ljava/util/List;
-Lcom/android/internal/telephony/CallManager;->getRingingPhone()Lcom/android/internal/telephony/Phone;
-Lcom/android/internal/telephony/CallManager;->getState()Lcom/android/internal/telephony/PhoneConstants$State;
-Lcom/android/internal/telephony/CallManager;->getState(I)Lcom/android/internal/telephony/PhoneConstants$State;
-Lcom/android/internal/telephony/CallManager;->hasActiveBgCall()Z
-Lcom/android/internal/telephony/CallManager;->hasActiveBgCall(I)Z
-Lcom/android/internal/telephony/CallManager;->hasActiveFgCall()Z
-Lcom/android/internal/telephony/CallManager;->hasActiveFgCall(I)Z
-Lcom/android/internal/telephony/CallManager;->hasActiveRingingCall(I)Z
-Lcom/android/internal/telephony/CallManager;->hasMoreThanOneRingingCall()Z
-Lcom/android/internal/telephony/CallManager;->hasMoreThanOneRingingCall(I)Z
-Lcom/android/internal/telephony/CallManager;->mBackgroundCalls:Ljava/util/ArrayList;
-Lcom/android/internal/telephony/CallManager;->mEmptyConnections:Ljava/util/ArrayList;
-Lcom/android/internal/telephony/CallManager;->mForegroundCalls:Ljava/util/ArrayList;
-Lcom/android/internal/telephony/CallManager;->mPhones:Ljava/util/ArrayList;
-Lcom/android/internal/telephony/CallManager;->mRingingCalls:Ljava/util/ArrayList;
-Lcom/android/internal/telephony/CallManager;->registerForDisconnect(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/CallManager;->registerForNewRingingConnection(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/CallManager;->registerForPreciseCallStateChanged(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/CallManager;->registerPhone(Lcom/android/internal/telephony/Phone;)Z
-Lcom/android/internal/telephony/CallManager;->unregisterForDisconnect(Landroid/os/Handler;)V
-Lcom/android/internal/telephony/CallManager;->unregisterForNewRingingConnection(Landroid/os/Handler;)V
-Lcom/android/internal/telephony/CallManager;->unregisterForPreciseCallStateChanged(Landroid/os/Handler;)V
-Lcom/android/internal/telephony/CallManager;->unregisterPhone(Lcom/android/internal/telephony/Phone;)V
-Lcom/android/internal/telephony/CallStateException;-><init>(Ljava/lang/String;)V
 Lcom/android/internal/telephony/CallTracker;-><init>()V
-Lcom/android/internal/telephony/CallTracker;->getState()Lcom/android/internal/telephony/PhoneConstants$State;
-Lcom/android/internal/telephony/CallTracker;->log(Ljava/lang/String;)V
-Lcom/android/internal/telephony/CallTracker;->mCi:Lcom/android/internal/telephony/CommandsInterface;
-Lcom/android/internal/telephony/CallTracker;->mNeedsPoll:Z
-Lcom/android/internal/telephony/CallTracker;->mNumberConverted:Z
-Lcom/android/internal/telephony/CallTracker;->mPendingOperations:I
-Lcom/android/internal/telephony/CallTracker;->registerForVoiceCallEnded(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/CarrierServiceBindHelper;->mContext:Landroid/content/Context;
-Lcom/android/internal/telephony/CarrierServiceBindHelper;->mHandler:Landroid/os/Handler;
-Lcom/android/internal/telephony/cat/AppInterface$CommandType;->CLOSE_CHANNEL:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
-Lcom/android/internal/telephony/cat/AppInterface$CommandType;->DISPLAY_TEXT:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
-Lcom/android/internal/telephony/cat/AppInterface$CommandType;->fromInt(I)Lcom/android/internal/telephony/cat/AppInterface$CommandType;
-Lcom/android/internal/telephony/cat/AppInterface$CommandType;->GET_CHANNEL_STATUS:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
-Lcom/android/internal/telephony/cat/AppInterface$CommandType;->GET_INKEY:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
-Lcom/android/internal/telephony/cat/AppInterface$CommandType;->GET_INPUT:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
-Lcom/android/internal/telephony/cat/AppInterface$CommandType;->LANGUAGE_NOTIFICATION:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
-Lcom/android/internal/telephony/cat/AppInterface$CommandType;->LAUNCH_BROWSER:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
-Lcom/android/internal/telephony/cat/AppInterface$CommandType;->OPEN_CHANNEL:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
-Lcom/android/internal/telephony/cat/AppInterface$CommandType;->PLAY_TONE:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
-Lcom/android/internal/telephony/cat/AppInterface$CommandType;->PROVIDE_LOCAL_INFORMATION:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
-Lcom/android/internal/telephony/cat/AppInterface$CommandType;->RECEIVE_DATA:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
-Lcom/android/internal/telephony/cat/AppInterface$CommandType;->REFRESH:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
-Lcom/android/internal/telephony/cat/AppInterface$CommandType;->SELECT_ITEM:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
-Lcom/android/internal/telephony/cat/AppInterface$CommandType;->SEND_DATA:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
-Lcom/android/internal/telephony/cat/AppInterface$CommandType;->SEND_DTMF:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
-Lcom/android/internal/telephony/cat/AppInterface$CommandType;->SEND_SMS:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
-Lcom/android/internal/telephony/cat/AppInterface$CommandType;->SEND_SS:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
-Lcom/android/internal/telephony/cat/AppInterface$CommandType;->SEND_USSD:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
-Lcom/android/internal/telephony/cat/AppInterface$CommandType;->SET_UP_CALL:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
-Lcom/android/internal/telephony/cat/AppInterface$CommandType;->SET_UP_EVENT_LIST:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
-Lcom/android/internal/telephony/cat/AppInterface$CommandType;->SET_UP_IDLE_MODE_TEXT:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
-Lcom/android/internal/telephony/cat/AppInterface$CommandType;->SET_UP_MENU:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
 Lcom/android/internal/telephony/cat/AppInterface$CommandType;->values()[Lcom/android/internal/telephony/cat/AppInterface$CommandType;
-Lcom/android/internal/telephony/cat/CatCmdMessage$CallSettings;->callMsg:Lcom/android/internal/telephony/cat/TextMessage;
-Lcom/android/internal/telephony/cat/CatCmdMessage$CallSettings;->confirmMsg:Lcom/android/internal/telephony/cat/TextMessage;
-Lcom/android/internal/telephony/cat/CatCmdMessage$SetupEventListSettings;->eventList:[I
-Lcom/android/internal/telephony/cat/CatCmdMessage;->getCallSettings()Lcom/android/internal/telephony/cat/CatCmdMessage$CallSettings;
-Lcom/android/internal/telephony/cat/CatCmdMessage;->getCmdType()Lcom/android/internal/telephony/cat/AppInterface$CommandType;
-Lcom/android/internal/telephony/cat/CatCmdMessage;->geTextMessage()Lcom/android/internal/telephony/cat/TextMessage;
-Lcom/android/internal/telephony/cat/CatCmdMessage;->getSetEventList()Lcom/android/internal/telephony/cat/CatCmdMessage$SetupEventListSettings;
-Lcom/android/internal/telephony/cat/CatCmdMessage;->hasIconLoadFailed()Z
-Lcom/android/internal/telephony/cat/CatCmdMessage;->mCallSettings:Lcom/android/internal/telephony/cat/CatCmdMessage$CallSettings;
-Lcom/android/internal/telephony/cat/CatCmdMessage;->mCmdDet:Lcom/android/internal/telephony/cat/CommandDetails;
-Lcom/android/internal/telephony/cat/CatCmdMessage;->mInput:Lcom/android/internal/telephony/cat/Input;
-Lcom/android/internal/telephony/cat/CatCmdMessage;->mMenu:Lcom/android/internal/telephony/cat/Menu;
-Lcom/android/internal/telephony/cat/CatCmdMessage;->mTextMsg:Lcom/android/internal/telephony/cat/TextMessage;
-Lcom/android/internal/telephony/cat/CatLog;->d(Ljava/lang/Object;Ljava/lang/String;)V
-Lcom/android/internal/telephony/cat/CatLog;->d(Ljava/lang/String;Ljava/lang/String;)V
-Lcom/android/internal/telephony/cat/CatLog;->e(Ljava/lang/Object;Ljava/lang/String;)V
-Lcom/android/internal/telephony/cat/CatResponseMessage;->setEventDownload(I[B)V
-Lcom/android/internal/telephony/cat/CatService;->dispose()V
-Lcom/android/internal/telephony/cat/CatService;->isStkAppInstalled()Z
-Lcom/android/internal/telephony/cat/CatService;->mCmdIf:Lcom/android/internal/telephony/CommandsInterface;
-Lcom/android/internal/telephony/cat/CatService;->mContext:Landroid/content/Context;
-Lcom/android/internal/telephony/cat/CatService;->mCurrntCmd:Lcom/android/internal/telephony/cat/CatCmdMessage;
-Lcom/android/internal/telephony/cat/CatService;->mMenuCmd:Lcom/android/internal/telephony/cat/CatCmdMessage;
-Lcom/android/internal/telephony/cat/CatService;->mMsgDecoder:Lcom/android/internal/telephony/cat/RilMessageDecoder;
-Lcom/android/internal/telephony/cat/CatService;->mSlotId:I
-Lcom/android/internal/telephony/cat/CatService;->mStkAppInstalled:Z
-Lcom/android/internal/telephony/cat/CatService;->mUiccController:Lcom/android/internal/telephony/uicc/UiccController;
-Lcom/android/internal/telephony/cat/CatService;->sendTerminalResponse(Lcom/android/internal/telephony/cat/CommandDetails;Lcom/android/internal/telephony/cat/ResultCode;ZILcom/android/internal/telephony/cat/ResponseData;)V
-Lcom/android/internal/telephony/cat/CatService;->sInstance:[Lcom/android/internal/telephony/cat/CatService;
-Lcom/android/internal/telephony/cat/CatService;->sInstanceLock:Ljava/lang/Object;
-Lcom/android/internal/telephony/cat/CommandDetails;->commandNumber:I
-Lcom/android/internal/telephony/cat/CommandDetails;->commandQualifier:I
-Lcom/android/internal/telephony/cat/CommandDetails;->compRequired:Z
-Lcom/android/internal/telephony/cat/CommandDetails;->typeOfCommand:I
-Lcom/android/internal/telephony/cat/CommandParams;-><init>(Lcom/android/internal/telephony/cat/CommandDetails;)V
-Lcom/android/internal/telephony/cat/CommandParams;->getCommandType()Lcom/android/internal/telephony/cat/AppInterface$CommandType;
-Lcom/android/internal/telephony/cat/CommandParams;->mCmdDet:Lcom/android/internal/telephony/cat/CommandDetails;
-Lcom/android/internal/telephony/cat/CommandParamsFactory;->dispose()V
-Lcom/android/internal/telephony/cat/CommandParamsFactory;->mIconLoader:Lcom/android/internal/telephony/cat/IconLoader;
-Lcom/android/internal/telephony/cat/CommandParamsFactory;->searchForNextTag(Lcom/android/internal/telephony/cat/ComprehensionTlvTag;Ljava/util/Iterator;)Lcom/android/internal/telephony/cat/ComprehensionTlv;
-Lcom/android/internal/telephony/cat/CommandParamsFactory;->searchForTag(Lcom/android/internal/telephony/cat/ComprehensionTlvTag;Ljava/util/List;)Lcom/android/internal/telephony/cat/ComprehensionTlv;
-Lcom/android/internal/telephony/cat/ComprehensionTlv;->getLength()I
-Lcom/android/internal/telephony/cat/ComprehensionTlv;->getRawValue()[B
-Lcom/android/internal/telephony/cat/ComprehensionTlv;->getTag()I
-Lcom/android/internal/telephony/cat/ComprehensionTlv;->getValueIndex()I
-Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->ADDRESS:Lcom/android/internal/telephony/cat/ComprehensionTlvTag;
-Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->ALPHA_ID:Lcom/android/internal/telephony/cat/ComprehensionTlvTag;
-Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->COMMAND_DETAILS:Lcom/android/internal/telephony/cat/ComprehensionTlvTag;
-Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->DEVICE_IDENTITIES:Lcom/android/internal/telephony/cat/ComprehensionTlvTag;
-Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->ICON_ID:Lcom/android/internal/telephony/cat/ComprehensionTlvTag;
-Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->RESULT:Lcom/android/internal/telephony/cat/ComprehensionTlvTag;
-Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->SMS_TPDU:Lcom/android/internal/telephony/cat/ComprehensionTlvTag;
-Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->TEXT_ATTRIBUTE:Lcom/android/internal/telephony/cat/ComprehensionTlvTag;
-Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->TEXT_STRING:Lcom/android/internal/telephony/cat/ComprehensionTlvTag;
-Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->USSD_STRING:Lcom/android/internal/telephony/cat/ComprehensionTlvTag;
-Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->value()I
-Lcom/android/internal/telephony/cat/DeviceIdentities;->destinationId:I
-Lcom/android/internal/telephony/cat/DisplayTextParams;-><init>(Lcom/android/internal/telephony/cat/CommandDetails;Lcom/android/internal/telephony/cat/TextMessage;)V
-Lcom/android/internal/telephony/cat/DisplayTextParams;->mTextMsg:Lcom/android/internal/telephony/cat/TextMessage;
-Lcom/android/internal/telephony/cat/Duration$TimeUnit;->value()I
-Lcom/android/internal/telephony/cat/Duration;->timeInterval:I
-Lcom/android/internal/telephony/cat/Duration;->timeUnit:Lcom/android/internal/telephony/cat/Duration$TimeUnit;
-Lcom/android/internal/telephony/cat/GetInputParams;-><init>(Lcom/android/internal/telephony/cat/CommandDetails;Lcom/android/internal/telephony/cat/Input;)V
-Lcom/android/internal/telephony/cat/IconId;->recordNumber:I
-Lcom/android/internal/telephony/cat/IconLoader;->loadIcon(ILandroid/os/Message;)V
-Lcom/android/internal/telephony/cat/Menu;->titleAttrs:Ljava/util/List;
-Lcom/android/internal/telephony/cat/PlayToneParams;-><init>(Lcom/android/internal/telephony/cat/CommandDetails;Lcom/android/internal/telephony/cat/TextMessage;Lcom/android/internal/telephony/cat/Tone;Lcom/android/internal/telephony/cat/Duration;Z)V
 Lcom/android/internal/telephony/cat/ResponseData;-><init>()V
-Lcom/android/internal/telephony/cat/ResponseData;->format(Ljava/io/ByteArrayOutputStream;)V
-Lcom/android/internal/telephony/cat/ResultCode;->BACKWARD_MOVE_BY_USER:Lcom/android/internal/telephony/cat/ResultCode;
-Lcom/android/internal/telephony/cat/ResultCode;->BEYOND_TERMINAL_CAPABILITY:Lcom/android/internal/telephony/cat/ResultCode;
-Lcom/android/internal/telephony/cat/ResultCode;->BIP_ERROR:Lcom/android/internal/telephony/cat/ResultCode;
-Lcom/android/internal/telephony/cat/ResultCode;->CMD_DATA_NOT_UNDERSTOOD:Lcom/android/internal/telephony/cat/ResultCode;
-Lcom/android/internal/telephony/cat/ResultCode;->HELP_INFO_REQUIRED:Lcom/android/internal/telephony/cat/ResultCode;
-Lcom/android/internal/telephony/cat/ResultCode;->LAUNCH_BROWSER_ERROR:Lcom/android/internal/telephony/cat/ResultCode;
-Lcom/android/internal/telephony/cat/ResultCode;->NETWORK_CRNTLY_UNABLE_TO_PROCESS:Lcom/android/internal/telephony/cat/ResultCode;
-Lcom/android/internal/telephony/cat/ResultCode;->NO_RESPONSE_FROM_USER:Lcom/android/internal/telephony/cat/ResultCode;
-Lcom/android/internal/telephony/cat/ResultCode;->OK:Lcom/android/internal/telephony/cat/ResultCode;
-Lcom/android/internal/telephony/cat/ResultCode;->PRFRMD_ICON_NOT_DISPLAYED:Lcom/android/internal/telephony/cat/ResultCode;
-Lcom/android/internal/telephony/cat/ResultCode;->PRFRMD_LIMITED_SERVICE:Lcom/android/internal/telephony/cat/ResultCode;
-Lcom/android/internal/telephony/cat/ResultCode;->PRFRMD_MODIFIED_BY_NAA:Lcom/android/internal/telephony/cat/ResultCode;
-Lcom/android/internal/telephony/cat/ResultCode;->PRFRMD_NAA_NOT_ACTIVE:Lcom/android/internal/telephony/cat/ResultCode;
-Lcom/android/internal/telephony/cat/ResultCode;->PRFRMD_TONE_NOT_PLAYED:Lcom/android/internal/telephony/cat/ResultCode;
-Lcom/android/internal/telephony/cat/ResultCode;->PRFRMD_WITH_ADDITIONAL_EFS_READ:Lcom/android/internal/telephony/cat/ResultCode;
-Lcom/android/internal/telephony/cat/ResultCode;->PRFRMD_WITH_MISSING_INFO:Lcom/android/internal/telephony/cat/ResultCode;
-Lcom/android/internal/telephony/cat/ResultCode;->PRFRMD_WITH_MODIFICATION:Lcom/android/internal/telephony/cat/ResultCode;
-Lcom/android/internal/telephony/cat/ResultCode;->PRFRMD_WITH_PARTIAL_COMPREHENSION:Lcom/android/internal/telephony/cat/ResultCode;
-Lcom/android/internal/telephony/cat/ResultCode;->REQUIRED_VALUES_MISSING:Lcom/android/internal/telephony/cat/ResultCode;
-Lcom/android/internal/telephony/cat/ResultCode;->TERMINAL_CRNTLY_UNABLE_TO_PROCESS:Lcom/android/internal/telephony/cat/ResultCode;
-Lcom/android/internal/telephony/cat/ResultCode;->UICC_SESSION_TERM_BY_USER:Lcom/android/internal/telephony/cat/ResultCode;
-Lcom/android/internal/telephony/cat/ResultCode;->USER_NOT_ACCEPT:Lcom/android/internal/telephony/cat/ResultCode;
-Lcom/android/internal/telephony/cat/ResultCode;->USIM_CALL_CONTROL_PERMANENT:Lcom/android/internal/telephony/cat/ResultCode;
-Lcom/android/internal/telephony/cat/ResultCode;->value()I
 Lcom/android/internal/telephony/cat/ResultCode;->values()[Lcom/android/internal/telephony/cat/ResultCode;
-Lcom/android/internal/telephony/cat/ResultException;-><init>(Lcom/android/internal/telephony/cat/ResultCode;)V
-Lcom/android/internal/telephony/cat/RilMessage;-><init>(ILjava/lang/String;)V
-Lcom/android/internal/telephony/cat/RilMessage;->mData:Ljava/lang/Object;
-Lcom/android/internal/telephony/cat/RilMessage;->mId:I
-Lcom/android/internal/telephony/cat/RilMessageDecoder;->getInstance(Landroid/os/Handler;Lcom/android/internal/telephony/uicc/IccFileHandler;I)Lcom/android/internal/telephony/cat/RilMessageDecoder;
-Lcom/android/internal/telephony/cat/RilMessageDecoder;->mCmdParamsFactory:Lcom/android/internal/telephony/cat/CommandParamsFactory;
 Lcom/android/internal/telephony/cat/RilMessageDecoder;->mCurrentRilMessage:Lcom/android/internal/telephony/cat/RilMessage;
-Lcom/android/internal/telephony/cat/RilMessageDecoder;->mInstance:[Lcom/android/internal/telephony/cat/RilMessageDecoder;
-Lcom/android/internal/telephony/cat/RilMessageDecoder;->mStateStart:Lcom/android/internal/telephony/cat/RilMessageDecoder$StateStart;
 Lcom/android/internal/telephony/cat/RilMessageDecoder;->sendCmdForExecution(Lcom/android/internal/telephony/cat/RilMessage;)V
 Lcom/android/internal/telephony/cat/RilMessageDecoder;->sendStartDecodingMessageParams(Lcom/android/internal/telephony/cat/RilMessage;)V
-Lcom/android/internal/telephony/cat/SelectItemParams;-><init>(Lcom/android/internal/telephony/cat/CommandDetails;Lcom/android/internal/telephony/cat/Menu;Z)V
-Lcom/android/internal/telephony/cat/TextMessage;-><init>()V
-Lcom/android/internal/telephony/cat/TextMessage;->iconSelfExplanatory:Z
-Lcom/android/internal/telephony/cat/TextMessage;->text:Ljava/lang/String;
 Lcom/android/internal/telephony/cat/ValueObject;-><init>()V
-Lcom/android/internal/telephony/cat/ValueParser;->retrieveAlphaId(Lcom/android/internal/telephony/cat/ComprehensionTlv;)Ljava/lang/String;
 Lcom/android/internal/telephony/cat/ValueParser;->retrieveDeviceIdentities(Lcom/android/internal/telephony/cat/ComprehensionTlv;)Lcom/android/internal/telephony/cat/DeviceIdentities;
-Lcom/android/internal/telephony/cat/ValueParser;->retrieveTextAttribute(Lcom/android/internal/telephony/cat/ComprehensionTlv;)Ljava/util/List;
-Lcom/android/internal/telephony/cat/ValueParser;->retrieveTextString(Lcom/android/internal/telephony/cat/ComprehensionTlv;)Ljava/lang/String;
-Lcom/android/internal/telephony/cdma/CdmaCallWaitingNotification;->number:Ljava/lang/String;
-Lcom/android/internal/telephony/cdma/CdmaMmiCode;->makeEmptyNull(Ljava/lang/String;)Ljava/lang/String;
-Lcom/android/internal/telephony/cdma/CdmaMmiCode;->mSc:Ljava/lang/String;
-Lcom/android/internal/telephony/cdma/CdmaSMSDispatcher;->getFormat()Ljava/lang/String;
-Lcom/android/internal/telephony/cdma/CdmaSMSDispatcher;->handleCdmaStatusReport(Lcom/android/internal/telephony/cdma/SmsMessage;)V
-Lcom/android/internal/telephony/cdma/CdmaSubscriptionSourceManager;->getCdmaSubscriptionSource()I
-Lcom/android/internal/telephony/cdma/CdmaSubscriptionSourceManager;->getInstance(Landroid/content/Context;Lcom/android/internal/telephony/CommandsInterface;Landroid/os/Handler;ILjava/lang/Object;)Lcom/android/internal/telephony/cdma/CdmaSubscriptionSourceManager;
-Lcom/android/internal/telephony/cdma/EriManager$EriDisplayInformation;->mEriIconText:Ljava/lang/String;
-Lcom/android/internal/telephony/cdma/EriManager;->getEriDisplayInformation(II)Lcom/android/internal/telephony/cdma/EriManager$EriDisplayInformation;
 Lcom/android/internal/telephony/cdma/sms/BearerData$CodingException;-><init>(Ljava/lang/String;)V
 Lcom/android/internal/telephony/cdma/sms/BearerData$TimeStamp;-><init>()V
 Lcom/android/internal/telephony/cdma/sms/BearerData;-><init>()V
@@ -2084,130 +1360,6 @@
 Lcom/android/internal/telephony/cdma/SmsMessage;->mEnvelope:Lcom/android/internal/telephony/cdma/sms/SmsEnvelope;
 Lcom/android/internal/telephony/cdma/SmsMessage;->parseSms()V
 Lcom/android/internal/telephony/cdma/SmsMessage;->privateGetSubmitPdu(Ljava/lang/String;ZLcom/android/internal/telephony/cdma/sms/UserData;)Lcom/android/internal/telephony/cdma/SmsMessage$SubmitPdu;
-Lcom/android/internal/telephony/CommandException$Error;->GENERIC_FAILURE:Lcom/android/internal/telephony/CommandException$Error;
-Lcom/android/internal/telephony/CommandException$Error;->PASSWORD_INCORRECT:Lcom/android/internal/telephony/CommandException$Error;
-Lcom/android/internal/telephony/CommandException$Error;->RADIO_NOT_AVAILABLE:Lcom/android/internal/telephony/CommandException$Error;
-Lcom/android/internal/telephony/CommandException$Error;->REQUEST_NOT_SUPPORTED:Lcom/android/internal/telephony/CommandException$Error;
-Lcom/android/internal/telephony/CommandException$Error;->SIM_PUK2:Lcom/android/internal/telephony/CommandException$Error;
-Lcom/android/internal/telephony/CommandException$Error;->SMS_FAIL_RETRY:Lcom/android/internal/telephony/CommandException$Error;
-Lcom/android/internal/telephony/CommandException;-><init>(Lcom/android/internal/telephony/CommandException$Error;)V
-Lcom/android/internal/telephony/CommandException;->fromRilErrno(I)Lcom/android/internal/telephony/CommandException;
-Lcom/android/internal/telephony/CommandException;->getCommandError()Lcom/android/internal/telephony/CommandException$Error;
-Lcom/android/internal/telephony/CommandException;->mError:Lcom/android/internal/telephony/CommandException$Error;
-Lcom/android/internal/telephony/CommandsInterface;->acceptCall(Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->acknowledgeLastIncomingCdmaSms(ZILandroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->acknowledgeLastIncomingGsmSms(ZILandroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->changeBarringPassword(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->deleteSmsOnRuim(ILandroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->deleteSmsOnSim(ILandroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->exitEmergencyCallbackMode(Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->getBasebandVersion(Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->getCdmaBroadcastConfig(Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->getCDMASubscription(Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->getDataCallList(Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->getIccCardStatus(Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->getIMEISV(Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->getIMSI(Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->getLastDataCallFailCause(Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->getLastPdpFailCause(Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->getNetworkSelectionMode(Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->getOperator(Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->getPDPContextList(Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->getPreferredNetworkType(Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->getSignalStrength(Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->getSmscAddress(Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->getVoiceRegistrationState(Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->handleCallSetupRequestFromSim(ZLandroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->iccIO(IILjava/lang/String;IIILjava/lang/String;Ljava/lang/String;Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->iccIOForApp(IILjava/lang/String;IIILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->invokeOemRilRequestRaw([BLandroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->queryCallForwardStatus(IILjava/lang/String;Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->queryCallWaiting(ILandroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->queryFacilityLock(Ljava/lang/String;Ljava/lang/String;ILandroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->queryTTYMode(Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->registerForAvailable(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/CommandsInterface;->registerForCdmaOtaProvision(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/CommandsInterface;->registerForCellInfoList(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/CommandsInterface;->registerForIccRefresh(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/CommandsInterface;->registerForImsNetworkStateChanged(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/CommandsInterface;->registerForNotAvailable(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/CommandsInterface;->registerForOffOrNotAvailable(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/CommandsInterface;->registerForOn(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/CommandsInterface;->registerForRadioStateChanged(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/CommandsInterface;->registerForRilConnected(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/CommandsInterface;->reportSmsMemoryStatus(ZLandroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->reportStkServiceIsRunning(Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->requestIccSimAuthentication(ILjava/lang/String;Ljava/lang/String;Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->requestShutdown(Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->sendDtmf(CLandroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->sendEnvelope(Ljava/lang/String;Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->sendTerminalResponse(Ljava/lang/String;Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->setCallForward(IIILjava/lang/String;ILandroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->setCallWaiting(ZILandroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->setCdmaBroadcastActivation(ZLandroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->setDataAllowed(ZLandroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->setEmergencyCallbackMode(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/CommandsInterface;->setFacilityLock(Ljava/lang/String;ZLjava/lang/String;ILandroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->setNetworkSelectionModeAutomatic(Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->setNetworkSelectionModeManual(Ljava/lang/String;Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->setOnCallRing(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/CommandsInterface;->setOnCatCallSetUp(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/CommandsInterface;->setOnCatCcAlphaNotify(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/CommandsInterface;->setOnCatEvent(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/CommandsInterface;->setOnCatProactiveCmd(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/CommandsInterface;->setOnCatSessionEnd(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/CommandsInterface;->setOnIccRefresh(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/CommandsInterface;->setOnIccSmsFull(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/CommandsInterface;->setOnNewGsmBroadcastSms(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/CommandsInterface;->setOnNITZTime(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/CommandsInterface;->setOnSignalStrengthUpdate(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/CommandsInterface;->setOnSmsOnSim(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/CommandsInterface;->setOnSmsStatus(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/CommandsInterface;->setOnSuppServiceNotification(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/CommandsInterface;->setPhoneType(I)V
-Lcom/android/internal/telephony/CommandsInterface;->setPreferredNetworkType(ILandroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->setRadioPower(ZLandroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->setSmscAddress(Ljava/lang/String;Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->setTTYMode(ILandroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->setUiccSubscription(IIIILandroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->supplyIccPin(Ljava/lang/String;Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->switchWaitingOrHoldingAndActive(Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->unregisterForAvailable(Landroid/os/Handler;)V
-Lcom/android/internal/telephony/CommandsInterface;->unregisterForCdmaOtaProvision(Landroid/os/Handler;)V
-Lcom/android/internal/telephony/CommandsInterface;->unregisterForOffOrNotAvailable(Landroid/os/Handler;)V
-Lcom/android/internal/telephony/CommandsInterface;->unregisterForOn(Landroid/os/Handler;)V
-Lcom/android/internal/telephony/CommandsInterface;->unregisterForRilConnected(Landroid/os/Handler;)V
-Lcom/android/internal/telephony/CommandsInterface;->unregisterForVoiceRadioTechChanged(Landroid/os/Handler;)V
-Lcom/android/internal/telephony/CommandsInterface;->writeSmsToRuim(ILjava/lang/String;Landroid/os/Message;)V
-Lcom/android/internal/telephony/CommandsInterface;->writeSmsToSim(ILjava/lang/String;Ljava/lang/String;Landroid/os/Message;)V
-Lcom/android/internal/telephony/Connection$PostDialState;->CANCELLED:Lcom/android/internal/telephony/Connection$PostDialState;
-Lcom/android/internal/telephony/Connection$PostDialState;->COMPLETE:Lcom/android/internal/telephony/Connection$PostDialState;
-Lcom/android/internal/telephony/Connection$PostDialState;->NOT_STARTED:Lcom/android/internal/telephony/Connection$PostDialState;
-Lcom/android/internal/telephony/Connection$PostDialState;->STARTED:Lcom/android/internal/telephony/Connection$PostDialState;
-Lcom/android/internal/telephony/Connection$PostDialState;->WAIT:Lcom/android/internal/telephony/Connection$PostDialState;
-Lcom/android/internal/telephony/Connection$PostDialState;->WILD:Lcom/android/internal/telephony/Connection$PostDialState;
-Lcom/android/internal/telephony/Connection;-><init>(I)V
-Lcom/android/internal/telephony/Connection;->getAddress()Ljava/lang/String;
-Lcom/android/internal/telephony/Connection;->getCall()Lcom/android/internal/telephony/Call;
-Lcom/android/internal/telephony/Connection;->getConnectTime()J
-Lcom/android/internal/telephony/Connection;->getCreateTime()J
-Lcom/android/internal/telephony/Connection;->getDisconnectCause()I
-Lcom/android/internal/telephony/Connection;->getDisconnectTime()J
-Lcom/android/internal/telephony/Connection;->getDurationMillis()J
-Lcom/android/internal/telephony/Connection;->getState()Lcom/android/internal/telephony/Call$State;
-Lcom/android/internal/telephony/Connection;->getUserData()Ljava/lang/Object;
-Lcom/android/internal/telephony/Connection;->hangup()V
-Lcom/android/internal/telephony/Connection;->isAlive()Z
-Lcom/android/internal/telephony/Connection;->isIncoming()Z
-Lcom/android/internal/telephony/Connection;->LOG_TAG:Ljava/lang/String;
-Lcom/android/internal/telephony/Connection;->mAddress:Ljava/lang/String;
-Lcom/android/internal/telephony/Connection;->mCnapName:Ljava/lang/String;
-Lcom/android/internal/telephony/Connection;->mCnapNamePresentation:I
-Lcom/android/internal/telephony/Connection;->mDialString:Ljava/lang/String;
-Lcom/android/internal/telephony/Connection;->mDuration:J
-Lcom/android/internal/telephony/Connection;->mIsIncoming:Z
-Lcom/android/internal/telephony/Connection;->mNumberPresentation:I
-Lcom/android/internal/telephony/Connection;->setVideoState(I)V
 Lcom/android/internal/telephony/DctConstants$Activity;->DATAIN:Lcom/android/internal/telephony/DctConstants$Activity;
 Lcom/android/internal/telephony/DctConstants$Activity;->DATAINANDOUT:Lcom/android/internal/telephony/DctConstants$Activity;
 Lcom/android/internal/telephony/DctConstants$Activity;->DATAOUT:Lcom/android/internal/telephony/DctConstants$Activity;
@@ -2220,22 +1372,7 @@
 Lcom/android/internal/telephony/DctConstants$State;->IDLE:Lcom/android/internal/telephony/DctConstants$State;
 Lcom/android/internal/telephony/DctConstants$State;->RETRYING:Lcom/android/internal/telephony/DctConstants$State;
 Lcom/android/internal/telephony/DctConstants$State;->values()[Lcom/android/internal/telephony/DctConstants$State;
-Lcom/android/internal/telephony/DefaultPhoneNotifier;->mRegistry:Lcom/android/internal/telephony/ITelephonyRegistry;
-Lcom/android/internal/telephony/DriverCall$State;->ACTIVE:Lcom/android/internal/telephony/DriverCall$State;
-Lcom/android/internal/telephony/DriverCall$State;->ALERTING:Lcom/android/internal/telephony/DriverCall$State;
-Lcom/android/internal/telephony/DriverCall$State;->DIALING:Lcom/android/internal/telephony/DriverCall$State;
-Lcom/android/internal/telephony/DriverCall$State;->HOLDING:Lcom/android/internal/telephony/DriverCall$State;
-Lcom/android/internal/telephony/DriverCall$State;->INCOMING:Lcom/android/internal/telephony/DriverCall$State;
 Lcom/android/internal/telephony/DriverCall$State;->values()[Lcom/android/internal/telephony/DriverCall$State;
-Lcom/android/internal/telephony/DriverCall$State;->WAITING:Lcom/android/internal/telephony/DriverCall$State;
-Lcom/android/internal/telephony/DriverCall;-><init>()V
-Lcom/android/internal/telephony/DriverCall;->index:I
-Lcom/android/internal/telephony/DriverCall;->isMT:Z
-Lcom/android/internal/telephony/DriverCall;->isVoice:Z
-Lcom/android/internal/telephony/DriverCall;->name:Ljava/lang/String;
-Lcom/android/internal/telephony/DriverCall;->number:Ljava/lang/String;
-Lcom/android/internal/telephony/DriverCall;->numberPresentation:I
-Lcom/android/internal/telephony/DriverCall;->state:Lcom/android/internal/telephony/DriverCall$State;
 Lcom/android/internal/telephony/gsm/GsmCellBroadcastHandler$SmsCbConcatInfo;-><init>(Lcom/android/internal/telephony/gsm/SmsCbHeader;Landroid/telephony/SmsCbLocation;)V
 Lcom/android/internal/telephony/gsm/GsmCellBroadcastHandler$SmsCbConcatInfo;->matchesLocation(Ljava/lang/String;II)Z
 Lcom/android/internal/telephony/gsm/GsmCellBroadcastHandler;->mSmsCbPageMap:Ljava/util/HashMap;
@@ -2314,79 +1451,7 @@
 Lcom/android/internal/telephony/gsm/UsimPhoneBookManager;->mPhoneBookRecords:Ljava/util/ArrayList;
 Lcom/android/internal/telephony/gsm/UsimPhoneBookManager;->reset()V
 Lcom/android/internal/telephony/GsmAlphabet$TextEncodingDetails;-><init>()V
-Lcom/android/internal/telephony/GsmCdmaCall;->attachFake(Lcom/android/internal/telephony/Connection;Lcom/android/internal/telephony/Call$State;)V
-Lcom/android/internal/telephony/GsmCdmaCallTracker;->clearDisconnected()V
-Lcom/android/internal/telephony/GsmCdmaCallTracker;->disableDataCallInEmergencyCall(Ljava/lang/String;)V
-Lcom/android/internal/telephony/GsmCdmaCallTracker;->fakeHoldForegroundBeforeDial()V
-Lcom/android/internal/telephony/GsmCdmaCallTracker;->getPhone()Lcom/android/internal/telephony/GsmCdmaPhone;
-Lcom/android/internal/telephony/GsmCdmaCallTracker;->handleEcmTimer(I)V
-Lcom/android/internal/telephony/GsmCdmaCallTracker;->isPhoneTypeGsm()Z
-Lcom/android/internal/telephony/GsmCdmaCallTracker;->log(Ljava/lang/String;)V
-Lcom/android/internal/telephony/GsmCdmaCallTracker;->mBackgroundCall:Lcom/android/internal/telephony/GsmCdmaCall;
-Lcom/android/internal/telephony/GsmCdmaCallTracker;->mForegroundCall:Lcom/android/internal/telephony/GsmCdmaCall;
-Lcom/android/internal/telephony/GsmCdmaCallTracker;->mPendingMO:Lcom/android/internal/telephony/GsmCdmaConnection;
-Lcom/android/internal/telephony/GsmCdmaCallTracker;->mPhone:Lcom/android/internal/telephony/GsmCdmaPhone;
-Lcom/android/internal/telephony/GsmCdmaCallTracker;->mRingingCall:Lcom/android/internal/telephony/GsmCdmaCall;
-Lcom/android/internal/telephony/GsmCdmaCallTracker;->mState:Lcom/android/internal/telephony/PhoneConstants$State;
-Lcom/android/internal/telephony/GsmCdmaCallTracker;->obtainCompleteMessage()Landroid/os/Message;
-Lcom/android/internal/telephony/GsmCdmaCallTracker;->obtainCompleteMessage(I)Landroid/os/Message;
-Lcom/android/internal/telephony/GsmCdmaCallTracker;->setMute(Z)V
-Lcom/android/internal/telephony/GsmCdmaCallTracker;->switchWaitingOrHoldingAndActive()V
-Lcom/android/internal/telephony/GsmCdmaCallTracker;->updatePhoneState()V
 Lcom/android/internal/telephony/GsmCdmaConnection$MyHandler;-><init>(Lcom/android/internal/telephony/GsmCdmaConnection;Landroid/os/Looper;)V
-Lcom/android/internal/telephony/GsmCdmaConnection;->acquireWakeLock()V
-Lcom/android/internal/telephony/GsmCdmaConnection;->createWakeLock(Landroid/content/Context;)V
-Lcom/android/internal/telephony/GsmCdmaConnection;->disconnectCauseFromCode(I)I
-Lcom/android/internal/telephony/GsmCdmaConnection;->fetchDtmfToneDelay(Lcom/android/internal/telephony/GsmCdmaPhone;)V
-Lcom/android/internal/telephony/GsmCdmaConnection;->findNextPCharOrNonPOrNonWCharIndex(Ljava/lang/String;I)I
-Lcom/android/internal/telephony/GsmCdmaConnection;->findPOrWCharToAppend(Ljava/lang/String;II)C
-Lcom/android/internal/telephony/GsmCdmaConnection;->formatDialString(Ljava/lang/String;)Ljava/lang/String;
-Lcom/android/internal/telephony/GsmCdmaConnection;->getState()Lcom/android/internal/telephony/Call$State;
-Lcom/android/internal/telephony/GsmCdmaConnection;->isPause(C)Z
-Lcom/android/internal/telephony/GsmCdmaConnection;->isPhoneTypeGsm()Z
-Lcom/android/internal/telephony/GsmCdmaConnection;->isWait(C)Z
-Lcom/android/internal/telephony/GsmCdmaConnection;->log(Ljava/lang/String;)V
-Lcom/android/internal/telephony/GsmCdmaConnection;->maskDialString(Ljava/lang/String;)Ljava/lang/String;
-Lcom/android/internal/telephony/GsmCdmaConnection;->mIndex:I
-Lcom/android/internal/telephony/GsmCdmaConnection;->mOwner:Lcom/android/internal/telephony/GsmCdmaCallTracker;
-Lcom/android/internal/telephony/GsmCdmaConnection;->onConnectedInOrOut()V
-Lcom/android/internal/telephony/GsmCdmaConnection;->updateParent(Lcom/android/internal/telephony/GsmCdmaCall;Lcom/android/internal/telephony/GsmCdmaCall;)V
-Lcom/android/internal/telephony/GsmCdmaPhone$Cfu;-><init>(Ljava/lang/String;Landroid/os/Message;)V
-Lcom/android/internal/telephony/GsmCdmaPhone;->exitEmergencyCallbackMode()V
-Lcom/android/internal/telephony/GsmCdmaPhone;->getCallTracker()Lcom/android/internal/telephony/CallTracker;
-Lcom/android/internal/telephony/GsmCdmaPhone;->getCdmaEriText()Ljava/lang/String;
-Lcom/android/internal/telephony/GsmCdmaPhone;->getEsn()Ljava/lang/String;
-Lcom/android/internal/telephony/GsmCdmaPhone;->getLine1Number()Ljava/lang/String;
-Lcom/android/internal/telephony/GsmCdmaPhone;->getPhoneType()I
-Lcom/android/internal/telephony/GsmCdmaPhone;->getServiceState()Landroid/telephony/ServiceState;
-Lcom/android/internal/telephony/GsmCdmaPhone;->getState()Lcom/android/internal/telephony/PhoneConstants$State;
-Lcom/android/internal/telephony/GsmCdmaPhone;->getSystemProperty(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
-Lcom/android/internal/telephony/GsmCdmaPhone;->handleInCallMmiCommands(Ljava/lang/String;)Z
-Lcom/android/internal/telephony/GsmCdmaPhone;->isCfEnable(I)Z
-Lcom/android/internal/telephony/GsmCdmaPhone;->isEriFileLoaded()Z
-Lcom/android/internal/telephony/GsmCdmaPhone;->isInCall()Z
-Lcom/android/internal/telephony/GsmCdmaPhone;->isManualSelProhibitedInGlobalMode()Z
-Lcom/android/internal/telephony/GsmCdmaPhone;->isPhoneTypeGsm()Z
-Lcom/android/internal/telephony/GsmCdmaPhone;->isValidCommandInterfaceCFAction(I)Z
-Lcom/android/internal/telephony/GsmCdmaPhone;->isValidCommandInterfaceCFReason(I)Z
-Lcom/android/internal/telephony/GsmCdmaPhone;->logd(Ljava/lang/String;)V
-Lcom/android/internal/telephony/GsmCdmaPhone;->loge(Ljava/lang/String;)V
-Lcom/android/internal/telephony/GsmCdmaPhone;->mCT:Lcom/android/internal/telephony/GsmCdmaCallTracker;
-Lcom/android/internal/telephony/GsmCdmaPhone;->mEcmExitRespRegistrant:Landroid/os/Registrant;
-Lcom/android/internal/telephony/GsmCdmaPhone;->mEriManager:Lcom/android/internal/telephony/cdma/EriManager;
-Lcom/android/internal/telephony/GsmCdmaPhone;->mIccSmsInterfaceManager:Lcom/android/internal/telephony/IccSmsInterfaceManager;
-Lcom/android/internal/telephony/GsmCdmaPhone;->mIsimUiccRecords:Lcom/android/internal/telephony/uicc/IsimUiccRecords;
-Lcom/android/internal/telephony/GsmCdmaPhone;->mPendingMMIs:Ljava/util/ArrayList;
-Lcom/android/internal/telephony/GsmCdmaPhone;->mSST:Lcom/android/internal/telephony/ServiceStateTracker;
-Lcom/android/internal/telephony/GsmCdmaPhone;->notifyPreciseCallStateChanged()V
-Lcom/android/internal/telephony/GsmCdmaPhone;->notifyServiceStateChanged(Landroid/telephony/ServiceState;)V
-Lcom/android/internal/telephony/GsmCdmaPhone;->setOnEcbModeExitResponse(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/GsmCdmaPhone;->syncClirSetting()V
-Lcom/android/internal/telephony/IccCard;->getState()Lcom/android/internal/telephony/IccCardConstants$State;
-Lcom/android/internal/telephony/IccCard;->registerForNetworkLocked(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/IccCard;->supplyNetworkDepersonalization(Ljava/lang/String;Landroid/os/Message;)V
-Lcom/android/internal/telephony/IccCard;->supplyPin(Ljava/lang/String;Landroid/os/Message;)V
-Lcom/android/internal/telephony/IccCard;->supplyPuk(Ljava/lang/String;Ljava/lang/String;Landroid/os/Message;)V
 Lcom/android/internal/telephony/IccCardConstants$State;->ABSENT:Lcom/android/internal/telephony/IccCardConstants$State;
 Lcom/android/internal/telephony/IccCardConstants$State;->CARD_IO_ERROR:Lcom/android/internal/telephony/IccCardConstants$State;
 Lcom/android/internal/telephony/IccCardConstants$State;->NETWORK_LOCKED:Lcom/android/internal/telephony/IccCardConstants$State;
@@ -2397,47 +1462,7 @@
 Lcom/android/internal/telephony/IccCardConstants$State;->READY:Lcom/android/internal/telephony/IccCardConstants$State;
 Lcom/android/internal/telephony/IccCardConstants$State;->UNKNOWN:Lcom/android/internal/telephony/IccCardConstants$State;
 Lcom/android/internal/telephony/IccCardConstants$State;->values()[Lcom/android/internal/telephony/IccCardConstants$State;
-Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->checkThread()V
-Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->DBG:Z
-Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->logd(Ljava/lang/String;)V
-Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->loge(Ljava/lang/String;)V
-Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mAdnCache:Lcom/android/internal/telephony/uicc/AdnRecordCache;
-Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mBaseHandler:Landroid/os/Handler;
-Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mPhone:Lcom/android/internal/telephony/Phone;
-Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->updateEfForIccType(I)I
 Lcom/android/internal/telephony/IccProvider;-><init>()V
-Lcom/android/internal/telephony/IccProvider;->ADDRESS_BOOK_COLUMN_NAMES:[Ljava/lang/String;
-Lcom/android/internal/telephony/IccProvider;->DBG:Z
-Lcom/android/internal/telephony/IccProvider;->loadRecord(Lcom/android/internal/telephony/uicc/AdnRecord;Landroid/database/MatrixCursor;I)V
-Lcom/android/internal/telephony/IccProvider;->log(Ljava/lang/String;)V
-Lcom/android/internal/telephony/IccSmsInterfaceManager;->copyMessageToIccEf(Ljava/lang/String;I[B[B)Z
-Lcom/android/internal/telephony/IccSmsInterfaceManager;->disableCdmaBroadcastRange(II)Z
-Lcom/android/internal/telephony/IccSmsInterfaceManager;->disableGsmBroadcastRange(II)Z
-Lcom/android/internal/telephony/IccSmsInterfaceManager;->enableCdmaBroadcastRange(II)Z
-Lcom/android/internal/telephony/IccSmsInterfaceManager;->enableGsmBroadcastRange(II)Z
-Lcom/android/internal/telephony/IccSmsInterfaceManager;->enforceReceiveAndSend(Ljava/lang/String;)V
-Lcom/android/internal/telephony/IccSmsInterfaceManager;->filterDestAddress(Ljava/lang/String;)Ljava/lang/String;
-Lcom/android/internal/telephony/IccSmsInterfaceManager;->getAllMessagesFromIccEf(Ljava/lang/String;)Ljava/util/List;
-Lcom/android/internal/telephony/IccSmsInterfaceManager;->getImsSmsFormat()Ljava/lang/String;
-Lcom/android/internal/telephony/IccSmsInterfaceManager;->getPremiumSmsPermission(Ljava/lang/String;)I
-Lcom/android/internal/telephony/IccSmsInterfaceManager;->injectSmsPdu([BLjava/lang/String;Landroid/app/PendingIntent;)V
-Lcom/android/internal/telephony/IccSmsInterfaceManager;->isImsSmsSupported()Z
-Lcom/android/internal/telephony/IccSmsInterfaceManager;->log(Ljava/lang/String;)V
-Lcom/android/internal/telephony/IccSmsInterfaceManager;->mAppOps:Landroid/app/AppOpsManager;
-Lcom/android/internal/telephony/IccSmsInterfaceManager;->mCellBroadcastRangeManager:Lcom/android/internal/telephony/IccSmsInterfaceManager$CellBroadcastRangeManager;
-Lcom/android/internal/telephony/IccSmsInterfaceManager;->mContext:Landroid/content/Context;
-Lcom/android/internal/telephony/IccSmsInterfaceManager;->mHandler:Landroid/os/Handler;
-Lcom/android/internal/telephony/IccSmsInterfaceManager;->mLock:Ljava/lang/Object;
-Lcom/android/internal/telephony/IccSmsInterfaceManager;->mPhone:Lcom/android/internal/telephony/Phone;
-Lcom/android/internal/telephony/IccSmsInterfaceManager;->mSms:Ljava/util/List;
-Lcom/android/internal/telephony/IccSmsInterfaceManager;->mSuccess:Z
-Lcom/android/internal/telephony/IccSmsInterfaceManager;->sendData(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I[BLandroid/app/PendingIntent;Landroid/app/PendingIntent;)V
-Lcom/android/internal/telephony/IccSmsInterfaceManager;->sendStoredMultipartText(Ljava/lang/String;Landroid/net/Uri;Ljava/lang/String;Ljava/util/List;Ljava/util/List;)V
-Lcom/android/internal/telephony/IccSmsInterfaceManager;->sendStoredText(Ljava/lang/String;Landroid/net/Uri;Ljava/lang/String;Landroid/app/PendingIntent;Landroid/app/PendingIntent;)V
-Lcom/android/internal/telephony/IccSmsInterfaceManager;->setCdmaBroadcastConfig([Lcom/android/internal/telephony/cdma/CdmaSmsBroadcastConfigInfo;)Z
-Lcom/android/internal/telephony/IccSmsInterfaceManager;->setCellBroadcastConfig([Lcom/android/internal/telephony/gsm/SmsBroadcastConfigInfo;)Z
-Lcom/android/internal/telephony/IccSmsInterfaceManager;->setPremiumSmsPermission(Ljava/lang/String;I)V
-Lcom/android/internal/telephony/IccSmsInterfaceManager;->updateMessageOnIccEf(Ljava/lang/String;II[B)Z
 Lcom/android/internal/telephony/IIccPhoneBook$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Lcom/android/internal/telephony/IIccPhoneBook$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IIccPhoneBook;
 Lcom/android/internal/telephony/IIccPhoneBook;->getAdnRecordsInEf(I)Ljava/util/List;
@@ -2446,142 +1471,24 @@
 Lcom/android/internal/telephony/IIccPhoneBook;->getAdnRecordsSizeForSubscriber(II)[I
 Lcom/android/internal/telephony/IIccPhoneBook;->updateAdnRecordsInEfBySearch(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z
 Lcom/android/internal/telephony/IMms$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IMms;
-Lcom/android/internal/telephony/imsphone/ImsExternalCall;-><init>(Lcom/android/internal/telephony/Phone;Lcom/android/internal/telephony/imsphone/ImsExternalConnection;)V
 Lcom/android/internal/telephony/imsphone/ImsExternalCallTracker$ExternalCallStateListener;-><init>(Lcom/android/internal/telephony/imsphone/ImsExternalCallTracker;)V
 Lcom/android/internal/telephony/imsphone/ImsExternalCallTracker$ExternalConnectionListener;-><init>(Lcom/android/internal/telephony/imsphone/ImsExternalCallTracker;)V
-Lcom/android/internal/telephony/imsphone/ImsExternalConnection;->rebuildCapabilities()V
-Lcom/android/internal/telephony/imsphone/ImsExternalConnection;->setActive()V
-Lcom/android/internal/telephony/imsphone/ImsPhone$Cf;-><init>(Ljava/lang/String;ZLandroid/os/Message;)V
-Lcom/android/internal/telephony/imsphone/ImsPhone;->getActionFromCFAction(I)I
-Lcom/android/internal/telephony/imsphone/ImsPhone;->getBackgroundCall()Lcom/android/internal/telephony/imsphone/ImsPhoneCall;
-Lcom/android/internal/telephony/imsphone/ImsPhone;->getCallForwardingOption(ILandroid/os/Message;)V
-Lcom/android/internal/telephony/imsphone/ImsPhone;->getCallWaiting(Landroid/os/Message;)V
-Lcom/android/internal/telephony/imsphone/ImsPhone;->getConditionFromCFReason(I)I
-Lcom/android/internal/telephony/imsphone/ImsPhone;->getForegroundCall()Lcom/android/internal/telephony/imsphone/ImsPhoneCall;
-Lcom/android/internal/telephony/imsphone/ImsPhone;->getRingingCall()Lcom/android/internal/telephony/imsphone/ImsPhoneCall;
-Lcom/android/internal/telephony/imsphone/ImsPhone;->getServiceState()Landroid/telephony/ServiceState;
-Lcom/android/internal/telephony/imsphone/ImsPhone;->getState()Lcom/android/internal/telephony/PhoneConstants$State;
-Lcom/android/internal/telephony/imsphone/ImsPhone;->handleEnterEmergencyCallbackMode()V
-Lcom/android/internal/telephony/imsphone/ImsPhone;->handleExitEmergencyCallbackMode()V
-Lcom/android/internal/telephony/imsphone/ImsPhone;->handleInCallMmiCommands(Ljava/lang/String;)Z
-Lcom/android/internal/telephony/imsphone/ImsPhone;->isCfEnable(I)Z
-Lcom/android/internal/telephony/imsphone/ImsPhone;->isUtEnabled()Z
-Lcom/android/internal/telephony/imsphone/ImsPhone;->isValidCommandInterfaceCFAction(I)Z
-Lcom/android/internal/telephony/imsphone/ImsPhone;->isValidCommandInterfaceCFReason(I)Z
-Lcom/android/internal/telephony/imsphone/ImsPhone;->isVolteEnabled()Z
-Lcom/android/internal/telephony/imsphone/ImsPhone;->mCT:Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;
-Lcom/android/internal/telephony/imsphone/ImsPhone;->mPendingMMIs:Ljava/util/ArrayList;
-Lcom/android/internal/telephony/imsphone/ImsPhone;->mSS:Landroid/telephony/ServiceState;
 Lcom/android/internal/telephony/imsphone/ImsPhone;->notifyCallForwardingIndicator()V
 Lcom/android/internal/telephony/imsphone/ImsPhone;->notifyPreciseCallStateChanged()V
-Lcom/android/internal/telephony/imsphone/ImsPhone;->notifyUnknownConnection(Lcom/android/internal/telephony/Connection;)V
-Lcom/android/internal/telephony/imsphone/ImsPhone;->onMMIDone(Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;)V
-Lcom/android/internal/telephony/imsphone/ImsPhone;->sendErrorResponse(Landroid/os/Message;)V
-Lcom/android/internal/telephony/imsphone/ImsPhone;->sendErrorResponse(Landroid/os/Message;Ljava/lang/Throwable;)V
-Lcom/android/internal/telephony/imsphone/ImsPhone;->setCallForwardingOption(IILjava/lang/String;IILandroid/os/Message;)V
-Lcom/android/internal/telephony/imsphone/ImsPhone;->setCallWaiting(ZLandroid/os/Message;)V
-Lcom/android/internal/telephony/imsphone/ImsPhone;->setImsRegistered(Z)V
-Lcom/android/internal/telephony/imsphone/ImsPhone;->setOnEcbModeExitResponse(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/imsphone/ImsPhone;->setServiceState(I)V
-Lcom/android/internal/telephony/imsphone/ImsPhoneCall;->attach(Lcom/android/internal/telephony/Connection;Lcom/android/internal/telephony/Call$State;)V
-Lcom/android/internal/telephony/imsphone/ImsPhoneCall;->attachFake(Lcom/android/internal/telephony/Connection;Lcom/android/internal/telephony/Call$State;)V
-Lcom/android/internal/telephony/imsphone/ImsPhoneCall;->getConnections()Ljava/util/List;
 Lcom/android/internal/telephony/imsphone/ImsPhoneCall;->getImsCall()Lcom/android/ims/ImsCall;
-Lcom/android/internal/telephony/imsphone/ImsPhoneCall;->hangup()V
-Lcom/android/internal/telephony/imsphone/ImsPhoneCall;->merge(Lcom/android/internal/telephony/imsphone/ImsPhoneCall;Lcom/android/internal/telephony/Call$State;)V
-Lcom/android/internal/telephony/imsphone/ImsPhoneCall;->onHangupLocal()V
-Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->addConnection(Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;)V
-Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->clearDisconnected()V
-Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->dial(Ljava/lang/String;ILandroid/os/Bundle;)Lcom/android/internal/telephony/Connection;
-Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->dialPendingMO()V
 Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->findConnection(Lcom/android/ims/ImsCall;)Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;
 Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->getEcbmInterface()Lcom/android/ims/ImsEcbm;
-Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->getUtInterface()Lcom/android/ims/ImsUtInterface;
-Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->handleEcmTimer(I)V
-Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->log(Ljava/lang/String;)V
-Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->loge(Ljava/lang/String;)V
-Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mAllowEmergencyVideoCalls:Z
-Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mBackgroundCall:Lcom/android/internal/telephony/imsphone/ImsPhoneCall;
 Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mCallExpectedToResume:Lcom/android/ims/ImsCall;
-Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mConnections:Ljava/util/ArrayList;
-Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mForegroundCall:Lcom/android/internal/telephony/imsphone/ImsPhoneCall;
-Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mHandoverCall:Lcom/android/internal/telephony/imsphone/ImsPhoneCall;
 Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mImsCallListener:Lcom/android/ims/ImsCall$Listener;
 Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mImsManager:Lcom/android/ims/ImsManager;
-Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mOnHoldToneId:I
-Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mOnHoldToneStarted:Z
-Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mPendingMO:Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;
-Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mPendingUssd:Landroid/os/Message;
-Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mPhone:Lcom/android/internal/telephony/imsphone/ImsPhone;
-Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mRingingCall:Lcom/android/internal/telephony/imsphone/ImsPhoneCall;
-Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mSwitchingFgAndBgCalls:Z
-Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mSyncHold:Ljava/lang/Object;
 Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mUssdSession:Lcom/android/ims/ImsCall;
 Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->processCallStateChange(Lcom/android/ims/ImsCall;Lcom/android/internal/telephony/Call$State;I)V
 Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->processCallStateChange(Lcom/android/ims/ImsCall;Lcom/android/internal/telephony/Call$State;IZ)V
-Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->removeConnection(Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;)V
 Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->setVideoCallProvider(Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;Lcom/android/ims/ImsCall;)V
-Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->switchAfterConferenceSuccess()V
-Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->updatePhoneState()V
 Lcom/android/internal/telephony/imsphone/ImsPhoneConnection$MyHandler;-><init>(Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;Landroid/os/Looper;)V
-Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->acquireWakeLock()V
-Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->createWakeLock(Landroid/content/Context;)V
-Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->getCall()Lcom/android/internal/telephony/imsphone/ImsPhoneCall;
-Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->getOwner()Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;
-Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->isMultiparty()Z
-Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->mDisconnected:Z
 Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->mImsCall:Lcom/android/ims/ImsCall;
-Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->mOwner:Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;
-Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->mParent:Lcom/android/internal/telephony/imsphone/ImsPhoneCall;
-Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->onDisconnect()Z
 Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->update(Lcom/android/ims/ImsCall;Lcom/android/internal/telephony/Call$State;)Z
-Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->getCLIRMode()I
-Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->getDialingNumber()Ljava/lang/String;
-Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->getErrorMessage(Landroid/os/AsyncResult;)Ljava/lang/CharSequence;
-Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->getScString()Ljava/lang/CharSequence;
-Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->isActivate()Z
-Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->isDeactivate()Z
-Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->isEmptyOrNull(Ljava/lang/CharSequence;)Z
-Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->isErasure()Z
-Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->isRegister()Z
-Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->isSupportedOverImsPhone()Z
-Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->isTemporaryModeCLIR()Z
-Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->mContext:Landroid/content/Context;
-Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->mPhone:Lcom/android/internal/telephony/imsphone/ImsPhone;
-Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->newFromDialString(Ljava/lang/String;Lcom/android/internal/telephony/imsphone/ImsPhone;)Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;
-Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->processCode()V
-Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->serviceClassToCFString(I)Ljava/lang/CharSequence;
 Lcom/android/internal/telephony/InboundSmsHandler$SmsBroadcastReceiver;-><init>(Lcom/android/internal/telephony/InboundSmsHandler;Lcom/android/internal/telephony/InboundSmsTracker;)V
-Lcom/android/internal/telephony/InboundSmsHandler$SmsBroadcastReceiver;->mDeleteWhere:Ljava/lang/String;
-Lcom/android/internal/telephony/InboundSmsHandler$SmsBroadcastReceiver;->mDeleteWhereArgs:[Ljava/lang/String;
-Lcom/android/internal/telephony/InboundSmsHandler;->acknowledgeLastIncomingSms(ZILandroid/os/Message;)V
-Lcom/android/internal/telephony/InboundSmsHandler;->deleteFromRawTable(Ljava/lang/String;[Ljava/lang/String;I)V
-Lcom/android/internal/telephony/InboundSmsHandler;->dispatchIntent(Landroid/content/Intent;Ljava/lang/String;ILandroid/os/Bundle;Landroid/content/BroadcastReceiver;Landroid/os/UserHandle;)V
-Lcom/android/internal/telephony/InboundSmsHandler;->dispatchNormalMessage(Lcom/android/internal/telephony/SmsMessageBase;)I
-Lcom/android/internal/telephony/InboundSmsHandler;->getPhone()Lcom/android/internal/telephony/Phone;
-Lcom/android/internal/telephony/InboundSmsHandler;->handleInjectSms(Landroid/os/AsyncResult;)V
-Lcom/android/internal/telephony/InboundSmsHandler;->handleNewSms(Landroid/os/AsyncResult;)V
-Lcom/android/internal/telephony/InboundSmsHandler;->handleSmsWhitelisting(Landroid/content/ComponentName;)Landroid/os/Bundle;
-Lcom/android/internal/telephony/InboundSmsHandler;->isSkipNotifyFlagSet(I)Z
-Lcom/android/internal/telephony/InboundSmsHandler;->log(Ljava/lang/String;)V
-Lcom/android/internal/telephony/InboundSmsHandler;->loge(Ljava/lang/String;)V
-Lcom/android/internal/telephony/InboundSmsHandler;->mCellBroadcastHandler:Lcom/android/internal/telephony/CellBroadcastHandler;
-Lcom/android/internal/telephony/InboundSmsHandler;->mContext:Landroid/content/Context;
-Lcom/android/internal/telephony/InboundSmsHandler;->mDeliveringState:Lcom/android/internal/telephony/InboundSmsHandler$DeliveringState;
-Lcom/android/internal/telephony/InboundSmsHandler;->mDeviceIdleController:Landroid/os/IDeviceIdleController;
-Lcom/android/internal/telephony/InboundSmsHandler;->mIdleState:Lcom/android/internal/telephony/InboundSmsHandler$IdleState;
-Lcom/android/internal/telephony/InboundSmsHandler;->mPhone:Lcom/android/internal/telephony/Phone;
-Lcom/android/internal/telephony/InboundSmsHandler;->mResolver:Landroid/content/ContentResolver;
-Lcom/android/internal/telephony/InboundSmsHandler;->mUserManager:Landroid/os/UserManager;
-Lcom/android/internal/telephony/InboundSmsHandler;->mWaitingState:Lcom/android/internal/telephony/InboundSmsHandler$WaitingState;
-Lcom/android/internal/telephony/InboundSmsHandler;->mWakeLock:Landroid/os/PowerManager$WakeLock;
-Lcom/android/internal/telephony/InboundSmsHandler;->mWapPush:Lcom/android/internal/telephony/WapPushOverSms;
-Lcom/android/internal/telephony/InboundSmsHandler;->processMessagePart(Lcom/android/internal/telephony/InboundSmsTracker;)Z
-Lcom/android/internal/telephony/InboundSmsHandler;->showNewMessageNotification()V
-Lcom/android/internal/telephony/InboundSmsHandler;->writeInboxMessage(Landroid/content/Intent;)Landroid/net/Uri;
-Lcom/android/internal/telephony/InboundSmsTracker;->getFormat()Ljava/lang/String;
-Lcom/android/internal/telephony/InboundSmsTracker;->getIndexOffset()I
-Lcom/android/internal/telephony/IntRangeManager;->mRanges:Ljava/util/ArrayList;
 Lcom/android/internal/telephony/IPhoneStateListener$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IPhoneStateListener;
 Lcom/android/internal/telephony/IPhoneSubInfo$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Lcom/android/internal/telephony/IPhoneSubInfo$Stub$Proxy;->getDeviceId(Ljava/lang/String;)Ljava/lang/String;
@@ -2603,91 +1510,6 @@
 Lcom/android/internal/telephony/ITelephonyRegistry$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Lcom/android/internal/telephony/ITelephonyRegistry$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/ITelephonyRegistry;
 Lcom/android/internal/telephony/IWapPushManager$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IWapPushManager;
-Lcom/android/internal/telephony/MccTable$MccEntry;->mIso:Ljava/lang/String;
-Lcom/android/internal/telephony/MccTable;->countryCodeForMcc(I)Ljava/lang/String;
-Lcom/android/internal/telephony/MccTable;->defaultLanguageForMcc(I)Ljava/lang/String;
-Lcom/android/internal/telephony/MccTable;->defaultTimeZoneForMcc(I)Ljava/lang/String;
-Lcom/android/internal/telephony/MccTable;->entryForMcc(I)Lcom/android/internal/telephony/MccTable$MccEntry;
-Lcom/android/internal/telephony/MccTable;->getLocaleForLanguageCountry(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)Ljava/util/Locale;
-Lcom/android/internal/telephony/MccTable;->smallestDigitsMccForMnc(I)I
-Lcom/android/internal/telephony/MmiCode$State;->CANCELLED:Lcom/android/internal/telephony/MmiCode$State;
-Lcom/android/internal/telephony/MmiCode$State;->COMPLETE:Lcom/android/internal/telephony/MmiCode$State;
-Lcom/android/internal/telephony/MmiCode$State;->FAILED:Lcom/android/internal/telephony/MmiCode$State;
-Lcom/android/internal/telephony/MmiCode$State;->PENDING:Lcom/android/internal/telephony/MmiCode$State;
-Lcom/android/internal/telephony/MmiCode;->getPhone()Lcom/android/internal/telephony/Phone;
-Lcom/android/internal/telephony/Phone;->dispose()V
-Lcom/android/internal/telephony/Phone;->exitEmergencyCallbackMode()V
-Lcom/android/internal/telephony/Phone;->getActiveApnTypes()[Ljava/lang/String;
-Lcom/android/internal/telephony/Phone;->getCallTracker()Lcom/android/internal/telephony/CallTracker;
-Lcom/android/internal/telephony/Phone;->getCellLocation()Landroid/telephony/CellLocation;
-Lcom/android/internal/telephony/Phone;->getContext()Landroid/content/Context;
-Lcom/android/internal/telephony/Phone;->getDataConnectionState()Lcom/android/internal/telephony/PhoneConstants$DataState;
-Lcom/android/internal/telephony/Phone;->getIccCard()Lcom/android/internal/telephony/IccCard;
-Lcom/android/internal/telephony/Phone;->getIccFileHandler()Lcom/android/internal/telephony/uicc/IccFileHandler;
-Lcom/android/internal/telephony/Phone;->getIccSerialNumber()Ljava/lang/String;
-Lcom/android/internal/telephony/Phone;->getIccSmsInterfaceManager()Lcom/android/internal/telephony/IccSmsInterfaceManager;
-Lcom/android/internal/telephony/Phone;->getImsPhone()Lcom/android/internal/telephony/Phone;
-Lcom/android/internal/telephony/Phone;->getIsimRecords()Lcom/android/internal/telephony/uicc/IsimRecords;
-Lcom/android/internal/telephony/Phone;->getMsisdn()Ljava/lang/String;
-Lcom/android/internal/telephony/Phone;->getNai()Ljava/lang/String;
-Lcom/android/internal/telephony/Phone;->getPhoneId()I
-Lcom/android/internal/telephony/Phone;->getPhoneName()Ljava/lang/String;
-Lcom/android/internal/telephony/Phone;->getPhoneType()I
-Lcom/android/internal/telephony/Phone;->getServiceStateTracker()Lcom/android/internal/telephony/ServiceStateTracker;
-Lcom/android/internal/telephony/Phone;->getSmscAddress(Landroid/os/Message;)V
-Lcom/android/internal/telephony/Phone;->getState()Lcom/android/internal/telephony/PhoneConstants$State;
-Lcom/android/internal/telephony/Phone;->getSubId()I
-Lcom/android/internal/telephony/Phone;->getSystemProperty(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
-Lcom/android/internal/telephony/Phone;->getUiccCard()Lcom/android/internal/telephony/uicc/UiccCard;
-Lcom/android/internal/telephony/Phone;->getVideoState(Lcom/android/internal/telephony/Call;)I
-Lcom/android/internal/telephony/Phone;->invokeOemRilRequestRaw([BLandroid/os/Message;)V
-Lcom/android/internal/telephony/Phone;->invokeOemRilRequestStrings([Ljava/lang/String;Landroid/os/Message;)V
-Lcom/android/internal/telephony/Phone;->isCspPlmnEnabled()Z
-Lcom/android/internal/telephony/Phone;->isUtEnabled()Z
-Lcom/android/internal/telephony/Phone;->isVideoEnabled()Z
-Lcom/android/internal/telephony/Phone;->isVolteEnabled()Z
-Lcom/android/internal/telephony/Phone;->isWifiCallingEnabled()Z
-Lcom/android/internal/telephony/Phone;->mCi:Lcom/android/internal/telephony/CommandsInterface;
-Lcom/android/internal/telephony/Phone;->mContext:Landroid/content/Context;
-Lcom/android/internal/telephony/Phone;->mIccRecords:Ljava/util/concurrent/atomic/AtomicReference;
-Lcom/android/internal/telephony/Phone;->mImsPhone:Lcom/android/internal/telephony/Phone;
-Lcom/android/internal/telephony/Phone;->mMmiRegistrants:Landroid/os/RegistrantList;
-Lcom/android/internal/telephony/Phone;->mNotifier:Lcom/android/internal/telephony/PhoneNotifier;
-Lcom/android/internal/telephony/Phone;->mPhoneId:I
-Lcom/android/internal/telephony/Phone;->mSmsStorageMonitor:Lcom/android/internal/telephony/SmsStorageMonitor;
-Lcom/android/internal/telephony/Phone;->mUiccApplication:Ljava/util/concurrent/atomic/AtomicReference;
-Lcom/android/internal/telephony/Phone;->mUiccController:Lcom/android/internal/telephony/uicc/UiccController;
-Lcom/android/internal/telephony/Phone;->needsOtaServiceProvisioning()Z
-Lcom/android/internal/telephony/Phone;->notifyOtaspChanged(I)V
-Lcom/android/internal/telephony/Phone;->registerForDisconnect(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/Phone;->registerForEcmTimerReset(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/Phone;->registerForIncomingRing(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/Phone;->registerForMmiComplete(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/Phone;->registerForMmiInitiate(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/Phone;->registerForNewRingingConnection(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/Phone;->registerForPreciseCallStateChanged(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/Phone;->registerForRingbackTone(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/Phone;->registerForServiceStateChanged(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/Phone;->registerForSimRecordsLoaded(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/Phone;->registerForUnknownConnection(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/Phone;->selectNetworkManually(Lcom/android/internal/telephony/OperatorInfo;ZLandroid/os/Message;)V
-Lcom/android/internal/telephony/Phone;->setNetworkSelectionModeAutomatic(Landroid/os/Message;)V
-Lcom/android/internal/telephony/Phone;->setOnEcbModeExitResponse(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/Phone;->setOnPostDialCharacter(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/Phone;->setPreferredNetworkType(ILandroid/os/Message;)V
-Lcom/android/internal/telephony/Phone;->setSmscAddress(Ljava/lang/String;Landroid/os/Message;)V
-Lcom/android/internal/telephony/Phone;->unregisterForDisconnect(Landroid/os/Handler;)V
-Lcom/android/internal/telephony/Phone;->unregisterForEcmTimerReset(Landroid/os/Handler;)V
-Lcom/android/internal/telephony/Phone;->unregisterForIncomingRing(Landroid/os/Handler;)V
-Lcom/android/internal/telephony/Phone;->unregisterForMmiComplete(Landroid/os/Handler;)V
-Lcom/android/internal/telephony/Phone;->unregisterForMmiInitiate(Landroid/os/Handler;)V
-Lcom/android/internal/telephony/Phone;->unregisterForNewRingingConnection(Landroid/os/Handler;)V
-Lcom/android/internal/telephony/Phone;->unregisterForPreciseCallStateChanged(Landroid/os/Handler;)V
-Lcom/android/internal/telephony/Phone;->unregisterForRingbackTone(Landroid/os/Handler;)V
-Lcom/android/internal/telephony/Phone;->unregisterForServiceStateChanged(Landroid/os/Handler;)V
-Lcom/android/internal/telephony/Phone;->unregisterForSimRecordsLoaded(Landroid/os/Handler;)V
-Lcom/android/internal/telephony/Phone;->unregisterForUnknownConnection(Landroid/os/Handler;)V
-Lcom/android/internal/telephony/Phone;->unsetOnEcbModeExitResponse(Landroid/os/Handler;)V
 Lcom/android/internal/telephony/PhoneConstants$DataState;->CONNECTED:Lcom/android/internal/telephony/PhoneConstants$DataState;
 Lcom/android/internal/telephony/PhoneConstants$DataState;->CONNECTING:Lcom/android/internal/telephony/PhoneConstants$DataState;
 Lcom/android/internal/telephony/PhoneConstants$DataState;->DISCONNECTED:Lcom/android/internal/telephony/PhoneConstants$DataState;
@@ -2701,152 +1523,7 @@
 Lcom/android/internal/telephony/PhoneConstants;->PRESENTATION_PAYPHONE:I
 Lcom/android/internal/telephony/PhoneConstants;->PRESENTATION_RESTRICTED:I
 Lcom/android/internal/telephony/PhoneConstants;->PRESENTATION_UNKNOWN:I
-Lcom/android/internal/telephony/PhoneFactory;->calculatePreferredNetworkType(Landroid/content/Context;I)I
-Lcom/android/internal/telephony/PhoneFactory;->getDefaultPhone()Lcom/android/internal/telephony/Phone;
-Lcom/android/internal/telephony/PhoneFactory;->getDefaultSubscription()I
-Lcom/android/internal/telephony/PhoneFactory;->getPhone(I)Lcom/android/internal/telephony/Phone;
-Lcom/android/internal/telephony/PhoneFactory;->getPhones()[Lcom/android/internal/telephony/Phone;
-Lcom/android/internal/telephony/PhoneFactory;->makeDefaultPhone(Landroid/content/Context;)V
-Lcom/android/internal/telephony/PhoneFactory;->sCommandsInterface:Lcom/android/internal/telephony/CommandsInterface;
-Lcom/android/internal/telephony/PhoneFactory;->sContext:Landroid/content/Context;
-Lcom/android/internal/telephony/PhoneFactory;->sMadeDefaults:Z
-Lcom/android/internal/telephony/PhoneFactory;->sPhoneNotifier:Lcom/android/internal/telephony/PhoneNotifier;
-Lcom/android/internal/telephony/PhoneInternalInterface$DataActivityState;->NONE:Lcom/android/internal/telephony/PhoneInternalInterface$DataActivityState;
-Lcom/android/internal/telephony/PhoneInternalInterface;->PREFERRED_NT_MODE:I
-Lcom/android/internal/telephony/PhoneNotifier;->notifyMessageWaitingChanged(Lcom/android/internal/telephony/Phone;)V
-Lcom/android/internal/telephony/PhoneNotifier;->notifySignalStrength(Lcom/android/internal/telephony/Phone;)V
-Lcom/android/internal/telephony/PhoneStateIntentReceiver;-><init>(Landroid/content/Context;Landroid/os/Handler;)V
-Lcom/android/internal/telephony/PhoneStateIntentReceiver;->getSignalStrengthDbm()I
-Lcom/android/internal/telephony/PhoneStateIntentReceiver;->mSignalStrength:Landroid/telephony/SignalStrength;
-Lcom/android/internal/telephony/PhoneStateIntentReceiver;->mWants:I
-Lcom/android/internal/telephony/PhoneStateIntentReceiver;->notifyServiceState(I)V
-Lcom/android/internal/telephony/PhoneStateIntentReceiver;->notifySignalStrength(I)V
-Lcom/android/internal/telephony/PhoneStateIntentReceiver;->registerIntent()V
-Lcom/android/internal/telephony/PhoneStateIntentReceiver;->unregisterIntent()V
-Lcom/android/internal/telephony/PhoneSubInfoController;->getDefaultSubscription()I
-Lcom/android/internal/telephony/PhoneSubInfoController;->getPhone(I)Lcom/android/internal/telephony/Phone;
-Lcom/android/internal/telephony/PhoneSubInfoController;->loge(Ljava/lang/String;)V
-Lcom/android/internal/telephony/PhoneSubInfoController;->mContext:Landroid/content/Context;
-Lcom/android/internal/telephony/PhoneSubInfoController;->mPhone:[Lcom/android/internal/telephony/Phone;
-Lcom/android/internal/telephony/PhoneSwitcher;->activate(I)V
-Lcom/android/internal/telephony/PhoneSwitcher;->deactivate(I)V
-Lcom/android/internal/telephony/PhoneSwitcher;->log(Ljava/lang/String;)V
-Lcom/android/internal/telephony/PhoneSwitcher;->mMaxActivePhones:I
-Lcom/android/internal/telephony/PhoneSwitcher;->mNumPhones:I
-Lcom/android/internal/telephony/PhoneSwitcher;->mPhones:[Lcom/android/internal/telephony/Phone;
-Lcom/android/internal/telephony/ProxyController;->completeRadioCapabilityTransaction()V
-Lcom/android/internal/telephony/ProxyController;->getInstance()Lcom/android/internal/telephony/ProxyController;
-Lcom/android/internal/telephony/ProxyController;->logd(Ljava/lang/String;)V
-Lcom/android/internal/telephony/ProxyController;->mOldRadioAccessFamily:[I
-Lcom/android/internal/telephony/ProxyController;->mRadioCapabilitySessionId:I
-Lcom/android/internal/telephony/ProxyController;->mSetRadioAccessFamilyStatus:[I
-Lcom/android/internal/telephony/ProxyController;->mUniqueIdGenerator:Ljava/util/concurrent/atomic/AtomicInteger;
-Lcom/android/internal/telephony/ProxyController;->sendRadioCapabilityRequest(IIIILjava/lang/String;II)V
-Lcom/android/internal/telephony/ProxyController;->sProxyController:Lcom/android/internal/telephony/ProxyController;
-Lcom/android/internal/telephony/RadioCapability;->getRadioAccessFamily()I
-Lcom/android/internal/telephony/RetryManager;->configure(Ljava/lang/String;)Z
-Lcom/android/internal/telephony/RetryManager;->getRetryTimer()I
-Lcom/android/internal/telephony/RetryManager;->log(Ljava/lang/String;)V
-Lcom/android/internal/telephony/RetryManager;->mApnType:Ljava/lang/String;
-Lcom/android/internal/telephony/RetryManager;->mFailFastInterApnDelay:J
-Lcom/android/internal/telephony/RetryManager;->mInterApnDelay:J
-Lcom/android/internal/telephony/RetryManager;->mPhone:Lcom/android/internal/telephony/Phone;
-Lcom/android/internal/telephony/RIL;-><init>(Landroid/content/Context;II)V
-Lcom/android/internal/telephony/RIL;-><init>(Landroid/content/Context;IILjava/lang/Integer;)V
-Lcom/android/internal/telephony/RIL;->acquireWakeLock(Lcom/android/internal/telephony/RILRequest;I)V
-Lcom/android/internal/telephony/RIL;->clearRequestList(IZ)V
-Lcom/android/internal/telephony/RIL;->clearWakeLock(I)Z
-Lcom/android/internal/telephony/RIL;->decrementWakeLock(Lcom/android/internal/telephony/RILRequest;)V
-Lcom/android/internal/telephony/RIL;->findAndRemoveRequestFromList(I)Lcom/android/internal/telephony/RILRequest;
-Lcom/android/internal/telephony/RIL;->getResponseForTimedOutRILRequest(Lcom/android/internal/telephony/RILRequest;)Ljava/lang/Object;
-Lcom/android/internal/telephony/RIL;->hangupForegroundResumeBackground(Landroid/os/Message;)V
-Lcom/android/internal/telephony/RIL;->hangupWaitingOrBackground(Landroid/os/Message;)V
-Lcom/android/internal/telephony/RIL;->invokeOemRilRequestRaw([BLandroid/os/Message;)V
-Lcom/android/internal/telephony/RIL;->makeStaticRadioCapability()Lcom/android/internal/telephony/RadioCapability;
-Lcom/android/internal/telephony/RIL;->mRequestList:Landroid/util/SparseArray;
-Lcom/android/internal/telephony/RIL;->mTestingEmergencyCall:Ljava/util/concurrent/atomic/AtomicBoolean;
-Lcom/android/internal/telephony/RIL;->mWakeLock:Landroid/os/PowerManager$WakeLock;
-Lcom/android/internal/telephony/RIL;->notifyRegistrantsCdmaInfoRec(Lcom/android/internal/telephony/cdma/CdmaInformationRecords;)V
-Lcom/android/internal/telephony/RIL;->notifyRegistrantsRilConnectionChanged(I)V
-Lcom/android/internal/telephony/RIL;->requestToString(I)Ljava/lang/String;
-Lcom/android/internal/telephony/RIL;->responseToString(I)Ljava/lang/String;
-Lcom/android/internal/telephony/RIL;->retToString(ILjava/lang/Object;)Ljava/lang/String;
-Lcom/android/internal/telephony/RIL;->riljLog(Ljava/lang/String;)V
-Lcom/android/internal/telephony/RIL;->setRadioPower(ZLandroid/os/Message;)V
-Lcom/android/internal/telephony/RIL;->unsljLog(I)V
-Lcom/android/internal/telephony/RIL;->unsljLogMore(ILjava/lang/String;)V
-Lcom/android/internal/telephony/RIL;->unsljLogRet(ILjava/lang/Object;)V
-Lcom/android/internal/telephony/RIL;->unsljLogvRet(ILjava/lang/Object;)V
 Lcom/android/internal/telephony/RILConstants;->PREFERRED_NETWORK_MODE:I
-Lcom/android/internal/telephony/RILRequest;->mRequest:I
-Lcom/android/internal/telephony/RILRequest;->mResult:Landroid/os/Message;
-Lcom/android/internal/telephony/RILRequest;->mSerial:I
-Lcom/android/internal/telephony/RILRequest;->obtain(ILandroid/os/Message;)Lcom/android/internal/telephony/RILRequest;
-Lcom/android/internal/telephony/RILRequest;->onError(ILjava/lang/Object;)V
-Lcom/android/internal/telephony/RILRequest;->release()V
-Lcom/android/internal/telephony/RILRequest;->serialString()Ljava/lang/String;
-Lcom/android/internal/telephony/ServiceStateTracker;->fixUnknownMcc(Ljava/lang/String;I)Ljava/lang/String;
-Lcom/android/internal/telephony/ServiceStateTracker;->getCurrentDataConnectionState()I
-Lcom/android/internal/telephony/ServiceStateTracker;->getDesiredPowerState()Z
-Lcom/android/internal/telephony/ServiceStateTracker;->getPhoneId()I
-Lcom/android/internal/telephony/ServiceStateTracker;->getSystemProperty(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
-Lcom/android/internal/telephony/ServiceStateTracker;->isConcurrentVoiceAndDataAllowed()Z
-Lcom/android/internal/telephony/ServiceStateTracker;->isGprsConsistent(II)Z
-Lcom/android/internal/telephony/ServiceStateTracker;->isImsRegistered()Z
-Lcom/android/internal/telephony/ServiceStateTracker;->isInHomeSidNid(II)Z
-Lcom/android/internal/telephony/ServiceStateTracker;->isInvalidOperatorNumeric(Ljava/lang/String;)Z
-Lcom/android/internal/telephony/ServiceStateTracker;->log(Ljava/lang/String;)V
-Lcom/android/internal/telephony/ServiceStateTracker;->loge(Ljava/lang/String;)V
-Lcom/android/internal/telephony/ServiceStateTracker;->mCi:Lcom/android/internal/telephony/CommandsInterface;
-Lcom/android/internal/telephony/ServiceStateTracker;->mCr:Landroid/content/ContentResolver;
-Lcom/android/internal/telephony/ServiceStateTracker;->mCurDataSpn:Ljava/lang/String;
-Lcom/android/internal/telephony/ServiceStateTracker;->mCurPlmn:Ljava/lang/String;
-Lcom/android/internal/telephony/ServiceStateTracker;->mCurShowPlmn:Z
-Lcom/android/internal/telephony/ServiceStateTracker;->mCurShowSpn:Z
-Lcom/android/internal/telephony/ServiceStateTracker;->mCurSpn:Ljava/lang/String;
-Lcom/android/internal/telephony/ServiceStateTracker;->mDataRoamingOffRegistrants:Landroid/os/RegistrantList;
-Lcom/android/internal/telephony/ServiceStateTracker;->mDataRoamingOnRegistrants:Landroid/os/RegistrantList;
-Lcom/android/internal/telephony/ServiceStateTracker;->mDefaultRoamingIndicator:I
-Lcom/android/internal/telephony/ServiceStateTracker;->mDesiredPowerState:Z
-Lcom/android/internal/telephony/ServiceStateTracker;->mDeviceShuttingDown:Z
-Lcom/android/internal/telephony/ServiceStateTracker;->mEmergencyOnly:Z
-Lcom/android/internal/telephony/ServiceStateTracker;->mIccRecords:Lcom/android/internal/telephony/uicc/IccRecords;
-Lcom/android/internal/telephony/ServiceStateTracker;->mIntentReceiver:Landroid/content/BroadcastReceiver;
-Lcom/android/internal/telephony/ServiceStateTracker;->mIsSubscriptionFromRuim:Z
-Lcom/android/internal/telephony/ServiceStateTracker;->mMaxDataCalls:I
-Lcom/android/internal/telephony/ServiceStateTracker;->mNetworkAttachedRegistrants:Landroid/os/RegistrantList;
-Lcom/android/internal/telephony/ServiceStateTracker;->mNewMaxDataCalls:I
-Lcom/android/internal/telephony/ServiceStateTracker;->mNewReasonDataDenied:I
-Lcom/android/internal/telephony/ServiceStateTracker;->mNewSS:Landroid/telephony/ServiceState;
-Lcom/android/internal/telephony/ServiceStateTracker;->mOnSubscriptionsChangedListener:Lcom/android/internal/telephony/ServiceStateTracker$SstSubscriptionsChangedListener;
-Lcom/android/internal/telephony/ServiceStateTracker;->mPhone:Lcom/android/internal/telephony/GsmCdmaPhone;
-Lcom/android/internal/telephony/ServiceStateTracker;->mPreferredNetworkType:I
-Lcom/android/internal/telephony/ServiceStateTracker;->mReasonDataDenied:I
-Lcom/android/internal/telephony/ServiceStateTracker;->mReportedGprsNoReg:Z
-Lcom/android/internal/telephony/ServiceStateTracker;->mRoamingIndicator:I
-Lcom/android/internal/telephony/ServiceStateTracker;->mSignalStrength:Landroid/telephony/SignalStrength;
-Lcom/android/internal/telephony/ServiceStateTracker;->mSpnUpdatePending:Z
-Lcom/android/internal/telephony/ServiceStateTracker;->mSS:Landroid/telephony/ServiceState;
-Lcom/android/internal/telephony/ServiceStateTracker;->mStartedGprsRegCheck:Z
-Lcom/android/internal/telephony/ServiceStateTracker;->mSubId:I
-Lcom/android/internal/telephony/ServiceStateTracker;->mSubscriptionController:Lcom/android/internal/telephony/SubscriptionController;
-Lcom/android/internal/telephony/ServiceStateTracker;->mSubscriptionManager:Landroid/telephony/SubscriptionManager;
-Lcom/android/internal/telephony/ServiceStateTracker;->mUiccApplcation:Lcom/android/internal/telephony/uicc/UiccCardApplication;
-Lcom/android/internal/telephony/ServiceStateTracker;->mUiccController:Lcom/android/internal/telephony/uicc/UiccController;
-Lcom/android/internal/telephony/ServiceStateTracker;->mVoiceRoamingOffRegistrants:Landroid/os/RegistrantList;
-Lcom/android/internal/telephony/ServiceStateTracker;->mVoiceRoamingOnRegistrants:Landroid/os/RegistrantList;
-Lcom/android/internal/telephony/ServiceStateTracker;->notifySignalStrength()Z
-Lcom/android/internal/telephony/ServiceStateTracker;->pollState()V
-Lcom/android/internal/telephony/ServiceStateTracker;->reRegisterNetwork(Landroid/os/Message;)V
-Lcom/android/internal/telephony/ServiceStateTracker;->resetServiceStateInIwlanMode()V
-Lcom/android/internal/telephony/ServiceStateTracker;->setOperatorIdd(Ljava/lang/String;)V
-Lcom/android/internal/telephony/ServiceStateTracker;->setRoamingType(Landroid/telephony/ServiceState;)V
-Lcom/android/internal/telephony/ServiceStateTracker;->setSignalStrengthDefaultValues()V
-Lcom/android/internal/telephony/ServiceStateTracker;->updateOtaspState()V
-Lcom/android/internal/telephony/ServiceStateTracker;->updatePhoneObject()V
-Lcom/android/internal/telephony/ServiceStateTracker;->updateRoamingState()V
-Lcom/android/internal/telephony/ServiceStateTracker;->updateSpnDisplay()V
-Lcom/android/internal/telephony/ServiceStateTracker;->useDataRegStateForDataOnlyDevices()V
 Lcom/android/internal/telephony/sip/SipPhone$SipCall;->hold()V
 Lcom/android/internal/telephony/sip/SipPhone$SipCall;->switchWith(Lcom/android/internal/telephony/sip/SipPhone$SipCall;)V
 Lcom/android/internal/telephony/sip/SipPhone$SipCall;->unhold()V
@@ -2870,100 +1547,14 @@
 Lcom/android/internal/telephony/SmsApplication;->isDefaultSmsApplication(Landroid/content/Context;Ljava/lang/String;)Z
 Lcom/android/internal/telephony/SmsApplication;->setDefaultApplication(Ljava/lang/String;Landroid/content/Context;)V
 Lcom/android/internal/telephony/SmsApplication;->shouldWriteMessageForPackage(Ljava/lang/String;Landroid/content/Context;)Z
-Lcom/android/internal/telephony/SmsBroadcastUndelivered;-><init>(Landroid/content/Context;Lcom/android/internal/telephony/gsm/GsmInboundSmsHandler;Lcom/android/internal/telephony/cdma/CdmaInboundSmsHandler;)V
-Lcom/android/internal/telephony/SMSDispatcher$ConfirmDialogListener;->mNegativeButton:Landroid/widget/Button;
-Lcom/android/internal/telephony/SMSDispatcher$ConfirmDialogListener;->mPositiveButton:Landroid/widget/Button;
-Lcom/android/internal/telephony/SMSDispatcher$ConfirmDialogListener;->mRememberUndoInstruction:Landroid/widget/TextView;
 Lcom/android/internal/telephony/SMSDispatcher$DataSmsSender;-><init>(Lcom/android/internal/telephony/SMSDispatcher;Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;)V
 Lcom/android/internal/telephony/SMSDispatcher$MultipartSmsSender;-><init>(Lcom/android/internal/telephony/SMSDispatcher;Ljava/util/ArrayList;[Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;)V
-Lcom/android/internal/telephony/SMSDispatcher$MultipartSmsSender;->sendSmsByCarrierApp(Ljava/lang/String;Lcom/android/internal/telephony/SMSDispatcher$MultipartSmsSenderCallback;)V
 Lcom/android/internal/telephony/SMSDispatcher$MultipartSmsSenderCallback;-><init>(Lcom/android/internal/telephony/SMSDispatcher;Lcom/android/internal/telephony/SMSDispatcher$MultipartSmsSender;)V
 Lcom/android/internal/telephony/SMSDispatcher$SmsSenderCallback;-><init>(Lcom/android/internal/telephony/SMSDispatcher;Lcom/android/internal/telephony/SMSDispatcher$SmsSender;)V
-Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->isMultipart()Z
-Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->mAppInfo:Landroid/content/pm/PackageInfo;
-Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->mData:Ljava/util/HashMap;
-Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->mDeliveryIntent:Landroid/app/PendingIntent;
-Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->mDestAddress:Ljava/lang/String;
-Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->mMessageRef:I
-Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->mMessageUri:Landroid/net/Uri;
-Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->mPersistMessage:Z
-Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->mSentIntent:Landroid/app/PendingIntent;
-Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->mTimestamp:J
-Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->onFailed(Landroid/content/Context;II)V
-Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->onSent(Landroid/content/Context;)V
-Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->updateSentMessageStatus(Landroid/content/Context;I)V
 Lcom/android/internal/telephony/SMSDispatcher$TextSmsSender;-><init>(Lcom/android/internal/telephony/SMSDispatcher;Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;)V
-Lcom/android/internal/telephony/SMSDispatcher;->calculateLength(Ljava/lang/CharSequence;Z)Lcom/android/internal/telephony/GsmAlphabet$TextEncodingDetails;
-Lcom/android/internal/telephony/SMSDispatcher;->checkCallerIsPhoneOrCarrierApp()V
-Lcom/android/internal/telephony/SMSDispatcher;->deliveryPendingList:Ljava/util/ArrayList;
-Lcom/android/internal/telephony/SMSDispatcher;->dispose()V
-Lcom/android/internal/telephony/SMSDispatcher;->getCarrierAppPackageName()Ljava/lang/String;
-Lcom/android/internal/telephony/SMSDispatcher;->getMultipartMessageText(Ljava/util/ArrayList;)Ljava/lang/String;
-Lcom/android/internal/telephony/SMSDispatcher;->getNextConcatenatedRef()I
-Lcom/android/internal/telephony/SMSDispatcher;->getSubId()I
-Lcom/android/internal/telephony/SMSDispatcher;->handleConfirmShortCode(ZLcom/android/internal/telephony/SMSDispatcher$SmsTracker;)V
-Lcom/android/internal/telephony/SMSDispatcher;->mCi:Lcom/android/internal/telephony/CommandsInterface;
-Lcom/android/internal/telephony/SMSDispatcher;->mContext:Landroid/content/Context;
-Lcom/android/internal/telephony/SMSDispatcher;->mPhone:Lcom/android/internal/telephony/Phone;
-Lcom/android/internal/telephony/SMSDispatcher;->mResolver:Landroid/content/ContentResolver;
-Lcom/android/internal/telephony/SMSDispatcher;->mTelephonyManager:Landroid/telephony/TelephonyManager;
-Lcom/android/internal/telephony/SMSDispatcher;->processSendSmsResponse(Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;II)V
-Lcom/android/internal/telephony/SMSDispatcher;->sendData(Ljava/lang/String;Ljava/lang/String;I[BLandroid/app/PendingIntent;Landroid/app/PendingIntent;)V
-Lcom/android/internal/telephony/SMSDispatcher;->sendMultipartSms(Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;)V
-Lcom/android/internal/telephony/SMSDispatcher;->sendSms(Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;)V
-Lcom/android/internal/telephony/SMSDispatcher;->sendSubmitPdu(Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;)V
 Lcom/android/internal/telephony/SmsHeader$ConcatRef;-><init>()V
 Lcom/android/internal/telephony/SmsHeader$PortAddrs;-><init>()V
 Lcom/android/internal/telephony/SmsMessageBase;-><init>()V
-Lcom/android/internal/telephony/SmsResponse;-><init>(ILjava/lang/String;I)V
-Lcom/android/internal/telephony/SmsResponse;->mAckPdu:Ljava/lang/String;
-Lcom/android/internal/telephony/SmsResponse;->mErrorCode:I
-Lcom/android/internal/telephony/SmsResponse;->mMessageRef:I
-Lcom/android/internal/telephony/SmsStorageMonitor;->mCi:Lcom/android/internal/telephony/CommandsInterface;
-Lcom/android/internal/telephony/SmsUsageMonitor;-><init>(Landroid/content/Context;)V
-Lcom/android/internal/telephony/SmsUsageMonitor;->check(Ljava/lang/String;I)Z
-Lcom/android/internal/telephony/SubscriptionController;->broadcastDefaultDataSubIdChanged(I)V
-Lcom/android/internal/telephony/SubscriptionController;->colorArr:[I
-Lcom/android/internal/telephony/SubscriptionController;->enforceModifyPhoneState(Ljava/lang/String;)V
-Lcom/android/internal/telephony/SubscriptionController;->getActiveSubInfoCount(Ljava/lang/String;)I
-Lcom/android/internal/telephony/SubscriptionController;->getActiveSubscriptionInfo(ILjava/lang/String;)Landroid/telephony/SubscriptionInfo;
-Lcom/android/internal/telephony/SubscriptionController;->getActiveSubscriptionInfoList(Ljava/lang/String;)Ljava/util/List;
-Lcom/android/internal/telephony/SubscriptionController;->getDefaultDataSubId()I
-Lcom/android/internal/telephony/SubscriptionController;->getDefaultSmsSubId()I
-Lcom/android/internal/telephony/SubscriptionController;->getDefaultSubId()I
-Lcom/android/internal/telephony/SubscriptionController;->getDefaultVoiceSubId()I
-Lcom/android/internal/telephony/SubscriptionController;->getInstance()Lcom/android/internal/telephony/SubscriptionController;
-Lcom/android/internal/telephony/SubscriptionController;->getPhoneId(I)I
-Lcom/android/internal/telephony/SubscriptionController;->getSubId(I)[I
-Lcom/android/internal/telephony/SubscriptionController;->getSubIdUsingPhoneId(I)I
-Lcom/android/internal/telephony/SubscriptionController;->getSubInfo(Ljava/lang/String;Ljava/lang/Object;)Ljava/util/List;
-Lcom/android/internal/telephony/SubscriptionController;->getSubInfoRecord(Landroid/database/Cursor;)Landroid/telephony/SubscriptionInfo;
-Lcom/android/internal/telephony/SubscriptionController;->isActiveSubId(I)Z
-Lcom/android/internal/telephony/SubscriptionController;->isSubInfoReady()Z
-Lcom/android/internal/telephony/SubscriptionController;->logd(Ljava/lang/String;)V
-Lcom/android/internal/telephony/SubscriptionController;->logdl(Ljava/lang/String;)V
-Lcom/android/internal/telephony/SubscriptionController;->loge(Ljava/lang/String;)V
-Lcom/android/internal/telephony/SubscriptionController;->mContext:Landroid/content/Context;
-Lcom/android/internal/telephony/SubscriptionController;->mDefaultPhoneId:I
-Lcom/android/internal/telephony/SubscriptionController;->mLock:Ljava/lang/Object;
-Lcom/android/internal/telephony/SubscriptionController;->notifySubscriptionInfoChanged()V
-Lcom/android/internal/telephony/SubscriptionController;->setDefaultDataSubId(I)V
-Lcom/android/internal/telephony/SubscriptionController;->setDefaultFallbackSubId(II)V
-Lcom/android/internal/telephony/SubscriptionController;->setDefaultSmsSubId(I)V
-Lcom/android/internal/telephony/SubscriptionController;->setDefaultVoiceSubId(I)V
-Lcom/android/internal/telephony/SubscriptionController;->setPlmnSpn(IZLjava/lang/String;ZLjava/lang/String;)Z
-Lcom/android/internal/telephony/SubscriptionController;->updateAllDataConnectionTrackers()V
-Lcom/android/internal/telephony/SubscriptionController;->validateSubId(I)V
-Lcom/android/internal/telephony/SubscriptionInfoUpdater;->broadcastSimStateChanged(ILjava/lang/String;Ljava/lang/String;)V
-Lcom/android/internal/telephony/SubscriptionInfoUpdater;->isAllIccIdQueryDone()Z
-Lcom/android/internal/telephony/SubscriptionInfoUpdater;->logd(Ljava/lang/String;)V
-Lcom/android/internal/telephony/SubscriptionInfoUpdater;->mContext:Landroid/content/Context;
-Lcom/android/internal/telephony/SubscriptionInfoUpdater;->mCurrentlyActiveUserId:I
-Lcom/android/internal/telephony/SubscriptionInfoUpdater;->mIccId:[Ljava/lang/String;
-Lcom/android/internal/telephony/SubscriptionInfoUpdater;->mPackageManager:Landroid/content/pm/IPackageManager;
-Lcom/android/internal/telephony/SubscriptionInfoUpdater;->mPhone:[Lcom/android/internal/telephony/Phone;
-Lcom/android/internal/telephony/SubscriptionInfoUpdater;->PROJECT_SIM_NUM:I
-Lcom/android/internal/telephony/TelephonyCapabilities;->supportsAdn(I)Z
 Lcom/android/internal/telephony/TelephonyProperties;->PROPERTY_ICC_OPERATOR_NUMERIC:Ljava/lang/String;
 Lcom/android/internal/telephony/test/InterpreterEx;-><init>(Ljava/lang/String;)V
 Lcom/android/internal/telephony/test/SimulatedCommands;->acceptCall(Landroid/os/Message;)V
@@ -2980,143 +1571,11 @@
 Lcom/android/internal/telephony/test/SimulatedGsmCallState;->releaseHeldOrUDUB()Z
 Lcom/android/internal/telephony/test/SimulatedGsmCallState;->separateCall(I)Z
 Lcom/android/internal/telephony/test/SimulatedGsmCallState;->switchActiveAndHeldOrWaiting()Z
-Lcom/android/internal/telephony/uicc/AdnRecord;-><init>(IILjava/lang/String;Ljava/lang/String;)V
-Lcom/android/internal/telephony/uicc/AdnRecord;-><init>(IILjava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V
-Lcom/android/internal/telephony/uicc/AdnRecord;-><init>(II[B)V
-Lcom/android/internal/telephony/uicc/AdnRecord;-><init>(Ljava/lang/String;Ljava/lang/String;)V
-Lcom/android/internal/telephony/uicc/AdnRecord;-><init>(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V
-Lcom/android/internal/telephony/uicc/AdnRecord;-><init>([B)V
-Lcom/android/internal/telephony/uicc/AdnRecord;->buildAdnString(I)[B
-Lcom/android/internal/telephony/uicc/AdnRecord;->CREATOR:Landroid/os/Parcelable$Creator;
-Lcom/android/internal/telephony/uicc/AdnRecord;->getEmails()[Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/AdnRecord;->getNumber()Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/AdnRecord;->isEmpty()Z
-Lcom/android/internal/telephony/uicc/AdnRecord;->mAlphaTag:Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/AdnRecord;->mEfid:I
-Lcom/android/internal/telephony/uicc/AdnRecord;->mEmails:[Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/AdnRecord;->mExtRecord:I
-Lcom/android/internal/telephony/uicc/AdnRecord;->mNumber:Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/AdnRecord;->mRecordNumber:I
-Lcom/android/internal/telephony/uicc/AdnRecord;->setEmails([Ljava/lang/String;)V
-Lcom/android/internal/telephony/uicc/AdnRecordCache;->extensionEfForEf(I)I
-Lcom/android/internal/telephony/uicc/AdnRecordCache;->getRecordsIfLoaded(I)Ljava/util/ArrayList;
-Lcom/android/internal/telephony/uicc/AdnRecordCache;->mAdnLikeWaiters:Landroid/util/SparseArray;
-Lcom/android/internal/telephony/uicc/AdnRecordCache;->mFh:Lcom/android/internal/telephony/uicc/IccFileHandler;
-Lcom/android/internal/telephony/uicc/AdnRecordCache;->mUserWriteResponse:Landroid/util/SparseArray;
-Lcom/android/internal/telephony/uicc/AdnRecordCache;->mUsimPhoneBookManager:Lcom/android/internal/telephony/gsm/UsimPhoneBookManager;
-Lcom/android/internal/telephony/uicc/AdnRecordCache;->reset()V
-Lcom/android/internal/telephony/uicc/AdnRecordCache;->sendErrorResponse(Landroid/os/Message;Ljava/lang/String;)V
-Lcom/android/internal/telephony/uicc/AdnRecordCache;->updateAdnByIndex(ILcom/android/internal/telephony/uicc/AdnRecord;ILjava/lang/String;Landroid/os/Message;)V
-Lcom/android/internal/telephony/uicc/AdnRecordLoader;-><init>(Lcom/android/internal/telephony/uicc/IccFileHandler;)V
-Lcom/android/internal/telephony/uicc/AdnRecordLoader;->getEFPath(I)Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/AdnRecordLoader;->loadFromEF(IIILandroid/os/Message;)V
-Lcom/android/internal/telephony/uicc/AdnRecordLoader;->mFh:Lcom/android/internal/telephony/uicc/IccFileHandler;
-Lcom/android/internal/telephony/uicc/AdnRecordLoader;->updateEF(Lcom/android/internal/telephony/uicc/AdnRecord;IIILjava/lang/String;Landroid/os/Message;)V
-Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;->APPSTATE_DETECTED:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;
-Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;->APPSTATE_PIN:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;
-Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;->APPSTATE_PUK:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;
-Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;->APPSTATE_READY:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;
-Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;->APPSTATE_SUBSCRIPTION_PERSO:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;
-Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;->APPSTATE_UNKNOWN:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;
 Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;->values()[Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;
-Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;->APPTYPE_CSIM:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
-Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;->APPTYPE_ISIM:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
-Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;->APPTYPE_RUIM:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
-Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;->APPTYPE_SIM:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
-Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;->APPTYPE_UNKNOWN:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
-Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;->APPTYPE_USIM:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
 Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;->values()[Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
-Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;->PERSOSUBSTATE_SIM_NETWORK:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;
-Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;->PERSOSUBSTATE_SIM_NETWORK_SUBSET:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;
-Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;->PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;
-Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;->PERSOSUBSTATE_SIM_SERVICE_PROVIDER:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;
-Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;->PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;
-Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;->PERSOSUBSTATE_UNKNOWN:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;
 Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;->values()[Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;
 Lcom/android/internal/telephony/uicc/IccCardApplicationStatus;-><init>()V
-Lcom/android/internal/telephony/uicc/IccCardApplicationStatus;->AppTypeFromRILInt(I)Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
-Lcom/android/internal/telephony/uicc/IccCardApplicationStatus;->app_type:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
-Lcom/android/internal/telephony/uicc/IccCardStatus$CardState;->CARDSTATE_ABSENT:Lcom/android/internal/telephony/uicc/IccCardStatus$CardState;
-Lcom/android/internal/telephony/uicc/IccCardStatus$CardState;->CARDSTATE_ERROR:Lcom/android/internal/telephony/uicc/IccCardStatus$CardState;
-Lcom/android/internal/telephony/uicc/IccCardStatus$CardState;->CARDSTATE_PRESENT:Lcom/android/internal/telephony/uicc/IccCardStatus$CardState;
-Lcom/android/internal/telephony/uicc/IccCardStatus$CardState;->isCardPresent()Z
-Lcom/android/internal/telephony/uicc/IccCardStatus$PinState;->PINSTATE_DISABLED:Lcom/android/internal/telephony/uicc/IccCardStatus$PinState;
-Lcom/android/internal/telephony/uicc/IccCardStatus$PinState;->PINSTATE_ENABLED_BLOCKED:Lcom/android/internal/telephony/uicc/IccCardStatus$PinState;
-Lcom/android/internal/telephony/uicc/IccCardStatus$PinState;->PINSTATE_ENABLED_PERM_BLOCKED:Lcom/android/internal/telephony/uicc/IccCardStatus$PinState;
-Lcom/android/internal/telephony/uicc/IccCardStatus;->mApplications:[Lcom/android/internal/telephony/uicc/IccCardApplicationStatus;
-Lcom/android/internal/telephony/uicc/IccCardStatus;->mCardState:Lcom/android/internal/telephony/uicc/IccCardStatus$CardState;
-Lcom/android/internal/telephony/uicc/IccCardStatus;->mCdmaSubscriptionAppIndex:I
-Lcom/android/internal/telephony/uicc/IccCardStatus;->mGsmUmtsSubscriptionAppIndex:I
-Lcom/android/internal/telephony/uicc/IccCardStatus;->mImsSubscriptionAppIndex:I
-Lcom/android/internal/telephony/uicc/IccCardStatus;->mUniversalPinState:Lcom/android/internal/telephony/uicc/IccCardStatus$PinState;
-Lcom/android/internal/telephony/uicc/IccFileHandler$LoadLinearFixedContext;-><init>(IILandroid/os/Message;)V
-Lcom/android/internal/telephony/uicc/IccFileHandler$LoadLinearFixedContext;->mRecordSize:I
-Lcom/android/internal/telephony/uicc/IccFileHandler$LoadLinearFixedContext;->results:Ljava/util/ArrayList;
-Lcom/android/internal/telephony/uicc/IccFileHandler;->getEFLinearRecordSize(ILandroid/os/Message;)V
-Lcom/android/internal/telephony/uicc/IccFileHandler;->getEFLinearRecordSize(ILjava/lang/String;Landroid/os/Message;)V
-Lcom/android/internal/telephony/uicc/IccFileHandler;->getEFPath(I)Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/IccFileHandler;->loadEFLinearFixed(IILandroid/os/Message;)V
-Lcom/android/internal/telephony/uicc/IccFileHandler;->loadEFLinearFixed(ILjava/lang/String;ILandroid/os/Message;)V
-Lcom/android/internal/telephony/uicc/IccFileHandler;->loadEFLinearFixedAll(ILandroid/os/Message;)V
-Lcom/android/internal/telephony/uicc/IccFileHandler;->loadEFLinearFixedAll(ILjava/lang/String;Landroid/os/Message;)V
-Lcom/android/internal/telephony/uicc/IccFileHandler;->loadEFTransparent(ILandroid/os/Message;)V
-Lcom/android/internal/telephony/uicc/IccFileHandler;->mAid:Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/IccFileHandler;->mCi:Lcom/android/internal/telephony/CommandsInterface;
-Lcom/android/internal/telephony/uicc/IccFileHandler;->mParentApp:Lcom/android/internal/telephony/uicc/UiccCardApplication;
-Lcom/android/internal/telephony/uicc/IccFileHandler;->updateEFLinearFixed(II[BLjava/lang/String;Landroid/os/Message;)V
-Lcom/android/internal/telephony/uicc/IccFileHandler;->updateEFLinearFixed(ILjava/lang/String;I[BLjava/lang/String;Landroid/os/Message;)V
-Lcom/android/internal/telephony/uicc/IccFileHandler;->updateEFTransparent(I[BLandroid/os/Message;)V
-Lcom/android/internal/telephony/uicc/IccIoResult;-><init>(IILjava/lang/String;)V
-Lcom/android/internal/telephony/uicc/IccIoResult;-><init>(II[B)V
-Lcom/android/internal/telephony/uicc/IccIoResult;->payload:[B
-Lcom/android/internal/telephony/uicc/IccIoResult;->success()Z
-Lcom/android/internal/telephony/uicc/IccIoResult;->sw1:I
-Lcom/android/internal/telephony/uicc/IccIoResult;->sw2:I
-Lcom/android/internal/telephony/uicc/IccRecords;->auth_rsp:Lcom/android/internal/telephony/uicc/IccIoResult;
-Lcom/android/internal/telephony/uicc/IccRecords;->getGid1()Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/IccRecords;->getIccId()Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/IccRecords;->getIccSimChallengeResponse(ILjava/lang/String;)Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/IccRecords;->getIMSI()Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/IccRecords;->getMsisdnNumber()Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/IccRecords;->getOperatorNumeric()Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/IccRecords;->getRecordsLoaded()Z
-Lcom/android/internal/telephony/uicc/IccRecords;->getServiceProviderName()Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/IccRecords;->getUsimServiceTable()Lcom/android/internal/telephony/uicc/UsimServiceTable;
-Lcom/android/internal/telephony/uicc/IccRecords;->handleRefresh(Lcom/android/internal/telephony/uicc/IccRefreshResponse;)V
-Lcom/android/internal/telephony/uicc/IccRecords;->log(Ljava/lang/String;)V
-Lcom/android/internal/telephony/uicc/IccRecords;->mAdnCache:Lcom/android/internal/telephony/uicc/AdnRecordCache;
-Lcom/android/internal/telephony/uicc/IccRecords;->mCi:Lcom/android/internal/telephony/CommandsInterface;
-Lcom/android/internal/telephony/uicc/IccRecords;->mContext:Landroid/content/Context;
-Lcom/android/internal/telephony/uicc/IccRecords;->mDestroyed:Ljava/util/concurrent/atomic/AtomicBoolean;
-Lcom/android/internal/telephony/uicc/IccRecords;->mFh:Lcom/android/internal/telephony/uicc/IccFileHandler;
-Lcom/android/internal/telephony/uicc/IccRecords;->mGid1:Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/IccRecords;->mIccId:Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/IccRecords;->mImsi:Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/IccRecords;->mIsVoiceMailFixed:Z
-Lcom/android/internal/telephony/uicc/IccRecords;->mLock:Ljava/lang/Object;
-Lcom/android/internal/telephony/uicc/IccRecords;->mMncLength:I
-Lcom/android/internal/telephony/uicc/IccRecords;->mParentApp:Lcom/android/internal/telephony/uicc/UiccCardApplication;
-Lcom/android/internal/telephony/uicc/IccRecords;->mRecordsEventsRegistrants:Landroid/os/RegistrantList;
-Lcom/android/internal/telephony/uicc/IccRecords;->mRecordsToLoad:I
-Lcom/android/internal/telephony/uicc/IccRecords;->mSpn:Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/IccRecords;->mTelephonyManager:Landroid/telephony/TelephonyManager;
-Lcom/android/internal/telephony/uicc/IccRecords;->mVoiceMailNum:Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/IccRecords;->registerForNetworkSelectionModeAutomatic(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/uicc/IccRecords;->registerForNewSms(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/uicc/IccRecords;->registerForRecordsEvents(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/uicc/IccRecords;->registerForRecordsLoaded(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/uicc/IccRecords;->setMsisdnNumber(Ljava/lang/String;Ljava/lang/String;Landroid/os/Message;)V
-Lcom/android/internal/telephony/uicc/IccRecords;->setVoiceCallForwardingFlag(IZLjava/lang/String;)V
-Lcom/android/internal/telephony/uicc/IccRecords;->unregisterForNetworkSelectionModeAutomatic(Landroid/os/Handler;)V
-Lcom/android/internal/telephony/uicc/IccRecords;->unregisterForNewSms(Landroid/os/Handler;)V
-Lcom/android/internal/telephony/uicc/IccRecords;->unregisterForRecordsEvents(Landroid/os/Handler;)V
-Lcom/android/internal/telephony/uicc/IccRecords;->unregisterForRecordsLoaded(Landroid/os/Handler;)V
 Lcom/android/internal/telephony/uicc/IccRefreshResponse;-><init>()V
-Lcom/android/internal/telephony/uicc/IccRefreshResponse;->aid:Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/IccRefreshResponse;->efId:I
-Lcom/android/internal/telephony/uicc/IccRefreshResponse;->refreshResult:I
-Lcom/android/internal/telephony/uicc/IccServiceTable;->getTag()Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/IccServiceTable;->mServiceTable:[B
 Lcom/android/internal/telephony/uicc/IccUtils;->adnStringFieldToString([BII)Ljava/lang/String;
 Lcom/android/internal/telephony/uicc/IccUtils;->bcdToString([BII)Ljava/lang/String;
 Lcom/android/internal/telephony/uicc/IccUtils;->bytesToHexString([B)Ljava/lang/String;
@@ -3128,175 +1587,7 @@
 Lcom/android/internal/telephony/uicc/IccUtils;->networkNameToString([BII)Ljava/lang/String;
 Lcom/android/internal/telephony/uicc/IccUtils;->parseToBnW([BI)Landroid/graphics/Bitmap;
 Lcom/android/internal/telephony/uicc/IccUtils;->parseToRGB([BIZ)Landroid/graphics/Bitmap;
-Lcom/android/internal/telephony/uicc/IsimRecords;->getIsimDomain()Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/IsimRecords;->getIsimImpi()Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/IsimRecords;->getIsimImpu()[Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/IsimUiccRecords;->auth_rsp:Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/IsimUiccRecords;->fetchIsimRecords()V
-Lcom/android/internal/telephony/uicc/IsimUiccRecords;->isimTlvToString([B)Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/IsimUiccRecords;->log(Ljava/lang/String;)V
-Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimDomain:Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimImpi:Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimImpu:[Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimIst:Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimPcscf:[Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mLock:Ljava/lang/Object;
-Lcom/android/internal/telephony/uicc/RuimRecords;->adjstMinDigits(I)I
-Lcom/android/internal/telephony/uicc/RuimRecords;->fetchRuimRecords()V
-Lcom/android/internal/telephony/uicc/RuimRecords;->getAssetLanguages(Landroid/content/Context;)[Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/RuimRecords;->getCsimSpnDisplayCondition()Z
-Lcom/android/internal/telephony/uicc/RuimRecords;->getMdn()Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/RuimRecords;->getMdnNumber()Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/RuimRecords;->getRUIMOperatorNumeric()Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/RuimRecords;->log(Ljava/lang/String;)V
-Lcom/android/internal/telephony/uicc/RuimRecords;->loge(Ljava/lang/String;)V
-Lcom/android/internal/telephony/uicc/RuimRecords;->mEFli:[B
-Lcom/android/internal/telephony/uicc/RuimRecords;->mEFpl:[B
-Lcom/android/internal/telephony/uicc/RuimRecords;->mMin:Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/RuimRecords;->mNai:Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/RuimRecords;->onGetCSimEprlDone(Landroid/os/AsyncResult;)V
-Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;->INIT:Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;
-Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;->READ_SPN_3GPP:Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;
-Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;->READ_SPN_CPHS:Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;
-Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;->READ_SPN_SHORT_CPHS:Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;
 Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;->values()[Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;
-Lcom/android/internal/telephony/uicc/SIMRecords;->fetchSimRecords()V
-Lcom/android/internal/telephony/uicc/SIMRecords;->getExtFromEf(I)I
-Lcom/android/internal/telephony/uicc/SIMRecords;->getMsisdnNumber()Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/SIMRecords;->getOperatorNumeric()Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/SIMRecords;->getSpnFsm(ZLandroid/os/AsyncResult;)V
-Lcom/android/internal/telephony/uicc/SIMRecords;->getVoiceMailNumber()Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/SIMRecords;->isCphsMailboxEnabled()Z
-Lcom/android/internal/telephony/uicc/SIMRecords;->log(Ljava/lang/String;)V
-Lcom/android/internal/telephony/uicc/SIMRecords;->loge(Ljava/lang/String;)V
-Lcom/android/internal/telephony/uicc/SIMRecords;->logv(Ljava/lang/String;)V
-Lcom/android/internal/telephony/uicc/SIMRecords;->mEfCff:[B
-Lcom/android/internal/telephony/uicc/SIMRecords;->mEfCfis:[B
-Lcom/android/internal/telephony/uicc/SIMRecords;->mEfCPHS_MWI:[B
-Lcom/android/internal/telephony/uicc/SIMRecords;->mEfLi:[B
-Lcom/android/internal/telephony/uicc/SIMRecords;->mEfMWIS:[B
-Lcom/android/internal/telephony/uicc/SIMRecords;->mEfPl:[B
-Lcom/android/internal/telephony/uicc/SIMRecords;->mSpnDisplayCondition:I
-Lcom/android/internal/telephony/uicc/SIMRecords;->mUsimServiceTable:Lcom/android/internal/telephony/uicc/UsimServiceTable;
-Lcom/android/internal/telephony/uicc/SIMRecords;->mVmConfig:Lcom/android/internal/telephony/uicc/VoiceMailConstants;
-Lcom/android/internal/telephony/uicc/SIMRecords;->setVoiceCallForwardingFlag(IZLjava/lang/String;)V
-Lcom/android/internal/telephony/uicc/UiccCard;->getApplication(I)Lcom/android/internal/telephony/uicc/UiccCardApplication;
-Lcom/android/internal/telephony/uicc/UiccCard;->getApplicationByType(I)Lcom/android/internal/telephony/uicc/UiccCardApplication;
-Lcom/android/internal/telephony/uicc/UiccCard;->getApplicationIndex(I)Lcom/android/internal/telephony/uicc/UiccCardApplication;
-Lcom/android/internal/telephony/uicc/UiccCard;->getCardState()Lcom/android/internal/telephony/uicc/IccCardStatus$CardState;
-Lcom/android/internal/telephony/uicc/UiccCard;->getCarrierPackageNamesForIntent(Landroid/content/pm/PackageManager;Landroid/content/Intent;)Ljava/util/List;
-Lcom/android/internal/telephony/uicc/UiccCard;->getIccId()Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/UiccCard;->getNumApplications()I
-Lcom/android/internal/telephony/uicc/UiccCard;->getOperatorBrandOverride()Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/UiccCard;->isApplicationOnIcc(Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;)Z
-Lcom/android/internal/telephony/uicc/UiccCard;->log(Ljava/lang/String;)V
-Lcom/android/internal/telephony/uicc/UiccCard;->loge(Ljava/lang/String;)V
-Lcom/android/internal/telephony/uicc/UiccCard;->mCardState:Lcom/android/internal/telephony/uicc/IccCardStatus$CardState;
-Lcom/android/internal/telephony/uicc/UiccCard;->mCi:Lcom/android/internal/telephony/CommandsInterface;
-Lcom/android/internal/telephony/uicc/UiccCard;->mContext:Landroid/content/Context;
-Lcom/android/internal/telephony/uicc/UiccCard;->mLock:Ljava/lang/Object;
-Lcom/android/internal/telephony/uicc/UiccCard;->mPhoneId:I
-Lcom/android/internal/telephony/uicc/UiccCardApplication;->dispose()V
-Lcom/android/internal/telephony/uicc/UiccCardApplication;->getAid()Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/UiccCardApplication;->getAuthContext()I
-Lcom/android/internal/telephony/uicc/UiccCardApplication;->getIccFileHandler()Lcom/android/internal/telephony/uicc/IccFileHandler;
-Lcom/android/internal/telephony/uicc/UiccCardApplication;->getIccRecords()Lcom/android/internal/telephony/uicc/IccRecords;
-Lcom/android/internal/telephony/uicc/UiccCardApplication;->getPersoSubState()Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;
-Lcom/android/internal/telephony/uicc/UiccCardApplication;->getPhoneId()I
-Lcom/android/internal/telephony/uicc/UiccCardApplication;->getPin1State()Lcom/android/internal/telephony/uicc/IccCardStatus$PinState;
-Lcom/android/internal/telephony/uicc/UiccCardApplication;->getState()Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;
-Lcom/android/internal/telephony/uicc/UiccCardApplication;->getType()Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
-Lcom/android/internal/telephony/uicc/UiccCardApplication;->log(Ljava/lang/String;)V
-Lcom/android/internal/telephony/uicc/UiccCardApplication;->loge(Ljava/lang/String;)V
-Lcom/android/internal/telephony/uicc/UiccCardApplication;->mAid:Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/UiccCardApplication;->mAppState:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;
-Lcom/android/internal/telephony/uicc/UiccCardApplication;->mAppType:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
-Lcom/android/internal/telephony/uicc/UiccCardApplication;->mCi:Lcom/android/internal/telephony/CommandsInterface;
-Lcom/android/internal/telephony/uicc/UiccCardApplication;->mDestroyed:Z
-Lcom/android/internal/telephony/uicc/UiccCardApplication;->mLock:Ljava/lang/Object;
-Lcom/android/internal/telephony/uicc/UiccCardApplication;->mPersoSubState:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;
-Lcom/android/internal/telephony/uicc/UiccCardApplication;->mPin1State:Lcom/android/internal/telephony/uicc/IccCardStatus$PinState;
-Lcom/android/internal/telephony/uicc/UiccCardApplication;->registerForReady(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/uicc/UiccCardApplication;->unregisterForReady(Landroid/os/Handler;)V
-Lcom/android/internal/telephony/uicc/UiccCardApplication;->update(Lcom/android/internal/telephony/uicc/IccCardApplicationStatus;Landroid/content/Context;Lcom/android/internal/telephony/CommandsInterface;)V
-Lcom/android/internal/telephony/uicc/UiccCarrierPrivilegeRules$TLV;->length:Ljava/lang/Integer;
-Lcom/android/internal/telephony/uicc/UiccCarrierPrivilegeRules$TLV;->value:Ljava/lang/String;
-Lcom/android/internal/telephony/uicc/UiccCarrierPrivilegeRules;->mLoadedCallback:Landroid/os/Message;
-Lcom/android/internal/telephony/uicc/UiccCarrierPrivilegeRules;->mState:Ljava/util/concurrent/atomic/AtomicInteger;
-Lcom/android/internal/telephony/uicc/UiccController;->getIccFileHandler(II)Lcom/android/internal/telephony/uicc/IccFileHandler;
-Lcom/android/internal/telephony/uicc/UiccController;->getIccRecords(II)Lcom/android/internal/telephony/uicc/IccRecords;
-Lcom/android/internal/telephony/uicc/UiccController;->getInstance()Lcom/android/internal/telephony/uicc/UiccController;
-Lcom/android/internal/telephony/uicc/UiccController;->getUiccCard(I)Lcom/android/internal/telephony/uicc/UiccCard;
-Lcom/android/internal/telephony/uicc/UiccController;->getUiccCardApplication(II)Lcom/android/internal/telephony/uicc/UiccCardApplication;
-Lcom/android/internal/telephony/uicc/UiccController;->log(Ljava/lang/String;)V
-Lcom/android/internal/telephony/uicc/UiccController;->mCis:[Lcom/android/internal/telephony/CommandsInterface;
-Lcom/android/internal/telephony/uicc/UiccController;->mContext:Landroid/content/Context;
-Lcom/android/internal/telephony/uicc/UiccController;->mInstance:Lcom/android/internal/telephony/uicc/UiccController;
-Lcom/android/internal/telephony/uicc/UiccController;->mLock:Ljava/lang/Object;
-Lcom/android/internal/telephony/uicc/UiccController;->registerForIccChanged(Landroid/os/Handler;ILjava/lang/Object;)V
-Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->ALLOWED_CSG_LISTS_AND_INDICATIONS:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
-Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->CFI_STATUS:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
-Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->CSG_DISPLAY_CONTROL:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
-Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->FDN:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
-Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->MBDN:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
-Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->MSISDN:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
-Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->MWI_STATUS:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
-Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->OPERATOR_CSG_LISTS_AND_INDICATIONS:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
-Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->OPERATOR_PLMN_LIST:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
-Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->PLMN_NETWORK_NAME:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
-Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->SDN:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
-Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->SM_OVER_IP:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
-Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->SM_SERVICE_PARAMS:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
-Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->SM_STORAGE:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
-Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->SPN:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
-Lcom/android/internal/telephony/uicc/UsimServiceTable;->isAvailable(Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;)Z
-Lcom/android/internal/telephony/uicc/VoiceMailConstants;-><init>()V
-Lcom/android/internal/telephony/UiccPhoneBookController;-><init>([Lcom/android/internal/telephony/Phone;)V
-Lcom/android/internal/telephony/UiccPhoneBookController;->getDefaultSubscription()I
-Lcom/android/internal/telephony/UiccPhoneBookController;->getIccPhoneBookInterfaceManager(I)Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;
-Lcom/android/internal/telephony/UiccPhoneBookController;->mPhone:[Lcom/android/internal/telephony/Phone;
-Lcom/android/internal/telephony/UiccSmsController;->copyMessageToIccEfForSubscriber(ILjava/lang/String;I[B[B)Z
-Lcom/android/internal/telephony/UiccSmsController;->disableCellBroadcastForSubscriber(III)Z
-Lcom/android/internal/telephony/UiccSmsController;->disableCellBroadcastRangeForSubscriber(IIII)Z
-Lcom/android/internal/telephony/UiccSmsController;->enableCellBroadcastForSubscriber(III)Z
-Lcom/android/internal/telephony/UiccSmsController;->enableCellBroadcastRangeForSubscriber(IIII)Z
-Lcom/android/internal/telephony/UiccSmsController;->getAllMessagesFromIccEfForSubscriber(ILjava/lang/String;)Ljava/util/List;
-Lcom/android/internal/telephony/UiccSmsController;->getIccSmsInterfaceManager(I)Lcom/android/internal/telephony/IccSmsInterfaceManager;
-Lcom/android/internal/telephony/UiccSmsController;->getImsSmsFormatForSubscriber(I)Ljava/lang/String;
-Lcom/android/internal/telephony/UiccSmsController;->getPreferredSmsSubscription()I
-Lcom/android/internal/telephony/UiccSmsController;->isImsSmsSupportedForSubscriber(I)Z
-Lcom/android/internal/telephony/UiccSmsController;->sendDataForSubscriber(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;I[BLandroid/app/PendingIntent;Landroid/app/PendingIntent;)V
-Lcom/android/internal/telephony/UiccSmsController;->sendErrorInPendingIntent(Landroid/app/PendingIntent;I)V
-Lcom/android/internal/telephony/UiccSmsController;->sendErrorInPendingIntents(Ljava/util/List;I)V
-Lcom/android/internal/telephony/UiccSmsController;->updateMessageOnIccEfForSubscriber(ILjava/lang/String;II[B)Z
-Lcom/android/internal/telephony/UUSInfo;->getDcs()I
-Lcom/android/internal/telephony/UUSInfo;->getType()I
-Lcom/android/internal/telephony/UUSInfo;->getUserData()[B
-Lcom/android/internal/telephony/WakeLockStateMachine;->log(Ljava/lang/String;)V
-Lcom/android/internal/telephony/WakeLockStateMachine;->mContext:Landroid/content/Context;
-Lcom/android/internal/telephony/WakeLockStateMachine;->mIdleState:Lcom/android/internal/telephony/WakeLockStateMachine$IdleState;
-Lcom/android/internal/telephony/WakeLockStateMachine;->mPhone:Lcom/android/internal/telephony/Phone;
-Lcom/android/internal/telephony/WapPushOverSms;->dispatchWapPdu([BLandroid/content/BroadcastReceiver;Lcom/android/internal/telephony/InboundSmsHandler;)I
-Lcom/android/internal/telephony/WapPushOverSms;->getDeliveryOrReadReportThreadId(Landroid/content/Context;Lcom/google/android/mms/pdu/GenericPdu;)J
-Lcom/android/internal/telephony/WapPushOverSms;->isDuplicateNotification(Landroid/content/Context;Lcom/google/android/mms/pdu/NotificationInd;)Z
-Lcom/android/internal/telephony/WapPushOverSms;->isWapPushForMms([BLcom/android/internal/telephony/InboundSmsHandler;)Z
-Lcom/android/internal/telephony/WapPushOverSms;->mContext:Landroid/content/Context;
-Lcom/android/internal/telephony/WapPushOverSms;->mDeviceIdleController:Landroid/os/IDeviceIdleController;
-Lcom/android/internal/telephony/WapPushOverSms;->mWapPushManager:Lcom/android/internal/telephony/IWapPushManager;
-Lcom/android/internal/telephony/WspTypeDecoder;-><init>([B)V
-Lcom/android/internal/telephony/WspTypeDecoder;->decodeContentType(I)Z
-Lcom/android/internal/telephony/WspTypeDecoder;->decodeIntegerValue(I)Z
-Lcom/android/internal/telephony/WspTypeDecoder;->decodeShortInteger(I)Z
-Lcom/android/internal/telephony/WspTypeDecoder;->decodeTextString(I)Z
-Lcom/android/internal/telephony/WspTypeDecoder;->decodeUintvarInteger(I)Z
-Lcom/android/internal/telephony/WspTypeDecoder;->decodeValueLength(I)Z
-Lcom/android/internal/telephony/WspTypeDecoder;->decodeXWapApplicationId(I)Z
-Lcom/android/internal/telephony/WspTypeDecoder;->getContentParameters()Ljava/util/HashMap;
-Lcom/android/internal/telephony/WspTypeDecoder;->getDecodedDataLength()I
-Lcom/android/internal/telephony/WspTypeDecoder;->getValue32()J
-Lcom/android/internal/telephony/WspTypeDecoder;->getValueString()Ljava/lang/String;
-Lcom/android/internal/telephony/WspTypeDecoder;->mWspData:[B
-Lcom/android/internal/telephony/WspTypeDecoder;->seekXWapApplicationId(II)Z
 Lcom/android/internal/textservice/ITextServicesManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Lcom/android/internal/util/ArrayUtils;->appendElement(Ljava/lang/Class;[Ljava/lang/Object;Ljava/lang/Object;)[Ljava/lang/Object;
 Lcom/android/internal/util/ArrayUtils;->appendInt([II)[I
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 56bf8fa..b039a60 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -139,6 +139,8 @@
 import com.android.internal.app.WindowDecorActionBar;
 import com.android.internal.policy.PhoneWindow;
 
+import dalvik.system.VMRuntime;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
@@ -2491,6 +2493,7 @@
             try {
                 ActivityTaskManager.getService().reportActivityFullyDrawn(
                         mToken, mRestoredFromBundle);
+                VMRuntime.getRuntime().notifyStartupCompleted();
             } catch (RemoteException e) {
             }
         }
@@ -8341,7 +8344,7 @@
         try {
             ActivityTaskManager.getService().setDisablePreviewScreenshots(mToken, disable);
         } catch (RemoteException e) {
-            Log.e(TAG, "Failed to call setDisablePreviewScreenshots", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -8362,7 +8365,7 @@
         try {
             ActivityTaskManager.getService().setShowWhenLocked(mToken, showWhenLocked);
         } catch (RemoteException e) {
-            Log.e(TAG, "Failed to call setShowWhenLocked", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -8386,7 +8389,7 @@
             ActivityTaskManager.getService().setInheritShowWhenLocked(
                     mToken, inheritShowWhenLocked);
         } catch (RemoteException e) {
-            Log.e(TAG, "Failed to call setInheritShowWhenLocked", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -8412,7 +8415,7 @@
         try {
             ActivityTaskManager.getService().setTurnScreenOn(mToken, turnScreenOn);
         } catch (RemoteException e) {
-            Log.e(TAG, "Failed to call setTurnScreenOn", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -8429,7 +8432,7 @@
         try {
             ActivityTaskManager.getService().registerRemoteAnimations(mToken, definition);
         } catch (RemoteException e) {
-            Log.e(TAG, "Failed to call registerRemoteAnimations", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 664f0a3..f6cfe48 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -329,6 +329,9 @@
     /** Returns true if the given uid is the app in the foreground. */
     public abstract boolean isAppForeground(int uid);
 
+    /** Returns true if the given uid is currently marked 'bad' */
+    public abstract boolean isAppBad(ApplicationInfo info);
+
     /** Remove pending backup for the given userId. */
     public abstract void clearPendingBackup(int userId);
 
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index e2d868f..da9ea83 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -222,6 +222,13 @@
     private static final String KEY_AVOID_MOVE_TO_FRONT = "android.activity.avoidMoveToFront";
 
     /**
+     * See {@link #setFreezeRecentTasksReordering()}.
+     * @hide
+     */
+    private static final String KEY_FREEZE_RECENT_TASKS_REORDERING =
+            "android.activity.freezeRecentTasksReordering";
+
+    /**
      * Where the split-screen-primary stack should be positioned.
      * @hide
      */
@@ -324,6 +331,7 @@
     private boolean mTaskOverlay;
     private boolean mTaskOverlayCanResume;
     private boolean mAvoidMoveToFront;
+    private boolean mFreezeRecentTasksReordering;
     private AppTransitionAnimationSpec mAnimSpecs[];
     private int mRotationAnimationHint = -1;
     private Bundle mAppVerificationBundle;
@@ -946,6 +954,7 @@
         mTaskOverlay = opts.getBoolean(KEY_TASK_OVERLAY, false);
         mTaskOverlayCanResume = opts.getBoolean(KEY_TASK_OVERLAY_CAN_RESUME, false);
         mAvoidMoveToFront = opts.getBoolean(KEY_AVOID_MOVE_TO_FRONT, false);
+        mFreezeRecentTasksReordering = opts.getBoolean(KEY_FREEZE_RECENT_TASKS_REORDERING, false);
         mSplitScreenCreateMode = opts.getInt(KEY_SPLIT_SCREEN_CREATE_MODE,
                 SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT);
         mDisallowEnterPictureInPictureWhileLaunching = opts.getBoolean(
@@ -1304,6 +1313,24 @@
         return mAvoidMoveToFront;
     }
 
+    /**
+     * Sets whether the launch of this activity should freeze the recent task list reordering until
+     * the next user interaction or timeout. This flag is only applied when starting an activity
+     * in recents.
+     * @hide
+     */
+    public void setFreezeRecentTasksReordering() {
+        mFreezeRecentTasksReordering = true;
+    }
+
+    /**
+     * @return whether the launch of this activity should freeze the recent task list reordering
+     * @hide
+     */
+    public boolean freezeRecentTasksReordering() {
+        return mFreezeRecentTasksReordering;
+    }
+
     /** @hide */
     public int getSplitScreenCreateMode() {
         return mSplitScreenCreateMode;
@@ -1502,6 +1529,9 @@
         if (mAvoidMoveToFront) {
             b.putBoolean(KEY_AVOID_MOVE_TO_FRONT, mAvoidMoveToFront);
         }
+        if (mFreezeRecentTasksReordering) {
+            b.putBoolean(KEY_FREEZE_RECENT_TASKS_REORDERING, mFreezeRecentTasksReordering);
+        }
         if (mSplitScreenCreateMode != SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT) {
             b.putInt(KEY_SPLIT_SCREEN_CREATE_MODE, mSplitScreenCreateMode);
         }
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 91df05f..1066fc7 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -2214,7 +2214,7 @@
         /**
          * @return The ops of the package.
          */
-        public List<OpEntry> getOps() {
+        public @NonNull List<OpEntry> getOps() {
             return mEntries;
         }
 
@@ -4371,7 +4371,8 @@
     @Deprecated
     @SystemApi
     @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS)
-    public List<PackageOps> getOpsForPackage(int uid, String packageName, int[] ops) {
+    public @NonNull List<PackageOps> getOpsForPackage(int uid, @NonNull String packageName,
+            @Nullable int[] ops) {
         try {
             return mService.getOpsForPackage(uid, packageName, ops);
         } catch (RemoteException e) {
@@ -4639,8 +4640,8 @@
      * @param packageName The name of the application to monitor.
      * @param callback Where to report changes.
      */
-    public void startWatchingMode(String op, String packageName,
-            final OnOpChangedListener callback) {
+    public void startWatchingMode(@NonNull String op, @Nullable String packageName,
+            @NonNull final OnOpChangedListener callback) {
         startWatchingMode(strOpToOp(op), packageName, callback);
     }
 
@@ -4653,8 +4654,8 @@
      * @param flags Option flags: any combination of {@link #WATCH_FOREGROUND_CHANGES} or 0.
      * @param callback Where to report changes.
      */
-    public void startWatchingMode(String op, String packageName, int flags,
-            final OnOpChangedListener callback) {
+    public void startWatchingMode(@NonNull String op, @Nullable String packageName, int flags,
+            @NonNull final OnOpChangedListener callback) {
         startWatchingMode(strOpToOp(op), packageName, flags, callback);
     }
 
@@ -4716,7 +4717,7 @@
      * Stop monitoring that was previously started with {@link #startWatchingMode}.  All
      * monitoring associated with this callback will be removed.
      */
-    public void stopWatchingMode(OnOpChangedListener callback) {
+    public void stopWatchingMode(@NonNull OnOpChangedListener callback) {
         synchronized (mModeWatchers) {
             IAppOpsCallback cb = mModeWatchers.remove(callback);
             if (cb != null) {
@@ -4875,7 +4876,7 @@
      * {@hide}
      */
     @TestApi
-    public static int strOpToOp(String op) {
+    public static int strOpToOp(@NonNull String op) {
         Integer val = sOpStrToOp.get(op);
         if (val == null) {
             throw new IllegalArgumentException("Unknown operation string: " + op);
@@ -4910,7 +4911,7 @@
      * causing the app to crash).
      * @throws SecurityException If the app has been configured to crash on this op.
      */
-    public int unsafeCheckOp(String op, int uid, String packageName) {
+    public int unsafeCheckOp(@NonNull String op, int uid, @NonNull String packageName) {
         return checkOp(strOpToOp(op), uid, packageName);
     }
 
@@ -4918,7 +4919,7 @@
      * @deprecated Renamed to {@link #unsafeCheckOp(String, int, String)}.
      */
     @Deprecated
-    public int checkOp(String op, int uid, String packageName) {
+    public int checkOp(@NonNull String op, int uid, @NonNull String packageName) {
         return checkOp(strOpToOp(op), uid, packageName);
     }
 
@@ -4926,7 +4927,7 @@
      * Like {@link #checkOp} but instead of throwing a {@link SecurityException} it
      * returns {@link #MODE_ERRORED}.
      */
-    public int unsafeCheckOpNoThrow(String op, int uid, String packageName) {
+    public int unsafeCheckOpNoThrow(@NonNull String op, int uid, @NonNull String packageName) {
         return checkOpNoThrow(strOpToOp(op), uid, packageName);
     }
 
@@ -4934,7 +4935,7 @@
      * @deprecated Renamed to {@link #unsafeCheckOpNoThrow(String, int, String)}.
      */
     @Deprecated
-    public int checkOpNoThrow(String op, int uid, String packageName) {
+    public int checkOpNoThrow(@NonNull String op, int uid, @NonNull String packageName) {
         return checkOpNoThrow(strOpToOp(op), uid, packageName);
     }
 
@@ -4942,7 +4943,7 @@
      * Like {@link #checkOp} but returns the <em>raw</em> mode associated with the op.
      * Does not throw a security exception, does not translate {@link #MODE_FOREGROUND}.
      */
-    public int unsafeCheckOpRaw(@NonNull String op, int uid, String packageName) {
+    public int unsafeCheckOpRaw(@NonNull String op, int uid, @NonNull String packageName) {
         try {
             return mService.checkOperationRaw(strOpToOp(op), uid, packageName);
         } catch (RemoteException e) {
@@ -4977,7 +4978,7 @@
      * causing the app to crash).
      * @throws SecurityException If the app has been configured to crash on this op.
      */
-    public int noteOp(String op, int uid, String packageName) {
+    public int noteOp(@NonNull String op, int uid, @NonNull String packageName) {
         return noteOp(strOpToOp(op), uid, packageName);
     }
 
@@ -4985,7 +4986,7 @@
      * Like {@link #noteOp} but instead of throwing a {@link SecurityException} it
      * returns {@link #MODE_ERRORED}.
      */
-    public int noteOpNoThrow(String op, int uid, String packageName) {
+    public int noteOpNoThrow(@NonNull String op, int uid, @NonNull String packageName) {
         return noteOpNoThrow(strOpToOp(op), uid, packageName);
     }
 
@@ -5004,7 +5005,7 @@
      * causing the app to crash).
      * @throws SecurityException If the app has been configured to crash on this op.
      */
-    public int noteProxyOp(String op, String proxiedPackageName) {
+    public int noteProxyOp(@NonNull String op, @NonNull String proxiedPackageName) {
         return noteProxyOp(strOpToOp(op), proxiedPackageName);
     }
 
@@ -5015,7 +5016,7 @@
      * <p>This API requires the package with the {@code proxiedPackageName} to belongs to
      * {@link Binder#getCallingUid()}.
      */
-    public int noteProxyOpNoThrow(String op, String proxiedPackageName) {
+    public int noteProxyOpNoThrow(@NonNull String op, @NonNull String proxiedPackageName) {
         return noteProxyOpNoThrow(strOpToOp(op), proxiedPackageName);
     }
 
@@ -5051,7 +5052,7 @@
      * causing the app to crash).
      * @throws SecurityException If the app has been configured to crash on this op.
      */
-    public int startOp(String op, int uid, String packageName) {
+    public int startOp(@NonNull String op, int uid, @NonNull String packageName) {
         return startOp(strOpToOp(op), uid, packageName);
     }
 
@@ -5059,7 +5060,7 @@
      * Like {@link #startOp} but instead of throwing a {@link SecurityException} it
      * returns {@link #MODE_ERRORED}.
      */
-    public int startOpNoThrow(String op, int uid, String packageName) {
+    public int startOpNoThrow(@NonNull String op, int uid, @NonNull String packageName) {
         return startOpNoThrow(strOpToOp(op), uid, packageName);
     }
 
@@ -5069,7 +5070,7 @@
      * or result; the parameters supplied here must be the exact same ones previously passed
      * in when starting the operation.
      */
-    public void finishOp(String op, int uid, String packageName) {
+    public void finishOp(@NonNull String op, int uid, @NonNull String packageName) {
         finishOp(strOpToOp(op), uid, packageName);
     }
 
@@ -5135,7 +5136,7 @@
      * @throws SecurityException if the package name doesn't belong to the given
      *             UID, or if ownership cannot be verified.
      */
-    public void checkPackage(int uid, String packageName) {
+    public void checkPackage(int uid, @NonNull String packageName) {
         try {
             if (mService.checkPackage(uid, packageName) != MODE_ALLOWED) {
                 throw new SecurityException(
diff --git a/core/java/android/app/AppOpsManagerInternal.java b/core/java/android/app/AppOpsManagerInternal.java
index da45054..08cad04 100644
--- a/core/java/android/app/AppOpsManagerInternal.java
+++ b/core/java/android/app/AppOpsManagerInternal.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.annotation.NonNull;
 import android.util.SparseIntArray;
 
 import com.android.internal.util.function.QuadFunction;
@@ -96,4 +97,18 @@
      * @param uid The uid
      */
     public abstract void setAllPkgModesToDefault(int code, int uid);
+
+    /**
+     * Get the (raw) mode of an app-op.
+     *
+     * <p>Does <u>not</u> verify that package belongs to uid. The caller needs to do that.
+     *
+     * @param code The code of the op
+     * @param uid The uid of the package the op belongs to
+     * @param packageName The package the op belongs to
+     *
+     * @return The mode of the op
+     */
+    public abstract @AppOpsManager.Mode int checkOperationUnchecked(int code, int uid,
+            @NonNull String packageName);
 }
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index d3e3507..a226062 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1301,8 +1301,7 @@
     }
 
     @Override public Drawable getDefaultActivityIcon() {
-        return Resources.getSystem().getDrawable(
-            com.android.internal.R.drawable.sym_def_app_icon);
+        return mContext.getDrawable(com.android.internal.R.drawable.sym_def_app_icon);
     }
 
     @Override public Drawable getApplicationIcon(ApplicationInfo info) {
@@ -1440,7 +1439,7 @@
         if (density <= 0) {
             density = mContext.getResources().getDisplayMetrics().densityDpi;
         }
-        return Resources.getSystem().getDrawableForDensity(drawableId, density);
+        return mContext.getResources().getDrawableForDensity(drawableId, density);
     }
 
     private Drawable getManagedProfileIconForDensity(UserHandle user, int drawableId, int density) {
@@ -2469,7 +2468,7 @@
     }
 
     @Override
-    public void setAppDetailsActivityEnabled(String packageName, boolean enabled) {
+    public void setSyntheticAppDetailsActivityEnabled(String packageName, boolean enabled) {
         try {
             ComponentName componentName = new ComponentName(packageName,
                     PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME);
@@ -2483,7 +2482,7 @@
     }
 
     @Override
-    public boolean getAppDetailsActivityEnabled(String packageName) {
+    public boolean getSyntheticAppDetailsActivityEnabled(String packageName) {
         try {
             ComponentName componentName = new ComponentName(packageName,
                     PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME);
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 29e6807..15084de 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -193,7 +193,7 @@
 
     void setNotificationDelegate(String callingPkg, String delegate);
     String getNotificationDelegate(String callingPkg);
-    boolean canNotifyAsPackage(String callingPkg, String targetPkg);
+    boolean canNotifyAsPackage(String callingPkg, String targetPkg, int userId);
 
     void setPrivateNotificationsAllowed(boolean allow);
     boolean getPrivateNotificationsAllowed();
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index a8a34d2..23f64b8 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1203,7 +1203,7 @@
 
     /**
      * {@link #extras} key: whether the notification should be colorized as
-     * supplied to {@link Builder#setColorized(boolean)}}.
+     * supplied to {@link Builder#setColorized(boolean)}.
      */
     public static final String EXTRA_COLORIZED = "android.colorized";
 
@@ -1358,7 +1358,7 @@
          *
          * This is intended for {@link RemoteInput}s that only accept data, meaning
          * {@link RemoteInput#getAllowFreeFormInput} is false, {@link RemoteInput#getChoices}
-         * is null or empty, and {@link RemoteInput#getAllowedDataTypes is non-null and not
+         * is null or empty, and {@link RemoteInput#getAllowedDataTypes} is non-null and not
          * empty. These {@link RemoteInput}s will be ignored by devices that do not
          * support non-text-based {@link RemoteInput}s. See {@link Builder#build}.
          *
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 204fb6a..6a301c9 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -627,7 +627,7 @@
     public boolean canNotifyAsPackage(@NonNull String pkg) {
         INotificationManager service = getService();
         try {
-            return service.canNotifyAsPackage(mContext.getPackageName(), pkg);
+            return service.canNotifyAsPackage(mContext.getPackageName(), pkg, mContext.getUserId());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1270,6 +1270,8 @@
 
     /**
      * Grants/revokes Notification Assistant access to {@code assistant} for current user.
+     * To grant access for a particular user, obtain this service by using the {@link Context}
+     * provided by {@link Context#createPackageContextAsUser}
      *
      * @param assistant Name of component to grant/revoke access or {@code null} to revoke access to
      *                  current assistant
@@ -1287,27 +1289,6 @@
         }
     }
 
-    /**
-     * Grants/revokes Notification Assistant access to {@code assistant} for given user.
-     *
-     * @param assistant Name of component to grant/revoke access or {@code null} to revoke access to
-     *                  current assistant
-     * @param user handle to associate assistant with
-     * @param granted Grant/revoke access
-     * @hide
-     */
-    @SystemApi
-    public void setNotificationAssistantAccessGrantedForUser(@Nullable ComponentName assistant,
-            @NonNull UserHandle user, boolean granted) {
-        INotificationManager service = getService();
-        try {
-            service.setNotificationAssistantAccessGrantedForUser(assistant, user.getIdentifier(),
-                    granted);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
     /** @hide */
     public List<ComponentName> getEnabledNotificationListeners(int userId) {
         INotificationManager service = getService();
@@ -1320,18 +1301,6 @@
 
     /** @hide */
     @SystemApi
-    public @Nullable ComponentName getAllowedNotificationAssistantForUser(
-            @NonNull UserHandle user) {
-        INotificationManager service = getService();
-        try {
-            return service.getAllowedNotificationAssistantForUser(user.getIdentifier());
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /** @hide */
-    @SystemApi
     public @Nullable ComponentName getAllowedNotificationAssistant() {
         INotificationManager service = getService();
         try {
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 2d9fbf9..35658fb 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -1091,6 +1091,16 @@
      */
     @UnsupportedAppUsage
     public void appendLibAssetForMainAssetPath(String assetPath, String libAsset) {
+        appendLibAssetsForMainAssetPath(assetPath, new String[] { libAsset });
+    }
+
+    /**
+     * Appends the library asset paths to any ResourcesImpl object that contains the main
+     * assetPath.
+     * @param assetPath The main asset path for which to add the library asset path.
+     * @param libAssets The library asset paths to add.
+     */
+    public void appendLibAssetsForMainAssetPath(String assetPath, String[] libAssets) {
         synchronized (this) {
             // Record which ResourcesImpl need updating
             // (and what ResourcesKey they should update to).
@@ -1102,15 +1112,13 @@
                 final WeakReference<ResourcesImpl> weakImplRef = mResourceImpls.valueAt(i);
                 final ResourcesImpl impl = weakImplRef != null ? weakImplRef.get() : null;
                 if (impl != null && Objects.equals(key.mResDir, assetPath)) {
-                    if (!ArrayUtils.contains(key.mLibDirs, libAsset)) {
-                        final int newLibAssetCount = 1 +
-                                (key.mLibDirs != null ? key.mLibDirs.length : 0);
-                        final String[] newLibAssets = new String[newLibAssetCount];
-                        if (key.mLibDirs != null) {
-                            System.arraycopy(key.mLibDirs, 0, newLibAssets, 0, key.mLibDirs.length);
-                        }
-                        newLibAssets[newLibAssetCount - 1] = libAsset;
+                    String[] newLibAssets = key.mLibDirs;
+                    for (String libAsset : libAssets) {
+                        newLibAssets =
+                                ArrayUtils.appendElement(String.class, newLibAssets, libAsset);
+                    }
 
+                    if (newLibAssets != key.mLibDirs) {
                         updatedResourceKeys.put(impl, new ResourcesKey(
                                 key.mResDir,
                                 key.mSplitResDirs,
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 90bc0a6..08e0880 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -104,11 +104,13 @@
 import android.net.IIpMemoryStore;
 import android.net.IIpSecService;
 import android.net.INetworkPolicyManager;
+import android.net.ITestNetworkManager;
 import android.net.IpMemoryStore;
 import android.net.IpSecManager;
 import android.net.NetworkPolicyManager;
 import android.net.NetworkScoreManager;
 import android.net.NetworkWatchlistManager;
+import android.net.TestNetworkManager;
 import android.net.lowpan.ILowpanManager;
 import android.net.lowpan.LowpanManager;
 import android.net.nsd.INsdManager;
@@ -146,6 +148,7 @@
 import android.os.IncidentManager;
 import android.os.PowerManager;
 import android.os.RecoverySystem;
+import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.ServiceManager.ServiceNotFoundException;
 import android.os.SystemUpdateManager;
@@ -357,6 +360,29 @@
                 return new IpSecManager(ctx, service);
             }});
 
+        registerService(
+                Context.TEST_NETWORK_SERVICE,
+                TestNetworkManager.class,
+                new StaticApplicationContextServiceFetcher<TestNetworkManager>() {
+                    @Override
+                    public TestNetworkManager createService(Context context)
+                            throws ServiceNotFoundException {
+                        IBinder csBinder =
+                                ServiceManager.getServiceOrThrow(Context.CONNECTIVITY_SERVICE);
+                        IConnectivityManager csMgr =
+                                IConnectivityManager.Stub.asInterface(csBinder);
+
+                        final IBinder tnBinder;
+                        try {
+                            tnBinder = csMgr.startOrGetTestNetworkService();
+                        } catch (RemoteException e) {
+                            throw new ServiceNotFoundException(Context.TEST_NETWORK_SERVICE);
+                        }
+                        ITestNetworkManager tnMgr = ITestNetworkManager.Stub.asInterface(tnBinder);
+                        return new TestNetworkManager(context, tnMgr);
+                    }
+                });
+
         registerService(Context.COUNTRY_DETECTOR, CountryDetector.class,
                 new StaticServiceFetcher<CountryDetector>() {
             @Override
@@ -1162,7 +1188,7 @@
                                 Context.CONTENT_SUGGESTIONS_SERVICE);
                         IContentSuggestionsManager service =
                                 IContentSuggestionsManager.Stub.asInterface(b);
-                        return new ContentSuggestionsManager(service);
+                        return new ContentSuggestionsManager(ctx.getUserId(), service);
                     }
                 });
 
diff --git a/core/java/android/app/admin/DelegatedAdminReceiver.java b/core/java/android/app/admin/DelegatedAdminReceiver.java
index 9605382..f66de8d 100644
--- a/core/java/android/app/admin/DelegatedAdminReceiver.java
+++ b/core/java/android/app/admin/DelegatedAdminReceiver.java
@@ -24,6 +24,9 @@
 import static android.app.admin.DeviceAdminReceiver.EXTRA_NETWORK_LOGS_COUNT;
 import static android.app.admin.DeviceAdminReceiver.EXTRA_NETWORK_LOGS_TOKEN;
 
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.Service;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -63,20 +66,21 @@
      *
      * <p> This callback is only applicable if the delegated app has
      * {@link DevicePolicyManager#DELEGATION_CERT_SELECTION} capability. Additionally, it must
-     * declare an intent fitler for {@link DeviceAdminReceiver#ACTION_CHOOSE_PRIVATE_KEY_ALIAS}
-     * in the receiver's manifest in order to receive this callback.
+     * declare an intent filter for {@link DeviceAdminReceiver#ACTION_CHOOSE_PRIVATE_KEY_ALIAS}
+     * in the receiver's manifest in order to receive this callback. The default implementation
+     * simply throws {@link UnsupportedOperationException}.
      *
      * @param context The running context as per {@link #onReceive}.
      * @param intent The received intent as per {@link #onReceive}.
-     * @param uid The uid asking for the private key and certificate pair.
+     * @param uid The uid of the app asking for the private key and certificate pair.
      * @param uri The URI to authenticate, may be null.
      * @param alias The alias preselected by the client, or null.
      * @return The private key alias to return and grant access to.
      * @see KeyChain#choosePrivateKeyAlias
      */
-    public String onChoosePrivateKeyAlias(Context context, Intent intent, int uid, Uri uri,
-            String alias) {
-        return null;
+    public @Nullable String onChoosePrivateKeyAlias(@NonNull Context context,
+            @NonNull Intent intent, int uid, @Nullable Uri uri, @Nullable String alias) {
+        throw new UnsupportedOperationException("onChoosePrivateKeyAlias should be implemented");
     }
 
     /**
@@ -91,8 +95,9 @@
      *
      * <p> This callback is only applicable if the delegated app has
      * {@link DevicePolicyManager#DELEGATION_NETWORK_LOGGING} capability. Additionally, it must
-     * declare an intent fitler for {@link DeviceAdminReceiver#ACTION_NETWORK_LOGS_AVAILABLE} in the
-     * receiver's manifest in order to receive this callback.
+     * declare an intent filter for {@link DeviceAdminReceiver#ACTION_NETWORK_LOGS_AVAILABLE} in the
+     * receiver's manifest in order to receive this callback. The default implementation
+     * simply throws {@link UnsupportedOperationException}.
      *
      * @param context The running context as per {@link #onReceive}.
      * @param intent The received intent as per {@link #onReceive}.
@@ -100,8 +105,9 @@
      * @param networkLogsCount The total count of events in the current batch of network logs.
      * @see DevicePolicyManager#retrieveNetworkLogs
      */
-    public void onNetworkLogsAvailable(Context context, Intent intent, long batchToken,
-            int networkLogsCount) {
+    public void onNetworkLogsAvailable(@NonNull Context context, @NonNull Intent intent,
+            long batchToken, @IntRange(from = 1) int networkLogsCount) {
+        throw new UnsupportedOperationException("onNetworkLogsAvailable should be implemented");
     }
 
     /**
@@ -109,7 +115,7 @@
      * this method; implement the convenience callbacks for each action instead.
      */
     @Override
-    public void onReceive(Context context, Intent intent) {
+    public final void onReceive(@NonNull Context context, @NonNull Intent intent) {
         String action = intent.getAction();
 
         if (ACTION_CHOOSE_PRIVATE_KEY_ALIAS.equals(action)) {
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index 5a7124e..4771fd8 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -19,6 +19,7 @@
 import android.accounts.AccountManager;
 import android.annotation.BroadcastBehavior;
 import android.annotation.IntDef;
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
@@ -515,7 +516,7 @@
      * Retrieve the DevicePolicyManager interface for this administrator to work
      * with the system.
      */
-    public DevicePolicyManager getManager(Context context) {
+    public @NonNull DevicePolicyManager getManager(@NonNull Context context) {
         if (mManager != null) {
             return mManager;
         }
@@ -529,7 +530,7 @@
      * use in {@link DevicePolicyManager} APIs that require the administrator to
      * identify itself.
      */
-    public ComponentName getWho(Context context) {
+    public @NonNull ComponentName getWho(@NonNull Context context) {
         if (mWho != null) {
             return mWho;
         }
@@ -550,7 +551,7 @@
      * @param context The running context as per {@link #onReceive}.
      * @param intent The received intent as per {@link #onReceive}.
      */
-    public void onEnabled(Context context, Intent intent) {
+    public void onEnabled(@NonNull Context context, @NonNull Intent intent) {
     }
 
     /**
@@ -564,7 +565,8 @@
      * @return Return the warning message to display to the user before
      * being disabled; if null is returned, no message is displayed.
      */
-    public CharSequence onDisableRequested(Context context, Intent intent) {
+    public @Nullable CharSequence onDisableRequested(@NonNull Context context,
+            @NonNull Intent intent) {
         return null;
     }
 
@@ -576,7 +578,7 @@
      * @param context The running context as per {@link #onReceive}.
      * @param intent The received intent as per {@link #onReceive}.
      */
-    public void onDisabled(Context context, Intent intent) {
+    public void onDisabled(@NonNull Context context, @NonNull Intent intent) {
     }
 
     /**
@@ -591,7 +593,7 @@
      *             {@link #onPasswordChanged(Context, Intent, UserHandle)} instead.
      */
     @Deprecated
-    public void onPasswordChanged(Context context, Intent intent) {
+    public void onPasswordChanged(@NonNull Context context, @NonNull Intent intent) {
     }
 
     /**
@@ -605,7 +607,8 @@
      *        user is the current profile or a parent user, check for equality with
      *        {@link Process#myUserHandle}.
      */
-    public void onPasswordChanged(Context context, Intent intent, UserHandle user) {
+    public void onPasswordChanged(@NonNull Context context, @NonNull Intent intent,
+            @NonNull UserHandle user) {
         onPasswordChanged(context, intent);
     }
 
@@ -621,7 +624,7 @@
      *             {@link #onPasswordFailed(Context, Intent, UserHandle)} instead.
      */
     @Deprecated
-    public void onPasswordFailed(Context context, Intent intent) {
+    public void onPasswordFailed(@NonNull Context context, @NonNull Intent intent) {
     }
 
     /**
@@ -635,7 +638,8 @@
      *        user is the current profile or a parent user, check for equality with
      *        {@link Process#myUserHandle}.
      */
-    public void onPasswordFailed(Context context, Intent intent, UserHandle user) {
+    public void onPasswordFailed(@NonNull Context context, @NonNull Intent intent,
+            @NonNull UserHandle user) {
         onPasswordFailed(context, intent);
     }
 
@@ -651,7 +655,7 @@
      *             {@link #onPasswordSucceeded(Context, Intent, UserHandle)} instead.
      */
     @Deprecated
-    public void onPasswordSucceeded(Context context, Intent intent) {
+    public void onPasswordSucceeded(@NonNull Context context, @NonNull Intent intent) {
     }
 
     /**
@@ -665,7 +669,8 @@
      *        user is the current profile or a parent user, check for equality with
      *        {@link Process#myUserHandle}.
      */
-    public void onPasswordSucceeded(Context context, Intent intent, UserHandle user) {
+    public void onPasswordSucceeded(@NonNull Context context, @NonNull Intent intent,
+            @NonNull UserHandle user) {
         onPasswordSucceeded(context, intent);
     }
 
@@ -691,7 +696,7 @@
      *             {@link #onPasswordExpiring(Context, Intent, UserHandle)} instead.
      */
     @Deprecated
-    public void onPasswordExpiring(Context context, Intent intent) {
+    public void onPasswordExpiring(@NonNull Context context, @NonNull Intent intent) {
     }
 
     /**
@@ -715,7 +720,8 @@
      *        user is the current profile or a parent user, check for equality with
      *        {@link Process#myUserHandle}.
      */
-    public void onPasswordExpiring(Context context, Intent intent, UserHandle user) {
+    public void onPasswordExpiring(@NonNull Context context, @NonNull Intent intent,
+            @NonNull UserHandle user) {
         onPasswordExpiring(context, intent);
     }
 
@@ -746,7 +752,7 @@
      * @param context The running context as per {@link #onReceive}.
      * @param intent The received intent as per {@link #onReceive}.
      */
-    public void onProfileProvisioningComplete(Context context, Intent intent) {
+    public void onProfileProvisioningComplete(@NonNull Context context, @NonNull Intent intent) {
     }
 
     /**
@@ -758,7 +764,7 @@
      * @deprecated Do not use
      */
     @Deprecated
-    public void onReadyForUserInitialization(Context context, Intent intent) {
+    public void onReadyForUserInitialization(@NonNull Context context, @NonNull Intent intent) {
     }
 
     /**
@@ -766,9 +772,10 @@
      *
      * @param context The running context as per {@link #onReceive}.
      * @param intent The received intent as per {@link #onReceive}.
-     * @param pkg If entering, the authorized package using lock task mode, otherwise null.
+     * @param pkg The authorized package using lock task mode.
      */
-    public void onLockTaskModeEntering(Context context, Intent intent, String pkg) {
+    public void onLockTaskModeEntering(@NonNull Context context, @NonNull Intent intent,
+            @NonNull String pkg) {
     }
 
     /**
@@ -777,7 +784,7 @@
      * @param context The running context as per {@link #onReceive}.
      * @param intent The received intent as per {@link #onReceive}.
      */
-    public void onLockTaskModeExiting(Context context, Intent intent) {
+    public void onLockTaskModeExiting(@NonNull Context context, @NonNull Intent intent) {
     }
 
     /**
@@ -787,14 +794,14 @@
      *
      * @param context The running context as per {@link #onReceive}.
      * @param intent The received intent as per {@link #onReceive}.
-     * @param uid The uid asking for the private key and certificate pair.
+     * @param uid The uid of the app asking for the private key and certificate pair.
      * @param uri The URI to authenticate, may be null.
      * @param alias The alias preselected by the client, or null.
      * @return The private key alias to return and grant access to.
      * @see KeyChain#choosePrivateKeyAlias
      */
-    public String onChoosePrivateKeyAlias(Context context, Intent intent, int uid, Uri uri,
-            String alias) {
+    public @Nullable String onChoosePrivateKeyAlias(@NonNull Context context,
+            @NonNull Intent intent, int uid, @Nullable Uri uri, @Nullable String alias) {
         return null;
     }
 
@@ -818,7 +825,8 @@
      *        the current pending update was first available. -1 if no pending update is available.
      * @see DevicePolicyManager#getPendingSystemUpdate
      */
-    public void onSystemUpdatePending(Context context, Intent intent, long receivedTime) {
+    public void onSystemUpdatePending(@NonNull Context context, @NonNull Intent intent,
+            long receivedTime) {
     }
 
     /**
@@ -830,7 +838,7 @@
      * @param intent The received intent as per {@link #onReceive}.
      * @see DevicePolicyManager#requestBugreport
      */
-    public void onBugreportSharingDeclined(Context context, Intent intent) {
+    public void onBugreportSharingDeclined(@NonNull Context context, @NonNull Intent intent) {
     }
 
     /**
@@ -845,7 +853,8 @@
      * @param bugreportHash SHA-256 hash of the bugreport file.
      * @see DevicePolicyManager#requestBugreport
      */
-    public void onBugreportShared(Context context, Intent intent, String bugreportHash) {
+    public void onBugreportShared(@NonNull Context context, @NonNull Intent intent,
+            @NonNull String bugreportHash) {
     }
 
     /**
@@ -860,7 +869,7 @@
      * or {@link #BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE}
      * @see DevicePolicyManager#requestBugreport
      */
-    public void onBugreportFailed(Context context, Intent intent,
+    public void onBugreportFailed(@NonNull Context context, @NonNull Intent intent,
             @BugreportFailureCode int failureCode) {
     }
 
@@ -879,7 +888,7 @@
      * @param intent The received intent as per {@link #onReceive}.
      * @see DevicePolicyManager#retrieveSecurityLogs(ComponentName)
      */
-    public void onSecurityLogsAvailable(Context context, Intent intent) {
+    public void onSecurityLogsAvailable(@NonNull Context context, @NonNull Intent intent) {
     }
 
     /**
@@ -900,8 +909,8 @@
      * @param networkLogsCount The total count of events in the current batch of network logs.
      * @see DevicePolicyManager#retrieveNetworkLogs
      */
-    public void onNetworkLogsAvailable(Context context, Intent intent, long batchToken,
-            int networkLogsCount) {
+    public void onNetworkLogsAvailable(@NonNull Context context, @NonNull Intent intent,
+            long batchToken, @IntRange(from = 1) int networkLogsCount) {
     }
 
     /**
@@ -913,7 +922,8 @@
      * @param intent The received intent as per {@link #onReceive}.
      * @param newUser The {@link UserHandle} of the user that has just been added.
      */
-    public void onUserAdded(Context context, Intent intent, @NonNull UserHandle newUser) {
+    public void onUserAdded(@NonNull Context context, @NonNull Intent intent,
+            @NonNull UserHandle newUser) {
     }
 
     /**
@@ -925,7 +935,8 @@
      * @param intent The received intent as per {@link #onReceive}.
      * @param removedUser The {@link UserHandle} of the user that has just been removed.
      */
-    public void onUserRemoved(Context context, Intent intent, @NonNull UserHandle removedUser) {
+    public void onUserRemoved(@NonNull Context context, @NonNull Intent intent,
+            @NonNull UserHandle removedUser) {
     }
 
     /**
@@ -937,7 +948,8 @@
      * @param intent The received intent as per {@link #onReceive}.
      * @param startedUser The {@link UserHandle} of the user that has just been started.
      */
-    public void onUserStarted(Context context, Intent intent, @NonNull UserHandle startedUser) {
+    public void onUserStarted(@NonNull Context context, @NonNull Intent intent,
+            @NonNull UserHandle startedUser) {
     }
 
     /**
@@ -949,7 +961,8 @@
      * @param intent The received intent as per {@link #onReceive}.
      * @param stoppedUser The {@link UserHandle} of the user that has just been stopped.
      */
-    public void onUserStopped(Context context, Intent intent, @NonNull UserHandle stoppedUser) {
+    public void onUserStopped(@NonNull Context context, @NonNull Intent intent,
+            @NonNull UserHandle stoppedUser) {
     }
 
     /**
@@ -961,7 +974,8 @@
      * @param intent The received intent as per {@link #onReceive}.
      * @param switchedUser The {@link UserHandle} of the user that has just been switched to.
      */
-    public void onUserSwitched(Context context, Intent intent, @NonNull UserHandle switchedUser) {
+    public void onUserSwitched(@NonNull Context context, @NonNull Intent intent,
+            @NonNull UserHandle switchedUser) {
     }
 
     /**
@@ -995,7 +1009,8 @@
      * @param user the {@link UserHandle} of the affiliated user
      * @see DevicePolicyManager#transferOwnership(ComponentName, ComponentName, PersistableBundle)
      */
-    public void onTransferAffiliatedProfileOwnershipComplete(Context context, UserHandle user) {
+    public void onTransferAffiliatedProfileOwnershipComplete(@NonNull Context context,
+            @NonNull UserHandle user) {
     }
 
     /**
@@ -1004,7 +1019,7 @@
      * convenience callbacks for each action.
      */
     @Override
-    public void onReceive(Context context, Intent intent) {
+    public void onReceive(@NonNull Context context, @NonNull Intent intent) {
         String action = intent.getAction();
 
         if (ACTION_PASSWORD_CHANGED.equals(action)) {
diff --git a/core/java/android/app/admin/DevicePolicyEventLogger.java b/core/java/android/app/admin/DevicePolicyEventLogger.java
index c89d868..44ea218 100644
--- a/core/java/android/app/admin/DevicePolicyEventLogger.java
+++ b/core/java/android/app/admin/DevicePolicyEventLogger.java
@@ -178,7 +178,7 @@
     }
 
     /**
-     * Retrieves the package name of the admin application from the {@link ComponentName}.
+     * Sets the package name of the admin application from the {@link ComponentName}.
      */
     public DevicePolicyEventLogger setAdmin(@Nullable ComponentName componentName) {
         mAdminPackageName = (componentName != null ? componentName.getPackageName() : null);
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index f8ccb13..9436145 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -112,6 +112,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import java.util.concurrent.CompletableFuture;
@@ -3393,9 +3394,6 @@
      * explicitly querying the parent profile screen lock complexity via {@link
      * #getParentProfileInstance}.
      *
-     * <p>On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, the
-     * password is always empty and this method returns {@link #PASSWORD_COMPLEXITY_NONE}.
-     *
      * @throws IllegalStateException if the user is not unlocked.
      * @throws SecurityException if the calling application does not have the permission
      *                           {@link permission#REQUEST_PASSWORD_COMPLEXITY}
@@ -5174,7 +5172,8 @@
      * </ul>
      * The call will fail if called with the package name of an unsupported VPN app.
      * <p> Enabling lockdown via {@code lockdownEnabled} argument carries the risk that any failure
-     * of the VPN provider could break networking for all apps.
+     * of the VPN provider could break networking for all apps. This method clears any lockdown
+     * whitelist set by {@link #setAlwaysOnVpnPackage(ComponentName, String, boolean, Set)}.
      *
      * @param vpnPackage The package name for an installed VPN app on the device, or {@code null} to
      *        remove an existing always-on VPN configuration.
@@ -5184,11 +5183,11 @@
      * @throws NameNotFoundException if {@code vpnPackage} is not installed.
      * @throws UnsupportedOperationException if {@code vpnPackage} exists but does not support being
      *         set as always-on, or if always-on VPN is not available.
-     * @see #setAlwaysOnVpnPackage(ComponentName, String, boolean, List)
+     * @see #setAlwaysOnVpnPackage(ComponentName, String, boolean, Set)
      */
     public void setAlwaysOnVpnPackage(@NonNull ComponentName admin, @Nullable String vpnPackage,
             boolean lockdownEnabled) throws NameNotFoundException {
-        setAlwaysOnVpnPackage(admin, vpnPackage, lockdownEnabled, Collections.emptyList());
+        setAlwaysOnVpnPackage(admin, vpnPackage, lockdownEnabled, Collections.emptySet());
     }
 
     /**
@@ -5198,6 +5197,11 @@
      * System apps can always bypass VPN.
      * <p> Note that the system doesn't update the whitelist when packages are installed or
      * uninstalled, the admin app must call this method to keep the list up to date.
+     * <p> When {@code lockdownEnabled} is false {@code lockdownWhitelist} is ignored . When
+     * {@code lockdownEnabled} is {@code true} and {@code lockdownWhitelist} is {@code null} or
+     * empty, only system apps can bypass VPN.
+     * <p> Setting always-on VPN package to {@code null} or using
+     * {@link #setAlwaysOnVpnPackage(ComponentName, String, boolean)} clears lockdown whitelist.
      *
      * @param vpnPackage package name for an installed VPN app on the device, or {@code null}
      *         to remove an existing always-on VPN configuration
@@ -5214,13 +5218,13 @@
      *         available.
      */
     public void setAlwaysOnVpnPackage(@NonNull ComponentName admin, @Nullable String vpnPackage,
-            boolean lockdownEnabled, @Nullable List<String> lockdownWhitelist)
+            boolean lockdownEnabled, @Nullable Set<String> lockdownWhitelist)
             throws NameNotFoundException {
         throwIfParentInstance("setAlwaysOnVpnPackage");
         if (mService != null) {
             try {
-                mService.setAlwaysOnVpnPackage(
-                        admin, vpnPackage, lockdownEnabled, lockdownWhitelist);
+                mService.setAlwaysOnVpnPackage(admin, vpnPackage, lockdownEnabled,
+                        lockdownWhitelist == null ? null : new ArrayList<>(lockdownWhitelist));
             } catch (ServiceSpecificException e) {
                 switch (e.errorCode) {
                     case ERROR_VPN_PACKAGE_NOT_FOUND:
@@ -5258,7 +5262,7 @@
     }
 
     /**
-     * Called by device or profile owner to query the list of packages that are allowed to access
+     * Called by device or profile owner to query the set of packages that are allowed to access
      * the network directly when always-on VPN is in lockdown mode but not connected. Returns
      * {@code null} when always-on VPN is not active or not in lockdown mode.
      *
@@ -5266,13 +5270,15 @@
      *
      * @throws SecurityException if {@code admin} is not a device or a profile owner.
      *
-     * @see #setAlwaysOnVpnPackage(ComponentName, String, boolean, List)
+     * @see #setAlwaysOnVpnPackage(ComponentName, String, boolean, Set)
      */
-    public @Nullable List<String> getAlwaysOnVpnLockdownWhitelist(@NonNull ComponentName admin) {
+    public @Nullable Set<String> getAlwaysOnVpnLockdownWhitelist(@NonNull ComponentName admin) {
         throwIfParentInstance("getAlwaysOnVpnLockdownWhitelist");
         if (mService != null) {
             try {
-                return mService.getAlwaysOnVpnLockdownWhitelist(admin);
+                final List<String> whitelist =
+                        mService.getAlwaysOnVpnLockdownWhitelist(admin);
+                return whitelist == null ? null : new HashSet<>(whitelist);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -10628,10 +10634,10 @@
      * Returns the system-wide Private DNS host.
      *
      * @param admin which {@link DeviceAdminReceiver} this request is associated with.
-     * @return The hostname used for Private DNS queries.
+     * @return The hostname used for Private DNS queries, null if none is set.
      * @throws SecurityException if the caller is not the device owner.
      */
-    public String getGlobalPrivateDnsHost(@NonNull ComponentName admin) {
+    public @Nullable String getGlobalPrivateDnsHost(@NonNull ComponentName admin) {
         throwIfParentInstance("setGlobalPrivateDns");
         if (mService == null) {
             return null;
@@ -10661,13 +10667,12 @@
     @SystemApi
     @RequiresPermission(value = android.Manifest.permission.GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS,
             conditional = true)
-    public void setProfileOwnerCanAccessDeviceIdsForUser(
-            @NonNull ComponentName who, @NonNull UserHandle userHandle) {
+    public void setProfileOwnerCanAccessDeviceIds(@NonNull ComponentName who) {
         if (mService == null) {
             return;
         }
         try {
-            mService.grantDeviceIdsAccessToProfileOwner(who, userHandle.getIdentifier());
+            mService.grantDeviceIdsAccessToProfileOwner(who, myUserId());
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
diff --git a/core/java/android/app/backup/IRestoreSession.aidl b/core/java/android/app/backup/IRestoreSession.aidl
index b9e9485..c3a298b 100644
--- a/core/java/android/app/backup/IRestoreSession.aidl
+++ b/core/java/android/app/backup/IRestoreSession.aidl
@@ -71,8 +71,8 @@
      *   applications mentioned in this list will have their data restored.
      * @param monitor If non null the binder will send important events to this monitor.
      */
-    int restoreSome(long token, IRestoreObserver observer, IBackupManagerMonitor monitor,
-            in String[] packages);
+    int restorePackages(long token, IRestoreObserver observer, in String[] packages,
+            IBackupManagerMonitor monitor);
 
     /**
      * Restore a single application from backup.  The data will be restored from the
diff --git a/core/java/android/app/backup/RestoreSession.java b/core/java/android/app/backup/RestoreSession.java
index 79925ec..084b13b 100644
--- a/core/java/android/app/backup/RestoreSession.java
+++ b/core/java/android/app/backup/RestoreSession.java
@@ -16,6 +16,8 @@
 
 package android.app.backup;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.content.Context;
 import android.os.Bundle;
@@ -24,6 +26,10 @@
 import android.os.RemoteException;
 import android.util.Log;
 
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
 /**
  * Interface for managing a restore session.
  * @hide
@@ -138,14 +144,15 @@
      *   the restore set that should be used.
      * @param observer If non-null, this binder points to an object that will receive
      *   progress callbacks during the restore operation.
-     * @param monitor If non-null, this binder points to an object that will receive
-     *   progress callbacks during the restore operation.
      * @param packages The set of packages for which to attempt a restore.  Regardless of
      *   the contents of the actual back-end dataset named by {@code token}, only
      *   applications mentioned in this list will have their data restored.
+     * @param monitor If non-null, this binder points to an object that will receive
+     *   progress callbacks during the restore operation containing detailed information on any
+     *   failures or important decisions made by {@link BackupManager}.
      */
-    public int restoreSome(long token, RestoreObserver observer, BackupManagerMonitor monitor,
-            String[] packages) {
+    public int restorePackages(long token, @Nullable RestoreObserver observer,
+            @NonNull Set<String> packages, @Nullable BackupManagerMonitor monitor) {
         int err = -1;
         if (mObserver != null) {
             Log.d(TAG, "restoreAll() called during active restore");
@@ -156,7 +163,8 @@
                 ? null
                 : new BackupManagerMonitorWrapper(monitor);
         try {
-            err = mBinder.restoreSome(token, mObserver, monitorWrapper, packages);
+            err = mBinder.restorePackages(token, mObserver, packages.toArray(new String[] {}),
+                    monitorWrapper);
         } catch (RemoteException e) {
             Log.d(TAG, "Can't contact server to restore packages");
         }
@@ -180,6 +188,60 @@
      *   the contents of the actual back-end dataset named by {@code token}, only
      *   applications mentioned in this list will have their data restored.
      */
+    public int restorePackages(long token, @Nullable RestoreObserver observer,
+            @NonNull Set<String> packages) {
+        return restorePackages(token, observer, packages, null);
+    }
+
+    /**
+     * Restore select packages from the given set onto the device, replacing the
+     * current data of any app contained in the set with the data previously
+     * backed up.
+     *
+     * <p>Callers must hold the android.permission.BACKUP permission to use this method.
+     *
+     * @return Zero on success, nonzero on error. The observer will only receive
+     *   progress callbacks if this method returned zero.
+     * @param token The token from {@link getAvailableRestoreSets()} corresponding to
+     *   the restore set that should be used.
+     * @param observer If non-null, this binder points to an object that will receive
+     *   progress callbacks during the restore operation.
+     * @param monitor If non-null, this binder points to an object that will receive
+     *   progress callbacks during the restore operation.
+     * @param packages The set of packages for which to attempt a restore.  Regardless of
+     *   the contents of the actual back-end dataset named by {@code token}, only
+     *   applications mentioned in this list will have their data restored.
+     *
+     * @deprecated use {@link RestoreSession#restorePackages(long, RestoreObserver,
+     *   BackupManagerMonitor, Set)} instead.
+     */
+    @Deprecated
+    public int restoreSome(long token, RestoreObserver observer, BackupManagerMonitor monitor,
+            String[] packages) {
+        return restorePackages(token, observer, new HashSet<>(Arrays.asList(packages)), monitor);
+    }
+
+    /**
+     * Restore select packages from the given set onto the device, replacing the
+     * current data of any app contained in the set with the data previously
+     * backed up.
+     *
+     * <p>Callers must hold the android.permission.BACKUP permission to use this method.
+     *
+     * @return Zero on success, nonzero on error. The observer will only receive
+     *   progress callbacks if this method returned zero.
+     * @param token The token from {@link getAvailableRestoreSets()} corresponding to
+     *   the restore set that should be used.
+     * @param observer If non-null, this binder points to an object that will receive
+     *   progress callbacks during the restore operation.
+     * @param packages The set of packages for which to attempt a restore.  Regardless of
+     *   the contents of the actual back-end dataset named by {@code token}, only
+     *   applications mentioned in this list will have their data restored.
+     *
+     * @deprecated use {@link RestoreSession#restorePackages(long, RestoreObserver, Set)}
+     *   instead.
+     */
+    @Deprecated
     public int restoreSome(long token, RestoreObserver observer, String[] packages) {
         return restoreSome(token, observer, null, packages);
     }
diff --git a/core/java/android/app/contentsuggestions/ContentSuggestionsManager.java b/core/java/android/app/contentsuggestions/ContentSuggestionsManager.java
index b4d8977..1bb81b1 100644
--- a/core/java/android/app/contentsuggestions/ContentSuggestionsManager.java
+++ b/core/java/android/app/contentsuggestions/ContentSuggestionsManager.java
@@ -20,11 +20,14 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.UserIdInt;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.util.Log;
 
+import com.android.internal.util.SyncResultReceiver;
+
 import java.util.List;
 import java.util.concurrent.Executor;
 
@@ -44,12 +47,22 @@
 public final class ContentSuggestionsManager {
     private static final String TAG = ContentSuggestionsManager.class.getSimpleName();
 
+    /**
+     * Timeout for calls to system_server.
+     */
+    private static final int SYNC_CALLS_TIMEOUT_MS = 5000;
+
     @Nullable
     private final IContentSuggestionsManager mService;
 
+    @NonNull
+    private final int mUser;
+
     /** @hide */
-    public ContentSuggestionsManager(@Nullable IContentSuggestionsManager service) {
+    public ContentSuggestionsManager(
+            @UserIdInt int userId, @Nullable IContentSuggestionsManager service) {
         mService = service;
+        mUser = userId;
     }
 
     /**
@@ -60,14 +73,15 @@
      * @param imageContextRequestExtras sent with with request to provide implementation specific
      *                                  extra information.
      */
-    public void provideContextImage(int taskId, @NonNull Bundle imageContextRequestExtras) {
+    public void provideContextImage(
+            int taskId, @NonNull Bundle imageContextRequestExtras) {
         if (mService == null) {
             Log.e(TAG, "provideContextImage called, but no ContentSuggestionsManager configured");
             return;
         }
 
         try {
-            mService.provideContextImage(taskId, imageContextRequestExtras);
+            mService.provideContextImage(mUser, taskId, imageContextRequestExtras);
         } catch (RemoteException e) {
             e.rethrowFromSystemServer();
         }
@@ -96,7 +110,7 @@
 
         try {
             mService.suggestContentSelections(
-                    request, new SelectionsCallbackWrapper(callback, callbackExecutor));
+                    mUser, request, new SelectionsCallbackWrapper(callback, callbackExecutor));
         } catch (RemoteException e) {
             e.rethrowFromSystemServer();
         }
@@ -123,7 +137,7 @@
 
         try {
             mService.classifyContentSelections(
-                    request, new ClassificationsCallbackWrapper(callback, callbackExecutor));
+                    mUser, request, new ClassificationsCallbackWrapper(callback, callbackExecutor));
         } catch (RemoteException e) {
             e.rethrowFromSystemServer();
         }
@@ -135,20 +149,42 @@
      * @param requestId the id for the associated interaction
      * @param interaction to report back to the system content suggestions service.
      */
-    public void notifyInteraction(@NonNull String requestId, @NonNull Bundle interaction) {
+    public void notifyInteraction(
+            @NonNull String requestId, @NonNull Bundle interaction) {
         if (mService == null) {
             Log.e(TAG, "notifyInteraction called, but no ContentSuggestionsManager configured");
             return;
         }
 
         try {
-            mService.notifyInteraction(requestId, interaction);
+            mService.notifyInteraction(mUser, requestId, interaction);
         } catch (RemoteException e) {
             e.rethrowFromSystemServer();
         }
     }
 
     /**
+     * Indicates that Content Suggestions is available and enabled for the provided user. That is,
+     * has an implementation and not disabled through device management.
+     *
+     * @return {@code true} if Content Suggestions is enabled and available for the provided user.
+     */
+    public boolean isEnabled() {
+        if (mService == null) {
+            return false;
+        }
+
+        SyncResultReceiver receiver = new SyncResultReceiver(SYNC_CALLS_TIMEOUT_MS);
+        try {
+            mService.isEnabled(mUser, receiver);
+            return receiver.getIntResult() != 0;
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+        return false;
+    }
+
+    /**
      * Callback to receive content selections from
      *  {@link #suggestContentSelections(SelectionsRequest, Executor, SelectionsCallback)}.
      */
diff --git a/core/java/android/app/contentsuggestions/IContentSuggestionsManager.aidl b/core/java/android/app/contentsuggestions/IContentSuggestionsManager.aidl
index 24f5ad8..b18a758 100644
--- a/core/java/android/app/contentsuggestions/IContentSuggestionsManager.aidl
+++ b/core/java/android/app/contentsuggestions/IContentSuggestionsManager.aidl
@@ -21,17 +21,23 @@
 import android.app.contentsuggestions.ClassificationsRequest;
 import android.app.contentsuggestions.SelectionsRequest;
 import android.os.Bundle;
+import android.os.UserHandle;
+import com.android.internal.os.IResultReceiver;
 
 /** @hide */
 oneway interface IContentSuggestionsManager {
     void provideContextImage(
+            int userId,
             int taskId,
             in Bundle imageContextRequestExtras);
     void suggestContentSelections(
+            int userId,
             in SelectionsRequest request,
             in ISelectionsCallback callback);
     void classifyContentSelections(
+            int userId,
             in ClassificationsRequest request,
             in IClassificationsCallback callback);
-    void notifyInteraction(in String requestId, in Bundle interaction);
+    void notifyInteraction(int userId, in String requestId, in Bundle interaction);
+    void isEnabled(int userId, in IResultReceiver receiver);
 }
diff --git a/core/java/android/app/prediction/AppPredictionContext.java b/core/java/android/app/prediction/AppPredictionContext.java
index 2da4671..b6f37f6 100644
--- a/core/java/android/app/prediction/AppPredictionContext.java
+++ b/core/java/android/app/prediction/AppPredictionContext.java
@@ -15,6 +15,7 @@
  */
 package android.app.prediction;
 
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
@@ -49,18 +50,19 @@
         mExtras = extras;
     }
 
-    private AppPredictionContext(Parcel parcel) {
+    private AppPredictionContext(@NonNull Parcel parcel) {
         mUiSurface = parcel.readString();
         mPredictedTargetCount = parcel.readInt();
         mPackageName = parcel.readString();
         mExtras = parcel.readBundle();
     }
 
+    @NonNull
     public String getUiSurface() {
         return mUiSurface;
     }
 
-    public int getPredictedTargetCount() {
+    public @IntRange(from = 0) int getPredictedTargetCount() {
         return mPredictedTargetCount;
     }
 
@@ -91,7 +93,7 @@
     }
 
     @Override
-    public void writeToParcel(Parcel dest, int flags) {
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeString(mUiSurface);
         dest.writeInt(mPredictedTargetCount);
         dest.writeString(mPackageName);
@@ -144,7 +146,8 @@
         /**
          * Sets the number of prediction targets as a hint.
          */
-        public Builder setPredictedTargetCount(int predictedTargetCount) {
+        @NonNull
+        public Builder setPredictedTargetCount(@IntRange(from = 0) int predictedTargetCount) {
             mPredictedTargetCount = predictedTargetCount;
             return this;
         }
@@ -152,7 +155,8 @@
         /**
          * Sets the UI surface.
          */
-        public Builder setUiSurface(@Nullable String uiSurface) {
+        @NonNull
+        public Builder setUiSurface(@NonNull String uiSurface) {
             mUiSurface = uiSurface;
             return this;
         }
@@ -160,6 +164,7 @@
         /**
          * Sets the extras.
          */
+        @NonNull
         public Builder setExtras(@Nullable Bundle extras) {
             mExtras = extras;
             return this;
@@ -168,6 +173,7 @@
         /**
          * Builds a new context instance.
          */
+        @NonNull
         public AppPredictionContext build() {
             return new AppPredictionContext(mUiSurface, mPredictedTargetCount, mPackageName,
                     mExtras);
diff --git a/core/java/android/app/prediction/AppPredictionManager.java b/core/java/android/app/prediction/AppPredictionManager.java
index 99f78f1..45825cf 100644
--- a/core/java/android/app/prediction/AppPredictionManager.java
+++ b/core/java/android/app/prediction/AppPredictionManager.java
@@ -42,6 +42,7 @@
     /**
      * Creates a new app prediction session.
      */
+    @NonNull
     public AppPredictor createAppPredictionSession(
             @NonNull AppPredictionContext predictionContext) {
         return new AppPredictor(mContext, predictionContext);
diff --git a/core/java/android/app/prediction/AppPredictor.java b/core/java/android/app/prediction/AppPredictor.java
index 12d6ce3..284327d 100644
--- a/core/java/android/app/prediction/AppPredictor.java
+++ b/core/java/android/app/prediction/AppPredictor.java
@@ -94,7 +94,7 @@
             mPredictionManager.createPredictionSession(predictionContext, mSessionId);
         } catch (RemoteException e) {
             Log.e(TAG, "Failed to create predictor", e);
-            return;
+            e.rethrowAsRuntimeException();
         }
 
         mCloseGuard.open("close");
@@ -112,6 +112,7 @@
             mPredictionManager.notifyAppTargetEvent(mSessionId, event);
         } catch (RemoteException e) {
             Log.e(TAG, "Failed to notify app target event", e);
+            e.rethrowAsRuntimeException();
         }
     }
 
@@ -129,6 +130,7 @@
                     new ParceledListSlice<>(targetIds));
         } catch (RemoteException e) {
             Log.e(TAG, "Failed to notify location shown event", e);
+            e.rethrowAsRuntimeException();
         }
     }
 
@@ -155,6 +157,7 @@
             mRegisteredCallbacks.put(callback, callbackWrapper);
         } catch (RemoteException e) {
             Log.e(TAG, "Failed to register for prediction updates", e);
+            e.rethrowAsRuntimeException();
         }
     }
 
@@ -176,6 +179,7 @@
             mPredictionManager.unregisterPredictionUpdates(mSessionId, callbackWrapper);
         } catch (RemoteException e) {
             Log.e(TAG, "Failed to unregister for prediction updates", e);
+            e.rethrowAsRuntimeException();
         }
     }
 
@@ -194,6 +198,7 @@
             mPredictionManager.requestPredictionUpdate(mSessionId);
         } catch (RemoteException e) {
             Log.e(TAG, "Failed to request prediction update", e);
+            e.rethrowAsRuntimeException();
         }
     }
 
@@ -213,14 +218,13 @@
                     new CallbackWrapper(callbackExecutor, callback));
         } catch (RemoteException e) {
             Log.e(TAG, "Failed to sort targets", e);
+            e.rethrowAsRuntimeException();
         }
     }
 
     /**
      * Destroys the client and unregisters the callback. Any method on this class after this call
      * with throw {@link IllegalStateException}.
-     *
-     * TODO(b/111701043): Add state check in other methods.
      */
     public void destroy() {
         if (!mIsClosed.getAndSet(true)) {
@@ -231,6 +235,7 @@
                 mPredictionManager.onDestroyPredictionSession(mSessionId);
             } catch (RemoteException e) {
                 Log.e(TAG, "Failed to notify app target event", e);
+                e.rethrowAsRuntimeException();
             }
         } else {
             throw new IllegalStateException("This client has already been destroyed.");
diff --git a/core/java/android/app/prediction/AppTarget.java b/core/java/android/app/prediction/AppTarget.java
index 752c92b..6f09d34 100644
--- a/core/java/android/app/prediction/AppTarget.java
+++ b/core/java/android/app/prediction/AppTarget.java
@@ -15,6 +15,7 @@
  */
 package android.app.prediction;
 
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
@@ -134,14 +135,19 @@
      * Sets the rank of the for the target.
      * @hide
      */
-    public void setRank(int rank) {
+    public void setRank(@IntRange(from = 0) int rank) {
+        if (rank < 0) {
+            throw new IllegalArgumentException("rank cannot be a negative value");
+        }
         mRank = rank;
     }
 
     /**
-     * Returns the rank for the target.
+     * Returns the rank for the target. Rank of an AppTarget is a non-negative integer that
+     * represents the importance of this target compared to other candidate targets. A smaller value
+     * means higher importance in the list.
      */
-    public int getRank() {
+    public @IntRange(from = 0) int getRank() {
         return mRank;
     }
 
diff --git a/core/java/android/app/prediction/AppTargetEvent.java b/core/java/android/app/prediction/AppTargetEvent.java
index 01452df..f6964f3 100644
--- a/core/java/android/app/prediction/AppTargetEvent.java
+++ b/core/java/android/app/prediction/AppTargetEvent.java
@@ -84,7 +84,7 @@
     /**
      * Returns the launch location.
      */
-    @NonNull
+    @Nullable
     public String getLaunchLocation() {
         return mLocation;
     }
@@ -92,8 +92,7 @@
     /**
      * Returns the action type.
      */
-    @NonNull
-    public int getAction() {
+    public @ActionType int getAction() {
         return mAction;
     }
 
@@ -152,7 +151,8 @@
         /**
          * Sets the launch location.
          */
-        public Builder setLaunchLocation(String location) {
+        @NonNull
+        public Builder setLaunchLocation(@Nullable String location) {
             mLocation = location;
             return this;
         }
@@ -160,6 +160,7 @@
         /**
          * Builds a new event instance.
          */
+        @NonNull
         public AppTargetEvent build() {
             return new AppTargetEvent(mTarget, mLocation, mAction);
         }
diff --git a/core/java/android/app/usage/IUsageStatsManager.aidl b/core/java/android/app/usage/IUsageStatsManager.aidl
index 62b24e9..83c1d61 100644
--- a/core/java/android/app/usage/IUsageStatsManager.aidl
+++ b/core/java/android/app/usage/IUsageStatsManager.aidl
@@ -60,7 +60,7 @@
             in PendingIntent sessionEndCallbackIntent, String callingPackage);
     void unregisterUsageSessionObserver(int sessionObserverId, String callingPackage);
     void registerAppUsageLimitObserver(int observerId, in String[] packages, long timeLimitMs,
-            long timeRemainingMs, in PendingIntent callback, String callingPackage);
+            long timeUsedMs, in PendingIntent callback, String callingPackage);
     void unregisterAppUsageLimitObserver(int observerId, String callingPackage);
     void reportUsageStart(in IBinder activity, String token, String callingPackage);
     void reportPastUsageStart(in IBinder activity, String token, long timeAgoMs,
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index b3d01fd..b564c31 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -428,7 +428,6 @@
 
         /**
          * Indicates whether it is an instant app.
-         * STOPSHIP b/111407095: Add GTS tests for the newly added API method.
          * @hide
          */
         @SystemApi
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index cee6b87..a6ceeb1 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -660,6 +660,29 @@
         }
     }
 
+
+    /**
+     * @deprecated use {@link #registerUsageSessionObserver(int, String[], Duration, Duration,
+     *                                                      PendingIntent, PendingIntent)}.
+     *
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE)
+    // STOPSHIP b/128455269: remove this method
+    public void registerUsageSessionObserver(int sessionObserverId,
+            @NonNull String[] observedEntities, long timeLimit, @NonNull TimeUnit timeUnit,
+            long sessionThresholdTime,  @NonNull TimeUnit sessionThresholdTimeUnit,
+            @NonNull PendingIntent limitReachedCallbackIntent,
+            @Nullable PendingIntent sessionEndCallbackIntent) {
+        final Duration timeLimitDuration = Duration.ofMillis(timeUnit.toMillis(timeLimit));
+        final Duration sessionThresholdDuration =
+                Duration.ofMillis(sessionThresholdTimeUnit.toMillis(sessionThresholdTime));
+        registerUsageSessionObserver(sessionObserverId, observedEntities, timeLimitDuration,
+                sessionThresholdDuration, limitReachedCallbackIntent, sessionEndCallbackIntent);
+    }
+
     /**
      * Register a usage session observer that receives a callback on the provided {@code
      * limitReachedCallbackIntent} when the sum of usages of apps and tokens in the {@code
@@ -679,11 +702,8 @@
      *                         null and must include at least one package or token.
      * @param timeLimit The total time the set of apps can be used continuously before the {@code
      *                  limitReachedCallbackIntent} is delivered. Must be at least one minute.
-     * @param timeUnit The unit for time specified in {@code timeLimit}. Cannot be null.
      * @param sessionThresholdTime The time that can take place between usage sessions before the
      *                             next session is considered a new session. Must be non-negative.
-     * @param sessionThresholdTimeUnit The unit for time specified in {@code sessionThreshold}.
-     *                                 Cannot be null.
      * @param limitReachedCallbackIntent The {@link PendingIntent} that will be dispatched when the
      *                                   usage limit is exceeded by the group of apps. The
      *                                   delivered Intent will also contain the extras {@link
@@ -703,14 +723,13 @@
     @SystemApi
     @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE)
     public void registerUsageSessionObserver(int sessionObserverId,
-            @NonNull String[] observedEntities, long timeLimit, @NonNull TimeUnit timeUnit,
-            long sessionThresholdTime,  @NonNull TimeUnit sessionThresholdTimeUnit,
+            @NonNull String[] observedEntities, @NonNull Duration timeLimit,
+            @NonNull Duration sessionThresholdTime,
             @NonNull PendingIntent limitReachedCallbackIntent,
             @Nullable PendingIntent sessionEndCallbackIntent) {
         try {
             mService.registerUsageSessionObserver(sessionObserverId, observedEntities,
-                    timeUnit.toMillis(timeLimit),
-                    sessionThresholdTimeUnit.toMillis(sessionThresholdTime),
+                    timeLimit.toMillis(), sessionThresholdTime.toMillis(),
                     limitReachedCallbackIntent, sessionEndCallbackIntent,
                     mContext.getOpPackageName());
         } catch (RemoteException e) {
@@ -747,7 +766,7 @@
      */
     @Deprecated
     @UnsupportedAppUsage
-    // STOPSHIP b/126917290: remove this method once ag/6591106 is merged and it's not being used.
+    // STOPSHIP b/126917290: remove this method once b/126926550 is fixed.
     public void registerAppUsageLimitObserver(int observerId, @NonNull String[] observedEntities,
             long timeLimit, @NonNull TimeUnit timeUnit, @Nullable PendingIntent callbackIntent) {
         final Duration timeLimitDuration = Duration.ofMillis(timeUnit.toMillis(timeLimit));
@@ -782,16 +801,17 @@
      *                         null and must include at least one package or token.
      * @param timeLimit The total time the set of apps can be in the foreground before the
      *                  {@code callbackIntent} is delivered. Must be at least one minute.
-     * @param timeRemaining The remaining time the set of apps can be in the foreground before the
-     *                      {@code callbackIntent} is delivered. Must be greater than
-     *                      {@code timeLimit}. Note: a limit of 0 can be set to indicate that the
-     *                      user has already exhausted the limit for a group, in which case,
-     *                      the given {@code callbackIntent} will be ignored.
+     * @param timeUsed The time that has already been used by the set of apps in
+     *                 {@code observedEntities}. Note: a time used equal to or greater than
+     *                 {@code timeLimit} can be set to indicate that the user has already exhausted
+     *                 the limit for a group, in which case, the given {@code callbackIntent} will
+     *                 be ignored.
      * @param callbackIntent The PendingIntent that will be dispatched when the usage limit is
      *                       exceeded by the group of apps. The delivered Intent will also contain
      *                       the extras {@link #EXTRA_OBSERVER_ID}, {@link #EXTRA_TIME_LIMIT} and
      *                       {@link #EXTRA_TIME_USED}. Cannot be {@code null} unless the observer is
-     *                       being registered with a {@code timeRemaining} of 0.
+     *                       being registered with a {@code timeUsed} equal to or greater than
+     *                       {@code timeLimit}.
      * @throws SecurityException if the caller doesn't have both SUSPEND_APPS and OBSERVE_APP_USAGE
      *                           permissions.
      * @hide
@@ -801,11 +821,11 @@
             android.Manifest.permission.SUSPEND_APPS,
             android.Manifest.permission.OBSERVE_APP_USAGE})
     public void registerAppUsageLimitObserver(int observerId, @NonNull String[] observedEntities,
-            @NonNull Duration timeLimit, @NonNull Duration timeRemaining,
+            @NonNull Duration timeLimit, @NonNull Duration timeUsed,
             @Nullable PendingIntent callbackIntent) {
         try {
             mService.registerAppUsageLimitObserver(observerId, observedEntities,
-                    timeLimit.toMillis(), timeRemaining.toMillis(), callbackIntent,
+                    timeLimit.toMillis(), timeUsed.toMillis(), callbackIntent,
                     mContext.getOpPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index c4bf1eb..442b239 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -224,8 +224,10 @@
                         if (VDBG) Log.d(TAG, "Unbinding service...");
                         try {
                             mServiceLock.writeLock().lock();
-                            mService = null;
-                            mContext.unbindService(mConnection);
+                            if (mService != null) {
+                                mService = null;
+                                mContext.unbindService(mConnection);
+                            }
                         } catch (Exception re) {
                             Log.e(TAG, "", re);
                         } finally {
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index ab8c196..b8a741a 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -19,6 +19,7 @@
 
 import android.Manifest;
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
@@ -3057,7 +3058,7 @@
      * permissions, or unable to start this CoC
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public BluetoothServerSocket listenUsingL2capChannel()
+    public @NonNull BluetoothServerSocket listenUsingL2capChannel()
             throws IOException {
         BluetoothServerSocket socket =
                             new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP_LE, true, true,
@@ -3115,7 +3116,7 @@
      * permissions, or unable to start this CoC
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public BluetoothServerSocket listenUsingInsecureL2capChannel()
+    public @NonNull BluetoothServerSocket listenUsingInsecureL2capChannel()
             throws IOException {
         BluetoothServerSocket socket =
                             new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP_LE, false, false,
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index f718415..fa2c9f8 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -17,6 +17,7 @@
 package android.bluetooth;
 
 import android.Manifest;
+import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
@@ -2182,7 +2183,7 @@
      * permissions
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public BluetoothSocket createL2capChannel(int psm) throws IOException {
+    public @NonNull BluetoothSocket createL2capChannel(int psm) throws IOException {
         if (!isBluetoothEnabled()) {
             Log.e(TAG, "createL2capChannel: Bluetooth is not enabled");
             throw new IOException();
@@ -2221,7 +2222,7 @@
      * permissions
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public BluetoothSocket createInsecureL2capChannel(int psm) throws IOException {
+    public @NonNull BluetoothSocket createInsecureL2capChannel(int psm) throws IOException {
         if (!isBluetoothEnabled()) {
             Log.e(TAG, "createInsecureL2capChannel: Bluetooth is not enabled");
             throw new IOException();
diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java
index b4eaab2..d6edb90 100644
--- a/core/java/android/bluetooth/BluetoothHearingAid.java
+++ b/core/java/android/bluetooth/BluetoothHearingAid.java
@@ -22,7 +22,6 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -92,7 +91,6 @@
      * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    @UnsupportedAppUsage
     public static final String ACTION_ACTIVE_DEVICE_CHANGED =
             "android.bluetooth.hearingaid.profile.action.ACTIVE_DEVICE_CHANGED";
 
@@ -324,7 +322,8 @@
     /**
      * {@inheritDoc}
      */
-    @Override public @NonNull List<BluetoothDevice> getDevicesMatchingConnectionStates(
+    @Override
+    public @NonNull List<BluetoothDevice> getDevicesMatchingConnectionStates(
     @NonNull int[] states) {
         if (VDBG) log("getDevicesMatchingStates()");
         try {
@@ -346,7 +345,8 @@
      * {@inheritDoc}
      */
     @Override
-    public int getConnectionState(@NonNull BluetoothDevice device) {
+    public @BluetoothProfile.BtProfileState int getConnectionState(
+    @NonNull BluetoothDevice device) {
         if (VDBG) log("getState(" + device + ")");
         try {
             mServiceLock.readLock().lock();
@@ -386,7 +386,6 @@
      * @return false on immediate error, true otherwise
      * @hide
      */
-    @UnsupportedAppUsage
     public boolean setActiveDevice(@Nullable BluetoothDevice device) {
         if (DBG) log("setActiveDevice(" + device + ")");
         try {
@@ -418,7 +417,6 @@
      * @hide
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
-    @UnsupportedAppUsage
     public List<BluetoothDevice> getActiveDevices() {
         if (VDBG) log("getActiveDevices()");
         try {
diff --git a/core/java/android/bluetooth/BluetoothHidHost.java b/core/java/android/bluetooth/BluetoothHidHost.java
index 58a2522..7c925a1 100644
--- a/core/java/android/bluetooth/BluetoothHidHost.java
+++ b/core/java/android/bluetooth/BluetoothHidHost.java
@@ -233,8 +233,10 @@
                         if (VDBG) Log.d(TAG, "Unbinding service...");
                         synchronized (mConnection) {
                             try {
-                                mService = null;
-                                mContext.unbindService(mConnection);
+                                if (mService != null) {
+                                    mService = null;
+                                    mContext.unbindService(mConnection);
+                                }
                             } catch (Exception re) {
                                 Log.e(TAG, "", re);
                             }
diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java
index a601df0..359bec6 100644
--- a/core/java/android/bluetooth/BluetoothPbap.java
+++ b/core/java/android/bluetooth/BluetoothPbap.java
@@ -121,8 +121,10 @@
                         log("Unbinding service...");
                         synchronized (mConnection) {
                             try {
-                                mService = null;
-                                mContext.unbindService(mConnection);
+                                if (mService != null) {
+                                    mService = null;
+                                    mContext.unbindService(mConnection);
+                                }
                             } catch (Exception re) {
                                 Log.e(TAG, "", re);
                             }
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index ef77596..dabe0fd 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -276,7 +276,7 @@
      * #STATE_CONNECTING}, {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING}
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public int getConnectionState(BluetoothDevice device);
+    @BtProfileState int getConnectionState(BluetoothDevice device);
 
     /**
      * An interface for notifying BluetoothProfile IPC clients when they have
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 0c76f3f..bb1501f 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -338,6 +338,25 @@
     public static final int BIND_ADJUST_BELOW_PERCEPTIBLE = 0x0100;
 
     /**
+     * Flag for {@link #bindService}: This flag is intended to be used only by the system to adjust
+     * the scheduling policy for IMEs (and any other out-of-process user-visible components that
+     * work closely with the top app) so that UI hosted in such services can have the same
+     * scheduling policy (e.g. SCHED_FIFO when it is enabled and TOP_APP_PRIORITY_BOOST otherwise)
+     * as the actual top-app.
+     * @hide
+     */
+    public static final int BIND_SCHEDULE_LIKE_TOP_APP = 0x00080000;
+
+    /**
+     * Flag for {@link #bindService}: allow background activity starts from the bound service's
+     * process.
+     * This flag is only respected if the caller is holding
+     * {@link android.Manifest.permission#START_ACTIVITIES_FROM_BACKGROUND}.
+     * @hide
+     */
+    public static final int BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS = 0x00100000;
+
+    /**
      * @hide Flag for {@link #bindService}: the service being bound to represents a
      * protected system component, so must have association restrictions applied to it.
      * That is, a system config must have one or more allow-association tags limiting
@@ -3127,6 +3146,7 @@
             CONNECTIVITY_SERVICE,
             //@hide: IP_MEMORY_STORE_SERVICE,
             IPSEC_SERVICE,
+            TEST_NETWORK_SERVICE,
             //@hide: UPDATE_LOCK_SERVICE,
             //@hide: NETWORKMANAGEMENT_SERVICE,
             NETWORK_STATS_SERVICE,
@@ -3289,11 +3309,16 @@
      * {@link #USB_SERVICE}, {@link #WALLPAPER_SERVICE}, {@link #WIFI_P2P_SERVICE},
      * {@link #WIFI_SERVICE}, {@link #WIFI_AWARE_SERVICE}. For these services this method will
      * return <code>null</code>.  Generally, if you are running as an instant app you should always
-     * check whether the result of this method is null.
+     * check whether the result of this method is {@code null}.
+     *
+     * <p>Note: When implementing this method, keep in mind that new services can be added on newer
+     * Android releases, so if you're looking for just the explicit names mentioned above, make sure
+     * to return {@code null} when you don't recognize the name &mdash; if you throw a
+     * {@link RuntimeException} exception instead, you're app might break on new Android releases.
      *
      * @param name The name of the desired service.
      *
-     * @return The service or null if the name does not exist.
+     * @return The service or {@code null} if the name does not exist.
      *
      * @see #WINDOW_SERVICE
      * @see android.view.WindowManager
@@ -3367,7 +3392,9 @@
      * {@link android.app.UiModeManager}, {@link android.app.DownloadManager},
      * {@link android.os.BatteryManager}, {@link android.app.job.JobScheduler},
      * {@link android.app.usage.NetworkStatsManager}.
-     * </p><p>
+     * </p>
+     *
+     * <p>
      * Note: System services obtained via this API may be closely associated with
      * the Context in which they are obtained from.  In general, do not share the
      * service objects between various different contexts (Activities, Applications,
@@ -3379,11 +3406,13 @@
      * {@link #FINGERPRINT_SERVICE}, {@link #KEYGUARD_SERVICE}, {@link #SHORTCUT_SERVICE},
      * {@link #USB_SERVICE}, {@link #WALLPAPER_SERVICE}, {@link #WIFI_P2P_SERVICE},
      * {@link #WIFI_SERVICE}, {@link #WIFI_AWARE_SERVICE}. For these services this method will
-     * return <code>null</code>.  Generally, if you are running as an instant app you should always
-     * check whether the result of this method is null.
+     * return {@code null}. Generally, if you are running as an instant app you should always
+     * check whether the result of this method is {@code null}.
+     * </p>
      *
      * @param serviceClass The class of the desired service.
-     * @return The service or null if the class is not a supported system service.
+     * @return The service or {@code null} if the class is not a supported system service. Note:
+     * <b>never</b> throw a {@link RuntimeException} if the name is not supported.
      */
     @SuppressWarnings("unchecked")
     public final @Nullable <T> T getSystemService(@NonNull Class<T> serviceClass) {
@@ -3691,6 +3720,15 @@
 
     /**
      * Use with {@link #getSystemService(String)} to retrieve a {@link
+     * android.net.TestNetworkManager} for building TUNs and limited-use Networks
+     *
+     * @see #getSystemService(String)
+     * @hide
+     */
+    @TestApi public static final String TEST_NETWORK_SERVICE = "test_network";
+
+    /**
+     * Use with {@link #getSystemService(String)} to retrieve a {@link
      * android.os.IUpdateLock} for managing runtime sequences that
      * must not be interrupted by headless OTA application or similar.
      *
@@ -3978,6 +4016,16 @@
 
     /**
      * Use with {@link #getSystemService(String)} to retrieve a
+     * {@link com.android.server.attention.AttentionManagerService} for attention services.
+     *
+     * @see #getSystemService(String)
+     * @see android.server.attention.AttentionManagerService
+     * @hide
+     */
+    public static final String ATTENTION_SERVICE = "attention";
+
+    /**
+     * Use with {@link #getSystemService(String)} to retrieve a
      * {@link android.view.inputmethod.InputMethodManager} for accessing input
      * methods.
      *
diff --git a/core/java/android/content/LoggingContentInterface.java b/core/java/android/content/LoggingContentInterface.java
index 26d01b9..6e12a57 100644
--- a/core/java/android/content/LoggingContentInterface.java
+++ b/core/java/android/content/LoggingContentInterface.java
@@ -66,7 +66,12 @@
         } else {
             sb.append(" = ").append(deepToString(res));
         }
-        Log.v(tag, sb.toString());
+
+        if (res instanceof Exception) {
+            Log.e(tag, sb.toString());
+        } else {
+            Log.v(tag, sb.toString());
+        }
     }
 
     private String deepToString(Object value) {
@@ -81,119 +86,194 @@
     public @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection,
             @Nullable Bundle queryArgs, @Nullable CancellationSignal cancellationSignal)
             throws RemoteException {
-        final Cursor res = delegate.query(uri, projection, queryArgs, cancellationSignal);
-        log("query", res, uri, projection, queryArgs, cancellationSignal);
-        return res;
+        try {
+            final Cursor res = delegate.query(uri, projection, queryArgs, cancellationSignal);
+            log("query", res, uri, projection, queryArgs, cancellationSignal);
+            return res;
+        } catch (Exception res) {
+            log("query", res, uri, projection, queryArgs, cancellationSignal);
+            throw res;
+        }
     }
 
     @Override
     public @Nullable String getType(@NonNull Uri uri) throws RemoteException {
-        final String res = delegate.getType(uri);
-        log("getType", res, uri);
-        return res;
+        try {
+            final String res = delegate.getType(uri);
+            log("getType", res, uri);
+            return res;
+        } catch (Exception res) {
+            log("getType", res, uri);
+            throw res;
+        }
     }
 
     @Override
     public @Nullable String[] getStreamTypes(@NonNull Uri uri, @NonNull String mimeTypeFilter)
             throws RemoteException {
-        final String[] res = delegate.getStreamTypes(uri, mimeTypeFilter);
-        log("getStreamTypes", res, uri, mimeTypeFilter);
-        return res;
+        try {
+            final String[] res = delegate.getStreamTypes(uri, mimeTypeFilter);
+            log("getStreamTypes", res, uri, mimeTypeFilter);
+            return res;
+        } catch (Exception res) {
+            log("getStreamTypes", res, uri, mimeTypeFilter);
+            throw res;
+        }
     }
 
     @Override
     public @Nullable Uri canonicalize(@NonNull Uri uri) throws RemoteException {
-        final Uri res = delegate.canonicalize(uri);
-        log("canonicalize", res, uri);
-        return res;
+        try {
+            final Uri res = delegate.canonicalize(uri);
+            log("canonicalize", res, uri);
+            return res;
+        } catch (Exception res) {
+            log("canonicalize", res, uri);
+            throw res;
+        }
     }
 
     @Override
     public @Nullable Uri uncanonicalize(@NonNull Uri uri) throws RemoteException {
-        final Uri res = delegate.uncanonicalize(uri);
-        log("uncanonicalize", res, uri);
-        return res;
+        try {
+            final Uri res = delegate.uncanonicalize(uri);
+            log("uncanonicalize", res, uri);
+            return res;
+        } catch (Exception res) {
+            log("uncanonicalize", res, uri);
+            throw res;
+        }
     }
 
     @Override
     public boolean refresh(@NonNull Uri uri, @Nullable Bundle args,
             @Nullable CancellationSignal cancellationSignal) throws RemoteException {
-        final boolean res = delegate.refresh(uri, args, cancellationSignal);
-        log("refresh", res, uri, args, cancellationSignal);
-        return res;
+        try {
+            final boolean res = delegate.refresh(uri, args, cancellationSignal);
+            log("refresh", res, uri, args, cancellationSignal);
+            return res;
+        } catch (Exception res) {
+            log("refresh", res, uri, args, cancellationSignal);
+            throw res;
+        }
     }
 
     @Override
     public @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues initialValues)
             throws RemoteException {
-        final Uri res = delegate.insert(uri, initialValues);
-        log("insert", res, uri, initialValues);
-        return res;
+        try {
+            final Uri res = delegate.insert(uri, initialValues);
+            log("insert", res, uri, initialValues);
+            return res;
+        } catch (Exception res) {
+            log("insert", res, uri, initialValues);
+            throw res;
+        }
     }
 
     @Override
     public int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] initialValues)
             throws RemoteException {
-        final int res = delegate.bulkInsert(uri, initialValues);
-        log("bulkInsert", res, uri, initialValues);
-        return res;
+        try {
+            final int res = delegate.bulkInsert(uri, initialValues);
+            log("bulkInsert", res, uri, initialValues);
+            return res;
+        } catch (Exception res) {
+            log("bulkInsert", res, uri, initialValues);
+            throw res;
+        }
     }
 
     @Override
     public int delete(@NonNull Uri uri, @Nullable String selection,
             @Nullable String[] selectionArgs) throws RemoteException {
-        final int res = delegate.delete(uri, selection, selectionArgs);
-        log("delete", res, uri, selection, selectionArgs);
-        return res;
+        try {
+            final int res = delegate.delete(uri, selection, selectionArgs);
+            log("delete", res, uri, selection, selectionArgs);
+            return res;
+        } catch (Exception res) {
+            log("delete", res, uri, selection, selectionArgs);
+            throw res;
+        }
     }
 
     @Override
     public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection,
             @Nullable String[] selectionArgs) throws RemoteException {
-        final int res = delegate.update(uri, values, selection, selectionArgs);
-        log("update", res, uri, values, selection, selectionArgs);
-        return res;
+        try {
+            final int res = delegate.update(uri, values, selection, selectionArgs);
+            log("update", res, uri, values, selection, selectionArgs);
+            return res;
+        } catch (Exception res) {
+            log("update", res, uri, values, selection, selectionArgs);
+            throw res;
+        }
     }
 
     @Override
     public @Nullable ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode,
             @Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException {
-        final ParcelFileDescriptor res = delegate.openFile(uri, mode, signal);
-        log("openFile", res, uri, mode, signal);
-        return res;
+        try {
+            final ParcelFileDescriptor res = delegate.openFile(uri, mode, signal);
+            log("openFile", res, uri, mode, signal);
+            return res;
+        } catch (Exception res) {
+            log("openFile", res, uri, mode, signal);
+            throw res;
+        }
     }
 
     @Override
     public @Nullable AssetFileDescriptor openAssetFile(@NonNull Uri uri, @NonNull String mode,
             @Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException {
-        final AssetFileDescriptor res = delegate.openAssetFile(uri, mode, signal);
-        log("openAssetFile", res, uri, mode, signal);
-        return res;
+        try {
+            final AssetFileDescriptor res = delegate.openAssetFile(uri, mode, signal);
+            log("openAssetFile", res, uri, mode, signal);
+            return res;
+        } catch (Exception res) {
+            log("openAssetFile", res, uri, mode, signal);
+            throw res;
+        }
     }
 
     @Override
     public @Nullable AssetFileDescriptor openTypedAssetFile(@NonNull Uri uri,
             @NonNull String mimeTypeFilter, @Nullable Bundle opts,
             @Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException {
-        final AssetFileDescriptor res = delegate.openTypedAssetFile(uri, mimeTypeFilter, opts, signal);
-        log("openTypedAssetFile", res, uri, mimeTypeFilter, opts, signal);
-        return res;
+        try {
+            final AssetFileDescriptor res = delegate.openTypedAssetFile(uri, mimeTypeFilter, opts, signal);
+            log("openTypedAssetFile", res, uri, mimeTypeFilter, opts, signal);
+            return res;
+        } catch (Exception res) {
+            log("openTypedAssetFile", res, uri, mimeTypeFilter, opts, signal);
+            throw res;
+        }
     }
 
     @Override
     public @NonNull ContentProviderResult[] applyBatch(@NonNull String authority,
             @NonNull ArrayList<ContentProviderOperation> operations)
             throws RemoteException, OperationApplicationException {
-        final ContentProviderResult[] res = delegate.applyBatch(authority, operations);
-        log("applyBatch", res, authority, operations);
-        return res;
+        try {
+            final ContentProviderResult[] res = delegate.applyBatch(authority, operations);
+            log("applyBatch", res, authority, operations);
+            return res;
+        } catch (Exception res) {
+            log("applyBatch", res, authority, operations);
+            throw res;
+        }
     }
 
     @Override
     public @Nullable Bundle call(@NonNull String authority, @NonNull String method,
             @Nullable String arg, @Nullable Bundle extras) throws RemoteException {
-        final Bundle res = delegate.call(authority, method, arg, extras);
-        log("call", res, authority, method, arg, extras);
-        return res;
+        try {
+            final Bundle res = delegate.call(authority, method, arg, extras);
+            log("call", res, authority, method, arg, extras);
+            return res;
+        } catch (Exception res) {
+            log("call", res, authority, method, arg, extras);
+            throw res;
+        }
     }
 }
diff --git a/core/java/android/content/pm/AndroidHidlUpdater.java b/core/java/android/content/pm/AndroidHidlUpdater.java
index b7ae8f4..d0657e5 100644
--- a/core/java/android/content/pm/AndroidHidlUpdater.java
+++ b/core/java/android/content/pm/AndroidHidlUpdater.java
@@ -34,8 +34,14 @@
 
     @Override
     public void updatePackage(Package pkg) {
+        ApplicationInfo info = pkg.applicationInfo;
+
         // This was the default <= P and is maintained for backwards compatibility.
-        if (pkg.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.P) {
+        boolean isLegacy = info.targetSdkVersion <= Build.VERSION_CODES.P;
+        // Only system apps use these libraries
+        boolean isSystem = info.isSystemApp() || info.isUpdatedSystemApp();
+
+        if (isLegacy && isSystem) {
             prefixRequiredLibrary(pkg, ANDROID_HIDL_BASE);
             prefixRequiredLibrary(pkg, ANDROID_HIDL_MANAGER);
         } else {
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 2a19763..954deac 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -142,17 +142,6 @@
     public static final String EXTRA_PIN_ITEM_REQUEST =
             "android.content.pm.extra.PIN_ITEM_REQUEST";
 
-    /**
-     * Metadata key that specifies vouched certs, so any apps signed by a cert in vouched certs
-     * will not show hidden icon in launcher even it does not have a launcher visible activity.
-     *
-     * If an app has this metadata in manifest, it won't be eligible to hide its icon even if its
-     * cert is in vouched certs list.
-     *
-     * @hide
-     */
-    public static final String VOUCHED_CERTS_KEY = "vouched_certs";
-
     private final Context mContext;
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private final ILauncherApps mService;
diff --git a/core/java/android/content/pm/PackageList.java b/core/java/android/content/pm/PackageList.java
index cfd99ab..f781758 100644
--- a/core/java/android/content/pm/PackageList.java
+++ b/core/java/android/content/pm/PackageList.java
@@ -45,16 +45,16 @@
     }
 
     @Override
-    public void onPackageAdded(String packageName) {
+    public void onPackageAdded(String packageName, int uid) {
         if (mWrappedObserver != null) {
-            mWrappedObserver.onPackageAdded(packageName);
+            mWrappedObserver.onPackageAdded(packageName, uid);
         }
     }
 
     @Override
-    public void onPackageRemoved(String packageName) {
+    public void onPackageRemoved(String packageName, int uid) {
         if (mWrappedObserver != null) {
-            mWrappedObserver.onPackageRemoved(packageName);
+            mWrappedObserver.onPackageRemoved(packageName, uid);
         }
     }
 
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index d1ebcfd..99324ba 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1389,6 +1389,14 @@
      */
     public static final int INSTALL_FAILED_BAD_SIGNATURE = -118;
 
+    /**
+     * Installation failed return code: a new staged session was attempted to be committed while
+     * there is already one in-progress.
+     *
+     * @hide
+     */
+    public static final int INSTALL_FAILED_OTHER_STAGED_SESSION_IN_PROGRESS = -119;
+
     /** @hide */
     @IntDef(flag = true, prefix = { "DELETE_" }, value = {
             DELETE_KEEP_DATA,
@@ -5866,34 +5874,37 @@
             @NonNull ComponentName componentName);
 
     /**
-     * Set the enabled setting for a package app settings activity.
+     * Set whether a synthetic app details activity will be generated if the app has no enabled
+     * launcher activity. Disabling this allows the app to have no launcher icon.
      *
      * @param packageName The package name of the app
-     * @param enabled The new enabled state for app details activity
+     * @param enabled The new enabled state for the synthetic app details activity.
      *
      * @hide
      */
     @RequiresPermission(value = android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE,
             conditional = true)
     @SystemApi
-    public void setAppDetailsActivityEnabled(@NonNull String packageName, boolean enabled) {
+    public void setSyntheticAppDetailsActivityEnabled(@NonNull String packageName,
+            boolean enabled) {
         throw new UnsupportedOperationException(
-                "setAppDetailsActivityEnabled not implemented");
+                "setSyntheticAppDetailsActivityEnabled not implemented");
     }
 
 
     /**
-     * Return the enabled setting for a package app settings activity.
+     * Return whether a synthetic app details activity will be generated if the app has no enabled
+     * launcher activity.
      *
      * @param packageName The package name of the app
-     * @return Returns the current enabled state for app settings activity.
+     * @return Returns the enabled state for the synthetic app details activity.
      *
      * @hide
      */
     @SystemApi
-    public boolean getAppDetailsActivityEnabled(@NonNull String packageName) {
+    public boolean getSyntheticAppDetailsActivityEnabled(@NonNull String packageName) {
         throw new UnsupportedOperationException(
-                "getAppDetailsActivityEnabled not implemented");
+                "getSyntheticAppDetailsActivityEnabled not implemented");
     }
 
     /**
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 2c1842c..b3cc627 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -22,6 +22,7 @@
 import android.annotation.UserIdInt;
 import android.content.ComponentName;
 import android.content.Intent;
+import android.content.IntentSender;
 import android.content.pm.PackageManager.ApplicationInfoFlags;
 import android.content.pm.PackageManager.ComponentInfoFlags;
 import android.content.pm.PackageManager.PackageInfoFlags;
@@ -78,9 +79,9 @@
     /** Observer called whenever the list of packages changes */
     public interface PackageListObserver {
         /** A package was added to the system. */
-        void onPackageAdded(@NonNull String packageName);
+        void onPackageAdded(@NonNull String packageName, int uid);
         /** A package was removed from the system. */
-        void onPackageRemoved(@NonNull String packageName);
+        void onPackageRemoved(@NonNull String packageName, int uid);
     }
 
     /** Interface to override permission checks via composition */
@@ -925,4 +926,21 @@
      * @param provider the provider
      */
     public abstract void setDefaultHomeProvider(@NonNull DefaultHomeProvider provider);
+
+    /**
+     * Returns {@code true} if given {@code packageName} is an apex package.
+     */
+    public abstract boolean isApexPackage(String packageName);
+
+    /**
+     * Uninstalls given {@code packageName}.
+     *
+     * @param packageName apex package to uninstall.
+     * @param versionCode version of a package to uninstall.
+     * @param userId user to uninstall apex package for. Must be
+     *               {@link android.os.UserHandle#USER_ALL}, otherwise failure will be reported.
+     * @param intentSender a {@link IntentSender} to send result of an uninstall to.
+     */
+    public abstract void uninstallApex(String packageName, long versionCode, int userId,
+            IntentSender intentSender);
 }
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 89c0690..9d0ece0 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1618,7 +1618,7 @@
             }
 
             final AttributeSet attrs = parser;
-            return parseApkLite(apkPath, parser, attrs, signingDetails, flags);
+            return parseApkLite(apkPath, parser, attrs, signingDetails);
 
         } catch (XmlPullParserException | IOException | RuntimeException e) {
             Slog.w(TAG, "Failed to parse " + apkPath, e);
@@ -1705,7 +1705,7 @@
     }
 
     private static ApkLite parseApkLite(String codePath, XmlPullParser parser, AttributeSet attrs,
-            SigningDetails signingDetails, int flags)
+            SigningDetails signingDetails)
             throws IOException, XmlPullParserException, PackageParserException {
         final Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs);
 
@@ -1713,12 +1713,11 @@
         int versionCode = 0;
         int versionCodeMajor = 0;
         int revisionCode = 0;
-        int targetSdkVersion = 0;
         boolean coreApp = false;
         boolean debuggable = false;
         boolean multiArch = false;
         boolean use32bitAbi = false;
-        Boolean extractNativeLibsProvided = null;
+        boolean extractNativeLibs = true;
         boolean isolatedSplits = false;
         boolean isFeatureSplit = false;
         boolean isSplitRequired = false;
@@ -1783,8 +1782,7 @@
                         use32bitAbi = attrs.getAttributeBooleanValue(i, false);
                     }
                     if ("extractNativeLibs".equals(attr)) {
-                        extractNativeLibsProvided = Boolean.valueOf(
-                                attrs.getAttributeBooleanValue(i, true));
+                        extractNativeLibs = attrs.getAttributeBooleanValue(i, true);
                     }
                     if ("useEmbeddedDex".equals(attr)) {
                         useEmbeddedDex = attrs.getAttributeBooleanValue(i, false);
@@ -1802,52 +1800,9 @@
                             PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
                             "<uses-split> tag requires 'android:name' attribute");
                 }
-            } else if (TAG_USES_SDK.equals(parser.getName())) {
-                final String[] errorMsg = new String[1];
-                Pair<Integer, Integer> versions = deriveSdkVersions(new AbstractVersionsAccessor() {
-                    @Override public String getMinSdkVersionCode() {
-                        return getAttributeAsString("minSdkVersion");
-                    }
-
-                    @Override public int getMinSdkVersion() {
-                        return getAttributeAsInt("minSdkVersion");
-                    }
-
-                    @Override public String getTargetSdkVersionCode() {
-                        return getAttributeAsString("targetSdkVersion");
-                    }
-
-                    @Override public int getTargetSdkVersion() {
-                        return getAttributeAsInt("targetSdkVersion");
-                    }
-
-                    private String getAttributeAsString(String name) {
-                        return attrs.getAttributeValue(ANDROID_RESOURCES, name);
-                    }
-
-                    private int getAttributeAsInt(String name) {
-                        try {
-                            return attrs.getAttributeIntValue(ANDROID_RESOURCES, name, -1);
-                        } catch (NumberFormatException e) {
-                            return -1;
-                        }
-                    }
-                }, flags, errorMsg);
-
-                if (versions == null) {
-                    throw new PackageParserException(
-                            PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, errorMsg[0]);
-                }
-
-                targetSdkVersion = versions.second;
             }
         }
 
-        // TODO: flip the default based on targetSdkVersion when possible.  See b/128335904.
-        final boolean extractNativeLibsDefault = true;
-        final boolean extractNativeLibs = (extractNativeLibsProvided != null)
-                ? extractNativeLibsProvided : extractNativeLibsDefault;
-
         return new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit,
                 configForSplit, usesSplitName, isSplitRequired, versionCode, versionCodeMajor,
                 revisionCode, installLocation, verifiers, signingDetails, coreApp, debuggable,
@@ -2253,60 +2208,64 @@
 
             } else if (tagName.equals(TAG_USES_SDK)) {
                 if (SDK_VERSION > 0) {
-                    sa = res.obtainAttributes(parser, R.styleable.AndroidManifestUsesSdk);
-                    final TypedArray saFinal = sa;
-                    Pair<Integer, Integer> versions = deriveSdkVersions(
-                            new AbstractVersionsAccessor() {
-                                @Override public String getMinSdkVersionCode() {
-                                    return getAttributeAsString(
-                                            R.styleable.AndroidManifestUsesSdk_minSdkVersion);
-                                }
+                    sa = res.obtainAttributes(parser,
+                            com.android.internal.R.styleable.AndroidManifestUsesSdk);
 
-                                @Override public int getMinSdkVersion() {
-                                    return getAttributeAsInt(
-                                            R.styleable.AndroidManifestUsesSdk_minSdkVersion);
-                                }
+                    int minVers = 1;
+                    String minCode = null;
+                    int targetVers = 0;
+                    String targetCode = null;
 
-                                @Override public String getTargetSdkVersionCode() {
-                                    return getAttributeAsString(
-                                            R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
-                                }
+                    TypedValue val = sa.peekValue(
+                            com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion);
+                    if (val != null) {
+                        if (val.type == TypedValue.TYPE_STRING && val.string != null) {
+                            minCode = val.string.toString();
+                        } else {
+                            // If it's not a string, it's an integer.
+                            minVers = val.data;
+                        }
+                    }
 
-                                @Override public int getTargetSdkVersion() {
-                                    return getAttributeAsInt(
-                                            R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
-                                }
+                    val = sa.peekValue(
+                            com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
+                    if (val != null) {
+                        if (val.type == TypedValue.TYPE_STRING && val.string != null) {
+                            targetCode = val.string.toString();
+                            if (minCode == null) {
+                                minCode = targetCode;
+                            }
+                        } else {
+                            // If it's not a string, it's an integer.
+                            targetVers = val.data;
+                        }
+                    } else {
+                        targetVers = minVers;
+                        targetCode = minCode;
+                    }
 
-                                private String getAttributeAsString(int index) {
-                                    TypedValue val = saFinal.peekValue(index);
-                                    if (val != null && val.type == TypedValue.TYPE_STRING
-                                            && val.string != null) {
-                                        return val.string.toString();
-                                    }
-                                    return null;
-                                }
+                    sa.recycle();
 
-                                private int getAttributeAsInt(int index) {
-                                    TypedValue val = saFinal.peekValue(index);
-                                    if (val != null && val.type != TypedValue.TYPE_STRING) {
-                                        // If it's not a string, it's an integer.
-                                        return val.data;
-                                    }
-                                    return -1;
-                                }
-                            }, flags, outError);
-
-                    if (versions == null) {
+                    final int minSdkVersion = PackageParser.computeMinSdkVersion(minVers, minCode,
+                            SDK_VERSION, SDK_CODENAMES, outError);
+                    if (minSdkVersion < 0) {
                         mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
                         return null;
                     }
 
-                    pkg.applicationInfo.minSdkVersion = versions.first;
-                    pkg.applicationInfo.targetSdkVersion = versions.second;
+                    final int targetSdkVersion = PackageParser.computeTargetSdkVersion(targetVers,
+                            targetCode, SDK_CODENAMES, outError);
+                    if (targetSdkVersion < 0) {
+                        mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
+                        return null;
+                    }
 
-                    sa.recycle();
+                    pkg.applicationInfo.minSdkVersion = minSdkVersion;
+                    pkg.applicationInfo.targetSdkVersion = targetSdkVersion;
                 }
+
                 XmlUtils.skipCurrentTag(parser);
+
             } else if (tagName.equals(TAG_SUPPORT_SCREENS)) {
                 sa = res.obtainAttributes(parser,
                         com.android.internal.R.styleable.AndroidManifestSupportsScreens);
@@ -2717,66 +2676,6 @@
         return -1;
     }
 
-    private interface AbstractVersionsAccessor {
-        /** Returns minimum SDK version code string, or null if absent. */
-        String getMinSdkVersionCode();
-
-        /** Returns minimum SDK version code, or -1 if absent. */
-        int getMinSdkVersion();
-
-        /** Returns target SDK version code string, or null if absent. */
-        String getTargetSdkVersionCode();
-
-        /** Returns target SDK version code, or -1 if absent. */
-        int getTargetSdkVersion();
-    }
-
-    private static @Nullable Pair<Integer, Integer> deriveSdkVersions(
-            @NonNull AbstractVersionsAccessor accessor, int flags, String[] outError) {
-        int minVers = 1;
-        String minCode = null;
-        int targetVers = 0;
-        String targetCode = null;
-
-        String code = accessor.getMinSdkVersionCode();
-        int version = accessor.getMinSdkVersion();
-        // Check integer first since code is almost never a null string (e.g. "28").
-        if (version >= 0) {
-            minVers = version;
-        } else if (code != null) {
-            minCode = code;
-        }
-
-        code = accessor.getTargetSdkVersionCode();
-        version = accessor.getTargetSdkVersion();
-        // Check integer first since code is almost never a null string (e.g. "28").
-        if (version >= 0) {
-            targetVers = version;
-        } else if (code != null) {
-            targetCode = code;
-            if (minCode == null) {
-                minCode = targetCode;
-            }
-        } else {
-            targetVers = minVers;
-            targetCode = minCode;
-        }
-
-        final int minSdkVersion = computeMinSdkVersion(minVers, minCode,
-                SDK_VERSION, SDK_CODENAMES, outError);
-        if (minSdkVersion < 0) {
-            return null;
-        }
-
-        final int targetSdkVersion = computeTargetSdkVersion(targetVers,
-                targetCode, SDK_CODENAMES, outError);
-        if (targetSdkVersion < 0) {
-            return null;
-        }
-
-        return Pair.create(minSdkVersion, targetSdkVersion);
-    }
-
     /**
      * Computes the minSdkVersion to use at runtime. If the package is not
      * compatible with this platform, populates {@code outError[0]} with an
@@ -3719,7 +3618,6 @@
             ai.flags |= ApplicationInfo.FLAG_MULTIARCH;
         }
 
-        // TODO: flip the default based on targetSdkVersion when possible.  See b/128335904.
         if (sa.getBoolean(
                 com.android.internal.R.styleable.AndroidManifestApplication_extractNativeLibs,
                 true)) {
@@ -4095,8 +3993,6 @@
         setMaxAspectRatio(owner);
         setMinAspectRatio(owner);
 
-        PackageBackwardCompatibility.modifySharedLibraries(owner);
-
         if (hasDomainURLs(owner)) {
             owner.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
         } else {
diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java
index 2287243..df67117 100644
--- a/core/java/android/content/pm/ShortcutManager.java
+++ b/core/java/android/content/pm/ShortcutManager.java
@@ -600,15 +600,17 @@
             mTargetComponent = targetComponent;
         }
 
-        private ShareShortcutInfo(Parcel in) {
+        private ShareShortcutInfo(@NonNull Parcel in) {
             mShortcutInfo = in.readParcelable(ShortcutInfo.class.getClassLoader());
             mTargetComponent = in.readParcelable(ComponentName.class.getClassLoader());
         }
 
+        @NonNull
         public ShortcutInfo getShortcutInfo() {
             return mShortcutInfo;
         }
 
+        @NonNull
         public ComponentName getTargetComponent() {
             return mTargetComponent;
         }
@@ -619,12 +621,12 @@
         }
 
         @Override
-        public void writeToParcel(Parcel dest, int flags) {
+        public void writeToParcel(@NonNull Parcel dest, int flags) {
             dest.writeParcelable(mShortcutInfo, flags);
             dest.writeParcelable(mTargetComponent, flags);
         }
 
-        public static final @android.annotation.NonNull Parcelable.Creator<ShareShortcutInfo> CREATOR =
+        public static final @NonNull Parcelable.Creator<ShareShortcutInfo> CREATOR =
                 new Parcelable.Creator<ShareShortcutInfo>() {
                     public ShareShortcutInfo createFromParcel(Parcel in) {
                         return new ShareShortcutInfo(in);
diff --git a/core/java/android/content/pm/TEST_MAPPING b/core/java/android/content/pm/TEST_MAPPING
index a2e98cc..df4ae09 100644
--- a/core/java/android/content/pm/TEST_MAPPING
+++ b/core/java/android/content/pm/TEST_MAPPING
@@ -1,6 +1,12 @@
 {
   "imports": [
     {
+      "path": "cts/tests/tests/packageinstaller"
+    },
+    {
+      "path": "cts/hostsidetests/stagedinstall"
+    },
+    {
       "path": "system/apex/tests"
     }
   ]
diff --git a/core/java/android/hardware/OWNERS b/core/java/android/hardware/OWNERS
index 29a339a..47dbf2d 100644
--- a/core/java/android/hardware/OWNERS
+++ b/core/java/android/hardware/OWNERS
@@ -1,2 +1,2 @@
 # Camera
-per-file *Camera* = cychen@google.com,epeev@google.com,etalvala@google.com,shuzhenwang@google.com,yinchiayeh@google.com,zhijunhe@google.com
+per-file *Camera*=cychen@google.com,epeev@google.com,etalvala@google.com,shuzhenwang@google.com,yinchiayeh@google.com,zhijunhe@google.com,jchowdhary@google.com
diff --git a/core/java/android/hardware/biometrics/BiometricFaceConstants.java b/core/java/android/hardware/biometrics/BiometricFaceConstants.java
index 3602a33..bae0fd3 100644
--- a/core/java/android/hardware/biometrics/BiometricFaceConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricFaceConstants.java
@@ -313,12 +313,17 @@
     public static final int FACE_ACQUIRED_START = 20;
 
     /**
+     * The sensor is dirty. The user should be informed to clean the sensor.
+     */
+    public static final int FACE_ACQUIRED_SENSOR_DIRTY = 21;
+
+    /**
      * Hardware vendors may extend this list if there are conditions that do not fall under one of
      * the above categories. Vendors are responsible for providing error strings for these errors.
      *
      * @hide
      */
-    public static final int FACE_ACQUIRED_VENDOR = 21;
+    public static final int FACE_ACQUIRED_VENDOR = 22;
 
     /**
      * @hide
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index e751b2c..08035972 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -523,6 +523,11 @@
      * cancelled notification through {@link AuthenticationCallback#onAuthenticationError(int,
      * CharSequence)}.
      *
+     * Note: Applications generally should not cancel and start authentication in quick succession.
+     * For example, to properly handle authentication across configuration changes, it's recommended
+     * to use BiometricPrompt in a fragment with setRetainInstance(true). By doing so, the
+     * application will not need to cancel/restart authentication during the configuration change.
+     *
      * @throws IllegalArgumentException If any of the arguments are null
      *
      * @param crypto Object associated with the call
@@ -568,6 +573,11 @@
      * authentication. The interrupted client will receive a cancelled notification through {@link
      * AuthenticationCallback#onAuthenticationError(int, CharSequence)}.
      *
+     * Note: Applications generally should not cancel and start authentication in quick succession.
+     * For example, to properly handle authentication across configuration changes, it's recommended
+     * to use BiometricPrompt in a fragment with setRetainInstance(true). By doing so, the
+     * application will not need to cancel/restart authentication during the configuration change.
+     *
      * @throws IllegalArgumentException If any of the arguments are null
      *
      * @param cancel An object that can be used to cancel authentication
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index f8b2a5b..c39796b 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -85,8 +85,7 @@
          *
          * @hide
          */
-        @UnsupportedAppUsage
-        public Key(@NonNull String name, @NonNull String fallbackName, @NonNull Class<T> type) {
+        public Key(String name, String fallbackName, Class<T> type) {
             mKey = new CameraMetadataNative.Key<T>(name,  fallbackName, type);
         }
 
@@ -337,6 +336,7 @@
      * <li>{@link RecommendedStreamConfigurationMap#USECASE_SNAPSHOT}</li>
      * <li>{@link RecommendedStreamConfigurationMap#USECASE_RAW}</li>
      * <li>{@link RecommendedStreamConfigurationMap#USECASE_ZSL}</li>
+     * <li>{@link RecommendedStreamConfigurationMap#USECASE_LOW_LATENCY_SNAPSHOT}</li>
      * </ul>
      * </p>
      *
@@ -401,7 +401,7 @@
     public @Nullable RecommendedStreamConfigurationMap getRecommendedStreamConfigurationMap(
             @RecommendedStreamConfigurationMap.RecommendedUsecase int usecase) {
         if (((usecase >= RecommendedStreamConfigurationMap.USECASE_PREVIEW) &&
-                (usecase <= RecommendedStreamConfigurationMap.USECASE_RAW)) ||
+                (usecase <= RecommendedStreamConfigurationMap.USECASE_LOW_LATENCY_SNAPSHOT)) ||
                 ((usecase >= RecommendedStreamConfigurationMap.USECASE_VENDOR_START) &&
                 (usecase < RecommendedStreamConfigurationMap.MAX_USECASE_COUNT))) {
             if (mRecommendedConfigurations == null) {
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 23401432..d5d25c5 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -680,7 +680,7 @@
         }
 
         /**
-         * Notify registered clients about a change in the camera access priorities.
+         * Called whenever camera access priorities change.
          *
          * <p>Notification that camera access priorities have changed and the camera may
          * now be openable. An application that was previously denied camera access due to
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 7382ac4..ba451e5 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -89,8 +89,7 @@
          *
          * @hide
          */
-        @UnsupportedAppUsage
-        public Key(@NonNull String name, @NonNull String fallbackName, @NonNull Class<T> type) {
+        public Key(String name, String fallbackName, Class<T> type) {
             mKey = new CameraMetadataNative.Key<T>(name, fallbackName, type);
         }
 
@@ -4252,7 +4251,6 @@
      * @see CaptureResult#SENSOR_TIMESTAMP
      * @hide
      */
-    @UnsupportedAppUsage
     public static final Key<long[]> STATISTICS_OIS_TIMESTAMPS =
             new Key<long[]>("android.statistics.oisTimestamps", long[].class);
 
@@ -4272,7 +4270,6 @@
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
      * @hide
      */
-    @UnsupportedAppUsage
     public static final Key<float[]> STATISTICS_OIS_X_SHIFTS =
             new Key<float[]>("android.statistics.oisXShifts", float[].class);
 
@@ -4292,7 +4289,6 @@
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
      * @hide
      */
-    @UnsupportedAppUsage
     public static final Key<float[]> STATISTICS_OIS_Y_SHIFTS =
             new Key<float[]>("android.statistics.oisYShifts", float[].class);
 
diff --git a/core/java/android/hardware/camera2/OWNERS b/core/java/android/hardware/camera2/OWNERS
index 18acfee..f48a95c 100644
--- a/core/java/android/hardware/camera2/OWNERS
+++ b/core/java/android/hardware/camera2/OWNERS
@@ -1,6 +1 @@
-cychen@google.com
-epeev@google.com
-etalvala@google.com
-shuzhenwang@google.com
-yinchiayeh@google.com
-zhijunhe@google.com
+include platform/frameworks/av:/camera/OWNERS
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index 1cdf235..e909c00 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -1113,8 +1113,10 @@
                         depthStreamDurationList.get(i), depthStreamStallList.get(i), depthScData);
             }
 
-            if ((scData.streamConfigurationArray == null) &&
-                    (depthScData.streamConfigurationArray == null)) {
+            if ((scData.streamConfigurationArray == null ||
+                    scData.streamConfigurationArray.length == 0) &&
+                    (depthScData.streamConfigurationArray == null ||
+                     depthScData.streamConfigurationArray.length == 0)) {
                 recommendedConfigurations.add(null);
                 continue;
             }
@@ -1125,6 +1127,7 @@
             switch (i) {
                 case RecommendedStreamConfigurationMap.USECASE_PREVIEW:
                 case RecommendedStreamConfigurationMap.USECASE_RAW:
+                case RecommendedStreamConfigurationMap.USECASE_LOW_LATENCY_SNAPSHOT:
                 case RecommendedStreamConfigurationMap.USECASE_VIDEO_SNAPSHOT:
                     map = new StreamConfigurationMap(scData.streamConfigurationArray,
                             scData.minDurationArray, scData.stallDurationArray,
diff --git a/core/java/android/hardware/camera2/params/RecommendedStreamConfigurationMap.java b/core/java/android/hardware/camera2/params/RecommendedStreamConfigurationMap.java
index 068c0ce..2d72598 100644
--- a/core/java/android/hardware/camera2/params/RecommendedStreamConfigurationMap.java
+++ b/core/java/android/hardware/camera2/params/RecommendedStreamConfigurationMap.java
@@ -21,6 +21,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.graphics.ImageFormat;
+import android.graphics.ImageFormat.Format;
 import android.graphics.PixelFormat;
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CameraDevice;
@@ -137,6 +138,17 @@
     public static final int USECASE_RAW = 0x5;
 
     /**
+     * The recommended stream configuration map for use case low latency snapshot must contain
+     * subset of configurations with end-to-end latency that does not exceed 200 ms. under standard
+     * operating conditions (reasonable light levels, not loaded system). The expected output format
+     * will be primarily {@link android.graphics.ImageFormat#JPEG} however other image formats can
+     * be present as well.  Even if available for the camera device, high speed and input
+     * configurations will be absent. This suggested configuration map may be absent on some devices
+     * that can not support any low latency requests.
+     */
+    public static final int USECASE_LOW_LATENCY_SNAPSHOT = 0x6;
+
+    /**
      * Device specific use cases.
      * @hide
      */
@@ -150,7 +162,8 @@
         USECASE_VIDEO_SNAPSHOT,
         USECASE_SNAPSHOT,
         USECASE_ZSL,
-        USECASE_RAW })
+        USECASE_RAW,
+        USECASE_LOW_LATENCY_SNAPSHOT})
      public @interface RecommendedUsecase {};
 
     /**
@@ -214,7 +227,7 @@
      *
      * @return a non-modifiable set of Integer formats
      */
-    public @Nullable Set<Integer> getValidOutputFormatsForInput(int inputFormat) {
+    public @Nullable Set<Integer> getValidOutputFormatsForInput(@Format int inputFormat) {
         return getUnmodifiableIntegerSet(mRecommendedMap.getValidOutputFormatsForInput(
                     inputFormat));
     }
@@ -250,7 +263,7 @@
      * @param format a format from {@link #getInputFormats}
      * @return a non-modifiable set of sizes, or {@code null} if the format was not available.
      */
-    public @Nullable Set<Size> getInputSizes(int format) {
+    public @Nullable Set<Size> getInputSizes(@Format int format) {
         return getUnmodifiableSizeSet(mRecommendedMap.getInputSizes(format));
     }
 
@@ -272,7 +285,7 @@
      *          if the image format was not a defined named constant
      *          from either {@link ImageFormat} or {@link PixelFormat}
      */
-    public boolean isOutputSupportedFor(int format) {
+    public boolean isOutputSupportedFor(@Format int format) {
         return mRecommendedMap.isOutputSupportedFor(format);
     }
 
@@ -288,7 +301,7 @@
      * @return  a non-modifiable set of supported sizes,
      *          or {@code null} if the {@code format} is not a supported output
      */
-    public @Nullable Set<Size> getOutputSizes(int format) {
+    public @Nullable Set<Size> getOutputSizes(@Format int format) {
         return getUnmodifiableSizeSet(mRecommendedMap.getOutputSizes(format));
     }
 
@@ -372,7 +385,7 @@
      * @return a non-modifiable set of supported slower high-resolution sizes, or {@code null} if
      *         the BURST_CAPTURE capability is not supported
      */
-    public @Nullable Set<Size> getHighResolutionOutputSizes(int format) {
+    public @Nullable Set<Size> getHighResolutionOutputSizes(@Format int format) {
         return getUnmodifiableSizeSet(mRecommendedMap.getHighResolutionOutputSizes(format));
     }
 
@@ -392,7 +405,8 @@
      *
      * @throws IllegalArgumentException if {@code format} or {@code size} was not supported
      */
-    public @IntRange(from = 0) long getOutputMinFrameDuration(int format, @NonNull Size size) {
+    public @IntRange(from = 0) long getOutputMinFrameDuration(@Format int format,
+            @NonNull Size size) {
         return mRecommendedMap.getOutputMinFrameDuration(format, size);
     }
 
@@ -409,7 +423,7 @@
      *
      * @throws IllegalArgumentException if {@code format} or {@code size} was not supported
      */
-    public @IntRange(from = 0) long getOutputStallDuration(int format, @NonNull Size size) {
+    public @IntRange(from = 0) long getOutputStallDuration(@Format int format, @NonNull Size size) {
         return mRecommendedMap.getOutputStallDuration(format, size);
     }
 
@@ -425,7 +439,7 @@
      *          a non-modifiable set of supported sizes for {@link ImageFormat#PRIVATE} format,
      *          or {@code null} if the {@code klass} is not a supported output.
      */
-    public <T> @Nullable Set<Size> getOutputSizes(@NonNull Class<T> klass) {
+    public @Nullable <T> Set<Size> getOutputSizes(@NonNull Class<T> klass) {
         if (mSupportsPrivate) {
             return getUnmodifiableSizeSet(mRecommendedMap.getOutputSizes(klass));
         }
@@ -448,7 +462,7 @@
      *
      * @throws IllegalArgumentException if {@code klass} or {@code size} was not supported
      */
-    public <T> @IntRange(from = 0) long getOutputMinFrameDuration(@NonNull final Class<T> klass,
+    public @IntRange(from = 0) <T> long getOutputMinFrameDuration(@NonNull final Class<T> klass,
             @NonNull final Size size) {
         if (mSupportsPrivate) {
             return mRecommendedMap.getOutputMinFrameDuration(klass, size);
@@ -471,7 +485,7 @@
      *
      * @throws IllegalArgumentException if {@code klass} or {@code size} was not supported
      */
-    public <T> @IntRange(from = 0) long getOutputStallDuration(@NonNull final Class<T> klass,
+    public @IntRange(from = 0) <T> long getOutputStallDuration(@NonNull final Class<T> klass,
             @NonNull final Size size) {
         if (mSupportsPrivate) {
             return mRecommendedMap.getOutputStallDuration(klass, size);
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index 139a5ee..3e8c334 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -634,6 +634,8 @@
                 return context.getString(R.string.face_acquired_obscured);
             case FACE_ACQUIRED_START:
                 return null;
+            case FACE_ACQUIRED_SENSOR_DIRTY:
+                return context.getString(R.string.face_acquired_sensor_dirty);
             case FACE_ACQUIRED_VENDOR: {
                 String[] msgArray = context.getResources().getStringArray(
                         R.array.face_acquired_vendor);
diff --git a/core/java/android/hardware/radio/RadioManager.java b/core/java/android/hardware/radio/RadioManager.java
index 92653d18..a7ff644 100644
--- a/core/java/android/hardware/radio/RadioManager.java
+++ b/core/java/android/hardware/radio/RadioManager.java
@@ -1761,7 +1761,7 @@
         TunerCallbackAdapter halCallback = new TunerCallbackAdapter(callback, handler);
         try {
             tuner = mService.openTuner(moduleId, config, withAudio, halCallback);
-        } catch (RemoteException | IllegalArgumentException ex) {
+        } catch (RemoteException | IllegalArgumentException | IllegalStateException ex) {
             Log.e(TAG, "Failed to open tuner", ex);
             return null;
         }
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 3f8410f..e5802c2 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -38,7 +38,6 @@
 import android.os.Build.VERSION_CODES;
 import android.os.Bundle;
 import android.os.Handler;
-import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.INetworkActivityListener;
 import android.os.INetworkManagementService;
@@ -75,6 +74,9 @@
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.RejectedExecutionException;
 
 /**
  * Class that answers queries about the state of network connectivity. It also
@@ -1813,23 +1815,26 @@
         public static final int MIN_INTERVAL = 10;
 
         private final Network mNetwork;
-        private final PacketKeepaliveCallback mCallback;
-        private final Looper mLooper;
-        private final Messenger mMessenger;
+        private final ISocketKeepaliveCallback mCallback;
+        private final ExecutorService mExecutor;
 
         private volatile Integer mSlot;
 
-        void stopLooper() {
-            mLooper.quit();
-        }
-
         @UnsupportedAppUsage
         public void stop() {
             try {
-                mService.stopKeepalive(mNetwork, mSlot);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Error stopping packet keepalive: ", e);
-                stopLooper();
+                mExecutor.execute(() -> {
+                    try {
+                        if (mSlot != null) {
+                            mService.stopKeepalive(mNetwork, mSlot);
+                        }
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Error stopping packet keepalive: ", e);
+                        throw e.rethrowFromSystemServer();
+                    }
+                });
+            } catch (RejectedExecutionException e) {
+                // The internal executor has already stopped due to previous event.
             }
         }
 
@@ -1837,40 +1842,43 @@
             Preconditions.checkNotNull(network, "network cannot be null");
             Preconditions.checkNotNull(callback, "callback cannot be null");
             mNetwork = network;
-            mCallback = callback;
-            HandlerThread thread = new HandlerThread(TAG);
-            thread.start();
-            mLooper = thread.getLooper();
-            mMessenger = new Messenger(new Handler(mLooper) {
+            mExecutor = Executors.newSingleThreadExecutor();
+            mCallback = new ISocketKeepaliveCallback.Stub() {
                 @Override
-                public void handleMessage(Message message) {
-                    switch (message.what) {
-                        case NetworkAgent.EVENT_SOCKET_KEEPALIVE:
-                            int error = message.arg2;
-                            try {
-                                if (error == SUCCESS) {
-                                    if (mSlot == null) {
-                                        mSlot = message.arg1;
-                                        mCallback.onStarted();
-                                    } else {
-                                        mSlot = null;
-                                        stopLooper();
-                                        mCallback.onStopped();
-                                    }
-                                } else {
-                                    stopLooper();
-                                    mCallback.onError(error);
-                                }
-                            } catch (Exception e) {
-                                Log.e(TAG, "Exception in keepalive callback(" + error + ")", e);
-                            }
-                            break;
-                        default:
-                            Log.e(TAG, "Unhandled message " + Integer.toHexString(message.what));
-                            break;
-                    }
+                public void onStarted(int slot) {
+                    Binder.withCleanCallingIdentity(() ->
+                            mExecutor.execute(() -> {
+                                mSlot = slot;
+                                callback.onStarted();
+                            }));
                 }
-            });
+
+                @Override
+                public void onStopped() {
+                    Binder.withCleanCallingIdentity(() ->
+                            mExecutor.execute(() -> {
+                                mSlot = null;
+                                callback.onStopped();
+                            }));
+                    mExecutor.shutdown();
+                }
+
+                @Override
+                public void onError(int error) {
+                    Binder.withCleanCallingIdentity(() ->
+                            mExecutor.execute(() -> {
+                                mSlot = null;
+                                callback.onError(error);
+                            }));
+                    mExecutor.shutdown();
+                }
+
+                @Override
+                public void onDataReceived() {
+                    // PacketKeepalive is only used for Nat-T keepalive and as such does not invoke
+                    // this callback when data is received.
+                }
+            };
         }
     }
 
@@ -1887,12 +1895,11 @@
             InetAddress srcAddr, int srcPort, InetAddress dstAddr) {
         final PacketKeepalive k = new PacketKeepalive(network, callback);
         try {
-            mService.startNattKeepalive(network, intervalSeconds, k.mMessenger, new Binder(),
+            mService.startNattKeepalive(network, intervalSeconds, k.mCallback,
                     srcAddr.getHostAddress(), srcPort, dstAddr.getHostAddress());
         } catch (RemoteException e) {
             Log.e(TAG, "Error starting packet keepalive: ", e);
-            k.stopLooper();
-            return null;
+            throw e.rethrowFromSystemServer();
         }
         return k;
     }
@@ -2805,24 +2812,7 @@
          *         {@link #TETHER_ERROR_PROVISION_FAILED}, or
          *         {@link #TETHER_ERROR_ENTITLEMENT_UNKONWN}.
          */
-        void onEntitlementResult(@EntitlementResultCode int resultCode);
-    }
-
-    /**
-     * @removed
-     * @deprecated This API would be removed when all of caller has been updated.
-     * */
-    @Deprecated
-    public abstract static class TetheringEntitlementValueListener  {
-        /**
-         * Called to notify entitlement result.
-         *
-         * @param resultCode a int value of entitlement result. It may be one of
-         *         {@link #TETHER_ERROR_NO_ERROR},
-         *         {@link #TETHER_ERROR_PROVISION_FAILED}, or
-         *         {@link #TETHER_ERROR_ENTITLEMENT_UNKONWN}.
-         */
-        public void onEntitlementResult(int resultCode) {}
+        void onTetheringEntitlementResult(@EntitlementResultCode int resultCode);
     }
 
     /**
@@ -2855,7 +2845,7 @@
             protected void onReceiveResult(int resultCode, Bundle resultData) {
                 Binder.withCleanCallingIdentity(() ->
                             executor.execute(() -> {
-                                listener.onEntitlementResult(resultCode);
+                                listener.onTetheringEntitlementResult(resultCode);
                             }));
             }
         };
@@ -2871,31 +2861,6 @@
     }
 
     /**
-     * @removed
-     * @deprecated This API would be removed when all of caller has been updated.
-     * */
-    @Deprecated
-    public void getLatestTetheringEntitlementValue(int type, boolean showEntitlementUi,
-            @NonNull final TetheringEntitlementValueListener listener, @Nullable Handler handler) {
-        Preconditions.checkNotNull(listener, "TetheringEntitlementValueListener cannot be null.");
-        ResultReceiver wrappedListener = new ResultReceiver(handler) {
-            @Override
-            protected void onReceiveResult(int resultCode, Bundle resultData) {
-                listener.onEntitlementResult(resultCode);
-            }
-        };
-
-        try {
-            String pkgName = mContext.getOpPackageName();
-            Log.i(TAG, "getLatestTetheringEntitlementValue:" + pkgName);
-            mService.getLatestTetheringEntitlementResult(type, wrappedListener,
-                    showEntitlementUi, pkgName);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
      * Report network connectivity status.  This is currently used only
      * to alter status bar UI.
      * <p>This method requires the caller to hold the permission
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 403b44d..24e6a85 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -27,6 +27,7 @@
 import android.net.NetworkQuotaInfo;
 import android.net.NetworkRequest;
 import android.net.NetworkState;
+import android.net.ISocketKeepaliveCallback;
 import android.net.ProxyInfo;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -194,15 +195,15 @@
 
     void factoryReset();
 
-    void startNattKeepalive(in Network network, int intervalSeconds, in Messenger messenger,
-            in IBinder binder, String srcAddr, int srcPort, String dstAddr);
+    void startNattKeepalive(in Network network, int intervalSeconds,
+            in ISocketKeepaliveCallback cb, String srcAddr, int srcPort, String dstAddr);
 
     void startNattKeepaliveWithFd(in Network network, in FileDescriptor fd, int resourceId,
-            int intervalSeconds, in Messenger messenger, in IBinder binder, String srcAddr,
+            int intervalSeconds, in ISocketKeepaliveCallback cb, String srcAddr,
             String dstAddr);
 
     void startTcpKeepalive(in Network network, in FileDescriptor fd, int intervalSeconds,
-            in Messenger messenger, in IBinder binder);
+            in ISocketKeepaliveCallback cb);
 
     void stopKeepalive(in Network network, int slot);
 
@@ -219,4 +220,6 @@
 
     void registerTetheringEventCallback(ITetheringEventCallback callback, String callerPkg);
     void unregisterTetheringEventCallback(ITetheringEventCallback callback, String callerPkg);
+
+    IBinder startOrGetTestNetworkService();
 }
diff --git a/core/java/android/net/INetworkStackConnector.aidl b/core/java/android/net/INetworkStackConnector.aidl
index e052488..edb9df6 100644
--- a/core/java/android/net/INetworkStackConnector.aidl
+++ b/core/java/android/net/INetworkStackConnector.aidl
@@ -16,7 +16,7 @@
 package android.net;
 
 import android.net.INetworkMonitorCallbacks;
-import android.net.NetworkParcelable;
+import android.net.Network;
 import android.net.dhcp.DhcpServingParamsParcel;
 import android.net.dhcp.IDhcpServerCallbacks;
 import android.net.ip.IIpClientCallbacks;
@@ -25,7 +25,6 @@
 oneway interface INetworkStackConnector {
     void makeDhcpServer(in String ifName, in DhcpServingParamsParcel params,
         in IDhcpServerCallbacks cb);
-    void makeNetworkMonitor(in NetworkParcelable network, String name,
-        in INetworkMonitorCallbacks cb);
+    void makeNetworkMonitor(in Network network, String name, in INetworkMonitorCallbacks cb);
     void makeIpClient(in String ifName, in IIpClientCallbacks callbacks);
 }
\ No newline at end of file
diff --git a/core/java/android/net/ISocketKeepaliveCallback.aidl b/core/java/android/net/ISocketKeepaliveCallback.aidl
new file mode 100644
index 0000000..020fbca
--- /dev/null
+++ b/core/java/android/net/ISocketKeepaliveCallback.aidl
@@ -0,0 +1,34 @@
+/**
+ * Copyright (c) 2019, 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.net;
+
+/**
+ * Callback to provide status changes of keepalive offload.
+ *
+ * @hide
+ */
+oneway interface ISocketKeepaliveCallback
+{
+    /** The keepalive was successfully started. */
+    void onStarted(int slot);
+    /** The keepalive was successfully stopped. */
+    void onStopped();
+    /** The keepalive was stopped because of an error. */
+    void onError(int error);
+    /** The keepalive on a TCP socket was stopped because the socket received data. */
+    void onDataReceived();
+}
diff --git a/core/java/android/net/InitialConfigurationParcelable.aidl b/core/java/android/net/InitialConfigurationParcelable.aidl
index bdda355..3fa88c3 100644
--- a/core/java/android/net/InitialConfigurationParcelable.aidl
+++ b/core/java/android/net/InitialConfigurationParcelable.aidl
@@ -16,12 +16,12 @@
 
 package android.net;
 
-import android.net.IpPrefixParcelable;
-import android.net.LinkAddressParcelable;
+import android.net.IpPrefix;
+import android.net.LinkAddress;
 
 parcelable InitialConfigurationParcelable {
-    LinkAddressParcelable[] ipAddresses;
-    IpPrefixParcelable[] directlyConnectedRoutes;
+    LinkAddress[] ipAddresses;
+    IpPrefix[] directlyConnectedRoutes;
     String[] dnsServers;
     String gateway;
 }
\ No newline at end of file
diff --git a/core/java/android/net/IpPrefix.aidl b/core/java/android/net/IpPrefix.aidl
index 837db5f..0d70f2a 100644
--- a/core/java/android/net/IpPrefix.aidl
+++ b/core/java/android/net/IpPrefix.aidl
@@ -17,4 +17,6 @@
 
 package android.net;
 
-parcelable IpPrefix cpp_header "binder/IpPrefix.h";
+// @JavaOnlyStableParcelable only affects the parcelable when built as stable aidl (aidl_interface
+// build rule). IpPrefix is also used in cpp but only as non-stable aidl.
+@JavaOnlyStableParcelable parcelable IpPrefix cpp_header "binder/IpPrefix.h";
diff --git a/core/java/android/net/IpPrefixParcelable.aidl b/core/java/android/net/IpPrefixParcelable.aidl
deleted file mode 100644
index 93a8d41..0000000
--- a/core/java/android/net/IpPrefixParcelable.aidl
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2019 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.net;
-
-parcelable IpPrefixParcelable {
-    String address;
-    int prefixLength;
-}
\ No newline at end of file
diff --git a/core/java/android/net/LinkAddress.aidl b/core/java/android/net/LinkAddress.aidl
index e7d8646..9c804db 100644
--- a/core/java/android/net/LinkAddress.aidl
+++ b/core/java/android/net/LinkAddress.aidl
@@ -17,5 +17,5 @@
 
 package android.net;
 
-parcelable LinkAddress;
+@JavaOnlyStableParcelable parcelable LinkAddress;
 
diff --git a/core/java/android/net/LinkAddressParcelable.aidl b/core/java/android/net/LinkAddressParcelable.aidl
deleted file mode 100644
index af8e79b..0000000
--- a/core/java/android/net/LinkAddressParcelable.aidl
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2019 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.net;
-
-parcelable LinkAddressParcelable {
-    String address;
-    int prefixLength;
-    int flags;
-    int scope;
-}
\ No newline at end of file
diff --git a/core/java/android/net/LinkProperties.aidl b/core/java/android/net/LinkProperties.aidl
index 3cb9525..a8b3c7b 100644
--- a/core/java/android/net/LinkProperties.aidl
+++ b/core/java/android/net/LinkProperties.aidl
@@ -17,4 +17,4 @@
 
 package android.net;
 
-parcelable LinkProperties;
+@JavaOnlyStableParcelable parcelable LinkProperties;
diff --git a/core/java/android/net/LinkPropertiesParcelable.aidl b/core/java/android/net/LinkPropertiesParcelable.aidl
deleted file mode 100644
index 6b52239..0000000
--- a/core/java/android/net/LinkPropertiesParcelable.aidl
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2019 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.net;
-
-import android.net.IpPrefixParcelable;
-import android.net.LinkAddressParcelable;
-import android.net.ProxyInfoParcelable;
-import android.net.RouteInfoParcelable;
-
-parcelable LinkPropertiesParcelable {
-    String ifaceName;
-    LinkAddressParcelable[] linkAddresses;
-    String[] dnses;
-    String[] pcscfs;
-    String[] validatedPrivateDnses;
-    boolean usePrivateDns;
-    String privateDnsServerName;
-    String domains;
-    RouteInfoParcelable[] routes;
-    ProxyInfoParcelable httpProxy;
-    int mtu;
-    String tcpBufferSizes;
-    IpPrefixParcelable nat64Prefix;
-}
\ No newline at end of file
diff --git a/core/java/android/net/NattSocketKeepalive.java b/core/java/android/net/NattSocketKeepalive.java
index 88631ae..84da294 100644
--- a/core/java/android/net/NattSocketKeepalive.java
+++ b/core/java/android/net/NattSocketKeepalive.java
@@ -17,7 +17,6 @@
 package android.net;
 
 import android.annotation.NonNull;
-import android.os.Binder;
 import android.os.RemoteException;
 import android.util.Log;
 
@@ -52,24 +51,30 @@
 
     @Override
     void startImpl(int intervalSec) {
-        try {
-            mService.startNattKeepaliveWithFd(mNetwork, mFd, mResourceId, intervalSec, mMessenger,
-                    new Binder(), mSource.getHostAddress(), mDestination.getHostAddress());
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error starting packet keepalive: ", e);
-            stopLooper();
-        }
+        mExecutor.execute(() -> {
+            try {
+                mService.startNattKeepaliveWithFd(mNetwork, mFd, mResourceId, intervalSec,
+                        mCallback,
+                        mSource.getHostAddress(), mDestination.getHostAddress());
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error starting socket keepalive: ", e);
+                throw e.rethrowFromSystemServer();
+            }
+        });
     }
 
     @Override
     void stopImpl() {
-        try {
-            if (mSlot != null) {
-                mService.stopKeepalive(mNetwork, mSlot);
+        mExecutor.execute(() -> {
+            try {
+                if (mSlot != null) {
+                    mService.stopKeepalive(mNetwork, mSlot);
+                }
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error stopping socket keepalive: ", e);
+                throw e.rethrowFromSystemServer();
             }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error stopping packet keepalive: ", e);
-            stopLooper();
-        }
+        });
+
     }
 }
diff --git a/core/java/android/net/Network.aidl b/core/java/android/net/Network.aidl
index 73ba1af..0562202 100644
--- a/core/java/android/net/Network.aidl
+++ b/core/java/android/net/Network.aidl
@@ -17,4 +17,4 @@
 
 package android.net;
 
-parcelable Network;
+@JavaOnlyStableParcelable parcelable Network;
diff --git a/core/java/android/net/ProvisioningConfigurationParcelable.aidl b/core/java/android/net/ProvisioningConfigurationParcelable.aidl
index 2a144f2..5b46d7f 100644
--- a/core/java/android/net/ProvisioningConfigurationParcelable.aidl
+++ b/core/java/android/net/ProvisioningConfigurationParcelable.aidl
@@ -19,7 +19,7 @@
 
 import android.net.ApfCapabilitiesParcelable;
 import android.net.InitialConfigurationParcelable;
-import android.net.NetworkParcelable;
+import android.net.Network;
 import android.net.StaticIpConfigurationParcelable;
 
 parcelable ProvisioningConfigurationParcelable {
@@ -33,6 +33,6 @@
     ApfCapabilitiesParcelable apfCapabilities;
     int provisioningTimeoutMs;
     int ipv6AddrGenMode;
-    NetworkParcelable network;
+    Network network;
     String displayName;
 }
diff --git a/core/java/android/net/ProxyInfo.aidl b/core/java/android/net/ProxyInfo.aidl
index 2c91960..a5d0c12 100644
--- a/core/java/android/net/ProxyInfo.aidl
+++ b/core/java/android/net/ProxyInfo.aidl
@@ -17,5 +17,5 @@
 
 package android.net;
 
-parcelable ProxyInfo;
+@JavaOnlyStableParcelable parcelable ProxyInfo;
 
diff --git a/core/java/android/net/RouteInfo.aidl b/core/java/android/net/RouteInfo.aidl
index 2296a57..7af9fda 100644
--- a/core/java/android/net/RouteInfo.aidl
+++ b/core/java/android/net/RouteInfo.aidl
@@ -16,4 +16,4 @@
 
 package android.net;
 
-parcelable RouteInfo;
+@JavaOnlyStableParcelable parcelable RouteInfo;
diff --git a/core/java/android/net/RouteInfoParcelable.aidl b/core/java/android/net/RouteInfoParcelable.aidl
deleted file mode 100644
index 15bcdcf..0000000
--- a/core/java/android/net/RouteInfoParcelable.aidl
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2019 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.net;
-
-import android.net.IpPrefixParcelable;
-
-parcelable RouteInfoParcelable {
-    IpPrefixParcelable destination;
-    String gatewayAddr;
-    String ifaceName;
-    int type;
-}
diff --git a/core/java/android/net/SocketKeepalive.java b/core/java/android/net/SocketKeepalive.java
index 07728be..0e768df 100644
--- a/core/java/android/net/SocketKeepalive.java
+++ b/core/java/android/net/SocketKeepalive.java
@@ -20,13 +20,8 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Messenger;
-import android.os.Process;
-import android.util.Log;
+import android.os.Binder;
+import android.os.RemoteException;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -152,10 +147,9 @@
 
     @NonNull final IConnectivityManager mService;
     @NonNull final Network mNetwork;
-    @NonNull private final Executor mExecutor;
-    @NonNull private final SocketKeepalive.Callback mCallback;
-    @NonNull private final Looper mLooper;
-    @NonNull final Messenger mMessenger;
+    @NonNull final Executor mExecutor;
+    @NonNull final ISocketKeepaliveCallback mCallback;
+    // TODO: remove slot since mCallback could be used to identify which keepalive to stop.
     @Nullable Integer mSlot;
 
     SocketKeepalive(@NonNull IConnectivityManager service, @NonNull Network network,
@@ -163,53 +157,53 @@
         mService = service;
         mNetwork = network;
         mExecutor = executor;
-        mCallback = callback;
-        // TODO: 1. Use other thread modeling instead of create one thread for every instance to
-        //          reduce the memory cost.
-        //       2. support restart.
-        //       3. Fix race condition which caused by rapidly start and stop.
-        HandlerThread thread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND
-                + Process.THREAD_PRIORITY_LESS_FAVORABLE);
-        thread.start();
-        mLooper = thread.getLooper();
-        mMessenger = new Messenger(new Handler(mLooper) {
+        mCallback = new ISocketKeepaliveCallback.Stub() {
             @Override
-            public void handleMessage(Message message) {
-                switch (message.what) {
-                    case NetworkAgent.EVENT_SOCKET_KEEPALIVE:
-                        final int status = message.arg2;
-                        try {
-                            if (status == SUCCESS) {
-                                if (mSlot == null) {
-                                    mSlot = message.arg1;
-                                    mExecutor.execute(() -> mCallback.onStarted());
-                                } else {
-                                    mSlot = null;
-                                    stopLooper();
-                                    mExecutor.execute(() -> mCallback.onStopped());
-                                }
-                            } else if (status == DATA_RECEIVED) {
-                                stopLooper();
-                                mExecutor.execute(() -> mCallback.onDataReceived());
-                            } else {
-                                stopLooper();
-                                mExecutor.execute(() -> mCallback.onError(status));
-                            }
-                        } catch (Exception e) {
-                            Log.e(TAG, "Exception in keepalive callback(" + status + ")", e);
-                        }
-                        break;
-                    default:
-                        Log.e(TAG, "Unhandled message " + Integer.toHexString(message.what));
-                        break;
-                }
+            public void onStarted(int slot) {
+                Binder.withCleanCallingIdentity(() ->
+                        mExecutor.execute(() -> {
+                            mSlot = slot;
+                            callback.onStarted();
+                        }));
             }
-        });
+
+            @Override
+            public void onStopped() {
+                Binder.withCleanCallingIdentity(() ->
+                        executor.execute(() -> {
+                            mSlot = null;
+                            callback.onStopped();
+                        }));
+            }
+
+            @Override
+            public void onError(int error) {
+                Binder.withCleanCallingIdentity(() ->
+                        executor.execute(() -> {
+                            mSlot = null;
+                            callback.onError(error);
+                        }));
+            }
+
+            @Override
+            public void onDataReceived() {
+                Binder.withCleanCallingIdentity(() ->
+                        executor.execute(() -> {
+                            mSlot = null;
+                            callback.onDataReceived();
+                        }));
+            }
+        };
     }
 
     /**
      * Request that keepalive be started with the given {@code intervalSec}. See
-     * {@link SocketKeepalive}.
+     * {@link SocketKeepalive}. If the remote binder dies, or the binder call throws an exception
+     * when invoking start or stop of the {@link SocketKeepalive}, a {@link RemoteException} will be
+     * thrown into the {@code executor}. This is typically not important to catch because the remote
+     * party is the system, so if it is not in shape to communicate through binder the system is
+     * probably going down anyway. If the caller cares regardless, it can use a custom
+     * {@link Executor} to catch the {@link RemoteException}.
      *
      * @param intervalSec The target interval in seconds between keepalive packet transmissions.
      *                    The interval should be between 10 seconds and 3600 seconds, otherwise
@@ -222,12 +216,6 @@
 
     abstract void startImpl(int intervalSec);
 
-    /** @hide */
-    protected void stopLooper() {
-        // TODO: remove this after changing thread modeling.
-        mLooper.quit();
-    }
-
     /**
      * Requests that keepalive be stopped. The application must wait for {@link Callback#onStopped}
      * before using the object. See {@link SocketKeepalive}.
@@ -245,7 +233,6 @@
     @Override
     public final void close() {
         stop();
-        stopLooper();
     }
 
     /**
@@ -259,7 +246,8 @@
         public void onStopped() {}
         /** An error occurred. */
         public void onError(@ErrorCode int error) {}
-        /** The keepalive on a TCP socket was stopped because the socket received data. */
+        /** The keepalive on a TCP socket was stopped because the socket received data. This is
+         * never called for UDP sockets. */
         public void onDataReceived() {}
     }
 }
diff --git a/core/java/android/net/StaticIpConfigurationParcelable.aidl b/core/java/android/net/StaticIpConfigurationParcelable.aidl
index 45dc021..6fffb42 100644
--- a/core/java/android/net/StaticIpConfigurationParcelable.aidl
+++ b/core/java/android/net/StaticIpConfigurationParcelable.aidl
@@ -17,10 +17,10 @@
 
 package android.net;
 
-import android.net.LinkAddressParcelable;
+import android.net.LinkAddress;
 
 parcelable StaticIpConfigurationParcelable {
-    LinkAddressParcelable ipAddress;
+    LinkAddress ipAddress;
     String gateway;
     String[] dnsServers;
     String domains;
diff --git a/core/java/android/net/TcpSocketKeepalive.java b/core/java/android/net/TcpSocketKeepalive.java
index f691a0d..26cc8ff 100644
--- a/core/java/android/net/TcpSocketKeepalive.java
+++ b/core/java/android/net/TcpSocketKeepalive.java
@@ -17,7 +17,6 @@
 package android.net;
 
 import android.annotation.NonNull;
-import android.os.Binder;
 import android.os.RemoteException;
 import android.util.Log;
 
@@ -56,24 +55,28 @@
      */
     @Override
     void startImpl(int intervalSec) {
-        try {
-            final FileDescriptor fd = mSocket.getFileDescriptor$();
-            mService.startTcpKeepalive(mNetwork, fd, intervalSec, mMessenger, new Binder());
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error starting packet keepalive: ", e);
-            stopLooper();
-        }
+        mExecutor.execute(() -> {
+            try {
+                final FileDescriptor fd = mSocket.getFileDescriptor$();
+                mService.startTcpKeepalive(mNetwork, fd, intervalSec, mCallback);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error starting packet keepalive: ", e);
+                throw e.rethrowFromSystemServer();
+            }
+        });
     }
 
     @Override
     void stopImpl() {
-        try {
-            if (mSlot != null) {
-                mService.stopKeepalive(mNetwork, mSlot);
+        mExecutor.execute(() -> {
+            try {
+                if (mSlot != null) {
+                    mService.stopKeepalive(mNetwork, mSlot);
+                }
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error stopping packet keepalive: ", e);
+                throw e.rethrowFromSystemServer();
             }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error stopping packet keepalive: ", e);
-            stopLooper();
-        }
+        });
     }
 }
diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java
index 870d8b1..ea245a4 100644
--- a/core/java/android/net/VpnService.java
+++ b/core/java/android/net/VpnService.java
@@ -27,6 +27,8 @@
 import android.app.Activity;
 import android.app.PendingIntent;
 import android.app.Service;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.IPackageManager;
@@ -48,6 +50,7 @@
 import java.net.Socket;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 /**
  * VpnService is a base class for applications to extend and build their
@@ -138,7 +141,7 @@
      * provides users with the ability to set it as always-on, so that VPN connection is
      * persisted after device reboot and app upgrade. Always-on VPN can also be enabled by device
      * owner and profile owner apps through
-     * {@link android.app.admin.DevicePolicyManager#setAlwaysOnVpnPackage}.
+     * {@link DevicePolicyManager#setAlwaysOnVpnPackage}.
      *
      * <p>VPN apps not supporting this feature should opt out by adding this meta-data field to the
      * {@code VpnService} component of {@code AndroidManifest.xml}. In case there is more than one
@@ -370,7 +373,10 @@
     }
 
     /**
-     * Returns whether the service is running in always-on VPN mode.
+     * Returns whether the service is running in always-on VPN mode. In this mode the system ensures
+     * that the service is always running by restarting it when necessary, e.g. after reboot.
+     *
+     * @see DevicePolicyManager#setAlwaysOnVpnPackage(ComponentName, String, boolean, Set)
      */
     public final boolean isAlwaysOn() {
         try {
@@ -381,8 +387,11 @@
     }
 
     /**
-     * Returns whether the service is running in always-on VPN mode blocking connections without
-     * VPN.
+     * Returns whether the service is running in always-on VPN lockdown mode. In this mode the
+     * system ensures that the service is always running and that the apps aren't allowed to bypass
+     * the VPN.
+     *
+     * @see DevicePolicyManager#setAlwaysOnVpnPackage(ComponentName, String, boolean, Set)
      */
     public final boolean isLockdownEnabled() {
         try {
diff --git a/core/java/android/net/ip/IIpClient.aidl b/core/java/android/net/ip/IIpClient.aidl
index a4a80e1..b834e45 100644
--- a/core/java/android/net/ip/IIpClient.aidl
+++ b/core/java/android/net/ip/IIpClient.aidl
@@ -15,7 +15,7 @@
  */
 package android.net.ip;
 
-import android.net.ProxyInfoParcelable;
+import android.net.ProxyInfo;
 import android.net.ProvisioningConfigurationParcelable;
 import android.net.TcpKeepalivePacketDataParcelable;
 
@@ -28,7 +28,7 @@
     void startProvisioning(in ProvisioningConfigurationParcelable req);
     void stop();
     void setTcpBufferSizes(in String tcpBufferSizes);
-    void setHttpProxy(in ProxyInfoParcelable proxyInfo);
+    void setHttpProxy(in ProxyInfo proxyInfo);
     void setMulticastFilter(boolean enabled);
     void addKeepalivePacketFilter(int slot, in TcpKeepalivePacketDataParcelable pkt);
     void removeKeepalivePacketFilter(int slot);
diff --git a/core/java/android/net/ip/IIpClientCallbacks.aidl b/core/java/android/net/ip/IIpClientCallbacks.aidl
index f077e3b..3681416 100644
--- a/core/java/android/net/ip/IIpClientCallbacks.aidl
+++ b/core/java/android/net/ip/IIpClientCallbacks.aidl
@@ -15,7 +15,7 @@
  */
 package android.net.ip;
 
-import android.net.LinkPropertiesParcelable;
+import android.net.LinkProperties;
 import android.net.ip.IIpClient;
 import android.net.DhcpResultsParcelable;
 
@@ -34,11 +34,11 @@
     // null or not.
     void onNewDhcpResults(in DhcpResultsParcelable dhcpResults);
 
-    void onProvisioningSuccess(in LinkPropertiesParcelable newLp);
-    void onProvisioningFailure(in LinkPropertiesParcelable newLp);
+    void onProvisioningSuccess(in LinkProperties newLp);
+    void onProvisioningFailure(in LinkProperties newLp);
 
     // Invoked on LinkProperties changes.
-    void onLinkPropertiesChange(in LinkPropertiesParcelable newLp);
+    void onLinkPropertiesChange(in LinkProperties newLp);
 
     // Called when the internal IpReachabilityMonitor (if enabled) has
     // detected the loss of a critical number of required neighbors.
diff --git a/core/java/android/os/AsyncResult.java b/core/java/android/os/AsyncResult.java
index 5bad09d..58a2701 100644
--- a/core/java/android/os/AsyncResult.java
+++ b/core/java/android/os/AsyncResult.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Message;
 
 /** @hide */
@@ -25,13 +26,17 @@
     /*************************** Instance Variables **************************/
 
     // Expect either exception or result to be null
+    @UnsupportedAppUsage
     public Object userObj;
+    @UnsupportedAppUsage
     public Throwable exception;
+    @UnsupportedAppUsage
     public Object result;
 
     /***************************** Class Methods *****************************/
 
     /** Saves and sets m.obj */
+    @UnsupportedAppUsage
     public static AsyncResult 
     forMessage(Message m, Object r, Throwable ex)
     {
@@ -45,6 +50,7 @@
     }
 
     /** Saves and sets m.obj */
+    @UnsupportedAppUsage
     public static AsyncResult 
     forMessage(Message m)
     {
@@ -58,6 +64,7 @@
     }
 
     /** please note, this sets m.obj to be this */
+    @UnsupportedAppUsage
     public 
     AsyncResult (Object uo, Object r, Throwable ex)
     {
diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java
index a851e04..d259f38 100644
--- a/core/java/android/os/AsyncTask.java
+++ b/core/java/android/os/AsyncTask.java
@@ -18,6 +18,7 @@
 
 import android.annotation.MainThread;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.WorkerThread;
 
 import java.util.ArrayDeque;
@@ -259,15 +260,20 @@
     private static final int MESSAGE_POST_RESULT = 0x1;
     private static final int MESSAGE_POST_PROGRESS = 0x2;
 
+    @UnsupportedAppUsage
     private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
     private static InternalHandler sHandler;
 
+    @UnsupportedAppUsage
     private final WorkerRunnable<Params, Result> mWorker;
+    @UnsupportedAppUsage
     private final FutureTask<Result> mFuture;
 
+    @UnsupportedAppUsage
     private volatile Status mStatus = Status.PENDING;
     
     private final AtomicBoolean mCancelled = new AtomicBoolean();
+    @UnsupportedAppUsage
     private final AtomicBoolean mTaskInvoked = new AtomicBoolean();
 
     private final Handler mHandler;
@@ -331,6 +337,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static void setDefaultExecutor(Executor exec) {
         sDefaultExecutor = exec;
     }
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index 3d4c00c..7f63f8f 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.util.MathUtils;
@@ -82,6 +83,7 @@
     // Invariant - exactly one of mMap / mParcelledData will be null
     // (except inside a call to unparcel)
 
+    @UnsupportedAppUsage
     ArrayMap<String, Object> mMap = null;
 
     /*
@@ -89,6 +91,7 @@
      * data are stored as a Parcel containing a Bundle.  When the data
      * are unparcelled, mParcelledData willbe set to null.
      */
+    @UnsupportedAppUsage
     Parcel mParcelledData = null;
 
     /**
@@ -225,6 +228,7 @@
      * If the underlying data are stored as a Parcel, unparcel them
      * using the currently assigned class loader.
      */
+    @UnsupportedAppUsage
     /* package */ void unparcel() {
         synchronized (this) {
             final Parcel source = mParcelledData;
@@ -311,6 +315,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isParcelled() {
         return mParcelledData != null;
     }
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index 6639f0f..5ced86c 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -21,6 +21,7 @@
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.Intent;
 import android.hardware.health.V1_0.Constants;
@@ -112,6 +113,7 @@
      * to the device.
      * {@hide}
      */
+    @UnsupportedAppUsage
     public static final String EXTRA_INVALID_CHARGER = "invalid_charger";
 
     /**
@@ -119,6 +121,7 @@
      * Int value set to the maximum charging current supported by the charger in micro amperes.
      * {@hide}
      */
+    @UnsupportedAppUsage
     public static final String EXTRA_MAX_CHARGING_CURRENT = "max_charging_current";
 
     /**
@@ -126,6 +129,7 @@
      * Int value set to the maximum charging voltage supported by the charger in micro volts.
      * {@hide}
      */
+    @UnsupportedAppUsage
     public static final String EXTRA_MAX_CHARGING_VOLTAGE = "max_charging_voltage";
 
     /**
@@ -133,6 +137,7 @@
      * integer containing the charge counter present in the battery.
      * {@hide}
      */
+     @UnsupportedAppUsage
      public static final String EXTRA_CHARGE_COUNTER = "charge_counter";
 
     /**
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index e4277e4..4fae3a8 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -18,6 +18,7 @@
 
 import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION;
 
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityManager;
 import android.app.job.JobParameters;
 import android.content.Context;
@@ -74,6 +75,7 @@
     /**
      * A constant indicating a partial wake lock timer.
      */
+    @UnsupportedAppUsage
     public static final int WAKE_TYPE_PARTIAL = 0;
 
     /**
@@ -199,6 +201,7 @@
     /**
      * Include only the current run in the stats.
      */
+    @UnsupportedAppUsage
     public static final int STATS_CURRENT = 1;
 
     /**
@@ -396,6 +399,7 @@
          *
          * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT
          */
+        @UnsupportedAppUsage
         public abstract int getCountLocked(int which);
 
         /**
@@ -504,6 +508,7 @@
          *
          * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT
          */
+        @UnsupportedAppUsage
         public abstract int getCountLocked(int which);
 
         /**
@@ -514,6 +519,7 @@
          * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT
          * @return a time in microseconds
          */
+        @UnsupportedAppUsage
         public abstract long getTotalTimeLocked(long elapsedRealtimeUs, int which);
 
         /**
@@ -616,6 +622,7 @@
          *
          * @return a Map from Strings to Uid.Wakelock objects.
          */
+        @UnsupportedAppUsage
         public abstract ArrayMap<String, ? extends Wakelock> getWakelockStats();
 
         /**
@@ -650,6 +657,7 @@
          * The statistics associated with a particular wake lock.
          */
         public static abstract class Wakelock {
+            @UnsupportedAppUsage
             public abstract Timer getWakeTime(int type);
         }
 
@@ -665,6 +673,7 @@
          *
          * @return a Map from Integer sensor ids to Uid.Sensor objects.
          */
+        @UnsupportedAppUsage
         public abstract SparseArray<? extends Sensor> getSensorStats();
 
         /**
@@ -677,6 +686,7 @@
          *
          * @return a Map from Strings to Uid.Proc objects.
          */
+        @UnsupportedAppUsage
         public abstract ArrayMap<String, ? extends Proc> getProcessStats();
 
         /**
@@ -684,6 +694,7 @@
          *
          * @return a Map from Strings to Uid.Pkg objects.
          */
+        @UnsupportedAppUsage
         public abstract ArrayMap<String, ? extends Pkg> getPackageStats();
 
         public abstract ControllerActivityCounter getWifiControllerActivity();
@@ -693,6 +704,7 @@
         /**
          * {@hide}
          */
+        @UnsupportedAppUsage
         public abstract int getUid();
 
         public abstract void noteWifiRunningLocked(long elapsedRealtime);
@@ -707,8 +719,11 @@
         public abstract void noteWifiMulticastDisabledLocked(long elapsedRealtime);
         public abstract void noteActivityResumedLocked(long elapsedRealtime);
         public abstract void noteActivityPausedLocked(long elapsedRealtime);
+        @UnsupportedAppUsage
         public abstract long getWifiRunningTime(long elapsedRealtimeUs, int which);
+        @UnsupportedAppUsage
         public abstract long getFullWifiLockTime(long elapsedRealtimeUs, int which);
+        @UnsupportedAppUsage
         public abstract long getWifiScanTime(long elapsedRealtimeUs, int which);
         public abstract int getWifiScanCount(int which);
         /**
@@ -722,10 +737,14 @@
          * Returns the timer keeping track of background wifi scans.
          */
         public abstract Timer getWifiScanBackgroundTimer();
+        @UnsupportedAppUsage
         public abstract long getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which);
         public abstract int getWifiBatchedScanCount(int csphBin, int which);
+        @UnsupportedAppUsage
         public abstract long getWifiMulticastTime(long elapsedRealtimeUs, int which);
+        @UnsupportedAppUsage
         public abstract Timer getAudioTurnedOnTimer();
+        @UnsupportedAppUsage
         public abstract Timer getVideoTurnedOnTimer();
         public abstract Timer getFlashlightTurnedOnTimer();
         public abstract Timer getCameraTurnedOnTimer();
@@ -857,8 +876,10 @@
         public abstract int getUserActivityCount(int type, int which);
 
         public abstract boolean hasNetworkActivity();
+        @UnsupportedAppUsage
         public abstract long getNetworkActivityBytes(int type, int which);
         public abstract long getNetworkActivityPackets(int type, int which);
+        @UnsupportedAppUsage
         public abstract long getMobileRadioActiveTime(int which);
         public abstract int getMobileRadioActiveCount(int which);
 
@@ -918,10 +939,13 @@
              * the sensor HAL, and therefore out of our control
              */
             // Magic sensor number for the GPS.
+            @UnsupportedAppUsage
             public static final int GPS = -10000;
 
+            @UnsupportedAppUsage
             public abstract int getHandle();
 
+            @UnsupportedAppUsage
             public abstract Timer getSensorTime();
 
             /** Returns a Timer for sensor usage when app is in the background. */
@@ -943,8 +967,11 @@
                 public static final int TYPE_WAKE = 1;
                 public static final int TYPE_CPU = 2;
 
+                @UnsupportedAppUsage
                 public int type;
+                @UnsupportedAppUsage
                 public long overTime;
+                @UnsupportedAppUsage
                 public long usedTime;
             }
 
@@ -958,6 +985,7 @@
              *
              * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
              */
+            @UnsupportedAppUsage
             public abstract long getUserTime(int which);
 
             /**
@@ -965,6 +993,7 @@
              *
              * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
              */
+            @UnsupportedAppUsage
             public abstract long getSystemTime(int which);
 
             /**
@@ -972,6 +1001,7 @@
              *
              * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
              */
+            @UnsupportedAppUsage
             public abstract int getStarts(int which);
 
             /**
@@ -993,10 +1023,13 @@
              * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
              * @return foreground cpu time in microseconds
              */
+            @UnsupportedAppUsage
             public abstract long getForegroundTime(int which);
 
+            @UnsupportedAppUsage
             public abstract int countExcessivePowers();
 
+            @UnsupportedAppUsage
             public abstract ExcessivePower getExcessivePower(int i);
         }
 
@@ -1010,11 +1043,13 @@
              * package.  The mapping keys are tag names for the alarms, the counter contains
              * the number of times the alarm was triggered while on battery.
              */
+            @UnsupportedAppUsage
             public abstract ArrayMap<String, ? extends Counter> getWakeupAlarmStats();
 
             /**
              * Returns a mapping containing service statistics.
              */
+            @UnsupportedAppUsage
             public abstract ArrayMap<String, ? extends Serv> getServiceStats();
 
             /**
@@ -1029,6 +1064,7 @@
                  * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
                  * @return
                  */
+                @UnsupportedAppUsage
                 public abstract long getStartTime(long batteryUptime, int which);
 
                 /**
@@ -1036,6 +1072,7 @@
                  *
                  * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
                  */
+                @UnsupportedAppUsage
                 public abstract int getStarts(int which);
 
                 /**
@@ -1043,6 +1080,7 @@
                  *
                  * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
                  */
+                @UnsupportedAppUsage
                 public abstract int getLaunches(int which);
             }
         }
@@ -1505,8 +1543,10 @@
         public HistoryItem next;
 
         // The time of this event in milliseconds, as per SystemClock.elapsedRealtime().
+        @UnsupportedAppUsage
         public long time;
 
+        @UnsupportedAppUsage
         public static final byte CMD_UPDATE = 0;        // These can be written as deltas
         public static final byte CMD_NULL = -1;
         public static final byte CMD_START = 4;
@@ -1515,6 +1555,7 @@
         public static final byte CMD_RESET = 7;
         public static final byte CMD_SHUTDOWN = 8;
 
+        @UnsupportedAppUsage
         public byte cmd = CMD_NULL;
 
         /**
@@ -1524,12 +1565,17 @@
             return cmd == CMD_UPDATE;
         }
 
+        @UnsupportedAppUsage
         public byte batteryLevel;
+        @UnsupportedAppUsage
         public byte batteryStatus;
+        @UnsupportedAppUsage
         public byte batteryHealth;
+        @UnsupportedAppUsage
         public byte batteryPlugType;
 
         public short batteryTemperature;
+        @UnsupportedAppUsage
         public char batteryVoltage;
 
         // The charge of the battery in micro-Ampere-hours.
@@ -1579,6 +1625,7 @@
 
         public static final int SETTLE_TO_ZERO_STATES = 0xffff0000 & ~MOST_INTERESTING_STATES;
 
+        @UnsupportedAppUsage
         public int states;
 
         // Constants from WIFI_SUPPL_STATE_*
@@ -1614,6 +1661,7 @@
 
         public static final int SETTLE_TO_ZERO_STATES2 = 0xffff0000 & ~MOST_INTERESTING_STATES2;
 
+        @UnsupportedAppUsage
         public int states2;
 
         // The wake lock that was acquired at this point.
@@ -1722,6 +1770,7 @@
         public final HistoryTag localWakeReasonTag = new HistoryTag();
         public final HistoryTag localEventTag = new HistoryTag();
 
+        @UnsupportedAppUsage
         public HistoryItem() {
         }
 
@@ -2023,6 +2072,7 @@
 
     public abstract int getHistoryUsedSize();
 
+    @UnsupportedAppUsage
     public abstract boolean startIteratingHistoryLocked();
 
     public abstract int getHistoryStringPoolSize();
@@ -2033,6 +2083,7 @@
 
     public abstract int getHistoryTagPoolUid(int index);
 
+    @UnsupportedAppUsage
     public abstract boolean getNextHistoryLocked(HistoryItem out);
 
     public abstract void finishIteratingHistoryLocked();
@@ -2059,6 +2110,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public abstract long getScreenOnTime(long elapsedRealtimeUs, int which);
 
     /**
@@ -2099,6 +2151,7 @@
         "0", "1", "2", "3", "4"
     };
 
+    @UnsupportedAppUsage
     public static final int NUM_SCREEN_BRIGHTNESS_BINS = 5;
 
     /**
@@ -2107,6 +2160,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public abstract long getScreenBrightnessTime(int brightnessBin,
             long elapsedRealtimeUs, int which);
 
@@ -2215,6 +2269,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public abstract long getPhoneOnTime(long elapsedRealtimeUs, int which);
 
     /**
@@ -2230,6 +2285,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public abstract long getPhoneSignalStrengthTime(int strengthBin,
             long elapsedRealtimeUs, int which);
 
@@ -2313,6 +2369,7 @@
         "other"
     };
 
+    @UnsupportedAppUsage
     public static final int NUM_DATA_CONNECTION_TYPES = DATA_CONNECTION_OTHER+1;
 
     /**
@@ -2475,6 +2532,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public abstract long getWifiOnTime(long elapsedRealtimeUs, int which);
 
     /**
@@ -2491,6 +2549,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public abstract long getGlobalWifiRunningTime(long elapsedRealtimeUs, int which);
 
     public static final int WIFI_STATE_OFF = 0;
@@ -2696,6 +2755,7 @@
     /**
      * Returns a SparseArray containing the statistics for each uid.
      */
+    @UnsupportedAppUsage
     public abstract SparseArray<? extends Uid> getUidStats();
 
     /**
@@ -2703,6 +2763,7 @@
      *
      * @param curTime the amount of elapsed realtime in microseconds.
      */
+    @UnsupportedAppUsage
     public abstract long getBatteryUptime(long curTime);
 
     /**
@@ -2783,6 +2844,7 @@
      * @param curTime the elapsed realtime in microseconds.
      * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
      */
+    @UnsupportedAppUsage
     public abstract long computeBatteryUptime(long curTime, int which);
 
     /**
@@ -2791,6 +2853,7 @@
      * @param curTime the current elapsed realtime in microseconds.
      * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
      */
+    @UnsupportedAppUsage
     public abstract long computeBatteryRealtime(long curTime, int which);
 
     /**
@@ -2833,6 +2896,7 @@
      *
      * @param curTime The current elepsed realtime in microseconds.
      */
+    @UnsupportedAppUsage
     public abstract long computeBatteryTimeRemaining(long curTime);
 
     // The part of a step duration that is the actual time.
@@ -2967,6 +3031,7 @@
      *
      * @param curTime The current elepsed realtime in microseconds.
      */
+    @UnsupportedAppUsage
     public abstract long computeChargeTimeRemaining(long curTime);
 
     /**
@@ -3251,6 +3316,7 @@
      * @param type type of data (e.g. "wakelock", "sensor", "process", "apk" ,  "process", "network")
      * @param args type-dependent data arguments
      */
+    @UnsupportedAppUsage
     private static final void dumpLine(PrintWriter pw, int uid, String category, String type,
            Object... args ) {
         dumpLineHeader(pw, uid, category, type);
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index d5ef249..eb91860 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.util.ExceptionUtils;
 import android.util.Log;
 import android.util.Slog;
@@ -247,6 +248,7 @@
     /**
      * Raw native pointer to JavaBBinderHolder object. Owned by this Java object. Not null.
      */
+    @UnsupportedAppUsage
     private final long mObject;
 
     private IInterface mOwner;
@@ -990,6 +992,7 @@
     }
 
     // Entry point from android_util_Binder.cpp's onTransact
+    @UnsupportedAppUsage
     private boolean execTransact(int code, long dataObj, long replyObj,
             int flags) {
         // At that point, the parcel request headers haven't been parsed so we do not know what
diff --git a/core/java/android/os/Broadcaster.java b/core/java/android/os/Broadcaster.java
index 70dcdd8..6ac7f1a 100644
--- a/core/java/android/os/Broadcaster.java
+++ b/core/java/android/os/Broadcaster.java
@@ -16,9 +16,12 @@
 
 package android.os;
 
+import android.annotation.UnsupportedAppUsage;
+
 /** @hide */
 public class Broadcaster
 {
+    @UnsupportedAppUsage
     public Broadcaster()
     {
     }
@@ -29,6 +32,7 @@
      *  When this broadcaster pushes a message with senderWhat in the what field,
      *  target will be sent a copy of that message with targetWhat in the what field.
      */
+    @UnsupportedAppUsage
     public void request(int senderWhat, Handler target, int targetWhat)
     {
         synchronized (this) {
@@ -96,6 +100,7 @@
     /**
      * Unregister for notifications for this senderWhat/target/targetWhat tuple.
      */
+    @UnsupportedAppUsage
     public void cancelRequest(int senderWhat, Handler target, int targetWhat)
     {
         synchronized (this) {
@@ -168,6 +173,7 @@
      * Send out msg.  Anyone who has registered via the request() method will be
      * sent the message.
      */
+    @UnsupportedAppUsage
     public void broadcast(Message msg)
     {
         synchronized (this) {
diff --git a/core/java/android/os/BugreportManager.java b/core/java/android/os/BugreportManager.java
index 672624c..f87abde 100644
--- a/core/java/android/os/BugreportManager.java
+++ b/core/java/android/os/BugreportManager.java
@@ -28,6 +28,8 @@
 
 import com.android.internal.util.Preconditions;
 
+import libcore.io.IoUtils;
+
 import java.io.FileDescriptor;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -124,6 +126,8 @@
      * <p>The bugreport artifacts will be copied over to the given file descriptors only if the
      * user consents to sharing with the calling app.
      *
+     * <p>{@link BugreportManager} takes ownership of {@code bugreportFd} and {@code screenshotFd}.
+     *
      * @param bugreportFd file to write the bugreport. This should be opened in write-only,
      *     append mode.
      * @param screenshotFd file to write the screenshot, if necessary. This should be opened
@@ -137,12 +141,13 @@
             @NonNull BugreportParams params,
             @NonNull @CallbackExecutor Executor executor,
             @NonNull BugreportCallback callback) {
-        Preconditions.checkNotNull(bugreportFd);
-        Preconditions.checkNotNull(params);
-        Preconditions.checkNotNull(executor);
-        Preconditions.checkNotNull(callback);
-        DumpstateListener dsListener = new DumpstateListener(executor, callback);
         try {
+            Preconditions.checkNotNull(bugreportFd);
+            Preconditions.checkNotNull(params);
+            Preconditions.checkNotNull(executor);
+            Preconditions.checkNotNull(callback);
+
+            DumpstateListener dsListener = new DumpstateListener(executor, callback);
             // Note: mBinder can get callingUid from the binder transaction.
             mBinder.startBugreport(-1 /* callingUid */,
                     mContext.getOpPackageName(),
@@ -152,6 +157,12 @@
                     params.getMode(), dsListener);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
+        } finally {
+            // We can close the file descriptors here because binder would have duped them.
+            IoUtils.closeQuietly(bugreportFd);
+            if (screenshotFd != null) {
+                IoUtils.closeQuietly(screenshotFd);
+            }
         }
     }
 
@@ -171,7 +182,7 @@
         private final Executor mExecutor;
         private final BugreportCallback mCallback;
 
-        DumpstateListener(Executor executor, @Nullable BugreportCallback callback) {
+        DumpstateListener(Executor executor, BugreportCallback callback) {
             mExecutor = executor;
             mCallback = callback;
         }
@@ -209,8 +220,6 @@
                 });
             } finally {
                 Binder.restoreCallingIdentity(identity);
-                // The bugreport has finished. Let's shutdown the service to minimize its footprint.
-                cancelBugreport();
             }
         }
 
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 0de4ddc..94c8b91 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -22,6 +22,7 @@
 import android.annotation.SuppressAutoDoc;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityThread;
 import android.app.Application;
 import android.content.Context;
@@ -321,6 +322,7 @@
         /**
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String[] ACTIVE_CODENAMES = "REL".equals(ALL_CODENAMES[0])
                 ? new String[0] : ALL_CODENAMES;
 
@@ -1202,6 +1204,7 @@
      * Returns true if we are running a debug build such as "user-debug" or "eng".
      * @hide
      */
+    @UnsupportedAppUsage
     public static final boolean IS_DEBUGGABLE =
             SystemProperties.getInt("ro.debuggable", 0) == 1;
 
@@ -1249,6 +1252,7 @@
         return TextUtils.isEmpty(propVal) ? null : propVal;
     }
 
+    @UnsupportedAppUsage
     private static String getString(String property) {
         return SystemProperties.get(property, UNKNOWN);
     }
@@ -1262,6 +1266,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private static long getLong(String property) {
         try {
             return Long.parseLong(SystemProperties.get(property));
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index 8e6a554..6432c24 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -17,6 +17,7 @@
 package android.os;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.util.ArrayMap;
 import android.util.Size;
 import android.util.SizeF;
@@ -173,6 +174,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static Bundle forPair(String key, String value) {
         Bundle b = new Bundle(1);
         b.putString(key, value);
@@ -229,6 +231,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public static Bundle setDefusable(Bundle bundle, boolean defusable) {
         if (bundle != null) {
             bundle.setDefusable(defusable);
@@ -303,6 +306,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getSize() {
         if (mParcelledData != null) {
             return mParcelledData.dataSize();
@@ -385,6 +389,7 @@
      * Filter values in Bundle to only basic types.
      * @hide
      */
+    @UnsupportedAppUsage
     public Bundle filterValues() {
         unparcel();
         Bundle bundle = this;
@@ -557,6 +562,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public void putParcelableList(String key, List<? extends Parcelable> value) {
         unparcel();
         mMap.put(key, value);
@@ -728,6 +734,7 @@
      * @deprecated
      * @hide This is the old name of the function.
      */
+    @UnsupportedAppUsage
     @Deprecated
     public void putIBinder(@Nullable String key, @Nullable IBinder value) {
         unparcel();
@@ -1180,6 +1187,7 @@
      * @deprecated
      * @hide This is the old name of the function.
      */
+    @UnsupportedAppUsage
     @Deprecated
     @Nullable
     public IBinder getIBinder(@Nullable String key) {
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index a395ed4..1213eea 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.app.AppGlobals;
 import android.content.Context;
 import android.util.Log;
@@ -87,6 +88,7 @@
     // set/cleared by waitForDebugger()
     private static volatile boolean mWaiting = false;
 
+    @UnsupportedAppUsage
     private Debug() {}
 
     /*
@@ -115,8 +117,10 @@
         public int dalvikPss;
         /** The proportional set size that is swappable for dalvik heap. */
         /** @hide We may want to expose this, eventually. */
+        @UnsupportedAppUsage
         public int dalvikSwappablePss;
         /** @hide The resident set size for dalvik heap.  (Without other Dalvik overhead.) */
+        @UnsupportedAppUsage
         public int dalvikRss;
         /** The private dirty pages used by dalvik heap. */
         public int dalvikPrivateDirty;
@@ -124,23 +128,29 @@
         public int dalvikSharedDirty;
         /** The private clean pages used by dalvik heap. */
         /** @hide We may want to expose this, eventually. */
+        @UnsupportedAppUsage
         public int dalvikPrivateClean;
         /** The shared clean pages used by dalvik heap. */
         /** @hide We may want to expose this, eventually. */
+        @UnsupportedAppUsage
         public int dalvikSharedClean;
         /** The dirty dalvik pages that have been swapped out. */
         /** @hide We may want to expose this, eventually. */
+        @UnsupportedAppUsage
         public int dalvikSwappedOut;
         /** The dirty dalvik pages that have been swapped out, proportional. */
         /** @hide We may want to expose this, eventually. */
+        @UnsupportedAppUsage
         public int dalvikSwappedOutPss;
 
         /** The proportional set size for the native heap. */
         public int nativePss;
         /** The proportional set size that is swappable for the native heap. */
         /** @hide We may want to expose this, eventually. */
+        @UnsupportedAppUsage
         public int nativeSwappablePss;
         /** @hide The resident set size for the native heap. */
+        @UnsupportedAppUsage
         public int nativeRss;
         /** The private dirty pages used by the native heap. */
         public int nativePrivateDirty;
@@ -148,23 +158,29 @@
         public int nativeSharedDirty;
         /** The private clean pages used by the native heap. */
         /** @hide We may want to expose this, eventually. */
+        @UnsupportedAppUsage
         public int nativePrivateClean;
         /** The shared clean pages used by the native heap. */
         /** @hide We may want to expose this, eventually. */
+        @UnsupportedAppUsage
         public int nativeSharedClean;
         /** The dirty native pages that have been swapped out. */
         /** @hide We may want to expose this, eventually. */
+        @UnsupportedAppUsage
         public int nativeSwappedOut;
         /** The dirty native pages that have been swapped out, proportional. */
         /** @hide We may want to expose this, eventually. */
+        @UnsupportedAppUsage
         public int nativeSwappedOutPss;
 
         /** The proportional set size for everything else. */
         public int otherPss;
         /** The proportional set size that is swappable for everything else. */
         /** @hide We may want to expose this, eventually. */
+        @UnsupportedAppUsage
         public int otherSwappablePss;
         /** @hide The resident set size for everything else. */
+        @UnsupportedAppUsage
         public int otherRss;
         /** The private dirty pages used by everything else. */
         public int otherPrivateDirty;
@@ -172,19 +188,24 @@
         public int otherSharedDirty;
         /** The private clean pages used by everything else. */
         /** @hide We may want to expose this, eventually. */
+        @UnsupportedAppUsage
         public int otherPrivateClean;
         /** The shared clean pages used by everything else. */
         /** @hide We may want to expose this, eventually. */
+        @UnsupportedAppUsage
         public int otherSharedClean;
         /** The dirty pages used by anyting else that have been swapped out. */
         /** @hide We may want to expose this, eventually. */
+        @UnsupportedAppUsage
         public int otherSwappedOut;
         /** The dirty pages used by anyting else that have been swapped out, proportional. */
         /** @hide We may want to expose this, eventually. */
+        @UnsupportedAppUsage
         public int otherSwappedOutPss;
 
         /** Whether the kernel reports proportional swap usage */
         /** @hide */
+        @UnsupportedAppUsage
         public boolean hasSwappedOutPss;
 
         /** @hide */
@@ -231,6 +252,7 @@
 
         // Needs to be declared here for the DVK_STAT ranges below.
         /** @hide */
+        @UnsupportedAppUsage
         public static final int NUM_OTHER_STATS = 17;
 
         // Dalvik subsections.
@@ -291,6 +313,7 @@
         public static final int OTHER_DVK_STAT_ART_END = OTHER_ART_BOOT - NUM_OTHER_STATS;
 
         /** @hide */
+        @UnsupportedAppUsage
         public static final int NUM_DVK_STATS = 14;
 
         /** @hide */
@@ -315,6 +338,7 @@
         /** @hide */
         public static final int OFFSET_SWAPPED_OUT_PSS = 8;
 
+        @UnsupportedAppUsage
         private int[] otherStats = new int[(NUM_OTHER_STATS+NUM_DVK_STATS)*NUM_CATEGORIES];
 
         public MemoryInfo() {
@@ -369,6 +393,7 @@
         /**
          * @hide Return total PSS memory usage in kB.
          */
+        @UnsupportedAppUsage
         public int getTotalUss() {
             return dalvikPrivateClean + dalvikPrivateDirty
                     + nativePrivateClean + nativePrivateDirty
@@ -435,6 +460,7 @@
         }
 
         /** @hide */
+        @UnsupportedAppUsage
         public int getOtherPss(int which) {
             return otherStats[which * NUM_CATEGORIES + OFFSET_PSS];
         }
@@ -450,11 +476,13 @@
         }
 
         /** @hide */
+        @UnsupportedAppUsage
         public int getOtherPrivateDirty(int which) {
             return otherStats[which * NUM_CATEGORIES + OFFSET_PRIVATE_DIRTY];
         }
 
         /** @hide */
+        @UnsupportedAppUsage
         public int getOtherSharedDirty(int which) {
             return otherStats[which * NUM_CATEGORIES + OFFSET_SHARED_DIRTY];
         }
@@ -465,6 +493,7 @@
         }
 
         /** @hide */
+        @UnsupportedAppUsage
         public int getOtherPrivate(int which) {
           return getOtherPrivateClean(which) + getOtherPrivateDirty(which);
         }
@@ -485,6 +514,7 @@
         }
 
         /** @hide */
+        @UnsupportedAppUsage
         public static String getOtherLabel(int which) {
             switch (which) {
                 case OTHER_DALVIK_OTHER: return "Dalvik Other";
@@ -662,6 +692,7 @@
          *    such thing as private clean for the Java Heap.
          * @hide
          */
+        @UnsupportedAppUsage
         public int getSummaryJavaHeap() {
             return dalvikPrivateDirty + getOtherPrivate(OTHER_ART);
         }
@@ -674,6 +705,7 @@
          *    such thing as private clean for the Native Heap.
          * @hide
          */
+        @UnsupportedAppUsage
         public int getSummaryNativeHeap() {
             return nativePrivateDirty;
         }
@@ -683,6 +715,7 @@
          * the application.
          * @hide
          */
+        @UnsupportedAppUsage
         public int getSummaryCode() {
             return getOtherPrivate(OTHER_SO)
               + getOtherPrivate(OTHER_JAR)
@@ -701,6 +734,7 @@
          *    such thing as private clean for the stack.
          * @hide
          */
+        @UnsupportedAppUsage
         public int getSummaryStack() {
             return getOtherPrivateDirty(OTHER_STACK);
         }
@@ -716,6 +750,7 @@
          *    memory into the System category.
          * @hide
          */
+        @UnsupportedAppUsage
         public int getSummaryGraphics() {
             return getOtherPrivate(OTHER_GL_DEV)
               + getOtherPrivate(OTHER_GRAPHICS)
@@ -727,6 +762,7 @@
          * accounted for.
          * @hide
          */
+        @UnsupportedAppUsage
         public int getSummaryPrivateOther() {
             return getTotalPrivateClean()
               + getTotalPrivateDirty()
@@ -743,6 +779,7 @@
          *  * Includes all shared memory.
          * @hide
          */
+        @UnsupportedAppUsage
         public int getSummarySystem() {
             return getTotalPss()
               - getTotalPrivateClean()
@@ -1782,6 +1819,7 @@
      * as the caller.
      * @hide
      */
+    @UnsupportedAppUsage
     public static native void getMemoryInfo(int pid, MemoryInfo memoryInfo);
 
     /**
@@ -1837,6 +1875,7 @@
      * as defined by MEMINFO_* offsets.
      * @hide
      */
+    @UnsupportedAppUsage
     public static native void getMemInfo(long[] outSizes);
 
     /**
@@ -1925,6 +1964,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static native void dumpNativeHeap(FileDescriptor fd);
 
     /**
@@ -1939,6 +1979,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static long countInstancesOfClass(Class cls) {
         return VMDebug.countInstancesOfClass(cls, true);
     }
@@ -1998,6 +2039,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final void dumpReferenceTables() {
         VMDebug.dumpReferenceTables();
     }
@@ -2364,6 +2406,7 @@
      * @return a string describing the call stack.
      * {@hide}
      */
+    @UnsupportedAppUsage
     public static String getCallers(final int depth) {
         final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
         StringBuffer sb = new StringBuffer();
@@ -2410,6 +2453,7 @@
      * @return a String describing the immediate caller of the calling method.
      * {@hide}
      */
+    @UnsupportedAppUsage
     public static String getCaller() {
         return getCaller(Thread.currentThread().getStackTrace(), 0);
     }
diff --git a/core/java/android/os/DropBoxManager.java b/core/java/android/os/DropBoxManager.java
index 1be7b6b..320f471 100644
--- a/core/java/android/os/DropBoxManager.java
+++ b/core/java/android/os/DropBoxManager.java
@@ -24,6 +24,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.util.Log;
 
@@ -50,6 +51,7 @@
     private static final String TAG = "DropBoxManager";
 
     private final Context mContext;
+    @UnsupportedAppUsage
     private final IDropBoxManagerService mService;
 
     /** Flag value: Entry's content was deleted to save space. */
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index fea69c0..cceb6ed 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.os.storage.StorageManager;
@@ -74,6 +75,7 @@
     private static final File DIR_PRODUCT_SERVICES_ROOT = getDirectory(ENV_PRODUCT_SERVICES_ROOT,
                                                            "/product_services");
 
+    @UnsupportedAppUsage
     private static UserEnvironment sCurrentUser;
     private static boolean sUserRequired;
 
@@ -82,6 +84,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public static void initForCurrentUser() {
         final int userId = UserHandle.myUserId();
         sCurrentUser = new UserEnvironment(userId);
@@ -91,10 +94,12 @@
     public static class UserEnvironment {
         private final int mUserId;
 
+        @UnsupportedAppUsage
         public UserEnvironment(int userId) {
             mUserId = userId;
         }
 
+        @UnsupportedAppUsage
         public File[] getExternalDirs() {
             final StorageVolume[] volumes = StorageManager.getVolumeList(mUserId,
                     StorageManager.FLAG_FOR_WRITE);
@@ -105,11 +110,13 @@
             return files;
         }
 
+        @UnsupportedAppUsage
         @Deprecated
         public File getExternalStorageDirectory() {
             return getExternalDirs()[0];
         }
 
+        @UnsupportedAppUsage
         @Deprecated
         public File getExternalStoragePublicDirectory(String type) {
             return buildExternalStoragePublicDirs(type)[0];
@@ -278,6 +285,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public static File getDataSystemDirectory() {
         return new File(getDataDirectory(), "system");
     }
@@ -553,11 +561,13 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public static File getLegacyExternalStorageDirectory() {
         return new File(System.getenv(ENV_EXTERNAL_STORAGE));
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public static File getLegacyExternalStorageObbDirectory() {
         return buildPath(getLegacyExternalStorageDirectory(), DIR_ANDROID, DIR_OBB);
     }
@@ -839,6 +849,7 @@
      * Returns the path for android-specific data on the SD card.
      * @hide
      */
+    @UnsupportedAppUsage
     public static File[] buildExternalStorageAndroidDataDirs() {
         throwIfUserRequired();
         return sCurrentUser.buildExternalStorageAndroidDataDirs();
@@ -848,6 +859,7 @@
      * Generates the raw path to an application's data
      * @hide
      */
+    @UnsupportedAppUsage
     public static File[] buildExternalStorageAppDataDirs(String packageName) {
         throwIfUserRequired();
         return sCurrentUser.buildExternalStorageAppDataDirs(packageName);
@@ -857,6 +869,7 @@
      * Generates the raw path to an application's media
      * @hide
      */
+    @UnsupportedAppUsage
     public static File[] buildExternalStorageAppMediaDirs(String packageName) {
         throwIfUserRequired();
         return sCurrentUser.buildExternalStorageAppMediaDirs(packageName);
@@ -866,6 +879,7 @@
      * Generates the raw path to an application's OBB files
      * @hide
      */
+    @UnsupportedAppUsage
     public static File[] buildExternalStorageAppObbDirs(String packageName) {
         throwIfUserRequired();
         return sCurrentUser.buildExternalStorageAppObbDirs(packageName);
@@ -875,6 +889,7 @@
      * Generates the path to an application's files.
      * @hide
      */
+    @UnsupportedAppUsage
     public static File[] buildExternalStorageAppFilesDirs(String packageName) {
         throwIfUserRequired();
         return sCurrentUser.buildExternalStorageAppFilesDirs(packageName);
@@ -884,6 +899,7 @@
      * Generates the path to an application's cache.
      * @hide
      */
+    @UnsupportedAppUsage
     public static File[] buildExternalStorageAppCacheDirs(String packageName) {
         throwIfUserRequired();
         return sCurrentUser.buildExternalStorageAppCacheDirs(packageName);
@@ -1118,6 +1134,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static File[] buildPaths(File[] base, String... segments) {
         File[] result = new File[base.length];
         for (int i = 0; i < base.length; i++) {
@@ -1157,6 +1174,7 @@
      * @deprecated disabled now that FUSE has been replaced by sdcardfs
      * @hide
      */
+    @UnsupportedAppUsage
     @Deprecated
     public static File maybeTranslateEmulatedPathToInternal(File path) {
         return StorageManager.maybeTranslateEmulatedPathToInternal(path);
diff --git a/core/java/android/os/FileObserver.java b/core/java/android/os/FileObserver.java
index 330bde5..4d9ebc2 100644
--- a/core/java/android/os/FileObserver.java
+++ b/core/java/android/os/FileObserver.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.util.Log;
 
 import java.io.File;
@@ -141,6 +142,7 @@
             stopWatching(m_fd, descriptors);
         }
 
+        @UnsupportedAppUsage
         public void onEvent(int wfd, @NotifyEventType int mask, String path) {
             // look up our observer, fixing up the map if necessary...
             FileObserver observer = null;
@@ -172,6 +174,7 @@
         private native void stopWatching(int fd, int[] wfds);
     }
 
+    @UnsupportedAppUsage
     private static ObserverThread s_observerThread;
 
     static {
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 316572c..f789b72 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -40,6 +40,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ContentResolver;
 import android.provider.DocumentsContract.Document;
 import android.system.ErrnoException;
@@ -103,6 +104,7 @@
     /** {@hide} */ public static final int S_IWOTH = 00002;
     /** {@hide} */ public static final int S_IXOTH = 00001;
 
+    @UnsupportedAppUsage
     private FileUtils() {
     }
 
@@ -135,6 +137,7 @@
      * @return 0 on success, otherwise errno.
      * @hide
      */
+    @UnsupportedAppUsage
     public static int setPermissions(File path, int mode, int uid, int gid) {
         return setPermissions(path.getAbsolutePath(), mode, uid, gid);
     }
@@ -148,6 +151,7 @@
      * @return 0 on success, otherwise errno.
      * @hide
      */
+    @UnsupportedAppUsage
     public static int setPermissions(String path, int mode, int uid, int gid) {
         try {
             Os.chmod(path, mode);
@@ -177,6 +181,7 @@
      * @return 0 on success, otherwise errno.
      * @hide
      */
+    @UnsupportedAppUsage
     public static int setPermissions(FileDescriptor fd, int mode, int uid, int gid) {
         try {
             Os.fchmod(fd, mode);
@@ -233,6 +238,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean sync(FileOutputStream stream) {
         try {
             if (stream != null) {
@@ -248,6 +254,7 @@
      * @deprecated use {@link #copy(File, File)} instead.
      * @hide
      */
+    @UnsupportedAppUsage
     @Deprecated
     public static boolean copyFile(File srcFile, File destFile) {
         try {
@@ -273,6 +280,7 @@
      * @deprecated use {@link #copy(InputStream, OutputStream)} instead.
      * @hide
      */
+    @UnsupportedAppUsage
     @Deprecated
     public static boolean copyToFile(InputStream inputStream, File destFile) {
         try {
@@ -584,6 +592,7 @@
      * @param file  The file to check
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isFilenameSafe(File file) {
         // Note, we check whether it matches what's known to be safe,
         // rather than what's known to be unsafe.  Non-ASCII, control
@@ -600,6 +609,7 @@
      * @throws IOException if something goes wrong reading the file
      * @hide
      */
+    @UnsupportedAppUsage
     public static String readTextFile(File file, int max, String ellipsis) throws IOException {
         InputStream input = new FileInputStream(file);
         // wrapping a BufferedInputStream around it because when reading /proc with unbuffered
@@ -654,6 +664,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public static void stringToFile(File file, String string) throws IOException {
         stringToFile(file.getAbsolutePath(), string);
     }
@@ -687,6 +698,7 @@
      * @throws IOException
      * @hide
      */
+    @UnsupportedAppUsage
     public static void stringToFile(String filename, String string) throws IOException {
         bytesToFile(filename, string.getBytes(StandardCharsets.UTF_8));
     }
@@ -701,6 +713,7 @@
      *             to its potential for collision.
      * @hide
      */
+    @UnsupportedAppUsage
     @Deprecated
     public static long checksumCrc32(File file) throws FileNotFoundException, IOException {
         CRC32 checkSummer = new CRC32();
@@ -783,6 +796,7 @@
      * @return if any files were deleted.
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean deleteOlderFiles(File dir, int minCount, long minAgeMs) {
         if (minCount < 0 || minAgeMs < 0) {
             throw new IllegalArgumentException("Constraints must be positive or 0");
@@ -891,6 +905,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public static boolean deleteContents(File dir) {
         File[] files = dir.listFiles();
         boolean success = true;
diff --git a/core/java/android/os/Handler.java b/core/java/android/os/Handler.java
index a039742..9af9eda 100644
--- a/core/java/android/os/Handler.java
+++ b/core/java/android/os/Handler.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.util.Log;
 import android.util.Printer;
 
@@ -168,6 +169,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public Handler(boolean async) {
         this(null, async);
     }
@@ -229,6 +231,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
         mLooper = looper;
         mQueue = looper.mQueue;
@@ -274,6 +277,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     @NonNull
     public static Handler getMain() {
         if (MAIN_THREAD_HANDLER == null) {
@@ -843,6 +847,7 @@
         + "}";
     }
 
+    @UnsupportedAppUsage
     final IMessenger getIMessenger() {
         synchronized (mQueue) {
             if (mMessenger != null) {
@@ -866,6 +871,7 @@
         return m;
     }
 
+    @UnsupportedAppUsage
     private static Message getPostMessage(Runnable r, Object token) {
         Message m = Message.obtain();
         m.obj = token;
@@ -877,10 +883,13 @@
         message.callback.run();
     }
 
+    @UnsupportedAppUsage
     final Looper mLooper;
     final MessageQueue mQueue;
+    @UnsupportedAppUsage
     final Callback mCallback;
     final boolean mAsynchronous;
+    @UnsupportedAppUsage
     IMessenger mMessenger;
 
     private static final class BlockingRunnable implements Runnable {
diff --git a/core/java/android/os/HwBinder.java b/core/java/android/os/HwBinder.java
index 9e3e83e..09afdc7 100644
--- a/core/java/android/os/HwBinder.java
+++ b/core/java/android/os/HwBinder.java
@@ -18,6 +18,7 @@
 
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 
 import libcore.util.NativeAllocationRegistry;
 
@@ -151,6 +152,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static void reportSyspropChanged() {
         native_report_sysprop_change();
     }
diff --git a/core/java/android/os/HwParcel.java b/core/java/android/os/HwParcel.java
index dc640c9..cfb582e 100644
--- a/core/java/android/os/HwParcel.java
+++ b/core/java/android/os/HwParcel.java
@@ -21,6 +21,7 @@
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 
 import libcore.util.NativeAllocationRegistry;
 
@@ -49,6 +50,7 @@
 
     private static final NativeAllocationRegistry sNativeRegistry;
 
+    @UnsupportedAppUsage
     private HwParcel(boolean allocate) {
         native_setup(allocate);
 
diff --git a/core/java/android/os/HwRemoteBinder.java b/core/java/android/os/HwRemoteBinder.java
index a07e42c..72ec958 100644
--- a/core/java/android/os/HwRemoteBinder.java
+++ b/core/java/android/os/HwRemoteBinder.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import android.annotation.UnsupportedAppUsage;
 import libcore.util.NativeAllocationRegistry;
 
 /** @hide */
@@ -24,6 +25,7 @@
 
     private static final NativeAllocationRegistry sNativeRegistry;
 
+    @UnsupportedAppUsage
     public HwRemoteBinder() {
         native_setup_empty();
 
diff --git a/core/java/android/os/IBinder.java b/core/java/android/os/IBinder.java
index e74b0bb..83f88ad 100644
--- a/core/java/android/os/IBinder.java
+++ b/core/java/android/os/IBinder.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 
 import java.io.FileDescriptor;
 
@@ -149,6 +150,7 @@
     int LIKE_TRANSACTION   = ('_'<<24)|('L'<<16)|('I'<<8)|'K';
 
     /** @hide */
+    @UnsupportedAppUsage
     int SYSPROPS_TRANSACTION = ('_'<<24)|('S'<<16)|('P'<<8)|'R';
 
     /**
diff --git a/core/java/android/os/IDeviceIdleController.aidl b/core/java/android/os/IDeviceIdleController.aidl
index fe17c6b..aa255bf 100644
--- a/core/java/android/os/IDeviceIdleController.aidl
+++ b/core/java/android/os/IDeviceIdleController.aidl
@@ -39,6 +39,7 @@
     int[] getAppIdTempWhitelist();
     boolean isPowerSaveWhitelistExceptIdleApp(String name);
     boolean isPowerSaveWhitelistApp(String name);
+    @UnsupportedAppUsage
     void addPowerSaveTempWhitelistApp(String name, long duration, int userId, String reason);
     long addPowerSaveTempWhitelistAppForMms(String name, int userId, String reason);
     long addPowerSaveTempWhitelistAppForSms(String name, int userId, String reason);
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 8ced722..f62a999 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -38,11 +38,13 @@
     /**
      * Register an observer to receive events.
      */
+    @UnsupportedAppUsage
     void registerObserver(INetworkManagementEventObserver obs);
 
     /**
      * Unregister an observer from receiving events.
      */
+    @UnsupportedAppUsage
     void unregisterObserver(INetworkManagementEventObserver obs);
 
     /**
@@ -54,16 +56,19 @@
      * Retrieves the specified interface config
      *
      */
+    @UnsupportedAppUsage
     InterfaceConfiguration getInterfaceConfig(String iface);
 
     /**
      * Sets the configuration of the specified interface
      */
+    @UnsupportedAppUsage
     void setInterfaceConfig(String iface, in InterfaceConfiguration cfg);
 
     /**
      * Clear all IP addresses on the specified interface
      */
+    @UnsupportedAppUsage
     void clearInterfaceAddresses(String iface);
 
     /**
@@ -79,22 +84,26 @@
     /**
      * Set interface IPv6 privacy extensions
      */
+    @UnsupportedAppUsage
     void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable);
 
     /**
      * Disable IPv6 on an interface
      */
+    @UnsupportedAppUsage
     void disableIpv6(String iface);
 
     /**
      * Enable IPv6 on an interface
      */
+    @UnsupportedAppUsage
     void enableIpv6(String iface);
 
     /**
      * Set IPv6 autoconf address generation mode.
      * This is a no-op if an unsupported mode is requested.
      */
+    @UnsupportedAppUsage
     void setIPv6AddrGenMode(String iface, int mode);
 
     /**
@@ -124,37 +133,44 @@
     /**
      * Returns true if IP forwarding is enabled
      */
+    @UnsupportedAppUsage
     boolean getIpForwardingEnabled();
 
     /**
      * Enables/Disables IP Forwarding
      */
+    @UnsupportedAppUsage
     void setIpForwardingEnabled(boolean enabled);
 
     /**
      * Start tethering services with the specified dhcp server range
      * arg is a set of start end pairs defining the ranges.
      */
+    @UnsupportedAppUsage
     void startTethering(in String[] dhcpRanges);
 
     /**
      * Stop currently running tethering services
      */
+    @UnsupportedAppUsage
     void stopTethering();
 
     /**
      * Returns true if tethering services are started
      */
+    @UnsupportedAppUsage
     boolean isTetheringStarted();
 
     /**
      * Tethers the specified interface
      */
+    @UnsupportedAppUsage
     void tetherInterface(String iface);
 
     /**
      * Untethers the specified interface
      */
+    @UnsupportedAppUsage
     void untetherInterface(String iface);
 
     /**
@@ -189,11 +205,13 @@
      *  The address and netmask of the external interface is used for
      *  the NAT'ed network.
      */
+    @UnsupportedAppUsage
     void enableNat(String internalInterface, String externalInterface);
 
     /**
      *  Disables Network Address Translation between two interfaces.
      */
+    @UnsupportedAppUsage
     void disableNat(String internalInterface, String externalInterface);
 
     /**
@@ -311,6 +329,7 @@
     /**
      * Return status of bandwidth control module.
      */
+    @UnsupportedAppUsage
     boolean isBandwidthControlEnabled();
 
     /**
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 483c41a..4233340 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -41,14 +41,17 @@
     void updateWakeLockWorkSource(IBinder lock, in WorkSource ws, String historyTag);
     boolean isWakeLockLevelSupported(int level);
 
+    @UnsupportedAppUsage
     void userActivity(long time, int event, int flags);
     void wakeUp(long time, int reason, String details, String opPackageName);
+    @UnsupportedAppUsage
     void goToSleep(long time, int reason, int flags);
     void nap(long time);
+    @UnsupportedAppUsage
     boolean isInteractive();
     boolean isPowerSaveMode();
     PowerSaveState getPowerSaveState(int serviceType);
-    boolean setPowerSaveMode(boolean mode);
+    boolean setPowerSaveModeEnabled(boolean mode);
     boolean setDynamicPowerSavings(boolean dynamicPowerSavingsEnabled, int disableThreshold);
     boolean setAdaptivePowerSavePolicy(in BatterySaverPolicyConfig config);
     boolean setAdaptivePowerSaveEnabled(boolean enabled);
@@ -56,6 +59,7 @@
     boolean isDeviceIdleMode();
     boolean isLightDeviceIdleMode();
 
+    @UnsupportedAppUsage
     void reboot(boolean confirm, String reason, boolean wait);
     void rebootSafeMode(boolean confirm, boolean wait);
     void shutdown(boolean confirm, String reason, boolean wait);
diff --git a/core/java/android/os/IRemoteCallback.aidl b/core/java/android/os/IRemoteCallback.aidl
index f0c6c73..71f3b06 100644
--- a/core/java/android/os/IRemoteCallback.aidl
+++ b/core/java/android/os/IRemoteCallback.aidl
@@ -21,5 +21,6 @@
 
 /** @hide */
 oneway interface IRemoteCallback {
+    @UnsupportedAppUsage
     void sendResult(in Bundle data);
 }
diff --git a/core/java/android/os/IServiceManager.java b/core/java/android/os/IServiceManager.java
index 89bf7b9..bc0690d 100644
--- a/core/java/android/os/IServiceManager.java
+++ b/core/java/android/os/IServiceManager.java
@@ -16,6 +16,8 @@
 
 package android.os;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * Basic interface for finding and publishing system services.
  *
@@ -33,12 +35,14 @@
      * service manager.  Blocks for a few seconds waiting for it to be
      * published if it does not already exist.
      */
+    @UnsupportedAppUsage
     IBinder getService(String name) throws RemoteException;
 
     /**
      * Retrieve an existing service called @a name from the
      * service manager.  Non-blocking.
      */
+    @UnsupportedAppUsage
     IBinder checkService(String name) throws RemoteException;
 
     /**
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 3017f25..63641e5 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -59,6 +59,7 @@
     boolean canAddMoreManagedProfiles(int userHandle, boolean allowedToRemoveOne);
     UserInfo getProfileParent(int userHandle);
     boolean isSameProfileGroup(int userHandle, int otherUserHandle);
+    @UnsupportedAppUsage
     UserInfo getUserInfo(int userHandle);
     String getUserAccount(int userHandle);
     void setUserAccount(int userHandle, String accountName);
@@ -100,6 +101,7 @@
     boolean isUserNameSet(int userHandle);
     boolean hasRestrictedProfiles();
     boolean requestQuietModeEnabled(String callingPackage, boolean enableQuietMode, int userHandle, in IntentSender target);
+    String getUserName();
     long getUserStartRealtime();
     long getUserUnlockRealtime();
 }
diff --git a/core/java/android/os/LocaleList.java b/core/java/android/os/LocaleList.java
index a9da080..351df1b 100644
--- a/core/java/android/os/LocaleList.java
+++ b/core/java/android/os/LocaleList.java
@@ -21,6 +21,7 @@
 import android.annotation.Nullable;
 import android.annotation.Size;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.LocaleProto;
 import android.icu.util.ULocale;
 import android.util.proto.ProtoOutputStream;
@@ -568,6 +569,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public static void setDefault(@NonNull @Size(min=1) LocaleList locales, int localeIndex) {
         if (locales == null) {
             throw new NullPointerException("locales is null");
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index a8d1215..3222fc4 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.util.Log;
 import android.util.Printer;
 import android.util.Slog;
@@ -67,13 +68,17 @@
     private static final String TAG = "Looper";
 
     // sThreadLocal.get() will return null unless you've called prepare().
+    @UnsupportedAppUsage
     static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
+    @UnsupportedAppUsage
     private static Looper sMainLooper;  // guarded by Looper.class
     private static Observer sObserver;
 
+    @UnsupportedAppUsage
     final MessageQueue mQueue;
     final Thread mThread;
 
+    @UnsupportedAppUsage
     private Printer mLogging;
     private long mTraceTag;
 
@@ -315,6 +320,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public void setTraceTag(long traceTag) {
         mTraceTag = traceTag;
     }
diff --git a/core/java/android/os/MemoryFile.java b/core/java/android/os/MemoryFile.java
index ff3258f..5a1e3d4 100644
--- a/core/java/android/os/MemoryFile.java
+++ b/core/java/android/os/MemoryFile.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import android.annotation.UnsupportedAppUsage;
 import android.system.ErrnoException;
 
 import java.io.FileDescriptor;
@@ -40,7 +41,9 @@
     private static String TAG = "MemoryFile";
 
     // Returns 'true' if purged, 'false' otherwise
+    @UnsupportedAppUsage
     private static native boolean native_pin(FileDescriptor fd, boolean pin) throws IOException;
+    @UnsupportedAppUsage
     private static native int native_get_size(FileDescriptor fd) throws IOException;
 
     private SharedMemory mSharedMemory;
@@ -79,6 +82,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     void deactivate() {
         if (mMapping != null) {
             SharedMemory.unmap(mMapping);
@@ -222,6 +226,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public FileDescriptor getFileDescriptor() throws IOException {
         return mSharedMemory.getFileDescriptor();
     }
@@ -234,6 +239,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static int getSize(FileDescriptor fd) throws IOException {
         return native_get_size(fd);
     }
diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java
index 317579e..6055bef 100644
--- a/core/java/android/os/Message.java
+++ b/core/java/android/os/Message.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import android.annotation.UnsupportedAppUsage;
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
 
@@ -111,6 +112,7 @@
     /** Flags to clear in the copyFrom method */
     /*package*/ static final int FLAGS_TO_CLEAR_ON_COPY_FROM = FLAG_IN_USE;
 
+    @UnsupportedAppUsage
     /*package*/ int flags;
 
     /**
@@ -118,16 +120,20 @@
      * {@link SystemClock#uptimeMillis}.
      * @hide Only for use within the tests.
      */
+    @UnsupportedAppUsage
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
     public long when;
 
     /*package*/ Bundle data;
 
+    @UnsupportedAppUsage
     /*package*/ Handler target;
 
+    @UnsupportedAppUsage
     /*package*/ Runnable callback;
 
     // sometimes we store linked lists of these things
+    @UnsupportedAppUsage
     /*package*/ Message next;
 
 
@@ -314,6 +320,7 @@
      * Recycles a Message that may be in-use.
      * Used internally by the MessageQueue and Looper when disposing of queued Messages.
      */
+    @UnsupportedAppUsage
     void recycleUnchecked() {
         // Mark the message as in use while it remains in the recycled object pool.
         // Clear out all other details.
@@ -397,6 +404,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public Message setCallback(Runnable r) {
         callback = r;
         return this;
@@ -510,6 +518,7 @@
         return ((flags & FLAG_IN_USE) == FLAG_IN_USE);
     }
 
+    @UnsupportedAppUsage
     /*package*/ void markInUse() {
         flags |= FLAG_IN_USE;
     }
@@ -524,6 +533,7 @@
         return toString(SystemClock.uptimeMillis());
     }
 
+    @UnsupportedAppUsage
     String toString(long now) {
         StringBuilder b = new StringBuilder();
         b.append("{ when=");
diff --git a/core/java/android/os/MessageQueue.java b/core/java/android/os/MessageQueue.java
index 7c2ecc5..c5f1698 100644
--- a/core/java/android/os/MessageQueue.java
+++ b/core/java/android/os/MessageQueue.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.MessageQueueProto;
 import android.util.Log;
 import android.util.Printer;
@@ -43,12 +44,16 @@
     private static final boolean DEBUG = false;
 
     // True if the message queue can be quit.
+    @UnsupportedAppUsage
     private final boolean mQuitAllowed;
 
+    @UnsupportedAppUsage
     @SuppressWarnings("unused")
     private long mPtr; // used by native code
 
+    @UnsupportedAppUsage
     Message mMessages;
+    @UnsupportedAppUsage
     private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();
     private SparseArray<FileDescriptorRecord> mFileDescriptorRecords;
     private IdleHandler[] mPendingIdleHandlers;
@@ -59,10 +64,12 @@
 
     // The next barrier token.
     // Barriers are indicated by messages with a null target whose arg1 field carries the token.
+    @UnsupportedAppUsage
     private int mNextBarrierToken;
 
     private native static long nativeInit();
     private native static void nativeDestroy(long ptr);
+    @UnsupportedAppUsage
     private native void nativePollOnce(long ptr, int timeoutMillis); /*non-static for callbacks*/
     private native static void nativeWake(long ptr);
     private native static boolean nativeIsPolling(long ptr);
@@ -260,6 +267,7 @@
     }
 
     // Called from native code.
+    @UnsupportedAppUsage
     private int dispatchEvents(int fd, int events) {
         // Get the file descriptor record and any state that might change.
         final FileDescriptorRecord record;
@@ -308,6 +316,7 @@
         return newWatchedEvents;
     }
 
+    @UnsupportedAppUsage
     Message next() {
         // Return here if the message loop has already quit and been disposed.
         // This can happen if the application tries to restart a looper after quit
@@ -607,6 +616,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     boolean hasMessages(Handler h, Runnable r, Object object) {
         if (h == null) {
             return false;
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 79e9ba5..de963c9 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -197,6 +198,7 @@
     private static final boolean DEBUG_ARRAY_MAP = false;
     private static final String TAG = "Parcel";
 
+    @UnsupportedAppUsage
     @SuppressWarnings({"UnusedDeclaration"})
     private long mNativePtr; // used by native code
 
@@ -453,9 +455,11 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static native long getGlobalAllocSize();
 
     /** @hide */
+    @UnsupportedAppUsage
     public static native long getGlobalAllocCount();
 
     /**
@@ -679,6 +683,7 @@
      * {@hide}
      * {@SystemApi}
      */
+    @UnsupportedAppUsage
     public final void writeBlob(@Nullable byte[] b) {
         writeBlob(b, 0, (b != null) ? b.length : 0);
     }
@@ -768,6 +773,7 @@
      * growing dataCapacity() if needed.
      * @hide
      */
+    @UnsupportedAppUsage
     public final void writeCharSequence(@Nullable CharSequence val) {
         TextUtils.writeToParcel(val, this, 0);
     }
@@ -929,6 +935,7 @@
     /**
      * @hide For testing only.
      */
+    @UnsupportedAppUsage
     public void writeArrayMap(@Nullable ArrayMap<String, Object> val) {
         writeArrayMapInternal(val);
     }
@@ -967,6 +974,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void writeArraySet(@Nullable ArraySet<? extends Object> val) {
         final int size = (val != null) ? val.size() : -1;
         writeInt(size);
@@ -1793,6 +1801,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public final void writeParcelableCreator(@NonNull Parcelable p) {
         String name = p.getClass().getName();
         writeString(name);
@@ -1991,6 +2000,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public final int readExceptionCode() {
         int code = readInt();
         if (code == EX_HAS_REPLY_HEADER) {
@@ -2137,6 +2147,7 @@
      * Read a CharSequence value from the parcel at the current dataPosition().
      * @hide
      */
+    @UnsupportedAppUsage
     @Nullable
     public final CharSequence readCharSequence() {
         return TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(this);
@@ -2158,6 +2169,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public final FileDescriptor readRawFileDescriptor() {
         return nativeReadFileDescriptor(mNativePtr);
     }
@@ -2349,6 +2361,7 @@
      * {@hide}
      * {@SystemApi}
      */
+    @UnsupportedAppUsage
     @Nullable
     public final byte[] readBlob() {
         return nativeReadBlob(mNativePtr);
@@ -2358,6 +2371,7 @@
      * Read and return a String[] object from the parcel.
      * {@hide}
      */
+    @UnsupportedAppUsage
     @Nullable
     public final String[] readStringArray() {
         String[] array = null;
@@ -2958,6 +2972,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     @SuppressWarnings("unchecked")
     @Nullable
     public final <T extends Parcelable> T readCreator(@NonNull Parcelable.Creator<?> creator,
@@ -2971,6 +2986,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     @Nullable
     public final Parcelable.Creator<?> readParcelableCreator(@Nullable ClassLoader loader) {
         String name = readString();
@@ -3253,6 +3269,7 @@
     /**
      * @hide For testing only.
      */
+    @UnsupportedAppUsage
     public void readArrayMap(@NonNull ArrayMap outVal, @Nullable ClassLoader loader) {
         final int N = readInt();
         if (N < 0) {
@@ -3268,6 +3285,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public @Nullable ArraySet<? extends Object> readArraySet(@Nullable ClassLoader loader) {
         final int size = readInt();
         if (size < 0) {
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 7a8727c..8355e08 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -32,6 +32,7 @@
 import static android.system.OsConstants.S_IWOTH;
 
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.BroadcastReceiver;
 import android.content.ContentProvider;
 import android.os.MessageQueue.OnFileDescriptorEventListener;
@@ -178,6 +179,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public ParcelFileDescriptor(FileDescriptor fd) {
         this(fd, null);
     }
@@ -372,7 +374,11 @@
     /**
      * Take ownership of a raw native fd in to a new ParcelFileDescriptor.
      * The returned ParcelFileDescriptor now owns the given fd, and will be
-     * responsible for closing it.  You must not close the fd yourself.
+     * responsible for closing it.
+     * <p>
+     * <strong>WARNING:</strong> You must not close the fd yourself after
+     * this call, and ownership of the file descriptor must have been
+     * released prior to the call to this function.
      *
      * @param fd The native fd that the ParcelFileDescriptor should adopt.
      *
@@ -391,6 +397,16 @@
      * ParcelFileDescriptor holds a dup of the original FileDescriptor in
      * the Socket, so you must still close the Socket as well as the new
      * ParcelFileDescriptor.
+     * <p>
+     * <strong>WARNING:</strong> Prior to API level 29, this function would not
+     * actually dup the Socket's FileDescriptor, and would take a
+     * reference to the its internal FileDescriptor instead. If the Socket
+     * gets garbage collected before the ParcelFileDescriptor, this may
+     * lead to the ParcelFileDescriptor being unexpectedly closed. To avoid
+     * this, the following pattern can be used:
+     * <pre>{@code
+     *    ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket).dup();
+     * }</pre>
      *
      * @param socket The Socket whose FileDescriptor is used to create
      *               a new ParcelFileDescriptor.
@@ -414,6 +430,16 @@
      * new ParcelFileDescriptor holds a dup of the original FileDescriptor in
      * the DatagramSocket, so you must still close the DatagramSocket as well
      * as the new ParcelFileDescriptor.
+     * <p>
+     * <strong>WARNING:</strong> Prior to API level 29, this function would not
+     * actually dup the DatagramSocket's FileDescriptor, and would take a
+     * reference to the its internal FileDescriptor instead. If the DatagramSocket
+     * gets garbage collected before the ParcelFileDescriptor, this may
+     * lead to the ParcelFileDescriptor being unexpectedly closed. To avoid
+     * this, the following pattern can be used:
+     * <pre>{@code
+     *    ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket).dup();
+     * }</pre>
      *
      * @param datagramSocket The DatagramSocket whose FileDescriptor is used
      *               to create a new ParcelFileDescriptor.
@@ -550,6 +576,7 @@
      * @return A ParcelFileDescriptor.
      * @throws IOException if there is an error while creating the shared memory area.
      */
+    @UnsupportedAppUsage
     @Deprecated
     public static ParcelFileDescriptor fromData(byte[] data, String name) throws IOException {
         if (data == null) return null;
@@ -635,6 +662,7 @@
      * and I really don't think we want it to be public.
      * @hide
      */
+    @UnsupportedAppUsage
     public long seekTo(long pos) throws IOException {
         if (mWrapped != null) {
             return mWrapped.seekTo(pos);
@@ -651,6 +679,9 @@
      * Return the native fd int for this ParcelFileDescriptor.  The
      * ParcelFileDescriptor still owns the fd, and it still must be closed
      * through this API.
+     * <p>
+     * <strong>WARNING:</strong> Do not call close on the return value of this
+     * function or pass it to a function that assumes ownership of the fd.
      */
     public int getFd() {
         if (mWrapped != null) {
diff --git a/core/java/android/os/ParcelableParcel.java b/core/java/android/os/ParcelableParcel.java
index 5bbe6488..61f3968 100644
--- a/core/java/android/os/ParcelableParcel.java
+++ b/core/java/android/os/ParcelableParcel.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import android.annotation.UnsupportedAppUsage;
 import android.util.MathUtils;
 
 /**
@@ -26,6 +27,7 @@
     final Parcel mParcel;
     final ClassLoader mClassLoader;
 
+    @UnsupportedAppUsage
     public ParcelableParcel(ClassLoader loader) {
         mParcel = Parcel.obtain();
         mClassLoader = loader;
@@ -44,11 +46,13 @@
         mParcel.appendFrom(src, pos, size);
     }
 
+    @UnsupportedAppUsage
     public Parcel getParcel() {
         mParcel.setDataPosition(0);
         return mParcel;
     }
 
+    @UnsupportedAppUsage
     public ClassLoader getClassLoader() {
         return mClassLoader;
     }
@@ -64,6 +68,7 @@
         dest.appendFrom(mParcel, 0, mParcel.dataSize());
     }
 
+    @UnsupportedAppUsage
     public static final Parcelable.ClassLoaderCreator<ParcelableParcel> CREATOR
             = new Parcelable.ClassLoaderCreator<ParcelableParcel>() {
         public ParcelableParcel createFromParcel(Parcel in) {
diff --git a/core/java/android/os/PerformanceCollector.java b/core/java/android/os/PerformanceCollector.java
index be1cf6d..33c86b8 100644
--- a/core/java/android/os/PerformanceCollector.java
+++ b/core/java/android/os/PerformanceCollector.java
@@ -17,6 +17,7 @@
 package android.os;
 
 
+import android.annotation.UnsupportedAppUsage;
 import java.util.ArrayList;
 
 /**
@@ -285,6 +286,7 @@
     private long mCpuTime;
     private long mExecTime;
 
+    @UnsupportedAppUsage
     public PerformanceCollector() {
     }
 
@@ -302,6 +304,7 @@
      * @param label description of code block between beginSnapshot and
      *              endSnapshot, used to label output
      */
+    @UnsupportedAppUsage
     public void beginSnapshot(String label) {
         if (mPerfWriter != null)
             mPerfWriter.writeBeginSnapshot(label);
@@ -346,6 +349,7 @@
      *         <li>{@link #METRIC_KEY_OTHER_SHARED_DIRTY other_shared_dirty}
      *         </ul>
      */
+    @UnsupportedAppUsage
     public Bundle endSnapshot() {
         endPerformanceSnapshot();
         if (mPerfWriter != null)
@@ -359,6 +363,7 @@
      * @param label description of code block between startTiming and
      *        stopTiming, used to label output
      */
+    @UnsupportedAppUsage
     public void startTiming(String label) {
         if (mPerfWriter != null)
             mPerfWriter.writeStartTiming(label);
@@ -408,6 +413,7 @@
      *         between calls to startTiming and stopTiming. List of iterations
      *         is keyed by {@link #METRIC_KEY_ITERATIONS iterations}.
      */
+    @UnsupportedAppUsage
     public Bundle stopTiming(String label) {
         addIteration(label);
         if (mPerfWriter != null)
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 728b215..36bae2d 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -25,6 +25,7 @@
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.service.dreams.Sandman;
 import android.util.ArrayMap;
@@ -290,6 +291,7 @@
      * Brightness value for fully on.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int BRIGHTNESS_ON = 255;
 
     /**
@@ -384,6 +386,7 @@
      * Go to sleep reason code: Going to sleep due to a screen timeout.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int GO_TO_SLEEP_REASON_TIMEOUT = 2;
 
     /**
@@ -805,6 +808,7 @@
     }
 
     final Context mContext;
+    @UnsupportedAppUsage
     final IPowerManager mService;
     final Handler mHandler;
 
@@ -829,6 +833,7 @@
      * this is the minimum value that can be set by the user.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getMinimumScreenBrightnessSetting() {
         return mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_screenBrightnessSettingMinimum);
@@ -840,6 +845,7 @@
      * this is the maximum value that can be set by the user.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getMaximumScreenBrightnessSetting() {
         return mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_screenBrightnessSettingMaximum);
@@ -849,6 +855,7 @@
      * Gets the default screen brightness setting.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getDefaultScreenBrightnessSetting() {
         return mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_screenBrightnessSettingDefault);
@@ -963,6 +970,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static void validateWakeLockParameters(int levelAndFlags, String tag) {
         switch (levelAndFlags & WAKE_LOCK_LEVEL_MASK) {
             case PARTIAL_WAKE_LOCK:
@@ -1095,6 +1103,7 @@
      *
      * @hide Requires signature permission.
      */
+    @UnsupportedAppUsage
     public void goToSleep(long time, int reason, int flags) {
         try {
             mService.goToSleep(time, reason, flags);
@@ -1151,6 +1160,7 @@
      * @deprecated Use {@link #wakeUp(long, int, String)} instead.
      * @hide
      */
+    @UnsupportedAppUsage
     @Deprecated
     public void wakeUp(long time, String details) {
         wakeUp(time, WAKE_REASON_UNKNOWN, details);
@@ -1419,9 +1429,9 @@
             android.Manifest.permission.DEVICE_POWER,
             android.Manifest.permission.POWER_SAVER
     })
-    public boolean setPowerSaveMode(boolean mode) {
+    public boolean setPowerSaveModeEnabled(boolean mode) {
         try {
-            return mService.setPowerSaveMode(mode);
+            return mService.setPowerSaveModeEnabled(mode);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1635,6 +1645,7 @@
      * restrictions have been lifted.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isLightDeviceIdleMode() {
         try {
             return mService.isLightDeviceIdleMode();
@@ -1970,6 +1981,7 @@
      * This broadcast is only sent to registered receivers.
      * @hide
      */
+    @UnsupportedAppUsage
     @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED
             = "android.os.action.LIGHT_DEVICE_IDLE_MODE_CHANGED";
@@ -1996,11 +2008,13 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_POWER_SAVE_MODE_CHANGING
             = "android.os.action.POWER_SAVE_MODE_CHANGING";
 
     /** @hide */
+    @UnsupportedAppUsage
     public static final String EXTRA_POWER_SAVE_MODE = "mode";
 
     /**
@@ -2051,7 +2065,9 @@
      * </p>
      */
     public final class WakeLock {
+        @UnsupportedAppUsage
         private int mFlags;
+        @UnsupportedAppUsage
         private String mTag;
         private final String mPackageName;
         private final IBinder mToken;
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 03fc2a9..a7ac7a1 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.system.Os;
 import android.system.OsConstants;
 import android.webkit.WebViewZygote;
@@ -60,30 +61,35 @@
      * Defines the UID/GID for the log group.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int LOG_UID = 1007;
 
     /**
      * Defines the UID/GID for the WIFI supplicant process.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int WIFI_UID = 1010;
 
     /**
      * Defines the UID/GID for the mediaserver process.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int MEDIA_UID = 1013;
 
     /**
      * Defines the UID/GID for the DRM process.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int DRM_UID = 1019;
 
     /**
      * Defines the UID/GID for the group that controls VPN services.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int VPN_UID = 1016;
 
     /**
@@ -96,6 +102,7 @@
      * Defines the UID/GID for the NFC service process.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int NFC_UID = 1027;
 
     /**
@@ -600,6 +607,7 @@
      * Returns the identifier of this process' parent.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int myPpid() {
         return Os.getppid();
     }
@@ -658,6 +666,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public static final boolean isIsolated(int uid) {
         uid = UserHandle.getAppId(uid);
         return (uid >= FIRST_ISOLATED_UID && uid <= LAST_ISOLATED_UID)
@@ -684,6 +693,7 @@
      * @return the uid of the process, or -1 if the process is not running.
      * @hide pending API council review
      */
+    @UnsupportedAppUsage
     public static final int getUidForPid(int pid) {
         String[] procStatusLabels = { "Uid:" };
         long[] procStatusValues = new long[1];
@@ -698,6 +708,7 @@
      * @return the parent process id of the process, or -1 if the process is not running.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int getParentPid(int pid) {
         String[] procStatusLabels = { "PPid:" };
         long[] procStatusValues = new long[1];
@@ -801,6 +812,7 @@
      *
      * Always sets cpusets.
      */
+    @UnsupportedAppUsage
     public static final native void setProcessGroup(int pid, int group)
             throws IllegalArgumentException, SecurityException;
 
@@ -942,6 +954,7 @@
      * 
      * {@hide}
      */
+    @UnsupportedAppUsage
     public static final native void setArgV0(String text);
 
     /**
@@ -992,41 +1005,55 @@
     public static final native void sendSignalQuiet(int pid, int signal);
     
     /** @hide */
+    @UnsupportedAppUsage
     public static final native long getFreeMemory();
     
     /** @hide */
+    @UnsupportedAppUsage
     public static final native long getTotalMemory();
     
     /** @hide */
+    @UnsupportedAppUsage
     public static final native void readProcLines(String path,
             String[] reqFields, long[] outSizes);
     
     /** @hide */
+    @UnsupportedAppUsage
     public static final native int[] getPids(String path, int[] lastArray);
     
     /** @hide */
+    @UnsupportedAppUsage
     public static final int PROC_TERM_MASK = 0xff;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int PROC_ZERO_TERM = 0;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int PROC_SPACE_TERM = (int)' ';
     /** @hide */
+    @UnsupportedAppUsage
     public static final int PROC_TAB_TERM = (int)'\t';
     /** @hide */
     public static final int PROC_NEWLINE_TERM = (int) '\n';
     /** @hide */
+    @UnsupportedAppUsage
     public static final int PROC_COMBINE = 0x100;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int PROC_PARENS = 0x200;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int PROC_QUOTES = 0x400;
     /** @hide */
     public static final int PROC_CHAR = 0x800;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int PROC_OUT_STRING = 0x1000;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int PROC_OUT_LONG = 0x2000;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int PROC_OUT_FLOAT = 0x4000;
 
     /**
@@ -1058,14 +1085,17 @@
      * @param outFloats the parsed {@code float}s from the file
      * @hide
      */
+    @UnsupportedAppUsage
     public static final native boolean readProcFile(String file, int[] format,
             String[] outStrings, long[] outLongs, float[] outFloats);
 
     /** @hide */
+    @UnsupportedAppUsage
     public static final native boolean parseProcLine(byte[] buffer, int startIndex, 
             int endIndex, int[] format, String[] outStrings, long[] outLongs, float[] outFloats);
 
     /** @hide */
+    @UnsupportedAppUsage
     public static final native int[] getPidsForCommands(String[] cmds);
 
     /**
@@ -1076,6 +1106,7 @@
      *  or -1 if the value cannot be determined 
      * @hide
      */
+    @UnsupportedAppUsage
     public static final native long getPss(int pid);
 
     /** @hide */
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 3ee54ce..6a01e56 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -22,6 +22,7 @@
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
@@ -355,6 +356,7 @@
      *
      * @return the verification result.
      */
+    @UnsupportedAppUsage
     private static boolean verifyPackageCompatibility(InputStream inputStream) throws IOException {
         ArrayList<String> list = new ArrayList<>();
         ZipInputStream zis = new ZipInputStream(inputStream);
diff --git a/core/java/android/os/Registrant.java b/core/java/android/os/Registrant.java
index 705cc5d..8fb123a 100644
--- a/core/java/android/os/Registrant.java
+++ b/core/java/android/os/Registrant.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Handler;
 import android.os.Message;
 
@@ -24,6 +25,7 @@
 /** @hide */
 public class Registrant
 {
+    @UnsupportedAppUsage
     public
     Registrant(Handler h, int what, Object obj)
     {
@@ -32,6 +34,7 @@
         userObj = obj;
     }
 
+    @UnsupportedAppUsage
     public void
     clear()
     {
@@ -39,12 +42,14 @@
         userObj = null;
     }
 
+    @UnsupportedAppUsage
     public void
     notifyRegistrant()
     {
         internalNotifyRegistrant (null, null);
     }
     
+    @UnsupportedAppUsage
     public void
     notifyResult(Object result)
     {
@@ -60,6 +65,7 @@
     /**
      * This makes a copy of @param ar
      */
+    @UnsupportedAppUsage
     public void
     notifyRegistrant(AsyncResult ar)
     {
@@ -88,6 +94,7 @@
      * NOTE: May return null if weak reference has been collected
      */
 
+    @UnsupportedAppUsage
     public Message
     messageForRegistrant()
     {
diff --git a/core/java/android/os/RegistrantList.java b/core/java/android/os/RegistrantList.java
index 9ab61f5..6e562ff 100644
--- a/core/java/android/os/RegistrantList.java
+++ b/core/java/android/os/RegistrantList.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Handler;         
 
 import java.util.ArrayList;
@@ -25,12 +26,14 @@
 {
     ArrayList   registrants = new ArrayList();      // of Registrant
 
+    @UnsupportedAppUsage
     public synchronized void
     add(Handler h, int what, Object obj)
     {
         add(new Registrant(h, what, obj));
     }
 
+    @UnsupportedAppUsage
     public synchronized void
     addUnique(Handler h, int what, Object obj)
     {
@@ -39,6 +42,7 @@
         add(new Registrant(h, what, obj));        
     }
     
+    @UnsupportedAppUsage
     public synchronized void
     add(Registrant r)
     {
@@ -46,6 +50,7 @@
         registrants.add(r);
     }
 
+    @UnsupportedAppUsage
     public synchronized void
     removeCleared()
     {
@@ -58,6 +63,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public synchronized int
     size()
     {
@@ -79,6 +85,7 @@
        }
     }
     
+    @UnsupportedAppUsage
     public /*synchronized*/ void
     notifyRegistrants()
     {
@@ -91,6 +98,7 @@
         internalNotifyRegistrants (null, exception);
     }
 
+    @UnsupportedAppUsage
     public /*synchronized*/ void
     notifyResult(Object result)
     {
@@ -98,12 +106,14 @@
     }
 
     
+    @UnsupportedAppUsage
     public /*synchronized*/ void
     notifyRegistrants(AsyncResult ar)
     {
         internalNotifyRegistrants(ar.result, ar.exception);
     }
     
+    @UnsupportedAppUsage
     public synchronized void
     remove(Handler h)
     {
diff --git a/core/java/android/os/RemoteCallbackList.java b/core/java/android/os/RemoteCallbackList.java
index be8f784..b377e8d 100644
--- a/core/java/android/os/RemoteCallbackList.java
+++ b/core/java/android/os/RemoteCallbackList.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import android.annotation.UnsupportedAppUsage;
 import android.util.ArrayMap;
 import android.util.Slog;
 
@@ -53,6 +54,7 @@
 public class RemoteCallbackList<E extends IInterface> {
     private static final String TAG = "RemoteCallbackList";
 
+    @UnsupportedAppUsage
     /*package*/ ArrayMap<IBinder, Callback> mCallbacks
             = new ArrayMap<IBinder, Callback>();
     private Object[] mActiveBroadcast;
diff --git a/core/java/android/os/RemoteException.java b/core/java/android/os/RemoteException.java
index 4e8b971..2e673a8 100644
--- a/core/java/android/os/RemoteException.java
+++ b/core/java/android/os/RemoteException.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import android.annotation.UnsupportedAppUsage;
 import android.util.AndroidException;
 
 /**
@@ -54,6 +55,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public RuntimeException rethrowFromSystemServer() {
         if (this instanceof DeadObjectException) {
             throw new RuntimeException(new DeadSystemException());
diff --git a/core/java/android/os/SELinux.java b/core/java/android/os/SELinux.java
index a96618a..8ffafe4 100644
--- a/core/java/android/os/SELinux.java
+++ b/core/java/android/os/SELinux.java
@@ -42,12 +42,14 @@
      * Determine whether SELinux is disabled or enabled.
      * @return a boolean indicating whether SELinux is enabled.
      */
+    @UnsupportedAppUsage
     public static final native boolean isSELinuxEnabled();
 
     /**
      * Determine whether SELinux is permissive or enforcing.
      * @return a boolean indicating whether SELinux is enforcing.
      */
+    @UnsupportedAppUsage
     public static final native boolean isSELinuxEnforced();
 
     /**
@@ -91,6 +93,7 @@
      * Gets the security context of the current process.
      * @return a String representing the security context of the current process.
      */
+    @UnsupportedAppUsage
     public static final native String getContext();
 
     /**
@@ -98,6 +101,7 @@
      * @param pid an int representing the process id to check.
      * @return a String representing the security context of the given pid.
      */
+    @UnsupportedAppUsage
     public static final native String getPidContext(int pid);
 
     /**
@@ -108,6 +112,7 @@
      * @param perm The permission name.
      * @return a boolean indicating whether permission was granted.
      */
+    @UnsupportedAppUsage
     public static final native boolean checkSELinuxAccess(String scon, String tcon, String tclass, String perm);
 
     /**
@@ -167,6 +172,7 @@
      *
      * @return a boolean indicating whether the relabeling succeeded.
      */
+    @UnsupportedAppUsage
     public static boolean restoreconRecursive(File file) {
         try {
             return native_restorecon(file.getCanonicalPath(), SELINUX_ANDROID_RESTORECON_RECURSE);
diff --git a/core/java/android/os/ServiceManager.java b/core/java/android/os/ServiceManager.java
index 2966bff..9a9b030 100644
--- a/core/java/android/os/ServiceManager.java
+++ b/core/java/android/os/ServiceManager.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import android.annotation.UnsupportedAppUsage;
 import android.util.ArrayMap;
 import android.util.Log;
 
@@ -30,11 +31,13 @@
     private static final String TAG = "ServiceManager";
     private static final Object sLock = new Object();
 
+    @UnsupportedAppUsage
     private static IServiceManager sServiceManager;
 
     /**
      * Cache for the "well known" services, such as WM and AM.
      */
+    @UnsupportedAppUsage
     private static Map<String, IBinder> sCache = new ArrayMap<String, IBinder>();
 
     /**
@@ -98,6 +101,7 @@
             "getService()",
     });
 
+    @UnsupportedAppUsage
     private static IServiceManager getIServiceManager() {
         if (sServiceManager != null) {
             return sServiceManager;
@@ -115,6 +119,7 @@
      * @param name the name of the service to get
      * @return a reference to the service, or <code>null</code> if the service doesn't exist
      */
+    @UnsupportedAppUsage
     public static IBinder getService(String name) {
         try {
             IBinder service = sCache.get(name);
@@ -151,6 +156,7 @@
      * @param name the name of the new service
      * @param service the service object
      */
+    @UnsupportedAppUsage
     public static void addService(String name, IBinder service) {
         addService(name, service, false, IServiceManager.DUMP_FLAG_PRIORITY_DEFAULT);
     }
@@ -164,6 +170,7 @@
      * @param allowIsolated set to true to allow isolated sandboxed processes
      * to access this service
      */
+    @UnsupportedAppUsage
     public static void addService(String name, IBinder service, boolean allowIsolated) {
         addService(name, service, allowIsolated, IServiceManager.DUMP_FLAG_PRIORITY_DEFAULT);
     }
@@ -178,6 +185,7 @@
      * @param dumpPriority supported dump priority levels as a bitmask
      * to access this service
      */
+    @UnsupportedAppUsage
     public static void addService(String name, IBinder service, boolean allowIsolated,
             int dumpPriority) {
         try {
@@ -191,6 +199,7 @@
      * Retrieve an existing service called @a name from the
      * service manager.  Non-blocking.
      */
+    @UnsupportedAppUsage
     public static IBinder checkService(String name) {
         try {
             IBinder service = sCache.get(name);
@@ -210,6 +219,7 @@
      * @return an array of all currently running services, or <code>null</code> in
      * case of an exception
      */
+    @UnsupportedAppUsage
     public static String[] listServices() {
         try {
             return getIServiceManager().listServices(IServiceManager.DUMP_FLAG_PRIORITY_ALL);
diff --git a/core/java/android/os/ServiceManagerNative.java b/core/java/android/os/ServiceManagerNative.java
index 589b8c4..b7c026c 100644
--- a/core/java/android/os/ServiceManagerNative.java
+++ b/core/java/android/os/ServiceManagerNative.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import android.annotation.UnsupportedAppUsage;
 import java.util.ArrayList;
 
 
@@ -30,6 +31,7 @@
      * Cast a Binder object into a service manager interface, generating
      * a proxy if needed.
      */
+    @UnsupportedAppUsage
     static public IServiceManager asInterface(IBinder obj)
     {
         if (obj == null) {
@@ -117,6 +119,7 @@
         return mRemote;
     }
 
+    @UnsupportedAppUsage
     public IBinder getService(String name) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
@@ -196,5 +199,6 @@
         data.recycle();
     }
 
+    @UnsupportedAppUsage
     private IBinder mRemote;
 }
diff --git a/core/java/android/os/SharedMemory.java b/core/java/android/os/SharedMemory.java
index 395485b..57a8801 100644
--- a/core/java/android/os/SharedMemory.java
+++ b/core/java/android/os/SharedMemory.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.system.OsConstants;
@@ -156,6 +157,7 @@
      *
      * @hide Exposed for native ASharedMemory_dupFromJava()
      */
+    @UnsupportedAppUsage
     public int getFd() {
         return mFileDescriptor.getInt$();
     }
diff --git a/core/java/android/os/ShellCommand.java b/core/java/android/os/ShellCommand.java
index 5228d6d..2fe8726 100644
--- a/core/java/android/os/ShellCommand.java
+++ b/core/java/android/os/ShellCommand.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import android.annotation.UnsupportedAppUsage;
 import android.util.Slog;
 
 import com.android.internal.util.FastPrintWriter;
@@ -304,6 +305,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public String peekNextArg() {
         if (mCurArgData != null) {
             return mCurArgData;
diff --git a/core/java/android/os/StatFs.java b/core/java/android/os/StatFs.java
index 4e0b238..881d0b4 100644
--- a/core/java/android/os/StatFs.java
+++ b/core/java/android/os/StatFs.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import android.annotation.UnsupportedAppUsage;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.system.StructStatVfs;
@@ -25,6 +26,7 @@
  * wrapper for Unix statvfs().
  */
 public class StatFs {
+    @UnsupportedAppUsage
     private StructStatVfs mStat;
 
     /**
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index f0b83d8..94cca30 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityManager;
 import android.app.ActivityThread;
 import android.app.IActivityManager;
@@ -421,6 +422,7 @@
         /** The default, lax policy which doesn't catch anything. */
         public static final ThreadPolicy LAX = new ThreadPolicy(0, null, null);
 
+        @UnsupportedAppUsage
         final @ThreadPolicyMask int mask;
         final OnThreadViolationListener mListener;
         final Executor mCallbackExecutor;
@@ -713,6 +715,7 @@
         /** The default, lax policy which doesn't catch anything. */
         public static final VmPolicy LAX = new VmPolicy(0, EMPTY_CLASS_LIMIT_MAP, null, null);
 
+        @UnsupportedAppUsage
         final @VmPolicyMask int mask;
         final OnVmViolationListener mListener;
         final Executor mCallbackExecutor;
@@ -758,6 +761,7 @@
          * </pre>
          */
         public static final class Builder {
+            @UnsupportedAppUsage
             private @VmPolicyMask int mMask;
             private OnVmViolationListener mListener;
             private Executor mExecutor;
@@ -1208,6 +1212,7 @@
      * @return the bitmask of all the DETECT_* and PENALTY_* bits currently enabled
      * @hide
      */
+    @UnsupportedAppUsage
     public static @ThreadPolicyMask int getThreadPolicyMask() {
         final BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
         if (policy instanceof AndroidBlockGuardPolicy) {
@@ -1412,6 +1417,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static void enableDeathOnFileUriExposure() {
         sVmPolicy =
                 new VmPolicy(
@@ -1429,6 +1435,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static void disableDeathOnFileUriExposure() {
         sVmPolicy =
                 new VmPolicy(
@@ -1440,6 +1447,7 @@
                         sVmPolicy.mCallbackExecutor);
     }
 
+    @UnsupportedAppUsage
     private static final ThreadLocal<ArrayList<ViolationInfo>> violationsBeingTimed =
             new ThreadLocal<ArrayList<ViolationInfo>>() {
                 @Override
@@ -2051,6 +2059,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static void onWebViewMethodCalledOnWrongThread(Throwable originStack) {
         onVmPolicyViolation(new WebViewMethodCalledOnWrongThreadViolation(originStack));
     }
@@ -2155,6 +2164,7 @@
     }
 
     // Map from VM violation fingerprint to uptime millis.
+    @UnsupportedAppUsage
     private static final HashMap<Integer, Long> sLastVmViolationTime = new HashMap<>();
 
     /** @hide */
@@ -2280,6 +2290,7 @@
      * Binder for its current (native) thread-local policy value and synchronize it to libcore's
      * (Java) thread-local policy value.
      */
+    @UnsupportedAppUsage
     private static void onBinderStrictModePolicyChange(@ThreadPolicyMask int newPolicy) {
         setBlockGuardPolicy(newPolicy);
     }
@@ -2316,6 +2327,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public void finish() {
             ThreadSpanState state = mContainerState;
             synchronized (state) {
@@ -2387,6 +2399,7 @@
                 }
             };
 
+    @UnsupportedAppUsage
     private static Singleton<IWindowManager> sWindowManager =
             new Singleton<IWindowManager>() {
                 protected IWindowManager create() {
@@ -2407,6 +2420,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static Span enterCriticalSpan(String name) {
         if (Build.IS_USER) {
             return NO_OP_SPAN;
@@ -2516,6 +2530,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static void incrementExpectedActivityCount(Class klass) {
         if (klass == null) {
             return;
diff --git a/core/java/android/os/SystemClock.java b/core/java/android/os/SystemClock.java
index b254166..e695a1b 100644
--- a/core/java/android/os/SystemClock.java
+++ b/core/java/android/os/SystemClock.java
@@ -17,6 +17,7 @@
 package android.os;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.app.IAlarmManager;
 import android.content.Context;
 import android.util.Slog;
@@ -104,6 +105,7 @@
     /**
      * This class is uninstantiable.
      */
+    @UnsupportedAppUsage
     private SystemClock() {
         // This space intentionally left blank.
     }
@@ -241,6 +243,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     @CriticalNative
     public static native long currentThreadTimeMicro();
 
@@ -251,6 +254,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     @CriticalNative
     public static native long currentTimeMicro();
 
diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
index cbcf600..edfdda8 100644
--- a/core/java/android/os/SystemProperties.java
+++ b/core/java/android/os/SystemProperties.java
@@ -20,6 +20,7 @@
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.util.Log;
 import android.util.MutableInt;
 
@@ -51,11 +52,13 @@
      * uses reflection to read this whenever text is selected (http://b/36095274).
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int PROP_NAME_MAX = Integer.MAX_VALUE;
 
     /** @hide */
     public static final int PROP_VALUE_MAX = 91;
 
+    @UnsupportedAppUsage
     @GuardedBy("sChangeCallbacks")
     private static final ArrayList<Runnable> sChangeCallbacks = new ArrayList<Runnable>();
 
@@ -83,9 +86,11 @@
         }
     }
 
+    @UnsupportedAppUsage
     private static native String native_get(String key);
     private static native String native_get(String key, String def);
     private static native int native_get_int(String key, int def);
+    @UnsupportedAppUsage
     private static native long native_get_long(String key, long def);
     private static native boolean native_get_boolean(String key, boolean def);
     private static native void native_set(String key, String def);
@@ -180,6 +185,7 @@
      * @throws IllegalArgumentException if the {@code val} exceeds 91 characters
      * @hide
      */
+    @UnsupportedAppUsage
     public static void set(@NonNull String key, @Nullable String val) {
         if (val != null && !val.startsWith("ro.") && val.length() > PROP_VALUE_MAX) {
             throw new IllegalArgumentException("value of system property '" + key
@@ -196,6 +202,7 @@
      * changes.
      * @hide
      */
+    @UnsupportedAppUsage
     public static void addChangeCallback(@NonNull Runnable callback) {
         synchronized (sChangeCallbacks) {
             if (sChangeCallbacks.size() == 0) {
@@ -233,6 +240,7 @@
      * Notifies listeners that a system property has changed
      * @hide
      */
+    @UnsupportedAppUsage
     public static void reportSyspropChanged() {
         native_report_sysprop_change();
     }
@@ -258,6 +266,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private SystemProperties() {
     }
 }
diff --git a/core/java/android/os/SystemService.java b/core/java/android/os/SystemService.java
index 41e7546..968c761 100644
--- a/core/java/android/os/SystemService.java
+++ b/core/java/android/os/SystemService.java
@@ -18,6 +18,7 @@
 
 import com.google.android.collect.Maps;
 
+import android.annotation.UnsupportedAppUsage;
 import java.util.HashMap;
 import java.util.concurrent.TimeoutException;
 
@@ -58,11 +59,13 @@
     }
 
     /** Request that the init daemon start a named service. */
+    @UnsupportedAppUsage
     public static void start(String name) {
         SystemProperties.set("ctl.start", name);
     }
 
     /** Request that the init daemon stop a named service. */
+    @UnsupportedAppUsage
     public static void stop(String name) {
         SystemProperties.set("ctl.stop", name);
     }
diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java
index c989197..4af514a 100644
--- a/core/java/android/os/SystemVibrator.java
+++ b/core/java/android/os/SystemVibrator.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.media.AudioAttributes;
 import android.util.Log;
@@ -31,10 +32,12 @@
     private final IVibratorService mService;
     private final Binder mToken = new Binder();
 
+    @UnsupportedAppUsage
     public SystemVibrator() {
         mService = IVibratorService.Stub.asInterface(ServiceManager.getService("vibrator"));
     }
 
+    @UnsupportedAppUsage
     public SystemVibrator(Context context) {
         super(context);
         mService = IVibratorService.Stub.asInterface(ServiceManager.getService("vibrator"));
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index 68d6d85..1456a73 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -17,6 +17,7 @@
 package android.os;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 
 import com.android.internal.os.Zygote;
 
@@ -52,6 +53,7 @@
     /** @hide */
     public static final long TRACE_TAG_INPUT = 1L << 2;
     /** @hide */
+    @UnsupportedAppUsage
     public static final long TRACE_TAG_VIEW = 1L << 3;
     /** @hide */
     public static final long TRACE_TAG_WEBVIEW = 1L << 4;
@@ -70,6 +72,7 @@
     /** @hide */
     public static final long TRACE_TAG_HAL = 1L << 11;
     /** @hide */
+    @UnsupportedAppUsage
     public static final long TRACE_TAG_APP = 1L << 12;
     /** @hide */
     public static final long TRACE_TAG_RESOURCES = 1L << 13;
@@ -104,10 +107,12 @@
     private static final int MAX_SECTION_NAME_LEN = 127;
 
     // Must be volatile to avoid word tearing.
+    @UnsupportedAppUsage
     private static volatile long sEnabledTags = TRACE_TAG_NOT_READY;
 
     private static int sZygoteDebugFlags = 0;
 
+    @UnsupportedAppUsage
     private static native long nativeGetEnabledTags();
     private static native void nativeSetAppTracingAllowed(boolean allowed);
     private static native void nativeSetTracingEnabled(boolean allowed);
@@ -171,6 +176,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isTagEnabled(long traceTag) {
         long tags = sEnabledTags;
         if (tags == TRACE_TAG_NOT_READY) {
@@ -188,6 +194,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static void traceCounter(long traceTag, String counterName, int counterValue) {
         if (isTagEnabled(traceTag)) {
             nativeTraceCounter(traceTag, counterName, counterValue);
@@ -200,6 +207,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static void setAppTracingAllowed(boolean allowed) {
         nativeSetAppTracingAllowed(allowed);
 
@@ -235,6 +243,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static void traceBegin(long traceTag, String methodName) {
         if (isTagEnabled(traceTag)) {
             nativeTraceBegin(traceTag, methodName);
@@ -249,6 +258,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static void traceEnd(long traceTag) {
         if (isTagEnabled(traceTag)) {
             nativeTraceEnd(traceTag);
@@ -268,6 +278,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static void asyncTraceBegin(long traceTag, String methodName, int cookie) {
         if (isTagEnabled(traceTag)) {
             nativeAsyncTraceBegin(traceTag, methodName, cookie);
@@ -285,6 +296,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static void asyncTraceEnd(long traceTag, String methodName, int cookie) {
         if (isTagEnabled(traceTag)) {
             nativeAsyncTraceEnd(traceTag, methodName, cookie);
diff --git a/core/java/android/os/UEventObserver.java b/core/java/android/os/UEventObserver.java
index 69a3922..dc98c42 100644
--- a/core/java/android/os/UEventObserver.java
+++ b/core/java/android/os/UEventObserver.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import android.annotation.UnsupportedAppUsage;
 import android.util.Log;
 
 import java.util.ArrayList;
@@ -49,6 +50,7 @@
     private static native void nativeAddMatch(String match);
     private static native void nativeRemoveMatch(String match);
 
+    @UnsupportedAppUsage
     public UEventObserver() {
     }
 
@@ -93,6 +95,7 @@
      * are expensive to parse.  For example, some devices may send one netlink message
      * for each vsync period.
      */
+    @UnsupportedAppUsage
     public final void startObserving(String match) {
         if (match == null || match.isEmpty()) {
             throw new IllegalArgumentException("match substring must be non-empty");
@@ -107,6 +110,7 @@
      * This process's UEvent thread will never call onUEvent() on this
      * UEventObserver after this call. Repeated calls have no effect.
      */
+    @UnsupportedAppUsage
     public final void stopObserving() {
         final UEventThread t = peekThread();
         if (t != null) {
@@ -118,6 +122,7 @@
      * Subclasses of UEventObserver should override this method to handle
      * UEvents.
      */
+    @UnsupportedAppUsage
     public abstract void onUEvent(UEvent event);
 
     /**
@@ -146,10 +151,12 @@
             }
         }
 
+        @UnsupportedAppUsage
         public String get(String key) {
             return mMap.get(key);
         }
 
+        @UnsupportedAppUsage
         public String get(String key, String defaultValue) {
             String result = mMap.get(key);
             return (result == null ? defaultValue : result);
diff --git a/core/java/android/os/UpdateLock.java b/core/java/android/os/UpdateLock.java
index 4060326..ea273ce 100644
--- a/core/java/android/os/UpdateLock.java
+++ b/core/java/android/os/UpdateLock.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.util.Log;
 
@@ -50,6 +51,7 @@
      * locker releases theirs.  The broadcast is sticky but is sent only to
      * registered receivers.
      */
+    @UnsupportedAppUsage
     public static final String UPDATE_LOCK_CHANGED = "android.os.UpdateLock.UPDATE_LOCK_CHANGED";
 
     /**
@@ -58,6 +60,7 @@
      * update operation.  True means that updates are okay right now; false indicates
      * that perhaps later would be a better time.
      */
+    @UnsupportedAppUsage
     public static final String NOW_IS_CONVENIENT = "nowisconvenient";
 
     /**
@@ -66,6 +69,7 @@
      * in the System.currentTimeMillis() time base, which may be non-monotonic especially
      * around reboots.
      */
+    @UnsupportedAppUsage
     public static final String TIMESTAMP = "timestamp";
 
     /**
@@ -90,6 +94,7 @@
     /**
      * Is this lock currently held?
      */
+    @UnsupportedAppUsage
     public boolean isHeld() {
         synchronized (mToken) {
             return mHeld;
@@ -99,6 +104,7 @@
     /**
      * Acquire an update lock.
      */
+    @UnsupportedAppUsage
     public void acquire() {
         if (DEBUG) {
             Log.v(TAG, "acquire() : " + this, new RuntimeException("here"));
@@ -125,6 +131,7 @@
     /**
      * Release this update lock.
      */
+    @UnsupportedAppUsage
     public void release() {
         if (DEBUG) Log.v(TAG, "release() : " + this, new RuntimeException("here"));
         checkService();
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index 286185b..b121234 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.UserIdInt;
 
 import java.io.PrintWriter;
@@ -33,9 +34,11 @@
     /**
      * @hide Range of uids allocated for a user.
      */
+    @UnsupportedAppUsage
     public static final int PER_USER_RANGE = 100000;
 
     /** @hide A user id to indicate all users on the device */
+    @UnsupportedAppUsage
     public static final @UserIdInt int USER_ALL = -1;
 
     /** @hide A user handle to indicate all users on the device */
@@ -44,6 +47,7 @@
     public static final @NonNull UserHandle ALL = new UserHandle(USER_ALL);
 
     /** @hide A user id to indicate the currently active user */
+    @UnsupportedAppUsage
     public static final @UserIdInt int USER_CURRENT = -2;
 
     /** @hide A user handle to indicate the current user of the device */
@@ -54,11 +58,13 @@
     /** @hide A user id to indicate that we would like to send to the current
      *  user, but if this is calling from a user process then we will send it
      *  to the caller's user instead of failing with a security exception */
+    @UnsupportedAppUsage
     public static final @UserIdInt int USER_CURRENT_OR_SELF = -3;
 
     /** @hide A user handle to indicate that we would like to send to the current
      *  user, but if this is calling from a user process then we will send it
      *  to the caller's user instead of failing with a security exception */
+    @UnsupportedAppUsage
     public static final @NonNull UserHandle CURRENT_OR_SELF = new UserHandle(USER_CURRENT_OR_SELF);
 
     /** @hide An undefined user id */
@@ -69,6 +75,7 @@
      * @deprecated Consider using either {@link UserHandle#USER_SYSTEM} constant or
      * check the target user's flag {@link android.content.pm.UserInfo#isAdmin}.
      */
+    @UnsupportedAppUsage
     @Deprecated
     public static final @UserIdInt int USER_OWNER = 0;
 
@@ -77,13 +84,16 @@
      * @deprecated Consider using either {@link UserHandle#SYSTEM} constant or
      * check the target user's flag {@link android.content.pm.UserInfo#isAdmin}.
      */
+    @UnsupportedAppUsage
     @Deprecated
     public static final @NonNull UserHandle OWNER = new UserHandle(USER_OWNER);
 
     /** @hide A user id constant to indicate the "system" user of the device */
+    @UnsupportedAppUsage
     public static final @UserIdInt int USER_SYSTEM = 0;
 
     /** @hide A user serial constant to indicate the "system" user of the device */
+    @UnsupportedAppUsage
     public static final int USER_SERIAL_SYSTEM = 0;
 
     /** @hide A user handle to indicate the "system" user of the device */
@@ -95,21 +105,29 @@
      * @hide Enable multi-user related side effects. Set this to false if
      * there are problems with single user use-cases.
      */
+    @UnsupportedAppUsage
     public static final boolean MU_ENABLED = true;
 
     /** @hide */
+    @UnsupportedAppUsage
     public static final int ERR_GID = -1;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int AID_ROOT = android.os.Process.ROOT_UID;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int AID_APP_START = android.os.Process.FIRST_APPLICATION_UID;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int AID_APP_END = android.os.Process.LAST_APPLICATION_UID;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int AID_SHARED_GID_START = android.os.Process.FIRST_SHARED_APPLICATION_GID;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int AID_CACHE_GID_START = android.os.Process.FIRST_APPLICATION_CACHE_GID;
 
+    @UnsupportedAppUsage
     final int mHandle;
 
     /**
@@ -129,6 +147,7 @@
      * @return whether the appId is the same for both uids
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isSameApp(int uid1, int uid2) {
         return getAppId(uid1) == getAppId(uid2);
     }
@@ -137,6 +156,7 @@
      * Whether a UID is an "isolated" UID.
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isIsolated(int uid) {
         if (uid > 0) {
             return Process.isIsolated(uid);
@@ -186,6 +206,7 @@
      * Returns the user id for a given uid.
      * @hide
      */
+    @UnsupportedAppUsage
     public static @UserIdInt int getUserId(int uid) {
         if (MU_ENABLED) {
             return uid / PER_USER_RANGE;
@@ -195,6 +216,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static @UserIdInt int getCallingUserId() {
         return getUserId(Binder.getCallingUid());
     }
@@ -214,6 +236,7 @@
      * Returns the uid that is composed from the userId and the appId.
      * @hide
      */
+    @UnsupportedAppUsage
     public static int getUid(@UserIdInt int userId, @AppIdInt int appId) {
         if (MU_ENABLED) {
             return userId * PER_USER_RANGE + (appId % PER_USER_RANGE);
@@ -260,6 +283,7 @@
      * Returns the app id for a given shared app gid. Returns -1 if the ID is invalid.
      * @hide
      */
+    @UnsupportedAppUsage
     public static @AppIdInt int getAppIdFromSharedAppGid(int gid) {
         final int appId = getAppId(gid) + Process.FIRST_APPLICATION_UID
                 - Process.FIRST_SHARED_APPLICATION_GID;
@@ -405,6 +429,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public UserHandle(int h) {
         mHandle = h;
     }
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 185df5e..790bb27 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -70,6 +70,7 @@
 public class UserManager {
 
     private static final String TAG = "UserManager";
+    @UnsupportedAppUsage
     private final IUserManager mService;
     private final Context mContext;
 
@@ -810,6 +811,7 @@
      * @see #getUserRestrictions()
      * @hide
      */
+    @UnsupportedAppUsage
     public static final String DISALLOW_RECORD_AUDIO = "no_record_audio";
 
     /**
@@ -1238,6 +1240,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static UserManager get(Context context) {
         return (UserManager) context.getSystemService(Context.USER_SERVICE);
     }
@@ -1341,6 +1344,7 @@
      * @return the user handle of this process.
      * @hide
      */
+    @UnsupportedAppUsage
     public @UserIdInt int getUserHandle() {
         return UserHandle.myUserId();
     }
@@ -1348,12 +1352,16 @@
     /**
      * Returns the user name of the user making this call.  This call is only
      * available to applications on the system image; it requires the
-     * MANAGE_USERS permission.
+     * {@code android.permission.MANAGE_USERS} or {@code android.permission.GET_ACCOUNTS_PRIVILEGED}
+     * permissions.
      * @return the user name
      */
     public String getUserName() {
-        UserInfo user = getUserInfo(getUserHandle());
-        return user == null ? "" : user.name;
+        try {
+            return mService.getUserName();
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -1428,6 +1436,7 @@
      * Returns whether the provided user is an admin user. There can be more than one admin
      * user.
      */
+    @UnsupportedAppUsage
     public boolean isUserAdmin(@UserIdInt int userId) {
         UserInfo user = getUserInfo(userId);
         return user != null && user.isAdmin();
@@ -1437,6 +1446,7 @@
      * @hide
      * @deprecated Use {@link #isRestrictedProfile()}
      */
+    @UnsupportedAppUsage
     @Deprecated
     public boolean isLinkedUser() {
         return isRestrictedProfile();
@@ -1490,6 +1500,7 @@
      * @return whether user is a guest user.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isGuestUser(int id) {
         UserInfo user = getUserInfo(id);
         return user != null && user.isGuest();
@@ -1699,6 +1710,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public boolean isUserUnlocked(@UserIdInt int userId) {
         try {
             return mService.isUserUnlocked(userId);
@@ -1727,6 +1739,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public long getUserStartRealtime() {
         try {
             return mService.getUserStartRealtime();
@@ -1741,6 +1754,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public long getUserUnlockRealtime() {
         try {
             return mService.getUserUnlockRealtime();
@@ -1756,6 +1770,7 @@
      * @return the UserInfo object for a specific user.
      * @hide
      */
+    @UnsupportedAppUsage
     public UserInfo getUserInfo(@UserIdInt int userHandle) {
         try {
             return mService.getUserInfo(userHandle);
@@ -1836,6 +1851,7 @@
      * @param restrictionKey the string key representing the restriction
      * @param userHandle the UserHandle of the user for whom to retrieve the restrictions.
      */
+    @UnsupportedAppUsage
     public boolean hasBaseUserRestriction(String restrictionKey, UserHandle userHandle) {
         try {
             return mService.hasBaseUserRestriction(restrictionKey, userHandle.getIdentifier());
@@ -1918,6 +1934,7 @@
      * @param restrictionKey the string key representing the restriction
      * @param userHandle the UserHandle of the user for whom to retrieve the restrictions.
      */
+    @UnsupportedAppUsage
     public boolean hasUserRestriction(String restrictionKey, UserHandle userHandle) {
         try {
             return mService.hasUserRestriction(restrictionKey,
@@ -1978,6 +1995,7 @@
      * @return the UserInfo object for the created user, or null if the user could not be created.
      * @hide
      */
+    @UnsupportedAppUsage
     public UserInfo createUser(String name, int flags) {
         UserInfo user = null;
         try {
@@ -2026,6 +2044,7 @@
      *         could not be created.
      * @hide
      */
+    @UnsupportedAppUsage
     public UserInfo createProfileForUser(String name, int flags, @UserIdInt int userHandle) {
         return createProfileForUser(name, flags, userHandle, null);
     }
@@ -2314,6 +2333,7 @@
      * @return the list of users that exist on the device.
      * @hide
      */
+    @UnsupportedAppUsage
     public List<UserInfo> getUsers() {
         try {
             return mService.getUsers(false);
@@ -2439,6 +2459,7 @@
      * @return the list of profiles.
      * @hide
      */
+    @UnsupportedAppUsage
     public List<UserInfo> getProfiles(@UserIdInt int userHandle) {
         try {
             return mService.getProfiles(userHandle, false /* enabledOnly */);
@@ -2472,6 +2493,7 @@
      * @return the list of profiles.
      * @hide
      */
+    @UnsupportedAppUsage
     public List<UserInfo> getEnabledProfiles(@UserIdInt int userHandle) {
         try {
             return mService.getProfiles(userHandle, true /* enabledOnly */);
@@ -2519,6 +2541,7 @@
      * @see #getProfileIds(int, boolean)
      * @hide
      */
+    @UnsupportedAppUsage
     public int[] getProfileIdsWithDisabled(@UserIdInt int userId) {
         return getProfileIds(userId, false /* enabledOnly */);
     }
@@ -2552,6 +2575,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public UserInfo getProfileParent(@UserIdInt int userHandle) {
         try {
             return mService.getProfileParent(userHandle);
@@ -2721,6 +2745,7 @@
      * @return the list of users that were created.
      * @hide
      */
+    @UnsupportedAppUsage
     public @NonNull List<UserInfo> getUsers(boolean excludeDying) {
         try {
             return mService.getUsers(excludeDying);
@@ -2735,6 +2760,7 @@
      * @param userHandle the integer handle of the user, where 0 is the primary user.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean removeUser(@UserIdInt int userHandle) {
         try {
             return mService.removeUser(userHandle);
@@ -2840,6 +2866,7 @@
      * @see com.android.internal.util.UserIcons#getDefaultUserIcon for a default.
      * @hide
      */
+    @UnsupportedAppUsage
     public Bitmap getUserIcon(@UserIdInt int userHandle) {
         try {
             ParcelFileDescriptor fd = mService.getUserIcon(userHandle);
@@ -2861,14 +2888,16 @@
 
     /**
      * Returns a Bitmap for the calling user's photo.
-     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+     * Requires {@link android.Manifest.permission#MANAGE_USERS}
+     * or {@link android.Manifest.permission#GET_ACCOUNTS_PRIVILEGED} permissions.
      *
      * @return a {@link Bitmap} of the user's photo, or null if there's no photo.
      * @see com.android.internal.util.UserIcons#getDefaultUserIcon for a default.
      * @hide
      */
     @SystemApi
-    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.GET_ACCOUNTS_PRIVILEGED})
     public @Nullable Bitmap getUserIcon() {
         return getUserIcon(getUserHandle());
     }
@@ -2879,6 +2908,7 @@
      * @hide
      * @return a value greater than or equal to 1
      */
+    @UnsupportedAppUsage
     public static int getMaxSupportedUsers() {
         // Don't allow multiple users on certain builds
         if (android.os.Build.ID.startsWith("JVP")) return 1;
@@ -2934,6 +2964,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isDeviceInDemoMode(Context context) {
         return Settings.Global.getInt(context.getContentResolver(),
                 Settings.Global.DEVICE_DEMO_MODE, 0) > 0;
@@ -2946,6 +2977,7 @@
      * @return a serial number associated with that user, or -1 if the userHandle is not valid.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getUserSerialNumber(@UserIdInt int userHandle) {
         try {
             return mService.getUserSerialNumber(userHandle);
@@ -2963,6 +2995,7 @@
      * is not valid.
      * @hide
      */
+    @UnsupportedAppUsage
     public @UserIdInt int getUserHandle(int userSerialNumber) {
         try {
             return mService.getUserHandle(userSerialNumber);
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index 226d1d0..28909c8 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityThread;
 import android.content.Context;
 import android.media.AudioAttributes;
@@ -85,6 +86,7 @@
     /**
      * @hide to prevent subclassing from outside of the framework
      */
+    @UnsupportedAppUsage
     public Vibrator() {
         mPackageName = ActivityThread.currentPackageName();
         final Context ctx = ActivityThread.currentActivityThread().getSystemContext();
diff --git a/core/java/android/os/WorkSource.java b/core/java/android/os/WorkSource.java
index 9980ade..0b4a561 100644
--- a/core/java/android/os/WorkSource.java
+++ b/core/java/android/os/WorkSource.java
@@ -3,6 +3,7 @@
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.WorkSourceProto;
 import android.provider.Settings;
@@ -24,8 +25,11 @@
     static final String TAG = "WorkSource";
     static final boolean DEBUG = false;
 
+    @UnsupportedAppUsage
     int mNum;
+    @UnsupportedAppUsage
     int[] mUids;
+    @UnsupportedAppUsage
     String[] mNames;
 
     private ArrayList<WorkChain> mChains;
@@ -103,6 +107,7 @@
         mChains = null;
     }
 
+    @UnsupportedAppUsage
     WorkSource(Parcel in) {
         mNum = in.readInt();
         mUids = in.createIntArray();
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index 60f4f06..40238d2 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -18,15 +18,16 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ApplicationInfo;
 import android.net.LocalSocket;
 import android.net.LocalSocketAddress;
-import android.provider.DeviceConfig;
 import android.util.Log;
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.os.Zygote;
+import com.android.internal.os.ZygoteConfig;
 
 import java.io.BufferedWriter;
 import java.io.DataInputStream;
@@ -41,10 +42,12 @@
 import java.util.UUID;
 
 /*package*/ class ZygoteStartFailedEx extends Exception {
+    @UnsupportedAppUsage
     ZygoteStartFailedEx(String s) {
         super(s);
     }
 
+    @UnsupportedAppUsage
     ZygoteStartFailedEx(Throwable cause) {
         super(cause);
     }
@@ -120,10 +123,6 @@
         mUsapPoolSecondarySocketAddress =
                 new LocalSocketAddress(Zygote.USAP_POOL_SECONDARY_SOCKET_NAME,
                                        LocalSocketAddress.Namespace.RESERVED);
-
-        if (fetchUsapPoolEnabledProp()) {
-            informZygotesOfUsapPoolStatus();
-        }
     }
 
     public ZygoteProcess(LocalSocketAddress primarySocketAddress,
@@ -151,7 +150,7 @@
         final DataInputStream mZygoteInputStream;
         final BufferedWriter mZygoteOutputWriter;
 
-        private final List<String> mABIList;
+        private final List<String> mAbiList;
 
         private boolean mClosed;
 
@@ -166,7 +165,7 @@
             this.mZygoteSessionSocket = zygoteSessionSocket;
             this.mZygoteInputStream = zygoteInputStream;
             this.mZygoteOutputWriter = zygoteOutputWriter;
-            this.mABIList = abiList;
+            this.mAbiList = abiList;
         }
 
         /**
@@ -179,14 +178,18 @@
          * address
          * @throws IOException
          */
-        public static ZygoteState connect(LocalSocketAddress zygoteSocketAddress,
-                                          LocalSocketAddress usapSocketAddress)
+        public static ZygoteState connect(@NonNull LocalSocketAddress zygoteSocketAddress,
+                                          @Nullable LocalSocketAddress usapSocketAddress)
                 throws IOException {
 
             DataInputStream zygoteInputStream = null;
             BufferedWriter zygoteOutputWriter = null;
             final LocalSocket zygoteSessionSocket = new LocalSocket();
 
+            if (zygoteSocketAddress == null) {
+                throw new IllegalArgumentException("zygoteSocketAddress can't be null");
+            }
+
             try {
                 zygoteSessionSocket.connect(zygoteSocketAddress);
                 zygoteInputStream = new DataInputStream(zygoteSessionSocket.getInputStream());
@@ -215,7 +218,7 @@
         }
 
         boolean matches(String abi) {
-            return mABIList.contains(abi);
+            return mAbiList.contains(abi);
         }
 
         public void close() {
@@ -338,7 +341,7 @@
         try {
             return startViaZygote(processClass, niceName, uid, gid, gids,
                     runtimeFlags, mountExternal, targetSdkVersion, seInfo,
-                    abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/false,
+                    abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,
                     packageName, packagesForUid, sandboxId,
                     useUsapPool, zygoteArgs);
         } catch (ZygoteStartFailedEx ex) {
@@ -374,7 +377,7 @@
         byte[] bytes = new byte[numBytes];
         inputStream.readFully(bytes);
 
-        String rawList = new String(bytes, StandardCharsets.US_ASCII);
+        final String rawList = new String(bytes, StandardCharsets.US_ASCII);
 
         return Arrays.asList(rawList.split(","));
     }
@@ -659,16 +662,13 @@
     private boolean fetchUsapPoolEnabledProp() {
         boolean origVal = mUsapPoolEnabled;
 
-        final String propertyString =
-                Zygote.getSystemProperty(
-                        DeviceConfig.RuntimeNative.USAP_POOL_ENABLED,
-                        USAP_POOL_ENABLED_DEFAULT);
+        final String propertyString = Zygote.getConfigurationProperty(
+                ZygoteConfig.USAP_POOL_ENABLED, USAP_POOL_ENABLED_DEFAULT);
 
         if (!propertyString.isEmpty()) {
-            mUsapPoolEnabled =
-                    Zygote.getSystemPropertyBoolean(
-                            DeviceConfig.RuntimeNative.USAP_POOL_ENABLED,
-                            Boolean.parseBoolean(USAP_POOL_ENABLED_DEFAULT));
+            mUsapPoolEnabled = Zygote.getConfigurationPropertyBoolean(
+                    ZygoteConfig.USAP_POOL_ENABLED,
+                    Boolean.parseBoolean(USAP_POOL_ENABLED_DEFAULT));
         }
 
         if (origVal != mUsapPoolEnabled) {
@@ -678,12 +678,15 @@
         return origVal != mUsapPoolEnabled;
     }
 
+    private boolean mIsFirstPropCheck = true;
     private long mLastPropCheckTimestamp = 0;
 
     private boolean fetchUsapPoolEnabledPropWithMinInterval() {
         final long currentTimestamp = SystemClock.elapsedRealtime();
 
-        if (currentTimestamp - mLastPropCheckTimestamp >= Zygote.PROPERTY_CHECK_INTERVAL) {
+        if (mIsFirstPropCheck
+                || (currentTimestamp - mLastPropCheckTimestamp >= Zygote.PROPERTY_CHECK_INTERVAL)) {
+            mIsFirstPropCheck = false;
             mLastPropCheckTimestamp = currentTimestamp;
             return fetchUsapPoolEnabledProp();
         }
@@ -919,11 +922,13 @@
                 return primaryZygoteState;
             }
 
-            // The primary zygote didn't match. Try the secondary.
-            attemptConnectionToSecondaryZygote();
+            if (mZygoteSecondarySocketAddress != null) {
+                // The primary zygote didn't match. Try the secondary.
+                attemptConnectionToSecondaryZygote();
 
-            if (secondaryZygoteState.matches(abi)) {
-                return secondaryZygoteState;
+                if (secondaryZygoteState.matches(abi)) {
+                    return secondaryZygoteState;
+                }
             }
         } catch (IOException ioe) {
             throw new ZygoteStartFailedEx("Error connecting to zygote", ioe);
@@ -1071,22 +1076,24 @@
                 return;
             }
 
-            try {
-                attemptConnectionToSecondaryZygote();
-
+            if (mZygoteSecondarySocketAddress != null) {
                 try {
-                    secondaryZygoteState.mZygoteOutputWriter.write(command);
-                    secondaryZygoteState.mZygoteOutputWriter.flush();
+                    attemptConnectionToSecondaryZygote();
 
-                    // Wait for the secondary Zygote to finish its work.
-                    secondaryZygoteState.mZygoteInputStream.readInt();
+                    try {
+                        secondaryZygoteState.mZygoteOutputWriter.write(command);
+                        secondaryZygoteState.mZygoteOutputWriter.flush();
+
+                        // Wait for the secondary Zygote to finish its work.
+                        secondaryZygoteState.mZygoteInputStream.readInt();
+                    } catch (IOException ioe) {
+                        throw new IllegalStateException(
+                                "USAP pool state change cause an irrecoverable error",
+                                ioe);
+                    }
                 } catch (IOException ioe) {
-                    throw new IllegalStateException(
-                            "USAP pool state change cause an irrecoverable error",
-                            ioe);
+                    // No secondary zygote present.  This is expected on some devices.
                 }
-            } catch (IOException ioe) {
-                // No secondary zygote present.  This is expected on some devices.
             }
 
             // Wait for the response from the primary zygote here so the primary/secondary zygotes
diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl
index f114b12..25f67f8 100644
--- a/core/java/android/os/storage/IStorageManager.aidl
+++ b/core/java/android/os/storage/IStorageManager.aidl
@@ -191,4 +191,6 @@
     String translateAppToSystem(String path, int pid, int uid) = 81;
     String translateSystemToApp(String path, int pid, int uid) = 82;
     void commitChanges() = 83;
+    boolean supportsCheckpoint() = 84;
+    void startCheckpoint(int numTries) = 85;
 }
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 27e3914..3e60d51 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -16,6 +16,8 @@
 
 package android.os.storage;
 
+import static android.content.ContentResolver.DEPRECATE_DATA_PREFIX;
+
 import android.annotation.BytesLong;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
@@ -30,6 +32,7 @@
 import android.annotation.WorkerThread;
 import android.app.Activity;
 import android.app.ActivityThread;
+import android.app.AppGlobals;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -1139,6 +1142,12 @@
         if (file == null) {
             return null;
         }
+        final String path = file.getAbsolutePath();
+        if (path.startsWith(DEPRECATE_DATA_PREFIX)) {
+            final Uri uri = ContentResolver.translateDeprecatedDataPath(path);
+            return AppGlobals.getInitialApplication().getSystemService(StorageManager.class)
+                    .getStorageVolume(uri);
+        }
         try {
             file = file.getCanonicalFile();
         } catch (IOException ignored) {
diff --git a/core/java/android/preference/DialogPreference.java b/core/java/android/preference/DialogPreference.java
index e656466..32511e9 100644
--- a/core/java/android/preference/DialogPreference.java
+++ b/core/java/android/preference/DialogPreference.java
@@ -19,6 +19,7 @@
 
 import android.annotation.CallSuper;
 import android.annotation.DrawableRes;
+import android.annotation.Nullable;
 import android.annotation.StringRes;
 import android.annotation.UnsupportedAppUsage;
 import android.app.AlertDialog;
@@ -354,6 +355,7 @@
      * @return the DecorView for the current dialog window, if it exists.
      * If the window does not exist, null is returned.
      */
+    @Nullable
     private View getDecorView() {
         if (mDialog != null && mDialog.getWindow() != null) {
             return mDialog.getWindow().getDecorView();
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 261e5db..6d32f8c 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -31,6 +31,7 @@
 import android.net.Uri;
 import android.provider.Settings.ResetMode;
 import android.util.ArrayMap;
+import android.util.Log;
 import android.util.Pair;
 
 import com.android.internal.annotations.GuardedBy;
@@ -77,6 +78,14 @@
             "activity_manager_native_boot";
 
     /**
+     * Namespace for AttentionManagerService related features.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String NAMESPACE_ATTENTION_MANAGER_SERVICE = "attention_manager_service";
+
+    /**
      * Namespace for autofill feature that provides suggestions across all apps when
      * the user interacts with input fields.
      *
@@ -105,6 +114,14 @@
     public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture";
 
     /**
+     * Namespace for how dex runs. The feature requires a reboot to reach a clean state.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String NAMESPACE_DEX_BOOT = "dex_boot";
+
+    /**
      * Namespace for all Game Driver features.
      *
      * @hide
@@ -122,6 +139,14 @@
     public static final String NAMESPACE_INPUT_NATIVE_BOOT = "input_native_boot";
 
     /**
+     * Namespace for attention-based features provided by on-device machine intelligence.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String NAMESPACE_INTELLIGENCE_ATTENTION = "intelligence_attention";
+
+    /**
      * Namespace for all media native related features.
      *
      * @hide
@@ -138,6 +163,25 @@
     public static final String NAMESPACE_NETD_NATIVE = "netd_native";
 
     /**
+     * Namespace for all runtime related features that don't require a reboot to become active.
+     * There are no feature flags using NAMESPACE_RUNTIME.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String NAMESPACE_RUNTIME = "runtime";
+
+    /**
+     * Namespace for all runtime related features that require system properties for accessing
+     * the feature flags from C++ or Java language code. One example is the app image startup
+     * cache feature use_app_image_startup_cache.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String NAMESPACE_RUNTIME_NATIVE = "runtime_native";
+
+    /**
      * Namespace for all runtime native boot related features. Boot in this case refers to the
      * fact that the properties only take affect after rebooting the device.
      *
@@ -163,79 +207,6 @@
     public static final String NAMESPACE_TEXTCLASSIFIER = "textclassifier";
 
     /**
-     * Namespace for all runtime related features.
-     *
-     * @hide
-     */
-    @SystemApi
-    public interface Runtime {
-        String NAMESPACE = "runtime";
-
-        /**
-         * Whether or not we use the precompiled layout.
-         */
-        String USE_PRECOMPILED_LAYOUT = "view.precompiled_layout_enabled";
-    }
-
-    /**
-     * Namespace for all runtime native related features.
-     *
-     * @hide
-     */
-    @SystemApi
-    public interface RuntimeNative {
-        String NAMESPACE = "runtime_native";
-
-        /**
-         * Zygote flags. See {@link com.internal.os.Zygote}.
-         */
-
-        /**
-         * If {@code true}, enables the unspecialized app process (USAP) pool feature.
-         *
-         * @hide for internal use only
-         */
-        String USAP_POOL_ENABLED = "usap_pool_enabled";
-
-        /**
-         * The maximum number of processes to keep in the USAP pool.
-         *
-         * @hide for internal use only
-         */
-        String USAP_POOL_SIZE_MAX = "usap_pool_size_max";
-
-        /**
-         * The minimum number of processes to keep in the USAP pool.
-         *
-         * @hide for internal use only
-         */
-        String USAP_POOL_SIZE_MIN = "usap_pool_size_min";
-
-        /**
-         * The threshold used to determine if the pool should be refilled.
-         *
-         * @hide for internal use only
-         */
-        String USAP_POOL_REFILL_THRESHOLD = "usap_refill_threshold";
-    }
-
-    /**
-     * Namespace for attention-based features provided by on-device machine intelligence.
-     *
-     * @hide
-     */
-    @SystemApi
-    public interface IntelligenceAttention {
-        String NAMESPACE = "intelligence_attention";
-
-        /** If {@code true}, enables the attention features. */
-        String ATTENTION_ENABLED = "attention_enabled";
-
-        /** Settings for the attention features. */
-        String ATTENTION_SETTINGS = "attention_settings";
-    }
-
-    /**
      * Privacy related properties definitions.
      *
      * @hide
@@ -290,34 +261,6 @@
     }
 
     /**
-     * Namespace for how dex runs.  The feature may requires reboot to a clean state.
-     *
-     * @hide
-     */
-    @SystemApi
-    public interface DexBoot {
-        String NAMESPACE = "dex_boot";
-        String PRIV_APPS_OOB_ENABLED = "priv_apps_oob_enabled";
-        String PRIV_APPS_OOB_WHITELIST = "priv_apps_oob_whitelist";
-    }
-
-    /**
-     * Namespace for {@link AttentionManagerService} related features.
-     *
-     * @hide
-     */
-    @SystemApi
-    public interface AttentionManagerService {
-        String NAMESPACE = "attention_manager_service";
-
-        /** If {@code true}, enables {@link AttentionManagerService} features. */
-        String SERVICE_ENABLED = "service_enabled";
-
-        /** Allows a CTS to inject a fake implementation. */
-        String COMPONENT_NAME = "component_name";
-    }
-
-    /**
      * Namespace for Rollback.
      *
      * @hide
@@ -406,6 +349,7 @@
             new ArrayMap<>();
     @GuardedBy("sLock")
     private static Map<String, Pair<ContentObserver, Integer>> sNamespaces = new HashMap<>();
+    private static final String TAG = "DeviceConfig";
 
     // Should never be invoked
     private DeviceConfig() {
@@ -422,7 +366,7 @@
     @SystemApi
     @TestApi
     @RequiresPermission(READ_DEVICE_CONFIG)
-    public static String getProperty(String namespace, String name) {
+    public static String getProperty(@NonNull String namespace, @NonNull String name) {
         ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver();
         String compositeName = createCompositeName(namespace, name);
         return Settings.Config.getString(contentResolver, compositeName);
@@ -441,7 +385,8 @@
     @SystemApi
     @TestApi
     @RequiresPermission(READ_DEVICE_CONFIG)
-    public static String getString(String namespace, String name, String defaultValue) {
+    public static String getString(@NonNull String namespace, @NonNull String name,
+            @Nullable String defaultValue) {
         String value = getProperty(namespace, name);
         return value != null ? value : defaultValue;
     }
@@ -459,7 +404,8 @@
     @SystemApi
     @TestApi
     @RequiresPermission(READ_DEVICE_CONFIG)
-    public static boolean getBoolean(String namespace, String name, boolean defaultValue) {
+    public static boolean getBoolean(@NonNull String namespace, @NonNull String name,
+            boolean defaultValue) {
         String value = getProperty(namespace, name);
         return value != null ? Boolean.parseBoolean(value) : defaultValue;
     }
@@ -477,11 +423,15 @@
     @SystemApi
     @TestApi
     @RequiresPermission(READ_DEVICE_CONFIG)
-    public static int getInt(String namespace, String name, int defaultValue) {
+    public static int getInt(@NonNull String namespace, @NonNull String name, int defaultValue) {
         String value = getProperty(namespace, name);
+        if (value == null) {
+            return defaultValue;
+        }
         try {
             return Integer.parseInt(value);
         } catch (NumberFormatException e) {
+            Log.e(TAG, "Parsing integer failed for " + namespace + ":" + name);
             return defaultValue;
         }
     }
@@ -499,11 +449,15 @@
     @SystemApi
     @TestApi
     @RequiresPermission(READ_DEVICE_CONFIG)
-    public static long getLong(String namespace, String name, long defaultValue) {
+    public static long getLong(@NonNull String namespace, @NonNull String name, long defaultValue) {
         String value = getProperty(namespace, name);
+        if (value == null) {
+            return defaultValue;
+        }
         try {
             return Long.parseLong(value);
         } catch (NumberFormatException e) {
+            Log.e(TAG, "Parsing long failed for " + namespace + ":" + name);
             return defaultValue;
         }
     }
@@ -521,13 +475,16 @@
     @SystemApi
     @TestApi
     @RequiresPermission(READ_DEVICE_CONFIG)
-    public static float getFloat(String namespace, String name, float defaultValue) {
+    public static float getFloat(@NonNull String namespace, @NonNull String name,
+            float defaultValue) {
         String value = getProperty(namespace, name);
+        if (value == null) {
+            return defaultValue;
+        }
         try {
             return Float.parseFloat(value);
         } catch (NumberFormatException e) {
-            return defaultValue;
-        } catch (NullPointerException e) {
+            Log.e(TAG, "Parsing float failed for " + namespace + ":" + name);
             return defaultValue;
         }
     }
@@ -554,10 +511,10 @@
     @SystemApi
     @TestApi
     @RequiresPermission(WRITE_DEVICE_CONFIG)
-    public static boolean setProperty(
-            String namespace, String name, String value, boolean makeDefault) {
-        ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver();
+    public static boolean setProperty(@NonNull String namespace, @NonNull String name,
+            @Nullable String value, boolean makeDefault) {
         String compositeName = createCompositeName(namespace, name);
+        ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver();
         return Settings.Config.putString(contentResolver, compositeName, value, makeDefault);
     }
 
@@ -700,11 +657,14 @@
         }
     }
 
-    private static String createCompositeName(String namespace, String name) {
+    private static String createCompositeName(@NonNull String namespace, @NonNull String name) {
+        Preconditions.checkNotNull(namespace);
+        Preconditions.checkNotNull(name);
         return namespace + "/" + name;
     }
 
-    private static Uri createNamespaceUri(String namespace) {
+    private static Uri createNamespaceUri(@NonNull String namespace) {
+        Preconditions.checkNotNull(namespace);
         return CONTENT_URI.buildUpon().appendPath(namespace).build();
     }
 
@@ -716,7 +676,8 @@
      * @param namespace The namespace to increment the count for.
      */
     @GuardedBy("sLock")
-    private static void incrementNamespace(String namespace) {
+    private static void incrementNamespace(@NonNull String namespace) {
+        Preconditions.checkNotNull(namespace);
         Pair<ContentObserver, Integer> namespaceCount = sNamespaces.get(namespace);
         if (namespaceCount != null) {
             sNamespaces.put(namespace, new Pair<>(namespaceCount.first, namespaceCount.second + 1));
@@ -725,7 +686,9 @@
             ContentObserver contentObserver = new ContentObserver(null) {
                 @Override
                 public void onChange(boolean selfChange, Uri uri) {
-                    handleChange(uri);
+                    if (uri != null) {
+                        handleChange(uri);
+                    }
                 }
             };
             ActivityThread.currentApplication().getContentResolver()
@@ -742,7 +705,8 @@
      * @param namespace The namespace to decrement the count for.
      */
     @GuardedBy("sLock")
-    private static void decrementNamespace(String namespace) {
+    private static void decrementNamespace(@NonNull String namespace) {
+        Preconditions.checkNotNull(namespace);
         Pair<ContentObserver, Integer> namespaceCount = sNamespaces.get(namespace);
         if (namespaceCount == null) {
             // This namespace is not registered and does not need to be decremented
@@ -757,7 +721,8 @@
         }
     }
 
-    private static void handleChange(Uri uri) {
+    private static void handleChange(@NonNull Uri uri) {
+        Preconditions.checkNotNull(uri);
         List<String> pathSegments = uri.getPathSegments();
         // pathSegments(0) is "config"
         final String namespace = pathSegments.get(1);
@@ -813,7 +778,8 @@
          * @param name      The name of the property which has changed.
          * @param value     The new value of the property which has changed.
          */
-        void onPropertyChanged(String namespace, String name, String value);
+        void onPropertyChanged(@NonNull String namespace, @NonNull String name,
+                @Nullable String value);
     }
 
     /**
@@ -915,9 +881,13 @@
         public int getInt(@NonNull String name, int defaultValue) {
             Preconditions.checkNotNull(name);
             String value = mMap.get(name);
+            if (value == null) {
+                return defaultValue;
+            }
             try {
                 return Integer.parseInt(value);
             } catch (NumberFormatException e) {
+                Log.e(TAG, "Parsing int failed for " + name);
                 return defaultValue;
             }
         }
@@ -933,9 +903,13 @@
         public long getLong(@NonNull String name, long defaultValue) {
             Preconditions.checkNotNull(name);
             String value = mMap.get(name);
+            if (value == null) {
+                return defaultValue;
+            }
             try {
                 return Long.parseLong(value);
             } catch (NumberFormatException e) {
+                Log.e(TAG, "Parsing long failed for " + name);
                 return defaultValue;
             }
         }
@@ -951,11 +925,13 @@
         public float getFloat(@NonNull String name, float defaultValue) {
             Preconditions.checkNotNull(name);
             String value = mMap.get(name);
+            if (value == null) {
+                return defaultValue;
+            }
             try {
                 return Float.parseFloat(value);
             } catch (NumberFormatException e) {
-                return defaultValue;
-            } catch (NullPointerException e) {
+                Log.e(TAG, "Parsing float failed for " + name);
                 return defaultValue;
             }
         }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 4836e6c..313384d 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5590,6 +5590,15 @@
         private static final Validator ALLOW_MOCK_LOCATION_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
+         * Setting to indicate that on device captions are enabled.
+         *
+         * @hide
+         */
+        public static final String ODI_CAPTIONS_ENABLED = "odi_captions_enabled";
+
+        private static final Validator ODI_CAPTIONS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
+        /**
          * On Android 8.0 (API level 26) and higher versions of the platform,
          * a 64-bit number (expressed as a hexadecimal string), unique to
          * each combination of app-signing key, user, and device.
@@ -6335,7 +6344,6 @@
          * Number of times the user has manually clicked the ringer toggle
          * @hide
          */
-        @SystemApi
         public static final String MANUAL_RINGER_TOGGLE_COUNT = "manual_ringer_toggle_count";
 
         private static final Validator MANUAL_RINGER_TOGGLE_COUNT_VALIDATOR =
@@ -8508,9 +8516,15 @@
         @SystemApi
         public static final String VOLUME_HUSH_GESTURE = "volume_hush_gesture";
 
-        /** @hide */ public static final int VOLUME_HUSH_OFF = 0;
-        /** @hide */ public static final int VOLUME_HUSH_VIBRATE = 1;
-        /** @hide */ public static final int VOLUME_HUSH_MUTE = 2;
+        /** @hide */
+        @SystemApi
+        public static final int VOLUME_HUSH_OFF = 0;
+        /** @hide */
+        @SystemApi
+        public static final int VOLUME_HUSH_VIBRATE = 1;
+        /** @hide */
+        @SystemApi
+        public static final int VOLUME_HUSH_MUTE = 2;
 
         private static final Validator VOLUME_HUSH_GESTURE_VALIDATOR =
                 NON_NEGATIVE_INTEGER_VALIDATOR;
@@ -8950,6 +8964,7 @@
             VALIDATORS.put(SILENCE_TIMER_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
             VALIDATORS.put(SILENCE_CALL_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
             VALIDATORS.put(SILENCE_NOTIFICATION_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
+            VALIDATORS.put(ODI_CAPTIONS_ENABLED, ODI_CAPTIONS_ENABLED_VALIDATOR);
         }
 
         /**
@@ -9040,69 +9055,23 @@
          * @deprecated use {@link LocationManager#isProviderEnabled(String)}
          */
         @Deprecated
-        public static final boolean isLocationProviderEnabled(ContentResolver cr, String provider) {
-            return isLocationProviderEnabledForUser(cr, provider, cr.getUserId());
-        }
-
-        /**
-         * Helper method for determining if a location provider is enabled.
-         * @param cr the content resolver to use
-         * @param provider the location provider to query
-         * @param userId the userId to query
-         * @return true if the provider is enabled
-         *
-         * @deprecated use {@link LocationManager#isProviderEnabled(String)}
-         * @hide
-         */
-        @Deprecated
-        public static final boolean isLocationProviderEnabledForUser(
-                ContentResolver cr, String provider, int userId) {
+        public static boolean isLocationProviderEnabled(ContentResolver cr, String provider) {
             String allowedProviders = Settings.Secure.getStringForUser(cr,
-                    LOCATION_PROVIDERS_ALLOWED, userId);
+                    LOCATION_PROVIDERS_ALLOWED, cr.getUserId());
             return TextUtils.delimitedStringContains(allowedProviders, ',', provider);
         }
 
         /**
-         * Thread-safe method for enabling or disabling a single location provider.
+         * Thread-safe method for enabling or disabling a single location provider. This will have
+         * no effect on Android Q and above.
          * @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 This API is deprecated. It requires WRITE_SECURE_SETTINGS permission to
-         *             change location settings.
+         * @deprecated This API is deprecated
          */
         @Deprecated
-        public static final void setLocationProviderEnabled(ContentResolver cr,
+        public static void setLocationProviderEnabled(ContentResolver cr,
                 String provider, boolean enabled) {
-            setLocationProviderEnabledForUser(cr, provider, enabled, cr.getUserId());
-        }
-
-        /**
-         * Thread-safe method for enabling or disabling a single location provider.
-         *
-         * @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
-         * @param userId the userId for which to enable/disable providers
-         * @return true if the value was set, false on database errors
-         *
-         * @deprecated use {@link LocationManager#setProviderEnabledForUser(String, boolean, int)}
-         * @hide
-         */
-        @Deprecated
-        public static final boolean setLocationProviderEnabledForUser(ContentResolver cr,
-                String provider, boolean enabled, int userId) {
-            synchronized (mLocationSettingsLock) {
-                // 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 putStringForUser(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, provider,
-                        userId);
-            }
         }
     }
 
@@ -11508,6 +11477,7 @@
          * service_min_restart_time_between     (long)
          * service_max_inactivity               (long)
          * service_bg_start_timeout             (long)
+         * service_bg_activity_start_timeout    (long)
          * process_start_async                  (boolean)
          * </pre>
          *
@@ -12007,6 +11977,8 @@
          * notification_conversation_action_types_default   (String[])
          * lang_id_threshold_override                       (float)
          * template_intent_factory_enabled                  (boolean)
+         * translate_in_classification_enabled              (boolean)
+         * detect_language_from_text_enabled                (boolean)
          * </pre>
          *
          * <p>
diff --git a/core/java/android/service/appprediction/AppPredictionService.java b/core/java/android/service/appprediction/AppPredictionService.java
index d012851..ff13e03 100644
--- a/core/java/android/service/appprediction/AppPredictionService.java
+++ b/core/java/android/service/appprediction/AppPredictionService.java
@@ -141,7 +141,8 @@
     }
 
     @Override
-    public final IBinder onBind(Intent intent) {
+    @NonNull
+    public final IBinder onBind(@NonNull Intent intent) {
         // TODO(b/111701043): Verify that the action is valid
         return mInterface.asBinder();
     }
diff --git a/core/java/android/service/attention/AttentionService.java b/core/java/android/service/attention/AttentionService.java
index 24d74ff..32f4ea9 100644
--- a/core/java/android/service/attention/AttentionService.java
+++ b/core/java/android/service/attention/AttentionService.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.app.Service;
 import android.content.Intent;
@@ -111,8 +112,9 @@
         }
     };
 
+    @Nullable
     @Override
-    public final IBinder onBind(Intent intent) {
+    public final IBinder onBind(@NonNull Intent intent) {
         if (SERVICE_INTERFACE.equals(intent.getAction())) {
             return mBinder;
         }
diff --git a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
index cd54930..19e216a 100644
--- a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
+++ b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
@@ -405,7 +405,6 @@
         private void update(@NonNull AutofillId focusedId, @NonNull AutofillValue focusedValue,
                 @NonNull IFillCallback callback) {
             synchronized (mLock) {
-                // TODO(b/123099468): should we close the popupwindow if the focused id changed?
                 mFocusedId = focusedId;
                 mFocusedValue = focusedValue;
                 if (mCallback != null) {
diff --git a/core/java/android/service/contentcapture/ActivityEvent.java b/core/java/android/service/contentcapture/ActivityEvent.java
index 7ac380d..5407c1d 100644
--- a/core/java/android/service/contentcapture/ActivityEvent.java
+++ b/core/java/android/service/contentcapture/ActivityEvent.java
@@ -47,10 +47,16 @@
      */
     public static final int TYPE_ACTIVITY_PAUSED = Event.ACTIVITY_PAUSED;
 
+    /**
+     * The activity stopped.
+     */
+    public static final int TYPE_ACTIVITY_STOPPED = Event.ACTIVITY_STOPPED;
+
     /** @hide */
     @IntDef(prefix = { "TYPE_" }, value = {
             TYPE_ACTIVITY_RESUMED,
-            TYPE_ACTIVITY_PAUSED
+            TYPE_ACTIVITY_PAUSED,
+            TYPE_ACTIVITY_STOPPED
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ActivityEventType{}
@@ -89,6 +95,8 @@
                 return "ACTIVITY_RESUMED";
             case TYPE_ACTIVITY_PAUSED:
                 return "ACTIVITY_PAUSED";
+            case TYPE_ACTIVITY_STOPPED:
+                return "ACTIVITY_STOPPED";
             default:
                 return "UKNOWN_TYPE: " + type;
         }
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
index 192abd5..6f4114d 100644
--- a/core/java/android/service/contentcapture/ContentCaptureService.java
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -102,9 +102,10 @@
 
         @Override
         public void onSessionStarted(ContentCaptureContext context, String sessionId, int uid,
-                IResultReceiver clientReceiver) {
+                IResultReceiver clientReceiver, int initialState) {
             mHandler.sendMessage(obtainMessage(ContentCaptureService::handleOnCreateSession,
-                    ContentCaptureService.this, context, sessionId, uid, clientReceiver));
+                    ContentCaptureService.this, context, sessionId, uid, clientReceiver,
+                    initialState));
         }
 
         @Override
@@ -335,7 +336,7 @@
     // so we don't need to create a temporary InteractionSessionId for each event.
 
     private void handleOnCreateSession(@NonNull ContentCaptureContext context,
-            @NonNull String sessionId, int uid, IResultReceiver clientReceiver) {
+            @NonNull String sessionId, int uid, IResultReceiver clientReceiver, int initialState) {
         mSessionUids.put(sessionId, uid);
         onCreateContentCaptureSession(context, new ContentCaptureSessionId(sessionId));
 
@@ -348,7 +349,7 @@
             stateFlags |= ContentCaptureSession.STATE_BY_APP;
         }
         if (stateFlags == 0) {
-            stateFlags = ContentCaptureSession.STATE_ACTIVE;
+            stateFlags = initialState;
         } else {
             stateFlags |= ContentCaptureSession.STATE_DISABLED;
 
diff --git a/core/java/android/service/contentcapture/IContentCaptureService.aidl b/core/java/android/service/contentcapture/IContentCaptureService.aidl
index f32432f..6be7a80 100644
--- a/core/java/android/service/contentcapture/IContentCaptureService.aidl
+++ b/core/java/android/service/contentcapture/IContentCaptureService.aidl
@@ -36,7 +36,7 @@
     void onConnected(IBinder callback, boolean verbose, boolean debug);
     void onDisconnected();
     void onSessionStarted(in ContentCaptureContext context, String sessionId, int uid,
-                          in IResultReceiver clientReceiver);
+                          in IResultReceiver clientReceiver, int initialState);
     void onSessionFinished(String sessionId);
     void onActivitySnapshot(String sessionId, in SnapshotData snapshotData);
     void onUserDataRemovalRequest(in UserDataRemovalRequest request);
diff --git a/core/java/android/service/euicc/EuiccService.java b/core/java/android/service/euicc/EuiccService.java
index a46d047..2288106 100644
--- a/core/java/android/service/euicc/EuiccService.java
+++ b/core/java/android/service/euicc/EuiccService.java
@@ -113,15 +113,27 @@
     public static final String ACTION_PROVISION_EMBEDDED_SUBSCRIPTION =
             "android.service.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION";
 
-    /** @see android.telephony.euicc.EuiccManager#ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED */
+    /**
+     * @see android.telephony.euicc.EuiccManager#ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED. This is
+     * a protected intent that can only be sent by the system, and requires the
+     * {@link android.Manifest.permission#BIND_EUICC_SERVICE} permission.
+     */
     public static final String ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED =
             "android.service.euicc.action.TOGGLE_SUBSCRIPTION_PRIVILEGED";
 
-    /** @see android.telephony.euicc.EuiccManager#ACTION_DELETE_SUBSCRIPTION_PRIVILEGED */
+    /**
+     * @see android.telephony.euicc.EuiccManager#ACTION_DELETE_SUBSCRIPTION_PRIVILEGED. This is
+     * a protected intent that can only be sent by the system, and requires the
+     * {@link android.Manifest.permission#BIND_EUICC_SERVICE} permission.
+     */
     public static final String ACTION_DELETE_SUBSCRIPTION_PRIVILEGED =
             "android.service.euicc.action.DELETE_SUBSCRIPTION_PRIVILEGED";
 
-    /** @see android.telephony.euicc.EuiccManager#ACTION_RENAME_SUBSCRIPTION_PRIVILEGED */
+    /**
+     * @see android.telephony.euicc.EuiccManager#ACTION_RENAME_SUBSCRIPTION_PRIVILEGED. This is
+     * a protected intent that can only be sent by the system, and requires the
+     * {@link android.Manifest.permission#BIND_EUICC_SERVICE} permission.
+     */
     public static final String ACTION_RENAME_SUBSCRIPTION_PRIVILEGED =
             "android.service.euicc.action.RENAME_SUBSCRIPTION_PRIVILEGED";
 
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
index c928da1..32982f9 100644
--- a/core/java/android/text/DynamicLayout.java
+++ b/core/java/android/text/DynamicLayout.java
@@ -674,7 +674,8 @@
             objects[0] = reflowed.getLineDirections(i);
 
             final int end = (i == n - 1) ? where + after : reflowed.getLineStart(i + 1);
-            ints[HYPHEN] = reflowed.getHyphen(i) & HYPHEN_MASK;
+            ints[HYPHEN] = StaticLayout.packHyphenEdit(
+                    reflowed.getStartHyphenEdit(i), reflowed.getEndHyphenEdit(i));
             ints[MAY_PROTRUDE_FROM_TOP_OR_BOTTOM] |=
                     contentMayProtrudeFromLineTopOrBottom(text, start, end) ?
                             MAY_PROTRUDE_FROM_TOP_OR_BOTTOM_MASK : 0;
@@ -1056,8 +1057,16 @@
      * @hide
      */
     @Override
-    public int getHyphen(int line) {
-        return mInts.getValue(line, HYPHEN) & HYPHEN_MASK;
+    public @Paint.StartHyphenEdit int getStartHyphenEdit(int line) {
+        return StaticLayout.unpackStartHyphenEdit(mInts.getValue(line, HYPHEN) & HYPHEN_MASK);
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public @Paint.EndHyphenEdit int getEndHyphenEdit(int line) {
+        return StaticLayout.unpackEndHyphenEdit(mInts.getValue(line, HYPHEN) & HYPHEN_MASK);
     }
 
     private boolean getContentMayProtrudeFromTopOrBottom(int line) {
diff --git a/core/java/android/text/Hyphenator.java b/core/java/android/text/Hyphenator.java
index e4200ac..6f0628a 100644
--- a/core/java/android/text/Hyphenator.java
+++ b/core/java/android/text/Hyphenator.java
@@ -16,142 +16,15 @@
 
 package android.text;
 
-import android.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
 /**
- * Provides constants and pack/unpack methods for the HyphenEdit.
+ * Does the native Hyphenator initialization.
  *
- * Hyphenator provides constant values for start of line and end of line modification.
- * For example, by passing {@link #END_HYPHEN_EDIT_INSERT_HYPHEN} like as follows, HYPHEN(U+2010)
- * character is appended at the end of line.
- *
- * <pre>
- * <code>
- *   Paint paint = new Paint();
- *   paint.setHyphenEdit(Hyphenator.packHyphenEdit(
- *       Hyphenator.START_HYPHEN_EDIT_NO_EDIT,
- *       Hyphenator.END_HYPHEN_EDIT_INSERT_HYPHEN));
- *   paint.measureText("abc", 0, 3);  // Returns the width of "abc‐"
- *   Canvas.drawText("abc", 0, 3, 0f, 0f, paint);  // Draws "abc‐"
- * </code>
- * </pre>
- *
- * @see android.graphics.Paint#setHyphenEdit(int)
+ * @hide
  */
 public class Hyphenator {
     private Hyphenator() {}
 
-    /** @hide */
-    @IntDef(prefix = { "START_HYPHEN_EDIT_" }, value = {
-        START_HYPHEN_EDIT_NO_EDIT,
-        START_HYPHEN_EDIT_INSERT_HYPHEN,
-        START_HYPHEN_EDIT_INSERT_ZWJ
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface StartHyphenEdit {}
-
-    /**
-     * An integer representing the starting of the line has no modification for hyphenation.
-     */
-    public static final int START_HYPHEN_EDIT_NO_EDIT = 0x00;
-
-    /**
-     * An integer representing the starting of the line has normal hyphen character (U+002D).
-     */
-    public static final int START_HYPHEN_EDIT_INSERT_HYPHEN = 0x01;
-
-    /**
-     * An integer representing the starting of the line has Zero-Width-Joiner (U+200D).
-     */
-    public static final int START_HYPHEN_EDIT_INSERT_ZWJ = 0x02;
-
-    /** @hide */
-    @IntDef(prefix = { "END_HYPHEN_EDIT_" }, value = {
-        END_HYPHEN_EDIT_NO_EDIT,
-        END_HYPHEN_EDIT_REPLACE_WITH_HYPHEN,
-        END_HYPHEN_EDIT_INSERT_HYPHEN,
-        END_HYPHEN_EDIT_INSERT_ARMENIAN_HYPHEN,
-        END_HYPHEN_EDIT_INSERT_MAQAF,
-        END_HYPHEN_EDIT_INSERT_UCAS_HYPHEN,
-        END_HYPHEN_EDIT_INSERT_ZWJ_AND_HYPHEN
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface EndHyphenEdit {}
-
-    /**
-     * An integer representing the end of the line has no modification for hyphenation.
-     */
-    public static final int END_HYPHEN_EDIT_NO_EDIT = 0x00;
-
-    /**
-     * An integer representing the character at the end of the line is replaced with hyphen
-     * character (U+002D).
-     */
-    public static final int END_HYPHEN_EDIT_REPLACE_WITH_HYPHEN = 0x01;
-
-    /**
-     * An integer representing the end of the line has normal hyphen character (U+002D).
-     */
-    public static final int END_HYPHEN_EDIT_INSERT_HYPHEN = 0x02;
-
-    /**
-     * An integer representing the end of the line has Armentian hyphen (U+058A).
-     */
-    public static final int END_HYPHEN_EDIT_INSERT_ARMENIAN_HYPHEN = 0x03;
-
-    /**
-     * An integer representing the end of the line has maqaf (Hebrew hyphen, U+05BE).
-     */
-    public static final int END_HYPHEN_EDIT_INSERT_MAQAF = 0x04;
-
-    /**
-     * An integer representing the end of the line has Canadian Syllabics hyphen (U+1400).
-     */
-    public static final int END_HYPHEN_EDIT_INSERT_UCAS_HYPHEN = 0x05;
-
-    /**
-     * An integer representing the end of the line has Zero-Width-Joiner (U+200D) followed by normal
-     * hyphen character (U+002D).
-     */
-    public static final int END_HYPHEN_EDIT_INSERT_ZWJ_AND_HYPHEN = 0x06;
-
-    // Following three constants are used for packing start hyphen edit and end hyphen edit into
-    // single integer. Following encodings must be the same as the minikin's one.
-    // See frameworks/minikin/include/Hyphenator.h for more details.
-    private static final int END_HYPHEN_EDIT_MASK = 0x07;  // 0b00111
-    private static final int START_HYPHEN_EDIT_MASK = 0x18;  // 0b11000
-    private static final int START_HYPHEN_EDIT_SHIFT = 0x03;
-
-    /**
-     * Extract start hyphen edit from packed value.
-     */
-    public static @StartHyphenEdit int unpackStartHyphenEdit(int hyphenEdit) {
-        return (hyphenEdit & START_HYPHEN_EDIT_MASK) >> START_HYPHEN_EDIT_SHIFT;
-    }
-
-    /**
-     * Extract end hyphen edit from packed value.
-     */
-    public static @EndHyphenEdit int unpackEndHyphenEdit(int hyphenEdit) {
-        return hyphenEdit & END_HYPHEN_EDIT_MASK;
-    }
-
-    /**
-     * Pack the start hyphen edit and end hyphen edit into single integer.
-     */
-    public static int packHyphenEdit(@StartHyphenEdit int startHyphenEdit,
-            @EndHyphenEdit int endHyphenEdit) {
-        return ((startHyphenEdit << START_HYPHEN_EDIT_SHIFT) & START_HYPHEN_EDIT_MASK)
-                | (endHyphenEdit & END_HYPHEN_EDIT_MASK);
-    }
-
-
-    /**
-     * @hide
-     */
+    // This method is called from Zygote.
     public static void init() {
         nInit();
     }
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 2d5f3bf..bf0ef94 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -437,7 +437,8 @@
             previousLineEnd = getLineStart(lineNum + 1);
             final boolean justify = isJustificationRequired(lineNum);
             int end = getLineVisibleEnd(lineNum, start, previousLineEnd);
-            paint.setHyphenEdit(getHyphen(lineNum));
+            paint.setStartHyphenEdit(getStartHyphenEdit(lineNum));
+            paint.setEndHyphenEdit(getEndHyphenEdit(lineNum));
 
             int ltop = previousLineBottom;
             int lbottom = getLineTop(lineNum + 1);
@@ -910,12 +911,21 @@
     public abstract int getBottomPadding();
 
     /**
-     * Returns the hyphen edit for a line.
+     * Returns the start hyphen edit for a line.
      *
      * @hide
      */
-    public int getHyphen(int line) {
-        return 0;
+    public @Paint.StartHyphenEdit int getStartHyphenEdit(int line) {
+        return Paint.START_HYPHEN_EDIT_NO_EDIT;
+    }
+
+    /**
+     * Returns the end hyphen edit for a line.
+     *
+     * @hide
+     */
+    public @Paint.EndHyphenEdit int getEndHyphenEdit(int line) {
+        return Paint.END_HYPHEN_EDIT_NO_EDIT;
     }
 
     /**
@@ -1418,7 +1428,8 @@
         final TextLine tl = TextLine.obtain();
         final TextPaint paint = mWorkPaint;
         paint.set(mPaint);
-        paint.setHyphenEdit(getHyphen(line));
+        paint.setStartHyphenEdit(getStartHyphenEdit(line));
+        paint.setEndHyphenEdit(getEndHyphenEdit(line));
         tl.set(paint, mText, start, end, dir, directions, hasTabs, tabStops,
                 getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line));
         if (isJustificationRequired(line)) {
@@ -1447,7 +1458,8 @@
         final TextLine tl = TextLine.obtain();
         final TextPaint paint = mWorkPaint;
         paint.set(mPaint);
-        paint.setHyphenEdit(getHyphen(line));
+        paint.setStartHyphenEdit(getStartHyphenEdit(line));
+        paint.setEndHyphenEdit(getEndHyphenEdit(line));
         tl.set(paint, mText, start, end, dir, directions, hasTabs, tabStops,
                 getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line));
         if (isJustificationRequired(line)) {
@@ -2180,26 +2192,26 @@
      */
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
     public static class TabStops {
-        private int[] mStops;
+        private float[] mStops;
         private int mNumStops;
-        private int mIncrement;
+        private float mIncrement;
 
-        public TabStops(int increment, Object[] spans) {
+        public TabStops(float increment, Object[] spans) {
             reset(increment, spans);
         }
 
-        void reset(int increment, Object[] spans) {
+        void reset(float increment, Object[] spans) {
             this.mIncrement = increment;
 
             int ns = 0;
             if (spans != null) {
-                int[] stops = this.mStops;
+                float[] stops = this.mStops;
                 for (Object o : spans) {
                     if (o instanceof TabStopSpan) {
                         if (stops == null) {
-                            stops = new int[10];
+                            stops = new float[10];
                         } else if (ns == stops.length) {
-                            int[] nstops = new int[ns * 2];
+                            float[] nstops = new float[ns * 2];
                             for (int i = 0; i < ns; ++i) {
                                 nstops[i] = stops[i];
                             }
@@ -2221,9 +2233,9 @@
         float nextTab(float h) {
             int ns = this.mNumStops;
             if (ns > 0) {
-                int[] stops = this.mStops;
+                float[] stops = this.mStops;
                 for (int i = 0; i < ns; ++i) {
-                    int stop = stops[i];
+                    float stop = stops[i];
                     if (stop > h) {
                         return stop;
                     }
@@ -2232,7 +2244,10 @@
             return nextDefaultStop(h, mIncrement);
         }
 
-        public static float nextDefaultStop(float h, int inc) {
+        /**
+         * Returns the position of next tab stop.
+         */
+        public static float nextDefaultStop(float h, float inc) {
             return ((int) ((h + inc) / inc)) * inc;
         }
     }
@@ -2570,7 +2585,7 @@
         ALIGN_RIGHT,
     }
 
-    private static final int TAB_INCREMENT = 20;
+    private static final float TAB_INCREMENT = 20;
 
     /** @hide */
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index defe2ce..69cfc03 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -737,14 +737,14 @@
                 }
             }
             // tab stop locations
-            int[] variableTabStops = null;
+            float[] variableTabStops = null;
             if (spanned != null) {
                 TabStopSpan[] spans = getParagraphSpans(spanned, paraStart,
                         paraEnd, TabStopSpan.class);
                 if (spans.length > 0) {
-                    int[] stops = new int[spans.length];
+                    float[] stops = new float[spans.length];
                     for (int i = 0; i < spans.length; i++) {
-                        stops[i] = spans[i].getTabStop();
+                        stops[i] = (float) spans[i].getTabStop();
                     }
                     Arrays.sort(stops, 0, stops.length);
                     variableTabStops = stops;
@@ -779,7 +779,8 @@
                 ascents[i] = res.getLineAscent(i);
                 descents[i] = res.getLineDescent(i);
                 hasTabs[i] = res.hasLineTab(i);
-                hyphenEdits[i] = res.getLineHyphenEdit(i);
+                hyphenEdits[i] =
+                    packHyphenEdit(res.getStartLineHyphenEdit(i), res.getEndLineHyphenEdit(i));
             }
 
             final int remainingLineCount = mMaximumVisibleLineCount - mLineCount;
@@ -1258,20 +1259,42 @@
         return mBottomPadding;
     }
 
+    // To store into single int field, pack the pair of start and end hyphen edit.
+    static int packHyphenEdit(
+            @Paint.StartHyphenEdit int start, @Paint.EndHyphenEdit int end) {
+        return start << START_HYPHEN_BITS_SHIFT | end;
+    }
+
+    static int unpackStartHyphenEdit(int packedHyphenEdit) {
+        return (packedHyphenEdit & START_HYPHEN_MASK) >> START_HYPHEN_BITS_SHIFT;
+    }
+
+    static int unpackEndHyphenEdit(int packedHyphenEdit) {
+        return packedHyphenEdit & END_HYPHEN_MASK;
+    }
+
     /**
-     * Returns the packed hyphen edit value for this line.
-     *
-     * You can extract start hyphen edit and end hyphen edit by using
-     * {@link Hyphenator#unpackStartHyphenEdit(int)} and
-     * {@link Hyphenator#unpackEndHyphenEdit(int)}.
+     * Returns the start hyphen edit value for this line.
      *
      * @param lineNumber a line number
-     * @return A packed hyphen edit value.
+     * @return A start hyphen edit value.
      * @hide
      */
     @Override
-    public int getHyphen(int lineNumber) {
-        return mLines[mColumns * lineNumber + HYPHEN] & HYPHEN_MASK;
+    public @Paint.StartHyphenEdit int getStartHyphenEdit(int lineNumber) {
+        return unpackStartHyphenEdit(mLines[mColumns * lineNumber + HYPHEN] & HYPHEN_MASK);
+    }
+
+    /**
+     * Returns the packed hyphen edit value for this line.
+     *
+     * @param lineNumber a line number
+     * @return An end hyphen edit value.
+     * @hide
+     */
+    @Override
+    public @Paint.EndHyphenEdit int getEndHyphenEdit(int lineNumber) {
+        return unpackEndHyphenEdit(mLines[mColumns * lineNumber + HYPHEN] & HYPHEN_MASK);
     }
 
     /**
@@ -1395,8 +1418,11 @@
     private static final int DIR_SHIFT  = 30;
     private static final int TAB_MASK   = 0x20000000;
     private static final int HYPHEN_MASK = 0xFF;
+    private static final int START_HYPHEN_BITS_SHIFT = 3;
+    private static final int START_HYPHEN_MASK = 0x18; // 0b11000
+    private static final int END_HYPHEN_MASK = 0x7;  // 0b00111
 
-    private static final int TAB_INCREMENT = 20; // same as Layout, but that's private
+    private static final float TAB_INCREMENT = 20; // same as Layout, but that's private
 
     private static final char CHAR_NEW_LINE = '\n';
 
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 915a18e..8665106 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -1012,19 +1012,14 @@
         return runIsRtl ? -ret : ret;
     }
 
-    private int adjustHyphenEdit(int start, int limit, int packedHyphenEdit) {
-        int result = packedHyphenEdit;
-        // Only draw hyphens on first or last run in line. Disable them otherwise.
-        if (start > 0) { // not the first run
-            result = Hyphenator.packHyphenEdit(Hyphenator.START_HYPHEN_EDIT_NO_EDIT,
-                    Hyphenator.unpackEndHyphenEdit(packedHyphenEdit));
-        }
-        if (limit < mLen) { // not the last run
-            result = Hyphenator.packHyphenEdit(Hyphenator.unpackStartHyphenEdit(packedHyphenEdit),
-                    Hyphenator.END_HYPHEN_EDIT_NO_EDIT);
-            result &= ~Paint.HYPHENEDIT_MASK_END_OF_LINE;
-        }
-        return result;
+    private int adjustStartHyphenEdit(int start, @Paint.StartHyphenEdit int startHyphenEdit) {
+        // Only draw hyphens on first in line. Disable them otherwise.
+        return start > 0 ? Paint.START_HYPHEN_EDIT_NO_EDIT : startHyphenEdit;
+    }
+
+    private int adjustEndHyphenEdit(int limit, @Paint.EndHyphenEdit int endHyphenEdit) {
+        // Only draw hyphens on last run in line. Disable them otherwise.
+        return limit < mLen ? Paint.END_HYPHEN_EDIT_NO_EDIT : endHyphenEdit;
     }
 
     private static final class DecorationInfo {
@@ -1115,7 +1110,8 @@
         if (!needsSpanMeasurement) {
             final TextPaint wp = mWorkPaint;
             wp.set(mPaint);
-            wp.setHyphenEdit(adjustHyphenEdit(start, limit, wp.getHyphenEdit()));
+            wp.setStartHyphenEdit(adjustStartHyphenEdit(start, wp.getStartHyphenEdit()));
+            wp.setEndHyphenEdit(adjustEndHyphenEdit(limit, wp.getEndHyphenEdit()));
             return handleText(wp, start, limit, start, limit, runIsRtl, c, x, top,
                     y, bottom, fmi, needWidth, measureLimit, null);
         }
@@ -1193,8 +1189,10 @@
                     // The style of the present chunk of text is substantially different from the
                     // style of the previous chunk. We need to handle the active piece of text
                     // and restart with the present chunk.
-                    activePaint.setHyphenEdit(adjustHyphenEdit(
-                            activeStart, activeEnd, mPaint.getHyphenEdit()));
+                    activePaint.setStartHyphenEdit(
+                            adjustStartHyphenEdit(activeStart, mPaint.getStartHyphenEdit()));
+                    activePaint.setEndHyphenEdit(
+                            adjustEndHyphenEdit(activeEnd, mPaint.getEndHyphenEdit()));
                     x += handleText(activePaint, activeStart, activeEnd, i, inext, runIsRtl, c, x,
                             top, y, bottom, fmi, needWidth || activeEnd < measureLimit,
                             Math.min(activeEnd, mlimit), mDecorations);
@@ -1218,8 +1216,10 @@
                 }
             }
             // Handle the final piece of text.
-            activePaint.setHyphenEdit(adjustHyphenEdit(
-                    activeStart, activeEnd, mPaint.getHyphenEdit()));
+            activePaint.setStartHyphenEdit(
+                    adjustStartHyphenEdit(activeStart, mPaint.getStartHyphenEdit()));
+            activePaint.setEndHyphenEdit(
+                    adjustEndHyphenEdit(activeEnd, mPaint.getEndHyphenEdit()));
             x += handleText(activePaint, activeStart, activeEnd, i, inext, runIsRtl, c, x,
                     top, y, bottom, fmi, needWidth || activeEnd < measureLimit,
                     Math.min(activeEnd, mlimit), mDecorations);
@@ -1323,7 +1323,8 @@
                 && lp.getTextSkewX() == rp.getTextSkewX()
                 && lp.getLetterSpacing() == rp.getLetterSpacing()
                 && lp.getWordSpacing() == rp.getWordSpacing()
-                && lp.getHyphenEdit() == rp.getHyphenEdit()
+                && lp.getStartHyphenEdit() == rp.getStartHyphenEdit()
+                && lp.getEndHyphenEdit() == rp.getEndHyphenEdit()
                 && lp.bgColor == rp.bgColor
                 && lp.baselineShift == rp.baselineShift
                 && lp.linkColor == rp.linkColor
diff --git a/core/java/android/text/style/ImageSpan.java b/core/java/android/text/style/ImageSpan.java
index 13ac9ff..98f58be 100644
--- a/core/java/android/text/style/ImageSpan.java
+++ b/core/java/android/text/style/ImageSpan.java
@@ -46,10 +46,10 @@
  * <p>
  * For example, an <code>ImagedSpan</code> can be used like this:
  * <pre>
- * SpannableString string = SpannableString("Bottom: span.\nBaseline: span.");
+ * SpannableString string = new SpannableString("Bottom: span.\nBaseline: span.");
  * // using the default alignment: ALIGN_BOTTOM
- * string.setSpan(ImageSpan(this, R.mipmap.ic_launcher), 7, 8, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- * string.setSpan(ImageSpan(this, R.mipmap.ic_launcher, DynamicDrawableSpan.ALIGN_BASELINE),
+ * string.setSpan(new ImageSpan(this, R.mipmap.ic_launcher), 7, 8, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ * string.setSpan(new ImageSpan(this, R.mipmap.ic_launcher, DynamicDrawableSpan.ALIGN_BASELINE),
  * 22, 23, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
  * </pre>
  * <img src="{@docRoot}reference/android/images/text/style/imagespan.png" />
diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java
index e2af6f5..436cb4f 100644
--- a/core/java/android/util/ArrayMap.java
+++ b/core/java/android/util/ArrayMap.java
@@ -16,12 +16,12 @@
 
 package android.util;
 
+import libcore.util.EmptyArray;
+
 import android.annotation.UnsupportedAppUsage;
 
 import com.android.internal.util.ArrayUtils;
 
-import libcore.util.EmptyArray;
-
 import java.util.Collection;
 import java.util.ConcurrentModificationException;
 import java.util.Map;
@@ -453,10 +453,6 @@
      * @return Returns the key stored at the given index.
      */
     public K keyAt(int index) {
-        if (index >= mSize) {
-            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
-            throw new ArrayIndexOutOfBoundsException(index);
-        }
         return (K)mArray[index << 1];
     }
 
@@ -466,10 +462,6 @@
      * @return Returns the value stored at the given index.
      */
     public V valueAt(int index) {
-        if (index >= mSize) {
-            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
-            throw new ArrayIndexOutOfBoundsException(index);
-        }
         return (V)mArray[(index << 1) + 1];
     }
 
@@ -480,10 +472,6 @@
      * @return Returns the previous value at the given index.
      */
     public V setValueAt(int index, V value) {
-        if (index >= mSize) {
-            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
-            throw new ArrayIndexOutOfBoundsException(index);
-        }
         index = (index << 1) + 1;
         V old = (V)mArray[index];
         mArray[index] = value;
@@ -677,11 +665,6 @@
      * @return Returns the value that was stored at this index.
      */
     public V removeAt(int index) {
-        if (index >= mSize) {
-            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
-            throw new ArrayIndexOutOfBoundsException(index);
-        }
-
         final Object old = mArray[(index << 1) + 1];
         final int osize = mSize;
         final int nsize;
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index c4f815b..c1504ae 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -51,7 +51,6 @@
         DEFAULT_FLAGS.put("settings_network_and_internet_v2", "true");
         DEFAULT_FLAGS.put("settings_slice_injection", "true");
         DEFAULT_FLAGS.put("settings_systemui_theme", "true");
-        DEFAULT_FLAGS.put("settings_wifi_mac_randomization", "true");
         DEFAULT_FLAGS.put("settings_mainline_module", "false");
         DEFAULT_FLAGS.put("settings_dynamic_android", "false");
         DEFAULT_FLAGS.put(SEAMLESS_TRANSFER, "false");
@@ -61,6 +60,7 @@
         DEFAULT_FLAGS.put(GLOBAL_ACTIONS_GRID_ENABLED, "true");
         DEFAULT_FLAGS.put(GLOBAL_ACTIONS_PANEL_ENABLED, "true");
         DEFAULT_FLAGS.put("settings_wifi_details_saved_screen", "false");
+        DEFAULT_FLAGS.put("settings_wifi_details_datausage_header", "false");
     }
 
     /**
diff --git a/core/java/android/util/LongSparseArray.java b/core/java/android/util/LongSparseArray.java
index e4de704..cf49803 100644
--- a/core/java/android/util/LongSparseArray.java
+++ b/core/java/android/util/LongSparseArray.java
@@ -21,6 +21,9 @@
 
 import libcore.util.EmptyArray;
 
+import java.util.Arrays;
+import java.util.Objects;
+
 /**
  * SparseArray mapping longs to Objects.  Unlike a normal array of Objects,
  * there can be gaps in the indices.  It is intended to be more memory efficient
@@ -144,10 +147,6 @@
      * Removes the mapping at the specified index.
      */
     public void removeAt(int index) {
-        if (index >= mSize) {
-            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
-            throw new ArrayIndexOutOfBoundsException(index);
-        }
         if (mValues[index] != DELETED) {
             mValues[index] = DELETED;
             mGarbage = true;
@@ -237,10 +236,6 @@
      * key.</p>
      */
     public long keyAt(int index) {
-        if (index >= mSize) {
-            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
-            throw new ArrayIndexOutOfBoundsException(index);
-        }
         if (mGarbage) {
             gc();
         }
@@ -261,10 +256,6 @@
      */
     @SuppressWarnings("unchecked")
     public E valueAt(int index) {
-        if (index >= mSize) {
-            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
-            throw new ArrayIndexOutOfBoundsException(index);
-        }
         if (mGarbage) {
             gc();
         }
@@ -278,10 +269,6 @@
      * LongSparseArray stores.
      */
     public void setValueAt(int index, E value) {
-        if (index >= mSize) {
-            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
-            throw new ArrayIndexOutOfBoundsException(index);
-        }
         if (mGarbage) {
             gc();
         }
diff --git a/core/java/android/util/LongSparseLongArray.java b/core/java/android/util/LongSparseLongArray.java
index f167f00..8dcdb40 100644
--- a/core/java/android/util/LongSparseLongArray.java
+++ b/core/java/android/util/LongSparseLongArray.java
@@ -16,13 +16,14 @@
 
 package android.util;
 
-import android.annotation.UnsupportedAppUsage;
-
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.GrowingArrayUtils;
 
+import android.annotation.UnsupportedAppUsage;
 import libcore.util.EmptyArray;
 
+import java.util.Arrays;
+
 /**
  * Map of {@code long} to {@code long}. Unlike a normal array of longs, there
  * can be gaps in the indices. It is intended to be more memory efficient than using a
@@ -172,10 +173,6 @@
      * key.</p>
      */
     public long keyAt(int index) {
-        if (index >= mSize) {
-            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
-            throw new ArrayIndexOutOfBoundsException(index);
-        }
         return mKeys[index];
     }
 
@@ -191,10 +188,6 @@
      * associated with the largest key.</p>
      */
     public long valueAt(int index) {
-        if (index >= mSize) {
-            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
-            throw new ArrayIndexOutOfBoundsException(index);
-        }
         return mValues[index];
     }
 
diff --git a/core/java/android/util/OWNERS b/core/java/android/util/OWNERS
index 86ed122..98297fb 100644
--- a/core/java/android/util/OWNERS
+++ b/core/java/android/util/OWNERS
@@ -1,2 +1,3 @@
 per-file FeatureFlagUtils.java = sbasi@google.com
 per-file FeatureFlagUtils.java = zhfan@google.com
+per-file FeatureFlagUtils.java = asapperstein@google.com
diff --git a/core/java/android/util/SparseArray.java b/core/java/android/util/SparseArray.java
index 67dfb02..89ea2d3 100644
--- a/core/java/android/util/SparseArray.java
+++ b/core/java/android/util/SparseArray.java
@@ -16,11 +16,10 @@
 
 package android.util;
 
-import android.annotation.UnsupportedAppUsage;
-
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.GrowingArrayUtils;
 
+import android.annotation.UnsupportedAppUsage;
 import libcore.util.EmptyArray;
 
 /**
@@ -172,10 +171,6 @@
      * the behavior is undefined.</p>
      */
     public void removeAt(int index) {
-        if (index >= mSize) {
-            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
-            throw new ArrayIndexOutOfBoundsException(index);
-        }
         if (mValues[index] != DELETED) {
             mValues[index] = DELETED;
             mGarbage = true;
@@ -284,10 +279,6 @@
      * the behavior is undefined.</p>
      */
     public int keyAt(int index) {
-        if (index >= mSize) {
-            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
-            throw new ArrayIndexOutOfBoundsException(index);
-        }
         if (mGarbage) {
             gc();
         }
@@ -311,10 +302,6 @@
      */
     @SuppressWarnings("unchecked")
     public E valueAt(int index) {
-        if (index >= mSize) {
-            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
-            throw new ArrayIndexOutOfBoundsException(index);
-        }
         if (mGarbage) {
             gc();
         }
@@ -330,10 +317,6 @@
      * <p>For indices outside of the range <code>0...size()-1</code>, the behavior is undefined.</p>
      */
     public void setValueAt(int index, E value) {
-        if (index >= mSize) {
-            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
-            throw new ArrayIndexOutOfBoundsException(index);
-        }
         if (mGarbage) {
             gc();
         }
diff --git a/core/java/android/util/SparseBooleanArray.java b/core/java/android/util/SparseBooleanArray.java
index 03fa1c9..d4c4095 100644
--- a/core/java/android/util/SparseBooleanArray.java
+++ b/core/java/android/util/SparseBooleanArray.java
@@ -16,11 +16,10 @@
 
 package android.util;
 
-import android.annotation.UnsupportedAppUsage;
-
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.GrowingArrayUtils;
 
+import android.annotation.UnsupportedAppUsage;
 import libcore.util.EmptyArray;
 
 /**
@@ -168,10 +167,6 @@
      * key.</p>
      */
     public int keyAt(int index) {
-        if (index >= mSize) {
-            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
-            throw new ArrayIndexOutOfBoundsException(index);
-        }
         return mKeys[index];
     }
 
@@ -187,10 +182,6 @@
      * associated with the largest key.</p>
      */
     public boolean valueAt(int index) {
-        if (index >= mSize) {
-            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
-            throw new ArrayIndexOutOfBoundsException(index);
-        }
         return mValues[index];
     }
 
@@ -198,19 +189,11 @@
      * Directly set the value at a particular index.
      */
     public void setValueAt(int index, boolean value) {
-        if (index >= mSize) {
-            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
-            throw new ArrayIndexOutOfBoundsException(index);
-        }
         mValues[index] = value;
     }
 
     /** @hide */
     public void setKeyAt(int index, int key) {
-        if (index >= mSize) {
-            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
-            throw new ArrayIndexOutOfBoundsException(index);
-        }
         mKeys[index] = key;
     }
 
diff --git a/core/java/android/util/SparseIntArray.java b/core/java/android/util/SparseIntArray.java
index c68dc4e..9e6bad1 100644
--- a/core/java/android/util/SparseIntArray.java
+++ b/core/java/android/util/SparseIntArray.java
@@ -16,15 +16,14 @@
 
 package android.util;
 
-import android.annotation.UnsupportedAppUsage;
-
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.GrowingArrayUtils;
 
-import libcore.util.EmptyArray;
-
 import java.util.Arrays;
 
+import android.annotation.UnsupportedAppUsage;
+import libcore.util.EmptyArray;
+
 /**
  * SparseIntArrays map integers to integers.  Unlike a normal array of integers,
  * there can be gaps in the indices.  It is intended to be more memory efficient
@@ -172,10 +171,6 @@
      * key.</p>
      */
     public int keyAt(int index) {
-        if (index >= mSize) {
-            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
-            throw new ArrayIndexOutOfBoundsException(index);
-        }
         return mKeys[index];
     }
 
@@ -191,10 +186,6 @@
      * associated with the largest key.</p>
      */
     public int valueAt(int index) {
-        if (index >= mSize) {
-            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
-            throw new ArrayIndexOutOfBoundsException(index);
-        }
         return mValues[index];
     }
 
@@ -202,10 +193,6 @@
      * Directly set the value at a particular index.
      */
     public void setValueAt(int index, int value) {
-        if (index >= mSize) {
-            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
-            throw new ArrayIndexOutOfBoundsException(index);
-        }
         mValues[index] = value;
     }
 
diff --git a/core/java/android/util/SparseLongArray.java b/core/java/android/util/SparseLongArray.java
index 37a9202..81db2b7 100644
--- a/core/java/android/util/SparseLongArray.java
+++ b/core/java/android/util/SparseLongArray.java
@@ -182,10 +182,6 @@
      * key.</p>
      */
     public int keyAt(int index) {
-        if (index >= mSize) {
-            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
-            throw new ArrayIndexOutOfBoundsException(index);
-        }
         return mKeys[index];
     }
 
@@ -201,10 +197,6 @@
      * associated with the largest key.</p>
      */
     public long valueAt(int index) {
-        if (index >= mSize) {
-            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
-            throw new ArrayIndexOutOfBoundsException(index);
-        }
         return mValues[index];
     }
 
diff --git a/core/java/android/view/GestureDetector.java b/core/java/android/view/GestureDetector.java
index c794a69..c1d122a 100644
--- a/core/java/android/view/GestureDetector.java
+++ b/core/java/android/view/GestureDetector.java
@@ -16,11 +16,20 @@
 
 package android.view;
 
+import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS;
+import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DOUBLE_TAP;
+import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS;
+import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SCROLL;
+import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP;
+import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION;
+
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Build;
 import android.os.Handler;
 import android.os.Message;
+import android.os.SystemClock;
+import android.util.StatsLog;
 
 /**
  * Detects various gestures and events using the supplied {@link MotionEvent}s.
@@ -251,8 +260,12 @@
     private boolean mAlwaysInTapRegion;
     private boolean mAlwaysInBiggerTapRegion;
     private boolean mIgnoreNextUpEvent;
+    // Whether a classification has been recorded by statsd for the current event stream. Reset on
+    // ACTION_DOWN.
+    private boolean mHasRecordedClassification;
 
     private MotionEvent mCurrentDownEvent;
+    private MotionEvent mCurrentMotionEvent;
     private MotionEvent mPreviousUpEvent;
 
     /**
@@ -297,6 +310,7 @@
                     break;
 
                 case LONG_PRESS:
+                    recordGestureClassification(msg.arg1);
                     dispatchLongPress();
                     break;
 
@@ -304,6 +318,8 @@
                     // If the user's finger is still down, do not count it as a tap
                     if (mDoubleTapListener != null) {
                         if (!mStillDown) {
+                            recordGestureClassification(
+                                    TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP);
                             mDoubleTapListener.onSingleTapConfirmed(mCurrentDownEvent);
                         } else {
                             mDeferConfirmSingleTap = true;
@@ -501,6 +517,11 @@
 
         final int action = ev.getAction();
 
+        if (mCurrentMotionEvent != null) {
+            mCurrentMotionEvent.recycle();
+        }
+        mCurrentMotionEvent = MotionEvent.obtain(ev);
+
         if (mVelocityTracker == null) {
             mVelocityTracker = VelocityTracker.obtain();
         }
@@ -569,6 +590,8 @@
                             && isConsideredDoubleTap(mCurrentDownEvent, mPreviousUpEvent, ev)) {
                         // This is a second tap
                         mIsDoubleTapping = true;
+                        recordGestureClassification(
+                                TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DOUBLE_TAP);
                         // Give a callback with the first tap of the double-tap
                         handled |= mDoubleTapListener.onDoubleTap(mCurrentDownEvent);
                         // Give a callback with down event of the double-tap
@@ -590,11 +613,17 @@
                 mStillDown = true;
                 mInLongPress = false;
                 mDeferConfirmSingleTap = false;
+                mHasRecordedClassification = false;
 
                 if (mIsLongpressEnabled) {
                     mHandler.removeMessages(LONG_PRESS);
-                    mHandler.sendEmptyMessageAtTime(LONG_PRESS, mCurrentDownEvent.getDownTime()
-                            + ViewConfiguration.getLongPressTimeout());
+                    mHandler.sendMessageAtTime(
+                            mHandler.obtainMessage(
+                                    LONG_PRESS,
+                                    TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS,
+                                    0 /* arg2 */),
+                            mCurrentDownEvent.getDownTime()
+                                    + ViewConfiguration.getLongPressTimeout());
                 }
                 mHandler.sendEmptyMessageAtTime(SHOW_PRESS,
                         mCurrentDownEvent.getDownTime() + TAP_TIMEOUT);
@@ -613,6 +642,8 @@
                 final float scrollY = mLastFocusY - focusY;
                 if (mIsDoubleTapping) {
                     // Give the move events of the double-tap
+                    recordGestureClassification(
+                            TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DOUBLE_TAP);
                     handled |= mDoubleTapListener.onDoubleTapEvent(ev);
                 } else if (mAlwaysInTapRegion) {
                     final int deltaX = (int) (focusX - mDownFocusX);
@@ -635,8 +666,12 @@
                             // reschedule long press with a modified timeout.
                             mHandler.removeMessages(LONG_PRESS);
                             final long longPressTimeout = ViewConfiguration.getLongPressTimeout();
-                            mHandler.sendEmptyMessageAtTime(LONG_PRESS, ev.getDownTime()
-                                    + (long) (longPressTimeout * multiplier));
+                            mHandler.sendMessageAtTime(
+                                    mHandler.obtainMessage(
+                                            LONG_PRESS,
+                                            TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS,
+                                            0 /* arg2 */),
+                                    ev.getDownTime() + (long) (longPressTimeout * multiplier));
                         }
                         // Inhibit default scroll. If a gesture is ambiguous, we prevent scroll
                         // until the gesture is resolved.
@@ -646,6 +681,8 @@
                     }
 
                     if (distance > slopSquare) {
+                        recordGestureClassification(
+                                TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SCROLL);
                         handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY);
                         mLastFocusX = focusX;
                         mLastFocusY = focusY;
@@ -659,6 +696,7 @@
                         mAlwaysInBiggerTapRegion = false;
                     }
                 } else if ((Math.abs(scrollX) >= 1) || (Math.abs(scrollY) >= 1)) {
+                    recordGestureClassification(TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SCROLL);
                     handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY);
                     mLastFocusX = focusX;
                     mLastFocusY = focusY;
@@ -667,7 +705,11 @@
                         motionClassification == MotionEvent.CLASSIFICATION_DEEP_PRESS;
                 if (deepPress && hasPendingLongPress) {
                     mHandler.removeMessages(LONG_PRESS);
-                    mHandler.sendEmptyMessage(LONG_PRESS);
+                    mHandler.sendMessage(
+                            mHandler.obtainMessage(
+                                  LONG_PRESS,
+                                  TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS,
+                                  0 /* arg2 */));
                 }
                 break;
 
@@ -676,11 +718,15 @@
                 MotionEvent currentUpEvent = MotionEvent.obtain(ev);
                 if (mIsDoubleTapping) {
                     // Finally, give the up event of the double-tap
+                    recordGestureClassification(
+                            TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DOUBLE_TAP);
                     handled |= mDoubleTapListener.onDoubleTapEvent(ev);
                 } else if (mInLongPress) {
                     mHandler.removeMessages(TAP);
                     mInLongPress = false;
                 } else if (mAlwaysInTapRegion && !mIgnoreNextUpEvent) {
+                    recordGestureClassification(
+                            TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP);
                     handled = mListener.onSingleTapUp(ev);
                     if (mDeferConfirmSingleTap && mDoubleTapListener != null) {
                         mDoubleTapListener.onSingleTapConfirmed(ev);
@@ -821,4 +867,21 @@
         mInLongPress = true;
         mListener.onLongPress(mCurrentDownEvent);
     }
+
+    private void recordGestureClassification(int classification) {
+        if (mHasRecordedClassification
+                || classification
+                    == TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION) {
+            // Only record the first classification for an event stream.
+            return;
+        }
+        StatsLog.write(
+                StatsLog.TOUCH_GESTURE_CLASSIFIED,
+                getClass().getName(),
+                classification,
+                (int) (SystemClock.uptimeMillis() - mCurrentMotionEvent.getDownTime()),
+                (float) Math.hypot(mCurrentMotionEvent.getRawX() - mCurrentDownEvent.getRawX(),
+                                   mCurrentMotionEvent.getRawY() - mCurrentDownEvent.getRawY()));
+        mHasRecordedClassification = true;
+    }
 }
diff --git a/core/java/android/view/InputWindowHandle.java b/core/java/android/view/InputWindowHandle.java
index ec79eea..16a6412 100644
--- a/core/java/android/view/InputWindowHandle.java
+++ b/core/java/android/view/InputWindowHandle.java
@@ -18,9 +18,12 @@
 
 import static android.view.Display.INVALID_DISPLAY;
 
+import android.annotation.Nullable;
 import android.graphics.Region;
 import android.os.IBinder;
 
+import java.lang.ref.WeakReference;
+
 /**
  * Functions as a handle for a window that can receive input.
  * Enables the native input dispatcher to refer indirectly to the window manager's window state.
@@ -38,7 +41,7 @@
     // The client window.
     public final IWindow clientWindow;
 
-    // The token assosciated with the window.
+    // The token associated with the window.
     public IBinder token;
 
     // The window name.
@@ -98,6 +101,23 @@
     // transports the touch of this window to the display indicated by portalToDisplayId.
     public int portalToDisplayId = INVALID_DISPLAY;
 
+    /**
+     * Crops the touchable region to the bounds of the surface provided.
+     *
+     * This can be used in cases where the window is not
+     * {@link android.view.WindowManager#FLAG_NOT_TOUCH_MODAL} but should be constrained to the
+     * bounds of a parent window. That is the window should receive touch events outside its
+     * window but be limited to its stack bounds, such as in the case of split screen.
+     */
+    public WeakReference<IBinder> touchableRegionCropHandle = new WeakReference<>(null);
+
+    /**
+     * Replace {@link touchableRegion} with the bounds of {@link touchableRegionCropHandle}. If
+     * the handle is {@code null}, the bounds of the surface associated with this window is used
+     * as the touchable region.
+     */
+    public boolean replaceTouchableRegionWithCrop;
+
     private native void nativeDispose();
 
     public InputWindowHandle(InputApplicationHandle inputApplicationHandle,
@@ -127,4 +147,25 @@
             super.finalize();
         }
     }
+
+    /**
+     * Set the window touchable region to the bounds of {@link touchableRegionBounds} ignoring any
+     * touchable region provided.
+     *
+     * @param bounds surface to set the touchable region to. Set to {@code null} to set the bounds
+     * to the current surface.
+     */
+    public void replaceTouchableRegionWithCrop(@Nullable SurfaceControl bounds) {
+        setTouchableRegionCrop(bounds);
+        replaceTouchableRegionWithCrop = true;
+    }
+
+    /**
+     * Crop the window touchable region to the bounds of the surface provided.
+     */
+    public void setTouchableRegionCrop(@Nullable SurfaceControl bounds) {
+        if (bounds != null) {
+            touchableRegionCropHandle = new WeakReference<>(bounds.getHandle());
+        }
+    }
 }
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index 2e27737..35cf129 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -83,6 +83,10 @@
     private static final boolean DEBUG = false;
 
     private static final String COMPILED_VIEW_DEX_FILE_NAME = "/compiled_view.dex";
+    /**
+     * Whether or not we use the precompiled layout.
+     */
+    private static final String USE_PRECOMPILED_LAYOUT = "view.precompiled_layout_enabled";
 
     /** Empty stack trace used to avoid log spam in re-throw exceptions. */
     private static final StackTraceElement[] EMPTY_STACK_TRACE = new StackTraceElement[0];
@@ -416,15 +420,15 @@
         String usePrecompiledLayout = null;
         try {
             usePrecompiledLayout = DeviceConfig.getProperty(
-                    DeviceConfig.Runtime.NAMESPACE,
-                    DeviceConfig.Runtime.USE_PRECOMPILED_LAYOUT);
+                    DeviceConfig.NAMESPACE_RUNTIME,
+                    USE_PRECOMPILED_LAYOUT);
         } catch (Exception e) {
           // May be caused by permission errors reading the property (i.e. instant apps).
         }
         boolean enabled = false;
         if (TextUtils.isEmpty(usePrecompiledLayout)) {
             enabled = SystemProperties.getBoolean(
-                    DeviceConfig.Runtime.USE_PRECOMPILED_LAYOUT,
+                    USE_PRECOMPILED_LAYOUT,
                     false);
         } else {
             enabled = Boolean.parseBoolean(usePrecompiledLayout);
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 998ad2a..cd075bf 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -63,6 +63,7 @@
 import java.io.Closeable;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
+import java.util.Objects;
 
 /**
  * Handle to an on-screen Surface managed by the system compositor. The SurfaceControl is
@@ -196,6 +197,9 @@
     private static native boolean nativeGetProtectedContentSupport();
     private static native void nativeSetMetadata(long transactionObj, int key, Parcel data);
     private static native void nativeSyncInputWindows(long transactionObj);
+    private static native boolean nativeGetDisplayBrightnessSupport(IBinder displayToken);
+    private static native boolean nativeSetDisplayBrightness(IBinder displayToken,
+            float brightness);
 
     private final CloseGuard mCloseGuard = CloseGuard.get();
     private String mName;
@@ -1961,6 +1965,47 @@
     }
 
     /**
+     * Returns whether brightness operations are supported on a display.
+     *
+     * @param displayToken
+     *      The token for the display.
+     *
+     * @return Whether brightness operations are supported on the display.
+     *
+     * @hide
+     */
+    public static boolean getDisplayBrightnessSupport(IBinder displayToken) {
+        return nativeGetDisplayBrightnessSupport(displayToken);
+    }
+
+    /**
+     * Sets the brightness of a display.
+     *
+     * @param displayToken
+     *      The token for the display whose brightness is set.
+     * @param brightness
+     *      A number between 0.0f (minimum brightness) and 1.0f (maximum brightness), or -1.0f to
+     *      turn the backlight off.
+     *
+     * @return Whether the method succeeded or not.
+     *
+     * @throws IllegalArgumentException if:
+     *      - displayToken is null;
+     *      - brightness is NaN or greater than 1.0f.
+     *
+     * @hide
+     */
+    public static boolean setDisplayBrightness(IBinder displayToken, float brightness) {
+        Objects.requireNonNull(displayToken);
+        if (Float.isNaN(brightness) || brightness > 1.0f
+                || (brightness < 0.0f && brightness != -1.0f)) {
+            throw new IllegalArgumentException("brightness must be a number between 0.0f and 1.0f,"
+                    + " or -1 to turn the backlight off.");
+        }
+        return nativeSetDisplayBrightness(displayToken, brightness);
+    }
+
+    /**
      * An atomic set of changes to a set of SurfaceControl.
      */
     public static class Transaction implements Closeable {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 7fcce6d..49eb78d 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -17,6 +17,10 @@
 package android.view;
 
 import static android.content.res.Resources.ID_NULL;
+import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS;
+import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS;
+import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP;
+import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION;
 import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
 import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED;
 
@@ -96,6 +100,7 @@
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 import android.util.StateSet;
+import android.util.StatsLog;
 import android.util.SuperNotCalledException;
 import android.util.TypedValue;
 import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
@@ -14542,7 +14547,12 @@
                     if (clickable) {
                         setPressed(true, x, y);
                     }
-                    checkForLongClick(ViewConfiguration.getLongPressTimeout(), x, y);
+                    checkForLongClick(
+                            ViewConfiguration.getLongPressTimeout(),
+                            x,
+                            y,
+                            // This is not a touch gesture -- do not classify it as one.
+                            TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION);
                     return true;
                 }
             }
@@ -15283,7 +15293,11 @@
                     mHasPerformedLongPress = false;
 
                     if (!clickable) {
-                        checkForLongClick(ViewConfiguration.getLongPressTimeout(), x, y);
+                        checkForLongClick(
+                                ViewConfiguration.getLongPressTimeout(),
+                                x,
+                                y,
+                                TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
                         break;
                     }
 
@@ -15307,7 +15321,11 @@
                     } else {
                         // Not inside a scrolling container, so show the feedback right away
                         setPressed(true, x, y);
-                        checkForLongClick(ViewConfiguration.getLongPressTimeout(), x, y);
+                        checkForLongClick(
+                                ViewConfiguration.getLongPressTimeout(),
+                                x,
+                                y,
+                                TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
                     }
                     break;
 
@@ -15344,7 +15362,11 @@
                                     * ambiguousMultiplier);
                             // Subtract the time already spent
                             delay -= event.getEventTime() - event.getDownTime();
-                            checkForLongClick(delay, x, y);
+                            checkForLongClick(
+                                    delay,
+                                    x,
+                                    y,
+                                    TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
                         }
                         touchSlop *= ambiguousMultiplier;
                     }
@@ -15366,7 +15388,11 @@
                     if (deepPress && hasPendingLongPressCallback()) {
                         // process the long click action immediately
                         removeLongPressCallback();
-                        checkForLongClick(0 /* send immediately */, x, y);
+                        checkForLongClick(
+                                0 /* send immediately */,
+                                x,
+                                y,
+                                TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS);
                     }
 
                     break;
@@ -17197,6 +17223,7 @@
      * and {@link #setTranslationY(float)} (float)}} instead.
      *
      * @param matrix The matrix, null indicates that the matrix should be cleared.
+     * @see #getAnimationMatrix()
      */
     public void setAnimationMatrix(@Nullable Matrix matrix) {
         invalidateViewProperty(true, false);
@@ -17207,6 +17234,22 @@
     }
 
     /**
+     * Return the current transformation matrix of the view. This is used in animation frameworks,
+     * such as {@link android.transition.Transition}. Returns <code>null</code> when there is no
+     * transformation provided by {@link #setAnimationMatrix(Matrix)}.
+     * Application developers should use transformation methods like {@link #setRotation(float)},
+     * {@link #setScaleX(float)}, {@link #setScaleX(float)}, {@link #setTranslationX(float)}}
+     * and {@link #setTranslationY(float)} (float)}} instead.
+     *
+     * @return the Matrix, null indicates there is no transformation
+     * @see #setAnimationMatrix(Matrix)
+     */
+    @Nullable
+    public Matrix getAnimationMatrix() {
+        return mRenderNode.getAnimationMatrix();
+    }
+
+    /**
      * Returns the current StateListAnimator if exists.
      *
      * @return StateListAnimator or null if it does not exists
@@ -26014,7 +26057,7 @@
         }
     }
 
-    private void checkForLongClick(long delay, float x, float y) {
+    private void checkForLongClick(long delay, float x, float y, int classification) {
         if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
             mHasPerformedLongPress = false;
 
@@ -26024,6 +26067,7 @@
             mPendingCheckForLongPress.setAnchor(x, y);
             mPendingCheckForLongPress.rememberWindowAttachCount();
             mPendingCheckForLongPress.rememberPressedState();
+            mPendingCheckForLongPress.setClassification(classification);
             postDelayed(mPendingCheckForLongPress, delay);
         }
     }
@@ -27581,11 +27625,17 @@
         private float mX;
         private float mY;
         private boolean mOriginalPressedState;
+        /**
+         * The classification of the long click being checked: one of the
+         * StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__* constants.
+         */
+        private int mClassification;
 
         @Override
         public void run() {
             if ((mOriginalPressedState == isPressed()) && (mParent != null)
                     && mOriginalWindowAttachCount == mWindowAttachCount) {
+                recordGestureClassification(mClassification);
                 if (performLongClick(mX, mY)) {
                     mHasPerformedLongPress = true;
                 }
@@ -27604,6 +27654,10 @@
         public void rememberPressedState() {
             mOriginalPressedState = isPressed();
         }
+
+        public void setClassification(int classification) {
+            mClassification = classification;
+        }
     }
 
     private final class CheckForTap implements Runnable {
@@ -27616,17 +27670,28 @@
             setPressed(true, x, y);
             final long delay =
                     ViewConfiguration.getLongPressTimeout() - ViewConfiguration.getTapTimeout();
-            checkForLongClick(delay, x, y);
+            checkForLongClick(delay, x, y, TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
         }
     }
 
     private final class PerformClick implements Runnable {
         @Override
         public void run() {
+            recordGestureClassification(TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP);
             performClickInternal();
         }
     }
 
+    /** Records a classification for the current event stream. */
+    private void recordGestureClassification(int classification) {
+        if (classification == TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION) {
+            return;
+        }
+        // To avoid negatively impacting View performance, the latency and displacement metrics
+        // are omitted.
+        StatsLog.write(StatsLog.TOUCH_GESTURE_CLASSIFIED, getClass().getName(), classification);
+    }
+
     /**
      * This method returns a ViewPropertyAnimator object, which can be used to animate
      * specific properties on this View.
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 4dc20d4..4964ee1 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -4284,35 +4284,38 @@
     }
 
     /**
-     * Returns the index of the child to draw for this iteration. Override this
+     * Converts drawing order position to container position. Override this
      * if you want to change the drawing order of children. By default, it
-     * returns i.
+     * returns drawingPosition.
      * <p>
      * NOTE: In order for this method to be called, you must enable child ordering
      * first by calling {@link #setChildrenDrawingOrderEnabled(boolean)}.
      *
-     * @param i The current iteration.
-     * @return The index of the child to draw this iteration.
+     * @param drawingPosition the drawing order position.
+     * @return the container position of a child for this drawing order position.
      *
      * @see #setChildrenDrawingOrderEnabled(boolean)
      * @see #isChildrenDrawingOrderEnabled()
      */
-    protected int getChildDrawingOrder(int childCount, int i) {
-        return i;
+    protected int getChildDrawingOrder(int childCount, int drawingPosition) {
+        return drawingPosition;
     }
 
     /**
-     * The public version of getChildDrawingOrder().
+     * Converts drawing order position to container position.
+     * <p>
+     * Children are not necessarily drawn in the order in which they appear in the container.
+     * ViewGroups can enable a custom ordering via {@link #setChildrenDrawingOrderEnabled(boolean)}.
+     * This method returns the container position of a child that appears in the given position
+     * in the current drawing order.
      *
-     * Returns the index of the child to draw for this iteration.
-     *
-     * @param i The current iteration.
-     * @return The index of the child to draw this iteration.
+     * @param drawingPosition the drawing order position.
+     * @return the container position of a child for this drawing order position.
      *
      * @see #getChildDrawingOrder(int, int)}
      */
-    public final int getChildDrawingOrder(int i) {
-        return getChildDrawingOrder(getChildCount(), i);
+    public final int getChildDrawingOrder(int drawingPosition) {
+        return getChildDrawingOrder(getChildCount(), drawingPosition);
     }
 
     private boolean hasChildWithZ() {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 9222bd6..a28d662 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1213,15 +1213,12 @@
 
         boolean useAutoDark = getNightMode() == Configuration.UI_MODE_NIGHT_YES;
 
-        // Allow debug.hwui.force_dark to override the target SDK check
-        if (useAutoDark && !SystemProperties.getBoolean("debug.hwui.force_dark", false)) {
-            useAutoDark = mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q;
-        }
-
         if (useAutoDark) {
+            boolean forceDarkAllowedDefault =
+                    SystemProperties.getBoolean("debug.hwui.force_dark", false);
             TypedArray a = mContext.obtainStyledAttributes(R.styleable.Theme);
             useAutoDark = a.getBoolean(R.styleable.Theme_isLightTheme, true)
-                    && a.getBoolean(R.styleable.Theme_forceDarkAllowed, true);
+                    && a.getBoolean(R.styleable.Theme_forceDarkAllowed, forceDarkAllowedDefault);
             a.recycle();
         }
 
diff --git a/core/java/android/view/autofill/AutofillId.java b/core/java/android/view/autofill/AutofillId.java
index 8fa29f3..2c79299 100644
--- a/core/java/android/view/autofill/AutofillId.java
+++ b/core/java/android/view/autofill/AutofillId.java
@@ -47,20 +47,20 @@
 
     /** @hide */
     @TestApi
-    public AutofillId(@NonNull AutofillId parent, int virtualChildId) {
-        this(FLAG_IS_VIRTUAL_INT, parent.mViewId, virtualChildId, NO_SESSION);
+    public AutofillId(@NonNull AutofillId hostId, int virtualChildId) {
+        this(FLAG_IS_VIRTUAL_INT, hostId.mViewId, virtualChildId, NO_SESSION);
     }
 
     /** @hide */
     @TestApi
-    public AutofillId(int parentId, int virtualChildId) {
-        this(FLAG_IS_VIRTUAL_INT, parentId, virtualChildId, NO_SESSION);
+    public AutofillId(int hostId, int virtualChildId) {
+        this(FLAG_IS_VIRTUAL_INT, hostId, virtualChildId, NO_SESSION);
     }
 
     /** @hide */
     @TestApi
-    public AutofillId(@NonNull AutofillId parent, long virtualChildId, int sessionId) {
-        this(FLAG_IS_VIRTUAL_LONG | FLAG_HAS_SESSION, parent.mViewId, virtualChildId, sessionId);
+    public AutofillId(@NonNull AutofillId hostId, long virtualChildId, int sessionId) {
+        this(FLAG_IS_VIRTUAL_LONG | FLAG_HAS_SESSION, hostId.mViewId, virtualChildId, sessionId);
     }
 
     private AutofillId(int flags, int parentId, long virtualChildId, int sessionId) {
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 0c0a555..604cce5 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -20,6 +20,7 @@
 import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
 import static android.view.autofill.Helper.sDebug;
 import static android.view.autofill.Helper.sVerbose;
+import static android.view.autofill.Helper.toList;
 
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.annotation.IntDef;
@@ -1872,10 +1873,6 @@
         }
     }
 
-    private <T> ArrayList<T> toList(@Nullable Set<T> set) {
-        return set == null ? null : new ArrayList<T>(set);
-    }
-
     /**
      * Notifies that a non-autofillable view was entered because the activity is whitelisted for
      * augmented autofill.
@@ -2211,12 +2208,17 @@
      *  when the service failed to fullfil the request, or {@link #STATE_DISABLED_BY_SERVICE}
      *  (because the autofill service or {@link #STATE_DISABLED_BY_SERVICE} (because the autofill
      *  service disabled further autofill requests for the activity).
+     * @param autofillableIds list of ids that could trigger autofill, use to not handle a new
+     *  session when they're entered.
      */
-    private void setSessionFinished(int newState) {
+    private void setSessionFinished(int newState, @Nullable List<AutofillId> autofillableIds) {
         synchronized (mLock) {
             if (sVerbose) {
                 Log.v(TAG, "setSessionFinished(): from " + getStateAsStringLocked() + " to "
-                        + getStateAsString(newState));
+                        + getStateAsString(newState) + "; autofillableIds=" + autofillableIds);
+            }
+            if (autofillableIds != null) {
+                mEnteredIds = new ArraySet<>(autofillableIds);
             }
             if (newState == STATE_UNKNOWN_COMPAT_MODE || newState == STATE_UNKNOWN_FAILED) {
                 resetSessionLocked(/* resetEnteredIds= */ true);
@@ -2328,7 +2330,7 @@
 
         if (sessionFinishedState != 0) {
             // Callback call was "hijacked" to also update the session state.
-            setSessionFinished(sessionFinishedState);
+            setSessionFinished(sessionFinishedState, /* autofillableIds= */ null);
         }
     }
 
@@ -3114,10 +3116,10 @@
         }
 
         @Override
-        public void setSessionFinished(int newState) {
+        public void setSessionFinished(int newState, List<AutofillId> autofillableIds) {
             final AutofillManager afm = mAfm.get();
             if (afm != null) {
-                afm.post(() -> afm.setSessionFinished(newState));
+                afm.post(() -> afm.setSessionFinished(newState, autofillableIds));
             }
         }
 
diff --git a/core/java/android/view/autofill/Helper.java b/core/java/android/view/autofill/Helper.java
index 48d0dbb..2f12bb2 100644
--- a/core/java/android/view/autofill/Helper.java
+++ b/core/java/android/view/autofill/Helper.java
@@ -19,7 +19,9 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Set;
 
 /** @hide */
 public final class Helper {
@@ -62,7 +64,8 @@
     }
 
     /**
-     * Convers a collaction of {@link AutofillId AutofillIds} to an array.
+     * Converts a collaction of {@link AutofillId AutofillIds} to an array.
+     *
      * @param collection The collection.
      * @return The array.
      */
@@ -75,6 +78,14 @@
         return array;
     }
 
+    /**
+     * Converts a Set to a List.
+     */
+    @Nullable
+    public static <T> ArrayList<T> toList(@Nullable Set<T> set) {
+        return set == null ? null : new ArrayList<T>(set);
+    }
+
     private Helper() {
         throw new UnsupportedOperationException("contains static members only");
     }
diff --git a/core/java/android/view/autofill/IAutoFillManagerClient.aidl b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
index 63394b4..85def7f 100644
--- a/core/java/android/view/autofill/IAutoFillManagerClient.aidl
+++ b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
@@ -98,8 +98,10 @@
      *
      * @param newState STATE_FINISHED (because the autofill service returned a null
      * FillResponse) or STATE_UNKNOWN (because the session was removed).
+     * @param autofillableIds list of ids that could trigger autofill, use to not handle a new
+     * session when they're entered.
      */
-   void setSessionFinished(int newState);
+   void setSessionFinished(int newState, in List<AutofillId> autofillableIds);
 
    /**
     * Gets a reference to the binder object that can be used by the Augmented Autofill service.
diff --git a/core/java/android/view/contentcapture/ContentCaptureContext.java b/core/java/android/view/contentcapture/ContentCaptureContext.java
index b9dc0dd..019ebff 100644
--- a/core/java/android/view/contentcapture/ContentCaptureContext.java
+++ b/core/java/android/view/contentcapture/ContentCaptureContext.java
@@ -71,10 +71,21 @@
     @TestApi
     public static final int FLAG_DISABLED_BY_FLAG_SECURE = 0x2;
 
+    /**
+     * Flag used when the event is sent because the Android System reconnected to the service (for
+     * example, after its process died).
+     *
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public static final int FLAG_RECONNECTED = 0x4;
+
     /** @hide */
     @IntDef(flag = true, prefix = { "FLAG_" }, value = {
             FLAG_DISABLED_BY_APP,
-            FLAG_DISABLED_BY_FLAG_SECURE
+            FLAG_DISABLED_BY_FLAG_SECURE,
+            FLAG_RECONNECTED
     })
     @Retention(RetentionPolicy.SOURCE)
     @interface ContextCreationFlags{}
@@ -126,6 +137,17 @@
         mDisplayId = Display.INVALID_DISPLAY;
     }
 
+    /** @hide */
+    public ContentCaptureContext(@Nullable ContentCaptureContext original, int extraFlags) {
+        mHasClientContext = original.mHasClientContext;
+        mExtras = original.mExtras;
+        mId = original.mId;
+        mComponentName = original.mComponentName;
+        mTaskId = original.mTaskId;
+        mFlags = original.mFlags | extraFlags;
+        mDisplayId = original.mDisplayId;
+    }
+
     /**
      * Gets the (optional) extras set by the app (through {@link Builder#setExtras(Bundle)}).
      *
@@ -199,8 +221,8 @@
     /**
      * Gets the flags associated with this context.
      *
-     * @return any combination of {@link #FLAG_DISABLED_BY_FLAG_SECURE} and
-     * {@link #FLAG_DISABLED_BY_APP}.
+     * @return any combination of {@link #FLAG_DISABLED_BY_FLAG_SECURE},
+     * {@link #FLAG_DISABLED_BY_APP} and {@link #FLAG_RECONNECTED}.
      *
      * @hide
      */
diff --git a/core/java/android/view/contentcapture/ContentCaptureEvent.java b/core/java/android/view/contentcapture/ContentCaptureEvent.java
index 67d3629..8188e05 100644
--- a/core/java/android/view/contentcapture/ContentCaptureEvent.java
+++ b/core/java/android/view/contentcapture/ContentCaptureEvent.java
@@ -303,6 +303,47 @@
         return mText;
     }
 
+    /**
+     * Merges event of the same type, either {@link #TYPE_VIEW_TEXT_CHANGED}
+     * or {@link #TYPE_VIEW_DISAPPEARED}.
+     *
+     * @hide
+     */
+    public void mergeEvent(@NonNull ContentCaptureEvent event) {
+        Preconditions.checkNotNull(event);
+        final int eventType = event.getType();
+        if (mType != eventType) {
+            Log.e(TAG, "mergeEvent(" + getTypeAsString(eventType) + ") cannot be merged "
+                    + "with different eventType=" + getTypeAsString(mType));
+            return;
+        }
+
+        if (eventType == TYPE_VIEW_DISAPPEARED) {
+            final List<AutofillId> ids = event.getIds();
+            final AutofillId id = event.getId();
+            if (ids != null) {
+                if (id != null) {
+                    Log.w(TAG, "got TYPE_VIEW_DISAPPEARED event with both id and ids: " + event);
+                }
+                for (int i = 0; i < ids.size(); i++) {
+                    addAutofillId(ids.get(i));
+                }
+                return;
+            }
+            if (id != null) {
+                addAutofillId(id);
+                return;
+            }
+            throw new IllegalArgumentException("mergeEvent(): got "
+                    + "TYPE_VIEW_DISAPPEARED event with neither id or ids: " + event);
+        } else if (eventType == TYPE_VIEW_TEXT_CHANGED) {
+            setText(event.getText());
+        } else {
+            Log.e(TAG, "mergeEvent(" + getTypeAsString(eventType)
+                    + ") does not support this event type.");
+        }
+    }
+
     /** @hide */
     public void dump(@NonNull PrintWriter pw) {
         pw.print("type="); pw.print(getTypeAsString(mType));
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index 1f0971e..6d41b28 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -127,6 +127,20 @@
      */
     public static final int STATE_NOT_WHITELISTED = 0x200;
 
+    /**
+     * Session is disabled because the service died.
+     *
+     * @hide
+     */
+    public static final int STATE_SERVICE_DIED = 0x400;
+
+    /**
+     * Session is enabled, after the service died and came back to live.
+     *
+     * @hide
+     */
+    public static final int STATE_SERVICE_RESURRECTED = 0x800;
+
     private static final int INITIAL_CHILDREN_CAPACITY = 5;
 
     /** @hide */
@@ -139,6 +153,8 @@
     public static final int FLUSH_REASON_SESSION_FINISHED = 4;
     /** @hide */
     public static final int FLUSH_REASON_IDLE_TIMEOUT = 5;
+    /** @hide */
+    public static final int FLUSH_REASON_TEXT_CHANGE_TIMEOUT = 6;
 
     /** @hide */
     @IntDef(prefix = { "FLUSH_REASON_" }, value = {
@@ -146,7 +162,8 @@
             FLUSH_REASON_VIEW_ROOT_ENTERED,
             FLUSH_REASON_SESSION_STARTED,
             FLUSH_REASON_SESSION_FINISHED,
-            FLUSH_REASON_IDLE_TIMEOUT
+            FLUSH_REASON_IDLE_TIMEOUT,
+            FLUSH_REASON_TEXT_CHANGE_TIMEOUT
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface FlushReason{}
@@ -375,7 +392,8 @@
      *
      * <p>Should only be called by views that handle their own virtual view hierarchy.
      *
-     * @param hostId id of the view hosting the virtual hierarchy.
+     * @param hostId id of the non-virtual view hosting the virtual view hierarchy (it can be
+     * obtained by calling {@link ViewStructure#getAutofillId()}).
      * @param virtualIds ids of the virtual children.
      *
      * @throws IllegalArgumentException if the {@code hostId} is an autofill id for a virtual view.
@@ -383,7 +401,7 @@
      */
     public final void notifyViewsDisappeared(@NonNull AutofillId hostId,
             @NonNull long[] virtualIds) {
-        Preconditions.checkArgument(hostId.isNonVirtual(), "parent cannot be virtual");
+        Preconditions.checkArgument(hostId.isNonVirtual(), "hostId cannot be virtual: %s", hostId);
         Preconditions.checkArgument(!ArrayUtils.isEmpty(virtualIds), "virtual ids cannot be empty");
         if (!isContentCaptureEnabled()) return;
 
@@ -428,18 +446,18 @@
      * Creates a new {@link AutofillId} for a virtual child, so it can be used to uniquely identify
      * the children in the session.
      *
-     * @param parentId id of the virtual view parent (it can be obtained by calling
-     * {@link ViewStructure#getAutofillId()} on the parent).
+     * @param hostId id of the non-virtual view hosting the virtual view hierarchy (it can be
+     * obtained by calling {@link ViewStructure#getAutofillId()}).
      * @param virtualChildId id of the virtual child, relative to the parent.
      *
      * @return if for the virtual child
      *
      * @throws IllegalArgumentException if the {@code parentId} is a virtual child id.
      */
-    public @NonNull AutofillId newAutofillId(@NonNull AutofillId parentId, long virtualChildId) {
-        Preconditions.checkNotNull(parentId);
-        Preconditions.checkArgument(parentId.isNonVirtual(), "virtual ids cannot have children");
-        return new AutofillId(parentId, virtualChildId, getIdAsInt());
+    public @NonNull AutofillId newAutofillId(@NonNull AutofillId hostId, long virtualChildId) {
+        Preconditions.checkNotNull(hostId);
+        Preconditions.checkArgument(hostId.isNonVirtual(), "hostId cannot be virtual: %s", hostId);
+        return new AutofillId(hostId, virtualChildId, getIdAsInt());
     }
 
     /**
@@ -510,6 +528,8 @@
                 return "FINISHED";
             case FLUSH_REASON_IDLE_TIMEOUT:
                 return "IDLE";
+            case FLUSH_REASON_TEXT_CHANGE_TIMEOUT:
+                return "TEXT_CHANGE";
             default:
                 return "UNKOWN-" + reason;
         }
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index dce8ebe..666af59 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -125,9 +125,20 @@
     // Used just for debugging purposes (on dump)
     private long mNextFlush;
 
+    /**
+     * Whether the next buffer flush is queued by a text changed event.
+     */
+    private boolean mNextFlushForTextChanged = false;
+
     @Nullable
     private final LocalLog mFlushHistory;
 
+    /**
+     * Binder object used to update the session state.
+     */
+    @NonNull
+    private final IResultReceiver.Stub mSessionStateReceiver;
+
     protected MainContentCaptureSession(@NonNull Context context,
             @NonNull ContentCaptureManager manager, @NonNull Handler handler,
             @NonNull IContentCaptureManager systemServerInterface) {
@@ -138,6 +149,26 @@
 
         final int logHistorySize = mManager.mOptions.logHistorySize;
         mFlushHistory = logHistorySize > 0 ? new LocalLog(logHistorySize) : null;
+
+        mSessionStateReceiver = new IResultReceiver.Stub() {
+            @Override
+            public void send(int resultCode, Bundle resultData) {
+                final IBinder binder;
+                if (resultData != null) {
+                    binder = resultData.getBinder(EXTRA_BINDER);
+                    if (binder == null) {
+                        Log.wtf(TAG, "No " + EXTRA_BINDER + " extra result");
+                        mHandler.post(() -> resetSession(
+                                STATE_DISABLED | STATE_INTERNAL_ERROR));
+                        return;
+                    }
+                } else {
+                    binder = null;
+                }
+                mHandler.post(() -> onSessionStarted(resultCode, binder));
+            }
+        };
+
     }
 
     @Override
@@ -185,24 +216,7 @@
 
         try {
             mSystemServerInterface.startSession(mApplicationToken, component, mId, flags,
-                    new IResultReceiver.Stub() {
-                        @Override
-                        public void send(int resultCode, Bundle resultData) {
-                            final IBinder binder;
-                            if (resultData != null) {
-                                binder = resultData.getBinder(EXTRA_BINDER);
-                                if (binder == null) {
-                                    Log.wtf(TAG, "No " + EXTRA_BINDER + " extra result");
-                                    mHandler.post(() -> resetSession(
-                                            STATE_DISABLED | STATE_INTERNAL_ERROR));
-                                    return;
-                                }
-                            } else {
-                                binder = null;
-                            }
-                            mHandler.post(() -> onSessionStarted(resultCode, binder));
-                        }
-                    });
+                    mSessionStateReceiver);
         } catch (RemoteException e) {
             Log.w(TAG, "Error starting session for " + component.flattenToShortString() + ": " + e);
         }
@@ -216,8 +230,7 @@
 
     /**
      * Callback from {@code system_server} after call to
-     * {@link IContentCaptureManager#startSession(IBinder, ComponentName, String, int,
-     * IResultReceiver)}
+     * {@link IContentCaptureManager#startSession(IBinder, ComponentName, String, int, IBinder)}
      *
      * @param resultCode session state
      * @param binder handle to {@code IContentCaptureDirectManager}
@@ -227,8 +240,9 @@
         if (binder != null) {
             mDirectServiceInterface = IContentCaptureDirectManager.Stub.asInterface(binder);
             mDirectServiceVulture = () -> {
-                Log.w(TAG, "Destroying session " + mId + " because service died");
-                destroy();
+                Log.w(TAG, "Keeping session " + mId + " when service died");
+                mState = STATE_SERVICE_DIED;
+                mDisabled.set(true);
             };
             try {
                 binder.linkToDeath(mDirectServiceVulture, 0);
@@ -295,8 +309,7 @@
                     Log.v(TAG, "Buffering VIEW_TEXT_CHANGED event, updated text="
                             + getSanitizedString(event.getText()));
                 }
-                // TODO(b/124107816): should call lastEvent.merge(event) instead
-                lastEvent.setText(event.getText());
+                lastEvent.mergeEvent(event);
                 addEvent = false;
             }
         }
@@ -309,7 +322,7 @@
                     Log.v(TAG, "Buffering TYPE_VIEW_DISAPPEARED events for session "
                             + lastEvent.getSessionId());
                 }
-                mergeViewsDisappearedEvent(lastEvent, event);
+                lastEvent.mergeEvent(event);
                 addEvent = false;
             }
         }
@@ -323,7 +336,21 @@
         final boolean bufferEvent = numberEvents < maxBufferSize;
 
         if (bufferEvent && !forceFlush) {
-            scheduleFlush(FLUSH_REASON_IDLE_TIMEOUT, /* checkExisting= */ true);
+            final int flushReason;
+            if (eventType == TYPE_VIEW_TEXT_CHANGED) {
+                mNextFlushForTextChanged = true;
+                flushReason = FLUSH_REASON_TEXT_CHANGE_TIMEOUT;
+            } else {
+                if (mNextFlushForTextChanged) {
+                    if (sVerbose) {
+                        Log.i(TAG, "Not scheduling flush because next flush is for text changed");
+                    }
+                    return;
+                }
+
+                flushReason = FLUSH_REASON_IDLE_TIMEOUT;
+            }
+            scheduleFlush(flushReason, /* checkExisting= */ true);
             return;
         }
 
@@ -357,30 +384,6 @@
         flush(flushReason);
     }
 
-    // TODO(b/124107816): should be ContentCaptureEvent Event.merge(event) instead (which would
-    // replace the addAutofillId() method - we would also need unit tests on ContentCaptureEventTest
-    // to check these scenarios)
-    private void mergeViewsDisappearedEvent(@NonNull ContentCaptureEvent lastEvent,
-            @NonNull ContentCaptureEvent event) {
-        final List<AutofillId> ids = event.getIds();
-        final AutofillId id = event.getId();
-        if (ids != null) {
-            if (id != null) {
-                Log.w(TAG, "got TYPE_VIEW_DISAPPEARED event with both id and ids: " + event);
-            }
-            for (int i = 0; i < ids.size(); i++) {
-                lastEvent.addAutofillId(ids.get(i));
-            }
-            return;
-        }
-        if (id != null) {
-            lastEvent.addAutofillId(id);
-            return;
-        }
-        throw new IllegalArgumentException(
-                "got TYPE_VIEW_DISAPPEARED event with neither id or ids: " + event);
-    }
-
     @UiThread
     private boolean hasStarted() {
         return mState != UNKNOWN_STATE;
@@ -408,14 +411,25 @@
             // "Renew" the flush message by removing the previous one
             mHandler.removeMessages(MSG_FLUSH);
         }
-        final int idleFlushingFrequencyMs = mManager.mOptions.idleFlushingFrequencyMs;
-        mNextFlush = System.currentTimeMillis() + idleFlushingFrequencyMs;
+
+        final int flushFrequencyMs;
+        if (reason == FLUSH_REASON_IDLE_TIMEOUT) {
+            flushFrequencyMs = mManager.mOptions.idleFlushingFrequencyMs;
+        } else if (reason == FLUSH_REASON_TEXT_CHANGE_TIMEOUT) {
+            flushFrequencyMs = mManager.mOptions.textChangeFlushingFrequencyMs;
+        } else {
+            Log.e(TAG, "handleScheduleFlush(" + getDebugState(reason) + "): not called with a "
+                    + "timeout reason.");
+            return;
+        }
+
+        mNextFlush = System.currentTimeMillis() + flushFrequencyMs;
         if (sVerbose) {
             Log.v(TAG, "handleScheduleFlush(): scheduled to flush in "
-                    + idleFlushingFrequencyMs + "ms: " + TimeUtils.logTimeOfDay(mNextFlush));
+                    + flushFrequencyMs + "ms: " + TimeUtils.logTimeOfDay(mNextFlush));
         }
         // Post using a Runnable directly to trim a few μs from PooledLambda.obtainMessage()
-        mHandler.postDelayed(() -> flushIfNeeded(reason), MSG_FLUSH, idleFlushingFrequencyMs);
+        mHandler.postDelayed(() -> flushIfNeeded(reason), MSG_FLUSH, flushFrequencyMs);
     }
 
     @UiThread
@@ -464,6 +478,10 @@
         try {
             mHandler.removeMessages(MSG_FLUSH);
 
+            if (reason == FLUSH_REASON_TEXT_CHANGE_TIMEOUT) {
+                mNextFlushForTextChanged = false;
+            }
+
             final ParceledListSlice<ContentCaptureEvent> events = clearEvents();
             mDirectServiceInterface.sendEvents(events);
         } catch (RemoteException e) {
@@ -641,8 +659,14 @@
                     pw.println();
                 }
             }
+            pw.print(prefix); pw.print("mNextFlushForTextChanged: ");
+            pw.println(mNextFlushForTextChanged);
             pw.print(prefix); pw.print("flush frequency: ");
-            pw.println(mManager.mOptions.idleFlushingFrequencyMs);
+            if (mNextFlushForTextChanged) {
+                pw.println(mManager.mOptions.textChangeFlushingFrequencyMs);
+            } else {
+                pw.println(mManager.mOptions.idleFlushingFrequencyMs);
+            }
             pw.print(prefix); pw.print("next flush: ");
             TimeUtils.formatDuration(mNextFlush - System.currentTimeMillis(), pw);
             pw.print(" ("); pw.print(TimeUtils.logTimeOfDay(mNextFlush)); pw.println(")");
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index e63a406..5e00425 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -2559,6 +2559,12 @@
         mPendingEventPool.release(p);
     }
 
+    /**
+     * Show IME picker popup window.
+     *
+     * <p>Requires the {@link PackageManager#FEATURE_INPUT_METHODS} feature which can be detected
+     * using {@link PackageManager#hasSystemFeature(String)}.
+     */
     public void showInputMethodPicker() {
         synchronized (mH) {
             showInputMethodPickerLocked();
diff --git a/core/java/android/view/inspector/IntEnumMapping.java b/core/java/android/view/inspector/IntEnumMapping.java
deleted file mode 100644
index 147bb46..0000000
--- a/core/java/android/view/inspector/IntEnumMapping.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.inspector;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.util.SparseArray;
-
-import java.util.Objects;
-
-/**
- * Maps the values of an {@code int} property to strings for properties that encode an enumeration.
- *
- * An {@link InspectionCompanion} may provide an instance of this class to a {@link PropertyMapper}
- * for flag values packed into primitive {@code int} properties.
- *
- * This class is an immutable wrapper for {@link SparseArray}, and must be constructed by a
- * {@link Builder}.
- *
- * @see PropertyMapper#mapIntEnum(String, int, IntEnumMapping)
- */
-public final class IntEnumMapping {
-    private final SparseArray<String> mValues;
-
-    /**
-     * Get the name for the given property value
-     *
-     * @param value The value of the property
-     * @return The name of the value in the enumeration, or null if no value is defined
-     */
-    @Nullable
-    public String get(int value) {
-        return mValues.get(value);
-    }
-
-    /**
-     * Create a new instance from a builder.
-     *
-     * This constructor is private, use {@link Builder#build()} instead.
-     *
-     * @param builder A builder to create from
-     */
-    private IntEnumMapping(Builder builder) {
-        mValues = builder.mValues.clone();
-    }
-
-    /**
-     * A builder for {@link IntEnumMapping}.
-     */
-    public static final class Builder {
-        @NonNull
-        private SparseArray<String> mValues;
-        private boolean mMustCloneValues = false;
-
-        public Builder() {
-            mValues = new SparseArray<>();
-        }
-
-        /**
-         * Add a new enumerated value.
-         *
-         * @param name The string name of the enumeration value
-         * @param value The {@code int} value of the enumeration value
-         * @return This builder
-         */
-        @NonNull
-        public Builder addValue(@NonNull String name, int value) {
-            // Save an allocation, only re-clone if the builder is used again after building
-            if (mMustCloneValues) {
-                mValues = mValues.clone();
-            }
-
-            mValues.put(value, Objects.requireNonNull(name));
-            return this;
-        }
-
-        /**
-         * Build a new {@link IntEnumMapping} from this builder.
-         *
-         * @return A new mapping
-         */
-        @NonNull
-        public IntEnumMapping build() {
-            mMustCloneValues = true;
-            return new IntEnumMapping(this);
-        }
-    }
-}
diff --git a/core/java/android/view/inspector/IntFlagMapping.java b/core/java/android/view/inspector/IntFlagMapping.java
index 2409081..f501329 100644
--- a/core/java/android/view/inspector/IntFlagMapping.java
+++ b/core/java/android/view/inspector/IntFlagMapping.java
@@ -21,6 +21,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Objects;
 import java.util.Set;
 
@@ -35,22 +36,20 @@
  * it by bitwise anding it with the mask and comparing the result against the target, that is,
  * {@code (value & mask) == target}.
  *
- * This class is immutable, and must be constructed by a {@link Builder}.
- *
- * @see PropertyMapper#mapIntFlag(String, int, IntFlagMapping)
+ * @see PropertyMapper#mapIntFlag(String, int, java.util.function.IntFunction)
  */
 public final class IntFlagMapping {
-    private final Flag[] mFlags;
+    private final List<Flag> mFlags = new ArrayList<>();
 
     /**
-     * Get an array of the names of enabled flags for a given property value.
+     * Get a set of the names of enabled flags for a given property value.
      *
      * @param value The value of the property
      * @return The names of the enabled flags, empty if no flags enabled
      */
     @NonNull
     public Set<String> get(int value) {
-        final Set<String> enabledFlagNames = new HashSet<>(mFlags.length);
+        final Set<String> enabledFlagNames = new HashSet<>(mFlags.size());
 
         for (Flag flag : mFlags) {
             if (flag.isEnabledFor(value)) {
@@ -62,70 +61,14 @@
     }
 
     /**
-     * Create a new instance from a builder.
+     * Add a mutually exclusive flag to the map.
      *
-     * This constructor is private, use {@link Builder#build()} instead.
-     *
-     * @param builder A builder to create from
+     * @param mask The bit mask to compare to and with a value
+     * @param target The target value to compare the masked value with
+     * @param name The name of the flag to include if enabled
      */
-    private IntFlagMapping(Builder builder) {
-        mFlags = builder.mFlags.toArray(new Flag[builder.mFlags.size()]);
-    }
-
-    /**
-     * A builder for {@link IntFlagMapping}.
-     */
-    public static final class Builder {
-        private ArrayList<Flag> mFlags;
-
-        public Builder() {
-            mFlags = new ArrayList<>();
-        }
-
-        /**
-         * Add a new flag without a mask.
-         *
-         * The target value will be used as a mask, to handle the common case where flag values
-         * are not mutually exclusive. The flag will be considered enabled for a property value if
-         * the result of bitwise anding the target and the value equals the target, that is:
-         * {@code (value & target) == target}.
-         *
-         * @param name The name of the flag
-         * @param target The value to compare against
-         * @return This builder
-         */
-        @NonNull
-        public Builder addFlag(@NonNull String name, int target) {
-            mFlags.add(new Flag(name, target, target));
-            return this;
-        }
-
-        /**
-         * Add a new flag with a mask.
-         *
-         * The flag will be considered enabled for a property value if the result of bitwise anding
-         * the value and the mask equals the target, that is: {@code (value & mask) == target}.
-         *
-         * @param name The name of the flag
-         * @param target The value to compare against
-         * @param mask A bit mask
-         * @return This builder
-         */
-        @NonNull
-        public Builder addFlag(@NonNull String name, int target, int mask) {
-            mFlags.add(new Flag(name, target, mask));
-            return this;
-        }
-
-        /**
-         * Build a new {@link IntFlagMapping} from this builder.
-         *
-         * @return A new mapping
-         */
-        @NonNull
-        public IntFlagMapping build() {
-            return new IntFlagMapping(this);
-        }
+    public void add(int mask, int target, @NonNull String name) {
+        mFlags.add(new Flag(mask, target, name));
     }
 
     /**
@@ -136,10 +79,10 @@
         private final int mTarget;
         private final int mMask;
 
-        private Flag(@NonNull String name, int target, int mask) {
-            mName = Objects.requireNonNull(name);
+        private Flag(int mask, int target, @NonNull String name) {
             mTarget = target;
             mMask = mask;
+            mName = Objects.requireNonNull(name);
         }
 
         /**
diff --git a/core/java/android/view/inspector/PropertyMapper.java b/core/java/android/view/inspector/PropertyMapper.java
index 54d99df..cbc690e 100644
--- a/core/java/android/view/inspector/PropertyMapper.java
+++ b/core/java/android/view/inspector/PropertyMapper.java
@@ -19,6 +19,9 @@
 import android.annotation.AttrRes;
 import android.annotation.NonNull;
 
+import java.util.Set;
+import java.util.function.IntFunction;
+
 /**
  * An interface for mapping the string names of inspectable properties to integer identifiers.
  *
@@ -154,7 +157,7 @@
     int mapIntEnum(
             @NonNull String name,
             @AttrRes int attributeId,
-            @NonNull IntEnumMapping mapping);
+            @NonNull IntFunction<String> mapping);
 
     /**
      * Map a string name to an integer ID for an attribute that contains resource IDs.
@@ -178,7 +181,7 @@
     int mapIntFlag(
             @NonNull String name,
             @AttrRes int attributeId,
-            @NonNull IntFlagMapping mapping);
+            @NonNull IntFunction<Set<String>> mapping);
     /**
      * Thrown from a map method if a property name is already mapped as different type.
      */
diff --git a/core/java/android/view/textclassifier/ActionsSuggestionsHelper.java b/core/java/android/view/textclassifier/ActionsSuggestionsHelper.java
index ddbff7b..9c268f2 100644
--- a/core/java/android/view/textclassifier/ActionsSuggestionsHelper.java
+++ b/core/java/android/view/textclassifier/ActionsSuggestionsHelper.java
@@ -23,10 +23,13 @@
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.Pair;
+import android.view.textclassifier.intent.LabeledIntent;
+import android.view.textclassifier.intent.TemplateIntentFactory;
 
 import com.android.internal.annotations.VisibleForTesting;
 
 import com.google.android.textclassifier.ActionsSuggestionsModel;
+import com.google.android.textclassifier.RemoteActionTemplate;
 
 import java.util.ArrayDeque;
 import java.util.ArrayList;
@@ -46,6 +49,7 @@
  */
 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
 public final class ActionsSuggestionsHelper {
+    private static final String TAG = "ActionsSuggestions";
     private static final int USER_LOCAL = 0;
     private static final int FIRST_NON_LOCAL_USER = 1;
 
@@ -82,9 +86,12 @@
             long referenceTime = message.getReferenceTime() == null
                     ? 0
                     : message.getReferenceTime().toInstant().toEpochMilli();
+            String timeZone = message.getReferenceTime() == null
+                    ? null
+                    : message.getReferenceTime().getZone().getId();
             nativeMessages.push(new ActionsSuggestionsModel.ConversationMessage(
                     personEncoder.encode(message.getAuthor()),
-                    message.getText().toString(), referenceTime,
+                    message.getText().toString(), referenceTime, timeZone,
                     languageDetector.apply(message.getText())));
         }
         return nativeMessages.toArray(
@@ -114,8 +121,33 @@
     }
 
     /**
-     * Returns a {@link android.view.textclassifier.LabeledIntent.TitleChooser} for
-     * conversation actions use case.
+     * Generated labeled intent from an action suggestion and return the resolved result.
+     */
+    @Nullable
+    public static LabeledIntent.Result createLabeledIntentResult(
+            Context context,
+            TemplateIntentFactory templateIntentFactory,
+            ActionsSuggestionsModel.ActionSuggestion nativeSuggestion) {
+        RemoteActionTemplate[] remoteActionTemplates =
+                nativeSuggestion.getRemoteActionTemplates();
+        if (remoteActionTemplates == null) {
+            Log.w(TAG, "createRemoteAction: Missing template for type "
+                    + nativeSuggestion.getActionType());
+            return null;
+        }
+        List<LabeledIntent> labeledIntents = templateIntentFactory.create(remoteActionTemplates);
+        if (labeledIntents.isEmpty()) {
+            return null;
+        }
+        // Given that we only support implicit intent here, we should expect there is just one
+        // intent for each action type.
+        LabeledIntent.TitleChooser titleChooser =
+                ActionsSuggestionsHelper.createTitleChooser(nativeSuggestion.getActionType());
+        return labeledIntents.get(0).resolve(context, titleChooser, null);
+    }
+
+    /**
+     * Returns a {@link LabeledIntent.TitleChooser} for conversation actions use case.
      */
     @Nullable
     public static LabeledIntent.TitleChooser createTitleChooser(String actionType) {
diff --git a/core/java/android/view/textclassifier/ConversationAction.java b/core/java/android/view/textclassifier/ConversationAction.java
index 2b952a3..f2d878a 100644
--- a/core/java/android/view/textclassifier/ConversationAction.java
+++ b/core/java/android/view/textclassifier/ConversationAction.java
@@ -92,10 +92,15 @@
      */
     public static final String TYPE_SHARE_LOCATION = "share_location";
 
+    // TODO: Make this public API
     /** @hide **/
     public static final String TYPE_ADD_CONTACT = "add_contact";
 
-    public static final @android.annotation.NonNull Creator<ConversationAction> CREATOR =
+    // TODO: Make this public API
+    /** @hide **/
+    public static final String TYPE_COPY = "copy";
+
+    public static final @NonNull Creator<ConversationAction> CREATOR =
             new Creator<ConversationAction>() {
                 @Override
                 public ConversationAction createFromParcel(Parcel in) {
diff --git a/core/java/android/view/textclassifier/ExtrasUtils.java b/core/java/android/view/textclassifier/ExtrasUtils.java
index df548ae..eadad28 100644
--- a/core/java/android/view/textclassifier/ExtrasUtils.java
+++ b/core/java/android/view/textclassifier/ExtrasUtils.java
@@ -19,6 +19,7 @@
 import android.annotation.Nullable;
 import android.app.RemoteAction;
 import android.content.Intent;
+import android.icu.util.ULocale;
 import android.os.Bundle;
 
 import java.util.ArrayList;
@@ -27,8 +28,10 @@
  * Utility class for inserting and retrieving data in TextClassifier request/response extras.
  * @hide
  */
+// TODO: Make this a TestApi for CTS testing.
 public final class ExtrasUtils {
 
+    private static final String ENTITIES_EXTRAS = "entities-extras";
     private static final String ACTION_INTENT = "action-intent";
     private static final String ACTIONS_INTENTS = "actions-intents";
     private static final String FOREIGN_LANGUAGE = "foreign-language";
@@ -36,6 +39,7 @@
     private static final String SCORE = "score";
     private static final String MODEL_VERSION = "model-version";
     private static final String MODEL_NAME = "model-name";
+    private static final String TEXT_LANGUAGES = "text-languages";
 
     private ExtrasUtils() {}
 
@@ -55,6 +59,8 @@
     /**
      * Stores {@code extra} as foreign language information in TextClassifier response object's
      * extras {@code container}.
+     *
+     * @see #getForeignLanguageExtra(TextClassification)
      */
     static void putForeignLanguageExtra(Bundle container, Bundle extra) {
         container.putParcelable(FOREIGN_LANGUAGE, extra);
@@ -63,13 +69,68 @@
     /**
      * Returns foreign language detection information contained in the TextClassification object.
      * responses.
+     *
+     * @see #putForeignLanguageExtra(Bundle, Bundle)
      */
     @Nullable
-    public static Bundle getForeignLanguageExtra(TextClassification classification) {
+    public static Bundle getForeignLanguageExtra(@Nullable TextClassification classification) {
+        if (classification == null) {
+            return null;
+        }
         return classification.getExtras().getBundle(FOREIGN_LANGUAGE);
     }
 
     /**
+     * @see #getTopLanguage(Intent)
+     */
+    static void putTopLanguageScores(Bundle container, EntityConfidence languageScores) {
+        final int maxSize = Math.min(3, languageScores.getEntities().size());
+        final String[] languages = languageScores.getEntities().subList(0, maxSize)
+                .toArray(new String[0]);
+        final float[] scores = new float[languages.length];
+        for (int i = 0; i < languages.length; i++) {
+            scores[i] = languageScores.getConfidenceScore(languages[i]);
+        }
+        container.putStringArray(ENTITY_TYPE, languages);
+        container.putFloatArray(SCORE, scores);
+    }
+
+    /**
+     * @see #putTopLanguageScores(Bundle, EntityConfidence)
+     */
+    @Nullable
+    public static ULocale getTopLanguage(@Nullable Intent intent) {
+        if (intent == null) {
+            return null;
+        }
+        final Bundle tcBundle = intent.getBundleExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER);
+        if (tcBundle == null) {
+            return null;
+        }
+        final Bundle textLanguagesExtra = tcBundle.getBundle(TEXT_LANGUAGES);
+        if (textLanguagesExtra == null) {
+            return null;
+        }
+        final String[] languages = textLanguagesExtra.getStringArray(ENTITY_TYPE);
+        final float[] scores = textLanguagesExtra.getFloatArray(SCORE);
+        if (languages == null || scores == null
+                || languages.length == 0 || languages.length != scores.length) {
+            return null;
+        }
+        int highestScoringIndex = 0;
+        for (int i = 1; i < languages.length; i++) {
+            if (scores[highestScoringIndex] < scores[i]) {
+                highestScoringIndex = i;
+            }
+        }
+        return ULocale.forLanguageTag(languages[highestScoringIndex]);
+    }
+
+    public static void putTextLanguagesExtra(Bundle container, Bundle extra) {
+        container.putBundle(TEXT_LANGUAGES, extra);
+    }
+
+    /**
      * Stores {@code actionIntents} information in TextClassifier response object's extras
      * {@code container}.
      */
@@ -94,10 +155,37 @@
     }
 
     /**
+     * Stores {@code entities} information in TextClassifier response object's extras
+     * {@code container}.
+     *
+     * @see {@link #getCopyText(Bundle)}
+     */
+    public static void putEntitiesExtras(Bundle container, @Nullable Bundle entitiesExtras) {
+        container.putParcelable(ENTITIES_EXTRAS, entitiesExtras);
+    }
+
+    /**
+     * Returns {@code entities} information contained in a TextClassifier response object.
+     *
+     * @see {@link #putEntitiesExtras(Bundle, Bundle)}
+     */
+    @Nullable
+    public static String getCopyText(Bundle container) {
+        Bundle entitiesExtras = container.getParcelable(ENTITIES_EXTRAS);
+        if (entitiesExtras == null) {
+            return null;
+        }
+        return entitiesExtras.getString("text");
+    }
+
+    /**
      * Returns {@code actionIntents} information contained in the TextClassification object.
      */
     @Nullable
-    public static ArrayList<Intent> getActionsIntents(TextClassification classification) {
+    public static ArrayList<Intent> getActionsIntents(@Nullable TextClassification classification) {
+        if (classification == null) {
+            return null;
+        }
         return classification.getExtras().getParcelableArrayList(ACTIONS_INTENTS);
     }
 
@@ -106,7 +194,11 @@
      * action string, {@code intentAction}.
      */
     @Nullable
-    public static RemoteAction findAction(TextClassification classification, String intentAction) {
+    public static RemoteAction findAction(
+            @Nullable TextClassification classification, @Nullable String intentAction) {
+        if (classification == null || intentAction == null) {
+            return null;
+        }
         final ArrayList<Intent> actionIntents = getActionsIntents(classification);
         if (actionIntents != null) {
             final int size = actionIntents.size();
@@ -124,7 +216,7 @@
      * Returns the first "translate" action found in the {@code classification} object.
      */
     @Nullable
-    public static RemoteAction findTranslateAction(TextClassification classification) {
+    public static RemoteAction findTranslateAction(@Nullable TextClassification classification) {
         return findAction(classification, Intent.ACTION_TRANSLATE);
     }
 
@@ -132,7 +224,10 @@
      * Returns the entity type contained in the {@code extra}.
      */
     @Nullable
-    public static String getEntityType(Bundle extra) {
+    public static String getEntityType(@Nullable Bundle extra) {
+        if (extra == null) {
+            return null;
+        }
         return extra.getString(ENTITY_TYPE);
     }
 
@@ -141,14 +236,21 @@
      */
     @Nullable
     public static float getScore(Bundle extra) {
-        return extra.getFloat(SCORE, -1);
+        final int defaultValue = -1;
+        if (extra == null) {
+            return defaultValue;
+        }
+        return extra.getFloat(SCORE, defaultValue);
     }
 
     /**
      * Returns the model name contained in the {@code extra}.
      */
     @Nullable
-    public static String getModelName(Bundle extra) {
+    public static String getModelName(@Nullable Bundle extra) {
+        if (extra == null) {
+            return null;
+        }
         return extra.getString(MODEL_NAME);
     }
 }
diff --git a/core/java/android/view/textclassifier/Log.java b/core/java/android/view/textclassifier/Log.java
index 5c60c09..03ed496 100644
--- a/core/java/android/view/textclassifier/Log.java
+++ b/core/java/android/view/textclassifier/Log.java
@@ -22,8 +22,10 @@
  * To enable full log:
  * 1. adb shell setprop log.tag.androidtc VERBOSE
  * 2. adb shell stop && adb shell start
+ *
+ * @hide
  */
-final class Log {
+public final class Log {
 
     /**
      * true: Enables full logging.
diff --git a/core/java/android/view/textclassifier/TextClassificationConstants.java b/core/java/android/view/textclassifier/TextClassificationConstants.java
index 125b0d3..876e5cc 100644
--- a/core/java/android/view/textclassifier/TextClassificationConstants.java
+++ b/core/java/android/view/textclassifier/TextClassificationConstants.java
@@ -48,6 +48,9 @@
  * notification_conversation_action_types_default   (String[])
  * lang_id_threshold_override                       (float)
  * template_intent_factory_enabled                  (boolean)
+ * translate_in_classification_enabled              (boolean)
+ * detect_languages_from_text_enabled               (boolean)
+ * lang_id_context_settings                         (float[])
  * </pre>
  *
  * <p>
@@ -56,12 +59,14 @@
  *
  * Example of setting the values for testing.
  * adb shell settings put global text_classifier_constants \
- *      model_dark_launch_enabled=true,smart_selection_enabled=true,\
- *      entity_list_default=phone:address
+ *      model_dark_launch_enabled=true,smart_selection_enabled=true, \
+ *      entity_list_default=phone:address, \
+ *      lang_id_context_settings=20:1.0:0.4
  * @hide
  */
 public final class TextClassificationConstants {
-    private static final String LOG_TAG = "TextClassificationConstants";
+
+    private static final String LOG_TAG = TextClassifier.DEFAULT_LOG_TAG;
 
     /**
      * Whether the smart linkify feature is enabled.
@@ -139,13 +144,38 @@
     private static final String NOTIFICATION_CONVERSATION_ACTION_TYPES_DEFAULT =
             "notification_conversation_action_types_default";
     /**
-     * Threshold in classifyText to consider a text is in a foreign language.
+     * Threshold to accept a suggested language from LangID model.
      */
     private static final String LANG_ID_THRESHOLD_OVERRIDE = "lang_id_threshold_override";
     /**
      * Whether to enable {@link android.view.textclassifier.TemplateIntentFactory}.
      */
     private static final String TEMPLATE_INTENT_FACTORY_ENABLED = "template_intent_factory_enabled";
+    /**
+     * Whether to enable "translate" action in classifyText.
+     */
+    private static final String TRANSLATE_IN_CLASSIFICATION_ENABLED =
+            "translate_in_classification_enabled";
+    /**
+     * Whether to detect the languages of the text in request by using langId for the native
+     * model.
+     */
+    private static final String DETECT_LANGUAGES_FROM_TEXT_ENABLED =
+            "detect_languages_from_text_enabled";
+    /**
+     * A colon(:) separated string that specifies the configuration to use when including
+     * surrounding context text in language detection queries.
+     * <p>
+     * Format= minimumTextSize<int>:penalizeRatio<float>:textScoreRatio<float>
+     * <p>
+     * e.g. 20:1.0:0.4
+     * <p>
+     * Accept all text lengths with minimumTextSize=0
+     * <p>
+     * Reject all text less than minimumTextSize with penalizeRatio=0
+     * @see {@code TextClassifierImpl#detectLanguages(String, int, int)} for reference.
+     */
+    private static final String LANG_ID_CONTEXT_SETTINGS = "lang_id_context_settings";
 
     private static final boolean LOCAL_TEXT_CLASSIFIER_ENABLED_DEFAULT = true;
     private static final boolean SYSTEM_TEXT_CLASSIFIER_ENABLED_DEFAULT = true;
@@ -179,15 +209,20 @@
                     .add(ConversationAction.TYPE_VIEW_CALENDAR)
                     .add(ConversationAction.TYPE_VIEW_MAP)
                     .add(ConversationAction.TYPE_ADD_CONTACT)
+                    .add(ConversationAction.TYPE_COPY)
                     .toString();
     /**
      * < 0  : Not set. Use value from LangId model.
      * 0 - 1: Override value in LangId model.
-     * > 1  : Effectively turns off the foreign language detection. Scores should never be > 1.
+     *
      * @see EntityConfidence
      */
     private static final float LANG_ID_THRESHOLD_OVERRIDE_DEFAULT = -1f;
     private static final boolean TEMPLATE_INTENT_FACTORY_ENABLED_DEFAULT = true;
+    private static final boolean TRANSLATE_IN_CLASSIFICATION_ENABLED_DEFAULT = true;
+    private static final boolean DETECT_LANGUAGES_FROM_TEXT_ENABLED_DEFAULT = true;
+    private static final String LANG_ID_CONTEXT_SETTINGS_DEFAULT =
+            new StringJoiner(STRING_LIST_DELIMITER).add("20").add("1.0").add("0.4").toString();
 
     private final boolean mSystemTextClassifierEnabled;
     private final boolean mLocalTextClassifierEnabled;
@@ -207,6 +242,9 @@
     private final List<String> mNotificationConversationActionTypesDefault;
     private final float mLangIdThresholdOverride;
     private final boolean mTemplateIntentFactoryEnabled;
+    private final boolean mTranslateInClassificationEnabled;
+    private final boolean mDetectLanguagesFromTextEnabled;
+    private final float[] mLangIdContextSettings;
 
     private TextClassificationConstants(@Nullable String settings) {
         ConfigParser configParser = new ConfigParser(settings);
@@ -254,9 +292,10 @@
                 configParser.getInt(
                         GENERATE_LINKS_LOG_SAMPLE_RATE,
                         GENERATE_LINKS_LOG_SAMPLE_RATE_DEFAULT);
-        mEntityListDefault = parseStringList(configParser.getString(
-                ENTITY_LIST_DEFAULT,
-                ENTITY_LIST_DEFAULT_VALUE));
+        mEntityListDefault = parseStringList(
+                configParser.getString(
+                        ENTITY_LIST_DEFAULT,
+                        ENTITY_LIST_DEFAULT_VALUE));
         mEntityListNotEditable = parseStringList(
                 configParser.getString(
                         ENTITY_LIST_NOT_EDITABLE,
@@ -277,9 +316,22 @@
                 configParser.getFloat(
                         LANG_ID_THRESHOLD_OVERRIDE,
                         LANG_ID_THRESHOLD_OVERRIDE_DEFAULT);
-        mTemplateIntentFactoryEnabled = configParser.getBoolean(
-                TEMPLATE_INTENT_FACTORY_ENABLED,
-                TEMPLATE_INTENT_FACTORY_ENABLED_DEFAULT);
+        mTemplateIntentFactoryEnabled =
+                configParser.getBoolean(
+                        TEMPLATE_INTENT_FACTORY_ENABLED,
+                        TEMPLATE_INTENT_FACTORY_ENABLED_DEFAULT);
+        mTranslateInClassificationEnabled =
+                configParser.getBoolean(
+                        TRANSLATE_IN_CLASSIFICATION_ENABLED,
+                        TRANSLATE_IN_CLASSIFICATION_ENABLED_DEFAULT);
+        mDetectLanguagesFromTextEnabled =
+                configParser.getBoolean(
+                        DETECT_LANGUAGES_FROM_TEXT_ENABLED,
+                        DETECT_LANGUAGES_FROM_TEXT_ENABLED_DEFAULT);
+        mLangIdContextSettings = parseFloatArray(
+                configParser,
+                LANG_ID_CONTEXT_SETTINGS,
+                LANG_ID_CONTEXT_SETTINGS_DEFAULT);
     }
 
     /** Load from a settings string. */
@@ -359,10 +411,43 @@
         return mTemplateIntentFactoryEnabled;
     }
 
+    public boolean isTranslateInClassificationEnabled() {
+        return mTranslateInClassificationEnabled;
+    }
+
+    public boolean isDetectLanguagesFromTextEnabled() {
+        return mDetectLanguagesFromTextEnabled;
+    }
+
+    public float[] getLangIdContextSettings() {
+        return mLangIdContextSettings;
+    }
+
     private static List<String> parseStringList(String listStr) {
         return Collections.unmodifiableList(Arrays.asList(listStr.split(STRING_LIST_DELIMITER)));
     }
 
+    private static float[] parseFloatArray(
+            ConfigParser configParser, String key, String defaultStr) {
+        final String str = configParser.getString(key, defaultStr);
+        final String[] defaultSplit = defaultStr.split(STRING_LIST_DELIMITER);
+        String[] split = str.split(STRING_LIST_DELIMITER);
+        if (split.length != defaultSplit.length) {
+            Log.v(LOG_TAG, "Error parsing " + key + " flag. Using defaults.");
+            split = defaultSplit;
+        }
+        final float[] result = new float[split.length];
+        for (int i = 0; i < split.length; i++) {
+            try {
+                result[i] = Float.parseFloat(split[i]);
+            } catch (NumberFormatException e) {
+                Log.v(LOG_TAG, "Error parsing part of " + key + " flag. Using defaults.");
+                result[i] = Float.parseFloat(defaultSplit[i]);
+            }
+        }
+        return result;
+    }
+
     void dump(IndentingPrintWriter pw) {
         pw.println("TextClassificationConstants:");
         pw.increaseIndent();
@@ -385,6 +470,9 @@
                 mNotificationConversationActionTypesDefault);
         pw.printPair("getLangIdThresholdOverride", mLangIdThresholdOverride);
         pw.printPair("isTemplateIntentFactoryEnabled", mTemplateIntentFactoryEnabled);
+        pw.printPair("isTranslateInClassificationEnabled", mTranslateInClassificationEnabled);
+        pw.printPair("isDetectLanguageFromTextEnabled", mDetectLanguagesFromTextEnabled);
+        pw.printPair("getLangIdContextSettings", Arrays.toString(mLangIdContextSettings));
         pw.decreaseIndent();
         pw.println();
     }
diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java
index a4e5502..ac8a429 100644
--- a/core/java/android/view/textclassifier/TextClassifier.java
+++ b/core/java/android/view/textclassifier/TextClassifier.java
@@ -33,11 +33,13 @@
 import android.text.util.Linkify.LinkifyMask;
 import android.util.ArrayMap;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.text.BreakIterator;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -644,11 +646,14 @@
      *  <li>Provides validation of input parameters to TextClassifier methods
      * </ul>
      *
-     * Intended to be used only in this package.
+     * Intended to be used only for TextClassifier purposes.
      * @hide
      */
     final class Utils {
 
+        @GuardedBy("WORD_ITERATOR")
+        private static final BreakIterator WORD_ITERATOR = BreakIterator.getWordInstance();
+
         /**
          * @throws IllegalArgumentException if text is null; startIndex is negative;
          *      endIndex is greater than text.length() or is not greater than startIndex;
@@ -666,6 +671,47 @@
         }
 
         /**
+         * Returns the substring of {@code text} that contains at least text from index
+         * {@code start} <i>(inclusive)</i> to index {@code end} <i><(exclusive)/i> with the goal of
+         * returning text that is at least {@code minimumLength}. If {@code text} is not long
+         * enough, this will return {@code text}. This method returns text at word boundaries.
+         *
+         * @param text the source text
+         * @param start the start index of text that must be included
+         * @param end the end index of text that must be included
+         * @param minimumLength minimum length of text to return if {@code text} is long enough
+         */
+        public static String getSubString(
+                String text, int start, int end, int minimumLength) {
+            Preconditions.checkArgument(start >= 0);
+            Preconditions.checkArgument(end <= text.length());
+            Preconditions.checkArgument(start <= end);
+
+            if (text.length() < minimumLength) {
+                return text;
+            }
+
+            final int length = end - start;
+            if (length >= minimumLength) {
+                return text.substring(start, end);
+            }
+
+            final int offset = (minimumLength - length) / 2;
+            int iterStart = Math.max(0, Math.min(start - offset, text.length() - minimumLength));
+            int iterEnd = Math.min(text.length(), iterStart + minimumLength);
+
+            synchronized (WORD_ITERATOR) {
+                WORD_ITERATOR.setText(text);
+                iterStart = WORD_ITERATOR.isBoundary(iterStart)
+                        ? iterStart : Math.max(0, WORD_ITERATOR.preceding(iterStart));
+                iterEnd = WORD_ITERATOR.isBoundary(iterEnd)
+                        ? iterEnd : Math.max(iterEnd, WORD_ITERATOR.following(iterEnd));
+                WORD_ITERATOR.setText("");
+                return text.substring(iterStart, iterEnd);
+            }
+        }
+
+        /**
          * Generates links using legacy {@link Linkify}.
          */
         public static TextLinks generateLegacyLinks(@NonNull TextLinks.Request request) {
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 35cd678..8f5f0a37 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -21,10 +21,19 @@
 import android.annotation.WorkerThread;
 import android.app.RemoteAction;
 import android.content.Context;
+import android.content.Intent;
 import android.icu.util.ULocale;
 import android.os.Bundle;
 import android.os.LocaleList;
 import android.os.ParcelFileDescriptor;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Pair;
+import android.view.textclassifier.intent.ClassificationIntentFactory;
+import android.view.textclassifier.intent.LabeledIntent;
+import android.view.textclassifier.intent.LegacyClassificationIntentFactory;
+import android.view.textclassifier.intent.TemplateClassificationIntentFactory;
+import android.view.textclassifier.intent.TemplateIntentFactory;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.IndentingPrintWriter;
@@ -33,6 +42,7 @@
 import com.google.android.textclassifier.ActionsSuggestionsModel;
 import com.google.android.textclassifier.AnnotatorModel;
 import com.google.android.textclassifier.LangIdModel;
+import com.google.android.textclassifier.LangIdModel.LanguageResult;
 
 import java.io.File;
 import java.io.FileNotFoundException;
@@ -41,11 +51,12 @@
 import java.time.ZonedDateTime;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashMap;
+import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Set;
 
 /**
  * Default implementation of the {@link TextClassifier} interface.
@@ -85,19 +96,19 @@
 
     private final Object mLock = new Object();
 
-    @GuardedBy("mLock") // Do not access outside this lock.
+    @GuardedBy("mLock")
     private ModelFileManager.ModelFile mAnnotatorModelInUse;
-    @GuardedBy("mLock") // Do not access outside this lock.
+    @GuardedBy("mLock")
     private AnnotatorModel mAnnotatorImpl;
 
-    @GuardedBy("mLock") // Do not access outside this lock.
+    @GuardedBy("mLock")
     private ModelFileManager.ModelFile mLangIdModelInUse;
-    @GuardedBy("mLock") // Do not access outside this lock.
+    @GuardedBy("mLock")
     private LangIdModel mLangIdImpl;
 
-    @GuardedBy("mLock") // Do not access outside this lock.
+    @GuardedBy("mLock")
     private ModelFileManager.ModelFile mActionModelInUse;
-    @GuardedBy("mLock") // Do not access outside this lock.
+    @GuardedBy("mLock")
     private ActionsSuggestionsModel mActionsImpl;
 
     private final SelectionSessionLogger mSessionLogger = new SelectionSessionLogger();
@@ -110,7 +121,7 @@
     private final ModelFileManager mLangIdModelFileManager;
     private final ModelFileManager mActionsModelFileManager;
 
-    private final IntentFactory mIntentFactory;
+    private final ClassificationIntentFactory mClassificationIntentFactory;
     private final TemplateIntentFactory mTemplateIntentFactory;
 
     public TextClassifierImpl(
@@ -142,10 +153,10 @@
                         ActionsSuggestionsModel::getLocales));
 
         mTemplateIntentFactory = new TemplateIntentFactory();
-        mIntentFactory = mSettings.isTemplateIntentFactoryEnabled()
+        mClassificationIntentFactory = mSettings.isTemplateIntentFactoryEnabled()
                 ? new TemplateClassificationIntentFactory(
-                mTemplateIntentFactory, new LegacyIntentFactory())
-                : new LegacyIntentFactory();
+                mTemplateIntentFactory, new LegacyClassificationIntentFactory())
+                : new LegacyClassificationIntentFactory();
     }
 
     public TextClassifierImpl(Context context, TextClassificationConstants settings) {
@@ -164,6 +175,7 @@
             if (string.length() > 0
                     && rangeLength <= mSettings.getSuggestSelectionMaxRangeLength()) {
                 final String localesString = concatenateLocales(request.getDefaultLocales());
+                final String detectLanguageTags = detectLanguageTagsFromText(request.getText());
                 final ZonedDateTime refTime = ZonedDateTime.now();
                 final AnnotatorModel annotatorImpl =
                         getAnnotatorImpl(request.getDefaultLocales());
@@ -175,7 +187,7 @@
                 } else {
                     final int[] startEnd = annotatorImpl.suggestSelection(
                             string, request.getStartIndex(), request.getEndIndex(),
-                            new AnnotatorModel.SelectionOptions(localesString));
+                            new AnnotatorModel.SelectionOptions(localesString, detectLanguageTags));
                     start = startEnd[0];
                     end = startEnd[1];
                 }
@@ -189,7 +201,8 @@
                                     new AnnotatorModel.ClassificationOptions(
                                             refTime.toInstant().toEpochMilli(),
                                             refTime.getZone().getId(),
-                                            localesString),
+                                            localesString,
+                                            detectLanguageTags),
                                     // Passing null here to suppress intent generation
                                     // TODO: Use an explicit flag to suppress it.
                                     /* appContext */ null,
@@ -227,6 +240,7 @@
             final String string = request.getText().toString();
             if (string.length() > 0 && rangeLength <= mSettings.getClassifyTextMaxRangeLength()) {
                 final String localesString = concatenateLocales(request.getDefaultLocales());
+                final String detectLanguageTags = detectLanguageTagsFromText(request.getText());
                 final ZonedDateTime refTime = request.getReferenceTime() != null
                         ? request.getReferenceTime() : ZonedDateTime.now();
                 final AnnotatorModel.ClassificationResult[] results =
@@ -236,9 +250,10 @@
                                         new AnnotatorModel.ClassificationOptions(
                                                 refTime.toInstant().toEpochMilli(),
                                                 refTime.getZone().getId(),
-                                                localesString),
+                                                localesString,
+                                                detectLanguageTags),
                                         mContext,
-                                        getResourceLocaleString()
+                                        getResourceLocalesString()
                                 );
                 if (results.length > 0) {
                     return createClassificationResult(
@@ -274,8 +289,10 @@
             final ZonedDateTime refTime = ZonedDateTime.now();
             final Collection<String> entitiesToIdentify = request.getEntityConfig() != null
                     ? request.getEntityConfig().resolveEntityListModifications(
-                    getEntitiesForHints(request.getEntityConfig().getHints()))
+                            getEntitiesForHints(request.getEntityConfig().getHints()))
                     : mSettings.getEntityListDefault();
+            final String localesString = concatenateLocales(request.getDefaultLocales());
+            final String detectLanguageTags = detectLanguageTagsFromText(request.getText());
             final AnnotatorModel annotatorImpl =
                     getAnnotatorImpl(request.getDefaultLocales());
             final AnnotatorModel.AnnotatedSpan[] annotations =
@@ -284,7 +301,8 @@
                             new AnnotatorModel.AnnotationOptions(
                                     refTime.toInstant().toEpochMilli(),
                                     refTime.getZone().getId(),
-                                    concatenateLocales(request.getDefaultLocales())));
+                                    localesString,
+                                    detectLanguageTags));
             for (AnnotatorModel.AnnotatedSpan span : annotations) {
                 final AnnotatorModel.ClassificationResult[] results =
                         span.getClassification();
@@ -292,7 +310,7 @@
                         || !entitiesToIdentify.contains(results[0].getCollection())) {
                     continue;
                 }
-                final Map<String, Float> entityScores = new HashMap<>();
+                final Map<String, Float> entityScores = new ArrayMap<>();
                 for (int i = 0; i < results.length; i++) {
                     entityScores.put(results[i].getCollection(), results[i].getScore());
                 }
@@ -386,8 +404,8 @@
                 return mFallback.suggestConversationActions(request);
             }
             ActionsSuggestionsModel.ConversationMessage[] nativeMessages =
-                    ActionsSuggestionsHelper.toNativeMessages(request.getConversation(),
-                            this::detectLanguageTagsFromText);
+                    ActionsSuggestionsHelper.toNativeMessages(
+                            request.getConversation(), this::detectLanguageTagsFromText);
             if (nativeMessages.length == 0) {
                 return mFallback.suggestConversationActions(request);
             }
@@ -399,7 +417,7 @@
                             nativeConversation,
                             null,
                             mContext,
-                            getResourceLocaleString());
+                            getResourceLocalesString());
             return createConversationActionResult(request, nativeSuggestions);
         } catch (Throwable t) {
             // Avoid throwing from this method. Log the error.
@@ -428,21 +446,20 @@
             if (!expectedTypes.contains(actionType)) {
                 continue;
             }
-            List<LabeledIntent> labeledIntents =
-                    mTemplateIntentFactory.create(nativeSuggestion.getRemoteActionTemplates());
-            Bundle extras = new Bundle();
+            LabeledIntent.Result labeledIntentResult =
+                    ActionsSuggestionsHelper.createLabeledIntentResult(
+                            mContext,
+                            mTemplateIntentFactory,
+                            nativeSuggestion);
             RemoteAction remoteAction = null;
-            // Given that we only support implicit intent here, we should expect there is just one
-            // intent for each action type.
-            if (!labeledIntents.isEmpty()) {
-                LabeledIntent.TitleChooser titleChooser =
-                        ActionsSuggestionsHelper.createTitleChooser(actionType);
-                LabeledIntent.Result result = labeledIntents.get(0).resolve(mContext, titleChooser);
-                if (result != null) {
-                    remoteAction = result.remoteAction;
-                    ExtrasUtils.putActionIntent(extras, result.resolvedIntent);
-                }
+            Bundle extras = new Bundle();
+            if (labeledIntentResult != null) {
+                remoteAction = labeledIntentResult.remoteAction;
+                ExtrasUtils.putActionIntent(extras, labeledIntentResult.resolvedIntent);
             }
+            ExtrasUtils.putEntitiesExtras(
+                    extras,
+                    TemplateIntentFactory.nameVariantsToBundle(nativeSuggestion.getEntityData()));
             conversationActions.add(
                     new ConversationAction.Builder(actionType)
                             .setConfidenceScore(nativeSuggestion.getScore())
@@ -463,19 +480,28 @@
 
     @Nullable
     private String detectLanguageTagsFromText(CharSequence text) {
+        if (!mSettings.isDetectLanguagesFromTextEnabled()) {
+            return null;
+        }
+        final float threshold = getLangIdThreshold();
+        if (threshold < 0 || threshold > 1) {
+            Log.w(LOG_TAG,
+                    "[detectLanguageTagsFromText] unexpected threshold is found: " + threshold);
+            return null;
+        }
         TextLanguage.Request request = new TextLanguage.Request.Builder(text).build();
         TextLanguage textLanguage = detectLanguage(request);
         int localeHypothesisCount = textLanguage.getLocaleHypothesisCount();
         List<String> languageTags = new ArrayList<>();
         for (int i = 0; i < localeHypothesisCount; i++) {
             ULocale locale = textLanguage.getLocale(i);
-            if (textLanguage.getConfidenceScore(locale) < getForeignLanguageThreshold()) {
+            if (textLanguage.getConfidenceScore(locale) < threshold) {
                 break;
             }
             languageTags.add(locale.toLanguageTag());
         }
         if (languageTags.isEmpty()) {
-            return LocaleList.getDefault().toLanguageTags();
+            return null;
         }
         return String.join(",", languageTags);
     }
@@ -600,97 +626,194 @@
             }
         }
 
-        final Bundle foreignLanguageBundle = detectForeignLanguage(classifiedText);
+        final Pair<Bundle, Bundle> languagesBundles = generateLanguageBundles(text, start, end);
+        final Bundle textLanguagesBundle = languagesBundles.first;
+        final Bundle foreignLanguageBundle = languagesBundles.second;
         builder.setForeignLanguageExtra(foreignLanguageBundle);
 
         boolean isPrimaryAction = true;
-        List<LabeledIntent> labeledIntents = mIntentFactory.create(
+        final List<LabeledIntent> labeledIntents = mClassificationIntentFactory.create(
                 mContext,
                 classifiedText,
                 foreignLanguageBundle != null,
                 referenceTime,
                 highestScoringResult);
-        LabeledIntent.TitleChooser titleChooser =
+        final LabeledIntent.TitleChooser titleChooser =
                 (labeledIntent, resolveInfo) -> labeledIntent.titleWithoutEntity;
+
         for (LabeledIntent labeledIntent : labeledIntents) {
-            LabeledIntent.Result result = labeledIntent.resolve(mContext, titleChooser);
+            final LabeledIntent.Result result =
+                    labeledIntent.resolve(mContext, titleChooser, textLanguagesBundle);
             if (result == null) {
                 continue;
             }
+
+            final Intent intent = result.resolvedIntent;
             final RemoteAction action = result.remoteAction;
             if (isPrimaryAction) {
                 // For O backwards compatibility, the first RemoteAction is also written to the
                 // legacy API fields.
                 builder.setIcon(action.getIcon().loadDrawable(mContext));
                 builder.setLabel(action.getTitle().toString());
-                builder.setIntent(result.resolvedIntent);
+                builder.setIntent(intent);
                 builder.setOnClickListener(TextClassification.createIntentOnClickListener(
-                        TextClassification.createPendingIntent(mContext,
-                                result.resolvedIntent, labeledIntent.requestCode)));
+                        TextClassification.createPendingIntent(
+                                mContext, intent, labeledIntent.requestCode)));
                 isPrimaryAction = false;
             }
-            builder.addAction(action, result.resolvedIntent);
+            builder.addAction(action, intent);
         }
 
         return builder.setId(createId(text, start, end)).build();
     }
 
     /**
-     * Returns a bundle with the language and confidence score if it finds the text to be
-     * in a foreign language. Otherwise returns null. This algorithm defines what the system thinks
-     * is a foreign language.
+     * Returns a bundle pair with language detection information for extras.
+     * <p>
+     * Pair.first = textLanguagesBundle - A bundle containing information about all detected
+     * languages in the text. May be null if language detection fails or is disabled. This is
+     * typically expected to be added to a textClassifier generated remote action intent.
+     * See {@link ExtrasUtils#putTextLanguagesExtra(Bundle, Bundle)}.
+     * See {@link ExtrasUtils#getTopLanguage(Intent)}.
+     * <p>
+     * Pair.second = foreignLanguageBundle - A bundle with the language and confidence score if the
+     * system finds the text to be in a foreign language. Otherwise is null.
+     * See {@link TextClassification.Builder#setForeignLanguageExtra(Bundle)}.
+     *
+     * @param context the context of the text to detect languages for
+     * @param start the start index of the text
+     * @param end the end index of the text
      */
     // TODO: Revisit this algorithm.
     // TODO: Consider making this public API.
-    @Nullable
-    private Bundle detectForeignLanguage(String text) {
+    private Pair<Bundle, Bundle> generateLanguageBundles(String context, int start, int end) {
+        if (!mSettings.isTranslateInClassificationEnabled()) {
+            return null;
+        }
         try {
-            final float threshold = getForeignLanguageThreshold();
-            if (threshold > 1) {
-                Log.v(LOG_TAG, "Foreign language detection disabled.");
-                return null;
+            final float threshold = getLangIdThreshold();
+            if (threshold < 0 || threshold > 1) {
+                Log.w(LOG_TAG,
+                        "[detectForeignLanguage] unexpected threshold is found: " + threshold);
+                return Pair.create(null, null);
             }
 
-            final LangIdModel langId = getLangIdImpl();
-            final LangIdModel.LanguageResult[] langResults = langId.detectLanguages(text);
-            if (langResults.length <= 0) {
-                return null;
+            final EntityConfidence languageScores = detectLanguages(context, start, end);
+            if (languageScores.getEntities().isEmpty()) {
+                return Pair.create(null, null);
             }
 
-            LangIdModel.LanguageResult highestScoringResult = langResults[0];
-            for (int i = 1; i < langResults.length; i++) {
-                if (langResults[i].getScore() > highestScoringResult.getScore()) {
-                    highestScoringResult = langResults[i];
-                }
-            }
-            if (highestScoringResult.getScore() < threshold) {
-                return null;
+            final Bundle textLanguagesBundle = new Bundle();
+            ExtrasUtils.putTopLanguageScores(textLanguagesBundle, languageScores);
+
+            final String language = languageScores.getEntities().get(0);
+            final float score = languageScores.getConfidenceScore(language);
+            if (score < threshold) {
+                return Pair.create(textLanguagesBundle, null);
             }
 
-            Log.v(LOG_TAG, String.format("Language detected: <%s:%s>",
-                    highestScoringResult.getLanguage(), highestScoringResult.getScore()));
+            Log.v(LOG_TAG, String.format(
+                    Locale.US, "Language detected: <%s:%.2f>", language, score));
 
-            final Locale detected = new Locale(highestScoringResult.getLanguage());
+            final Locale detected = new Locale(language);
             final LocaleList deviceLocales = LocaleList.getDefault();
             final int size = deviceLocales.size();
             for (int i = 0; i < size; i++) {
                 if (deviceLocales.get(i).getLanguage().equals(detected.getLanguage())) {
-                    return null;
+                    return Pair.create(textLanguagesBundle, null);
                 }
             }
-            return ExtrasUtils.createForeignLanguageExtra(
-                    detected.getLanguage(), highestScoringResult.getScore(), langId.getVersion());
+            final Bundle foreignLanguageBundle = ExtrasUtils.createForeignLanguageExtra(
+                    detected.getLanguage(), score, getLangIdImpl().getVersion());
+            return Pair.create(textLanguagesBundle, foreignLanguageBundle);
         } catch (Throwable t) {
-            Log.e(LOG_TAG, "Error detecting foreign text. Ignored.", t);
+            Log.e(LOG_TAG, "Error generating language bundles.", t);
         }
-        return null;
+        return Pair.create(null, null);
     }
 
-    private float getForeignLanguageThreshold() {
+    /**
+     * Detect the language of a piece of text by taking surrounding text into consideration.
+     *
+     * @param text text providing context for the text for which its language is to be detected
+     * @param start the start index of the text to detect its language
+     * @param end the end index of the text to detect its language
+     */
+    // TODO: Revisit this algorithm.
+    private EntityConfidence detectLanguages(String text, int start, int end)
+            throws FileNotFoundException {
+        Preconditions.checkArgument(start >= 0);
+        Preconditions.checkArgument(end <= text.length());
+        Preconditions.checkArgument(start <= end);
+
+        final float[] langIdContextSettings = mSettings.getLangIdContextSettings();
+        // The minimum size of text to prefer for detection.
+        final int minimumTextSize = (int) langIdContextSettings[0];
+        // For reducing the score when text is less than the preferred size.
+        final float penalizeRatio = langIdContextSettings[1];
+        // Original detection score to surrounding text detection score ratios.
+        final float subjectTextScoreRatio = langIdContextSettings[2];
+        final float moreTextScoreRatio = 1f - subjectTextScoreRatio;
+        Log.v(LOG_TAG,
+                String.format(Locale.US, "LangIdContextSettings: "
+                        + "minimumTextSize=%d, penalizeRatio=%.2f, "
+                        + "subjectTextScoreRatio=%.2f, moreTextScoreRatio=%.2f",
+                        minimumTextSize, penalizeRatio, subjectTextScoreRatio, moreTextScoreRatio));
+
+        if (end - start < minimumTextSize && penalizeRatio <= 0) {
+            return new EntityConfidence(Collections.emptyMap());
+        }
+
+        final String subject = text.substring(start, end);
+        final EntityConfidence scores = detectLanguages(subject);
+
+        if (subject.length() >= minimumTextSize
+                || subject.length() == text.length()
+                || subjectTextScoreRatio * penalizeRatio >= 1) {
+            return scores;
+        }
+
+        final EntityConfidence moreTextScores;
+        if (moreTextScoreRatio >= 0) {
+            // Attempt to grow the detection text to be at least minimumTextSize long.
+            final String moreText = Utils.getSubString(text, start, end, minimumTextSize);
+            moreTextScores = detectLanguages(moreText);
+        } else {
+            moreTextScores = new EntityConfidence(Collections.emptyMap());
+        }
+
+        // Combine the original detection scores with the those returned after including more text.
+        final Map<String, Float> newScores = new ArrayMap<>();
+        final Set<String> languages = new ArraySet<>();
+        languages.addAll(scores.getEntities());
+        languages.addAll(moreTextScores.getEntities());
+        for (String language : languages) {
+            final float score = (subjectTextScoreRatio * scores.getConfidenceScore(language)
+                    + moreTextScoreRatio * moreTextScores.getConfidenceScore(language))
+                    * penalizeRatio;
+            newScores.put(language, score);
+        }
+        return new EntityConfidence(newScores);
+    }
+
+    /**
+     * Detect languages for the specified text.
+     */
+    private EntityConfidence detectLanguages(String text) throws FileNotFoundException {
+        final LangIdModel langId = getLangIdImpl();
+        final LangIdModel.LanguageResult[] langResults = langId.detectLanguages(text);
+        final Map<String, Float> languagesMap = new ArrayMap<>();
+        for (LanguageResult langResult : langResults) {
+            languagesMap.put(langResult.getLanguage(), langResult.getScore());
+        }
+        return new EntityConfidence(languagesMap);
+    }
+
+    private float getLangIdThreshold() {
         try {
             return mSettings.getLangIdThresholdOverride() >= 0
                     ? mSettings.getLangIdThresholdOverride()
-                    : getLangIdImpl().getTranslateThreshold();
+                    : getLangIdImpl().getLangIdThreshold();
         } catch (FileNotFoundException e) {
             final float defaultThreshold = 0.5f;
             Log.v(LOG_TAG, "Using default foreign language threshold: " + defaultThreshold);
@@ -746,15 +869,14 @@
     }
 
     /**
-     * Returns the locale string for the current resources configuration.
+     * Returns the locales string for the current resources configuration.
      */
-    private String getResourceLocaleString() {
-        // TODO: Pass the locale list once it is supported in native side.
+    private String getResourceLocalesString() {
         try {
-            return mContext.getResources().getConfiguration().getLocales().get(0).toLanguageTag();
+            return mContext.getResources().getConfiguration().getLocales().toLanguageTags();
         } catch (NullPointerException e) {
             // NPE is unexpected. Erring on the side of caution.
-            return LocaleList.getDefault().get(0).toLanguageTag();
+            return LocaleList.getDefault().toLanguageTags();
         }
     }
 }
diff --git a/core/java/android/view/textclassifier/IntentFactory.java b/core/java/android/view/textclassifier/intent/ClassificationIntentFactory.java
similarity index 89%
rename from core/java/android/view/textclassifier/IntentFactory.java
rename to core/java/android/view/textclassifier/intent/ClassificationIntentFactory.java
index 722c812..b034846 100644
--- a/core/java/android/view/textclassifier/IntentFactory.java
+++ b/core/java/android/view/textclassifier/intent/ClassificationIntentFactory.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.view.textclassifier;
+package android.view.textclassifier.intent;
 
 import android.annotation.Nullable;
 import android.content.Context;
@@ -27,7 +27,7 @@
 /**
  * @hide
  */
-public interface IntentFactory {
+public interface ClassificationIntentFactory {
 
     /**
      * Return a list of LabeledIntent from the classification result.
@@ -51,8 +51,7 @@
                 new Intent(Intent.ACTION_TRANSLATE)
                         // TODO: Probably better to introduce a "translate" scheme instead of
                         // using EXTRA_TEXT.
-                        .putExtra(Intent.EXTRA_TEXT, text)
-                        .putExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER, true),
+                        .putExtra(Intent.EXTRA_TEXT, text),
                 text.hashCode()));
     }
 }
diff --git a/core/java/android/view/textclassifier/LabeledIntent.java b/core/java/android/view/textclassifier/intent/LabeledIntent.java
similarity index 81%
rename from core/java/android/view/textclassifier/LabeledIntent.java
rename to core/java/android/view/textclassifier/intent/LabeledIntent.java
index d2897b2..11d64f1 100644
--- a/core/java/android/view/textclassifier/LabeledIntent.java
+++ b/core/java/android/view/textclassifier/intent/LabeledIntent.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.view.textclassifier;
+package android.view.textclassifier.intent;
 
 import android.annotation.Nullable;
 import android.app.PendingIntent;
@@ -24,7 +24,12 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.graphics.drawable.Icon;
+import android.os.Bundle;
 import android.text.TextUtils;
+import android.view.textclassifier.ExtrasUtils;
+import android.view.textclassifier.Log;
+import android.view.textclassifier.TextClassification;
+import android.view.textclassifier.TextClassifier;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.Preconditions;
@@ -85,10 +90,16 @@
 
     /**
      * Return the resolved result.
+     *
+     * @param context the context to resolve the result's intent and action
+     * @param titleChooser for choosing an action title
+     * @param textLanguagesBundle containing language detection information
      */
     @Nullable
     public Result resolve(
-            Context context, @Nullable TitleChooser titleChooser) {
+            Context context,
+            @Nullable TitleChooser titleChooser,
+            @Nullable Bundle textLanguagesBundle) {
         final PackageManager pm = context.getPackageManager();
         final ResolveInfo resolveInfo = pm.resolveActivity(intent, 0);
 
@@ -104,6 +115,10 @@
         }
         Intent resolvedIntent = new Intent(intent);
         resolvedIntent.setComponent(new ComponentName(packageName, className));
+        resolvedIntent.putExtra(
+                TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER,
+                getFromTextClassifierExtra(textLanguagesBundle));
+
         boolean shouldShowIcon = false;
         Icon icon = null;
         if (!"android".equals(packageName)) {
@@ -115,25 +130,32 @@
         }
         if (icon == null) {
             // RemoteAction requires that there be an icon.
-            icon = Icon.createWithResource("android",
-                    com.android.internal.R.drawable.ic_more_items);
+            icon = Icon.createWithResource(
+                    "android", com.android.internal.R.drawable.ic_more_items);
         }
         final PendingIntent pendingIntent =
                 TextClassification.createPendingIntent(context, resolvedIntent, requestCode);
-        if (titleChooser == null) {
-            titleChooser = DEFAULT_TITLE_CHOOSER;
-        }
+        titleChooser = titleChooser == null ? DEFAULT_TITLE_CHOOSER : titleChooser;
         CharSequence title = titleChooser.chooseTitle(this, resolveInfo);
         if (TextUtils.isEmpty(title)) {
             Log.w(TAG, "Custom titleChooser return null, fallback to the default titleChooser");
             title = DEFAULT_TITLE_CHOOSER.chooseTitle(this, resolveInfo);
         }
-        final RemoteAction action =
-                new RemoteAction(icon, title, description, pendingIntent);
+        final RemoteAction action = new RemoteAction(icon, title, description, pendingIntent);
         action.setShouldShowIcon(shouldShowIcon);
         return new Result(resolvedIntent, action);
     }
 
+    private Bundle getFromTextClassifierExtra(@Nullable Bundle textLanguagesBundle) {
+        if (textLanguagesBundle != null) {
+            final Bundle bundle = new Bundle();
+            ExtrasUtils.putTextLanguagesExtra(bundle, textLanguagesBundle);
+            return bundle;
+        } else {
+            return Bundle.EMPTY;
+        }
+    }
+
     /**
      * Data class that holds the result.
      */
diff --git a/core/java/android/view/textclassifier/LegacyIntentFactory.java b/core/java/android/view/textclassifier/intent/LegacyClassificationIntentFactory.java
similarity index 96%
rename from core/java/android/view/textclassifier/LegacyIntentFactory.java
rename to core/java/android/view/textclassifier/intent/LegacyClassificationIntentFactory.java
index ea9229d..7916791 100644
--- a/core/java/android/view/textclassifier/LegacyIntentFactory.java
+++ b/core/java/android/view/textclassifier/intent/LegacyClassificationIntentFactory.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.view.textclassifier;
+package android.view.textclassifier.intent;
 
 import static java.time.temporal.ChronoUnit.MILLIS;
 
@@ -29,6 +29,8 @@
 import android.provider.Browser;
 import android.provider.CalendarContract;
 import android.provider.ContactsContract;
+import android.view.textclassifier.Log;
+import android.view.textclassifier.TextClassifier;
 
 import com.google.android.textclassifier.AnnotatorModel;
 
@@ -44,14 +46,12 @@
  * Creates intents based on the classification type.
  * @hide
  */
-public final class LegacyIntentFactory implements IntentFactory {
+public final class LegacyClassificationIntentFactory implements ClassificationIntentFactory {
 
-    private static final String TAG = "LegacyIntentFactory";
+    private static final String TAG = "LegacyClassificationIntentFactory";
     private static final long MIN_EVENT_FUTURE_MILLIS = TimeUnit.MINUTES.toMillis(5);
     private static final long DEFAULT_EVENT_DURATION = TimeUnit.HOURS.toMillis(1);
 
-    public LegacyIntentFactory() {}
-
     @NonNull
     @Override
     public List<LabeledIntent> create(Context context, String text, boolean foreignText,
@@ -96,10 +96,8 @@
                 break;
         }
         if (foreignText) {
-            IntentFactory.insertTranslateAction(actions, context, text);
+            ClassificationIntentFactory.insertTranslateAction(actions, context, text);
         }
-        actions.forEach(
-                action -> action.intent.putExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER, true));
         return actions;
     }
 
diff --git a/core/java/android/view/textclassifier/TemplateClassificationIntentFactory.java b/core/java/android/view/textclassifier/intent/TemplateClassificationIntentFactory.java
similarity index 82%
rename from core/java/android/view/textclassifier/TemplateClassificationIntentFactory.java
rename to core/java/android/view/textclassifier/intent/TemplateClassificationIntentFactory.java
index ed0259f..111fc6a 100644
--- a/core/java/android/view/textclassifier/TemplateClassificationIntentFactory.java
+++ b/core/java/android/view/textclassifier/intent/TemplateClassificationIntentFactory.java
@@ -13,14 +13,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.view.textclassifier;
+package android.view.textclassifier.intent;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
+import android.view.textclassifier.Log;
+import android.view.textclassifier.TextClassifier;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.Preconditions;
 
 import com.google.android.textclassifier.AnnotatorModel;
@@ -36,19 +37,19 @@
  * @hide
  */
 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
-public final class TemplateClassificationIntentFactory implements IntentFactory {
+public final class TemplateClassificationIntentFactory implements ClassificationIntentFactory {
     private static final String TAG = TextClassifier.DEFAULT_LOG_TAG;
     private final TemplateIntentFactory mTemplateIntentFactory;
-    private final IntentFactory mFallback;
+    private final ClassificationIntentFactory mFallback;
 
     public TemplateClassificationIntentFactory(TemplateIntentFactory templateIntentFactory,
-            IntentFactory fallback) {
+            ClassificationIntentFactory fallback) {
         mTemplateIntentFactory = Preconditions.checkNotNull(templateIntentFactory);
         mFallback = Preconditions.checkNotNull(fallback);
     }
 
     /**
-     * Returns a list of {@link android.view.textclassifier.LabeledIntent}
+     * Returns a list of {@link LabeledIntent}
      * that are constructed from the classification result.
      */
     @NonNull
@@ -63,15 +64,16 @@
             return Collections.emptyList();
         }
         RemoteActionTemplate[] remoteActionTemplates = classification.getRemoteActionTemplates();
-        if (ArrayUtils.isEmpty(remoteActionTemplates)) {
+        if (remoteActionTemplates == null) {
             // RemoteActionTemplate is missing, fallback.
-            Log.w(TAG, "RemoteActionTemplate is missing, fallback to LegacyIntentFactory.");
+            Log.w(TAG, "RemoteActionTemplate is missing, fallback to"
+                    + " LegacyClassificationIntentFactory.");
             return mFallback.create(context, text, foreignText, referenceTime, classification);
         }
         final List<LabeledIntent> labeledIntents =
                 mTemplateIntentFactory.create(remoteActionTemplates);
         if (foreignText) {
-            IntentFactory.insertTranslateAction(labeledIntents, context, text.trim());
+            ClassificationIntentFactory.insertTranslateAction(labeledIntents, context, text.trim());
         }
         return labeledIntents;
     }
diff --git a/core/java/android/view/textclassifier/TemplateIntentFactory.java b/core/java/android/view/textclassifier/intent/TemplateIntentFactory.java
similarity index 87%
rename from core/java/android/view/textclassifier/TemplateIntentFactory.java
rename to core/java/android/view/textclassifier/intent/TemplateIntentFactory.java
index 0696d98..59cd7ab 100644
--- a/core/java/android/view/textclassifier/TemplateIntentFactory.java
+++ b/core/java/android/view/textclassifier/intent/TemplateIntentFactory.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.view.textclassifier;
+package android.view.textclassifier.intent;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -21,15 +21,15 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.text.TextUtils;
+import android.view.textclassifier.Log;
+import android.view.textclassifier.TextClassifier;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
 
 import com.google.android.textclassifier.NamedVariant;
 import com.google.android.textclassifier.RemoteActionTemplate;
 
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
 
 /**
@@ -41,11 +41,14 @@
 public final class TemplateIntentFactory {
     private static final String TAG = TextClassifier.DEFAULT_LOG_TAG;
 
-    @NonNull
+    /**
+     * Constructs and returns a list of {@link LabeledIntent} based on the given templates.
+     */
+    @Nullable
     public List<LabeledIntent> create(
-            @Nullable RemoteActionTemplate[] remoteActionTemplates) {
-        if (ArrayUtils.isEmpty(remoteActionTemplates)) {
-            return Collections.emptyList();
+            @NonNull RemoteActionTemplate[] remoteActionTemplates) {
+        if (remoteActionTemplates.length == 0) {
+            return new ArrayList<>();
         }
         final List<LabeledIntent> labeledIntents = new ArrayList<>();
         for (RemoteActionTemplate remoteActionTemplate : remoteActionTemplates) {
@@ -63,8 +66,6 @@
                                     ? LabeledIntent.DEFAULT_REQUEST_CODE
                                     : remoteActionTemplate.requestCode));
         }
-        labeledIntents.forEach(
-                action -> action.intent.putExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER, true));
         return labeledIntents;
     }
 
@@ -108,11 +109,14 @@
                 }
             }
         }
-        intent.putExtras(createExtras(remoteActionTemplate.extras));
+        intent.putExtras(nameVariantsToBundle(remoteActionTemplate.extras));
         return intent;
     }
 
-    private static Bundle createExtras(NamedVariant[] namedVariants) {
+    /**
+     * Converts an array of {@link NamedVariant} to a Bundle and returns it.
+     */
+    public static Bundle nameVariantsToBundle(@Nullable NamedVariant[] namedVariants) {
         if (namedVariants == null) {
             return Bundle.EMPTY;
         }
@@ -142,7 +146,8 @@
                     break;
                 default:
                     Log.w(TAG,
-                            "Unsupported type found in createExtras : " + namedVariant.getType());
+                            "Unsupported type found in nameVariantsToBundle : "
+                                    + namedVariant.getType());
             }
         }
         return bundle;
diff --git a/core/java/android/webkit/WebViewDelegate.java b/core/java/android/webkit/WebViewDelegate.java
index 3d3d941..f5657df 100644
--- a/core/java/android/webkit/WebViewDelegate.java
+++ b/core/java/android/webkit/WebViewDelegate.java
@@ -209,19 +209,17 @@
      * Adds the WebView asset path to {@link android.content.res.AssetManager}.
      */
     public void addWebViewAssetPath(Context context) {
-        final String newAssetPath = WebViewFactory.getLoadedPackageInfo().applicationInfo.sourceDir;
-
+        final String[] newAssetPaths =
+                WebViewFactory.getLoadedPackageInfo().applicationInfo.getAllApkPaths();
         final ApplicationInfo appInfo = context.getApplicationInfo();
-        final String[] libs = appInfo.sharedLibraryFiles;
-        if (!ArrayUtils.contains(libs, newAssetPath)) {
-            // Build the new library asset path list.
-            final int newLibAssetsCount = 1 + (libs != null ? libs.length : 0);
-            final String[] newLibAssets = new String[newLibAssetsCount];
-            if (libs != null) {
-                System.arraycopy(libs, 0, newLibAssets, 0, libs.length);
-            }
-            newLibAssets[newLibAssetsCount - 1] = newAssetPath;
 
+        // Build the new library asset path list.
+        String[] newLibAssets = appInfo.sharedLibraryFiles;
+        for (String newAssetPath : newAssetPaths) {
+            newLibAssets = ArrayUtils.appendElement(String.class, newLibAssets, newAssetPath);
+        }
+
+        if (newLibAssets != appInfo.sharedLibraryFiles) {
             // Update the ApplicationInfo object with the new list.
             // We know this will persist and future Resources created via ResourcesManager
             // will include the shared library because this ApplicationInfo comes from the
@@ -230,8 +228,8 @@
             appInfo.sharedLibraryFiles = newLibAssets;
 
             // Update existing Resources with the WebView library.
-            ResourcesManager.getInstance().appendLibAssetForMainAssetPath(
-                    appInfo.getBaseResourcePath(), newAssetPath);
+            ResourcesManager.getInstance().appendLibAssetsForMainAssetPath(
+                    appInfo.getBaseResourcePath(), newAssetPaths);
         }
     }
 
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index 89e205c..8785251 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import android.annotation.DrawableRes;
+import android.annotation.IntDef;
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Resources.Theme;
@@ -44,6 +45,8 @@
 
 import com.android.internal.R;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.lang.ref.WeakReference;
 
 /**
@@ -1259,9 +1262,20 @@
     }
 
     /**
+     * The valid input method modes for the {@link AutoCompleteTextView}:
+     *
+     * {@hide}
+     */
+    @IntDef({ListPopupWindow.INPUT_METHOD_FROM_FOCUSABLE,
+            ListPopupWindow.INPUT_METHOD_NEEDED,
+            ListPopupWindow.INPUT_METHOD_NOT_NEEDED})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface InputMethodMode {}
+
+    /**
      * Returns the input method mode used by the auto complete dropdown.
      */
-    public int getInputMethodMode() {
+    public @InputMethodMode int getInputMethodMode() {
         return mPopup.getInputMethodMode();
     }
 
@@ -1277,7 +1291,7 @@
      * {@link ListPopupWindow#INPUT_METHOD_NOT_NEEDED}. The auto-complete suggestions are always
      * displayed, even if the suggestions cover/hide the input method.
      */
-    public void setInputMethodMode(int mode) {
+    public void setInputMethodMode(@InputMethodMode int mode) {
         mPopup.setInputMethodMode(mode);
     }
 
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index 25e5dd3..16b903d 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -702,7 +702,7 @@
 
             mPopup.setWidth(widthSpec);
             mPopup.setHeight(heightSpec);
-            mPopup.setClipToScreenEnabled(true);
+            mPopup.setIsClippedToScreen(true);
 
             // use outside touchable to dismiss drop down when touching outside of it, so
             // only set this if the dropdown is not always visible
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 2798296..20fc0b1 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -886,9 +886,9 @@
      * containing window<p/>
      *
      * @return true if popup will be clipped to the screen instead of the window, false otherwise
-     *
-     * @see #setClipToScreenEnabled(boolean)
+     * @deprecated Use {@link #isClippedToScreen()} instead
      */
+    @Deprecated
     public boolean isClipToScreenEnabled() {
         return mClipToScreen;
     }
@@ -900,11 +900,37 @@
      * the next time the popup is shown or through a manual call to one of
      * the {@link #update()} methods.</p>
      *
+     * @deprecated Use {@link #setIsClippedToScreen(boolean)} instead
+     */
+    @Deprecated
+    public void setClipToScreenEnabled(boolean enabled) {
+        mClipToScreen = enabled;
+    }
+
+    /**
+     * <p>Indicates whether this popup will be clipped to the screen and not to the
+     * containing window<p/>
+     *
+     * @return true if popup will be clipped to the screen instead of the window, false otherwise
+     *
+     * @see #setIsClippedToScreen(boolean)
+     */
+    public boolean isClippedToScreen() {
+        return mClipToScreen;
+    }
+
+    /**
+     * <p>Clip this popup window to the screen, but not to the containing window.</p>
+     *
+     * <p>If the popup is showing, calling this method will take effect only
+     * the next time the popup is shown or through a manual call to one of
+     * the {@link #update()} methods.</p>
+     *
      * @param enabled true to clip to the screen.
      *
-     * @see #isClipToScreenEnabled()
+     * @see #isClippedToScreen()
      */
-    public void setClipToScreenEnabled(boolean enabled) {
+    public void setIsClippedToScreen(boolean enabled) {
         mClipToScreen = enabled;
     }
 
@@ -961,8 +987,9 @@
      *
      * @return true if the window will always be positioned in screen coordinates.
      *
-     * @see #setLayoutInScreenEnabled(boolean)
+     * @deprecated Use {@link #isLaidOutInScreen()} instead
      */
+    @Deprecated
     public boolean isLayoutInScreenEnabled() {
         return mLayoutInScreen;
     }
@@ -973,14 +1000,39 @@
      * This will cause the popup to be positioned in absolute screen coordinates.</p>
      *
      * @param enabled true if the popup should always be positioned in screen coordinates
-     *
-     * @see #isLayoutInScreenEnabled()
+     * @deprecated Use {@link #setIsLaidOutInScreen(boolean)} instead
      */
+    @Deprecated
     public void setLayoutInScreenEnabled(boolean enabled) {
         mLayoutInScreen = enabled;
     }
 
     /**
+     * <p>Indicates whether the popup window will be forced into using absolute screen coordinates
+     * for positioning.</p>
+     *
+     * @return true if the window will always be positioned in screen coordinates.
+     *
+     * @see #setIsLaidOutInScreen(boolean)
+     */
+    public boolean isLaidOutInScreen() {
+        return mLayoutInScreen;
+    }
+
+    /**
+     * <p>Allows the popup window to force the flag
+     * {@link WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN}, overriding default behavior.
+     * This will cause the popup to be positioned in absolute screen coordinates.</p>
+     *
+     * @param enabled true if the popup should always be positioned in screen coordinates
+     *
+     * @see #isLaidOutInScreen()
+     */
+    public void setIsLaidOutInScreen(boolean enabled) {
+        mLayoutInScreen = enabled;
+    }
+
+    /**
      * <p>Indicates whether the popup window will be attached in the decor frame of its parent
      * window.
      *
@@ -1016,7 +1068,7 @@
      * This will cause the popup to inset its content to account for system windows overlaying
      * the screen, such as the status bar.
      *
-     * <p>This will often be combined with {@link #setLayoutInScreenEnabled(boolean)}.
+     * <p>This will often be combined with {@link #setIsLaidOutInScreen(boolean)}.
      *
      * @param enabled true if the popup's views should inset content to account for system windows,
      *                the way that decor views behave for full-screen windows.
@@ -2114,7 +2166,7 @@
      *     <li>{@link #setTouchable(boolean)}</li>
      *     <li>{@link #setAnimationStyle(int)}</li>
      *     <li>{@link #setTouchModal(boolean)} (boolean)}</li>
-     *     <li>{@link #setClipToScreenEnabled(boolean)}</li>
+     *     <li>{@link #setIsClippedToScreen(boolean)}</li>
      * </ul>
      */
     public void update() {
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index 8ee31e2..37bed65 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -35,6 +35,9 @@
 import android.view.ViewHierarchyEncoder;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.inspector.InspectableProperty;
+import android.view.inspector.InspectionCompanion;
+import android.view.inspector.PropertyMapper;
+import android.view.inspector.PropertyReader;
 import android.widget.RemoteViews.RemoteView;
 
 import com.android.internal.R;
@@ -1286,7 +1289,6 @@
          * the anchor's visibility is GONE.
          */
         @ViewDebug.ExportedProperty(category = "layout")
-        @InspectableProperty(name = "layout_alignWithParentIfMissing")
         public boolean alignWithParent;
 
         public LayoutParams(Context c, AttributeSet attrs) {
@@ -1723,6 +1725,146 @@
             super.encodeProperties(encoder);
             encoder.addProperty("layout:alignWithParent", alignWithParent);
         }
+
+        /** @hide */
+        public static final class InspectionCompanion
+                implements android.view.inspector.InspectionCompanion<LayoutParams> {
+            private boolean mPropertiesMapped;
+
+            private int mAboveId;
+            private int mAlignBaselineId;
+            private int mAlignBottomId;
+            private int mAlignEndId;
+            private int mAlignLeftId;
+            private int mAlignParentBottomId;
+            private int mAlignParentEndId;
+            private int mAlignParentLeftId;
+            private int mAlignParentRightId;
+            private int mAlignParentStartId;
+            private int mAlignParentTopId;
+            private int mAlignRightId;
+            private int mAlignStartId;
+            private int mAlignTopId;
+            private int mAlignWithParentIfMissingId;
+            private int mBelowId;
+            private int mCenterHorizontalId;
+            private int mCenterInParentId;
+            private int mCenterVerticalId;
+            private int mToEndOfId;
+            private int mToLeftOfId;
+            private int mToRightOfId;
+            private int mToStartOfId;
+
+            @Override
+            public void mapProperties(@NonNull PropertyMapper propertyMapper) {
+                mPropertiesMapped = true;
+
+                mAboveId = propertyMapper.mapResourceId("layout_above", R.attr.layout_above);
+
+                mAlignBaselineId = propertyMapper.mapResourceId(
+                        "layout_alignBaseline", R.attr.layout_alignBaseline);
+
+                mAlignBottomId = propertyMapper.mapResourceId(
+                        "layout_alignBottom", R.attr.layout_alignBottom);
+
+                mAlignEndId = propertyMapper.mapResourceId(
+                        "layout_alignEnd", R.attr.layout_alignEnd);
+
+                mAlignLeftId = propertyMapper.mapResourceId(
+                        "layout_alignLeft", R.attr.layout_alignLeft);
+
+                mAlignParentBottomId = propertyMapper.mapBoolean(
+                        "layout_alignParentBottom", R.attr.layout_alignParentBottom);
+
+                mAlignParentEndId = propertyMapper.mapBoolean(
+                        "layout_alignParentEnd", R.attr.layout_alignParentEnd);
+
+                mAlignParentLeftId = propertyMapper.mapBoolean(
+                        "layout_alignParentLeft", R.attr.layout_alignParentLeft);
+
+                mAlignParentRightId = propertyMapper.mapBoolean(
+                        "layout_alignParentRight", R.attr.layout_alignParentRight);
+
+                mAlignParentStartId = propertyMapper.mapBoolean(
+                        "layout_alignParentStart", R.attr.layout_alignParentStart);
+
+                mAlignParentTopId = propertyMapper.mapBoolean(
+                        "layout_alignParentTop", R.attr.layout_alignParentTop);
+
+                mAlignRightId = propertyMapper.mapResourceId(
+                        "layout_alignRight", R.attr.layout_alignRight);
+
+                mAlignStartId = propertyMapper.mapResourceId(
+                        "layout_alignStart", R.attr.layout_alignStart);
+
+                mAlignTopId = propertyMapper.mapResourceId(
+                        "layout_alignTop", R.attr.layout_alignTop);
+
+                mAlignWithParentIfMissingId = propertyMapper.mapBoolean(
+                        "layout_alignWithParentIfMissing",
+                        R.attr.layout_alignWithParentIfMissing);
+
+                mBelowId = propertyMapper.mapResourceId("layout_below", R.attr.layout_below);
+
+                mCenterHorizontalId = propertyMapper.mapBoolean(
+                        "layout_centerHorizontal", R.attr.layout_centerHorizontal);
+
+                mCenterInParentId = propertyMapper.mapBoolean(
+                        "layout_centerInParent", R.attr.layout_centerInParent);
+
+                mCenterVerticalId = propertyMapper.mapBoolean(
+                        "layout_centerVertical", R.attr.layout_centerVertical);
+
+                mToEndOfId = propertyMapper.mapResourceId(
+                        "layout_toEndOf", R.attr.layout_toEndOf);
+
+                mToLeftOfId = propertyMapper.mapResourceId(
+                        "layout_toLeftOf", R.attr.layout_toLeftOf);
+
+                mToRightOfId = propertyMapper.mapResourceId(
+                        "layout_toRightOf", R.attr.layout_toRightOf);
+
+                mToStartOfId = propertyMapper.mapResourceId(
+                        "layout_toStartOf", R.attr.layout_toStartOf);
+            }
+
+            @Override
+            public void readProperties(
+                    @NonNull LayoutParams node,
+                    @NonNull PropertyReader propertyReader
+            ) {
+                if (!mPropertiesMapped) {
+                    throw new UninitializedPropertyMapException();
+                }
+
+                final int[] rules = node.getRules();
+
+                propertyReader.readResourceId(mAboveId, rules[ABOVE]);
+                propertyReader.readResourceId(mAlignBaselineId, rules[ALIGN_BASELINE]);
+                propertyReader.readResourceId(mAlignBottomId, rules[ALIGN_BOTTOM]);
+                propertyReader.readResourceId(mAlignEndId, rules[ALIGN_END]);
+                propertyReader.readResourceId(mAlignLeftId, rules[ALIGN_LEFT]);
+                propertyReader.readBoolean(
+                        mAlignParentBottomId, rules[ALIGN_PARENT_BOTTOM] == TRUE);
+                propertyReader.readBoolean(mAlignParentEndId, rules[ALIGN_PARENT_END] == TRUE);
+                propertyReader.readBoolean(mAlignParentLeftId, rules[ALIGN_PARENT_LEFT] == TRUE);
+                propertyReader.readBoolean(mAlignParentRightId, rules[ALIGN_PARENT_RIGHT] == TRUE);
+                propertyReader.readBoolean(mAlignParentStartId, rules[ALIGN_PARENT_START] == TRUE);
+                propertyReader.readBoolean(mAlignParentTopId, rules[ALIGN_PARENT_TOP] == TRUE);
+                propertyReader.readResourceId(mAlignRightId, rules[ALIGN_RIGHT]);
+                propertyReader.readResourceId(mAlignStartId, rules[ALIGN_START]);
+                propertyReader.readResourceId(mAlignTopId, rules[ALIGN_TOP]);
+                propertyReader.readBoolean(mAlignWithParentIfMissingId, node.alignWithParent);
+                propertyReader.readResourceId(mBelowId, rules[BELOW]);
+                propertyReader.readBoolean(mCenterHorizontalId, rules[CENTER_HORIZONTAL] == TRUE);
+                propertyReader.readBoolean(mCenterInParentId, rules[CENTER_IN_PARENT] == TRUE);
+                propertyReader.readBoolean(mCenterVerticalId, rules[CENTER_VERTICAL] == TRUE);
+                propertyReader.readResourceId(mToEndOfId, rules[END_OF]);
+                propertyReader.readResourceId(mToLeftOfId, rules[LEFT_OF]);
+                propertyReader.readResourceId(mToRightOfId, rules[RIGHT_OF]);
+                propertyReader.readResourceId(mToStartOfId, rules[START_OF]);
+            }
+        }
     }
 
     private static class DependencyGraph {
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 91928b5..f250666 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -42,7 +42,6 @@
 import android.content.IntentSender;
 import android.content.IntentSender.SendIntentException;
 import android.content.ServiceConnection;
-import android.content.SharedPreferences;
 import android.content.pm.ActivityInfo;
 import android.content.pm.LabeledIntent;
 import android.content.pm.LauncherApps;
@@ -65,7 +64,6 @@
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Bundle;
-import android.os.Environment;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
@@ -75,7 +73,6 @@
 import android.os.ResultReceiver;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.os.storage.StorageManager;
 import android.provider.DocumentsContract;
 import android.provider.Downloads;
 import android.provider.OpenableColumns;
@@ -114,7 +111,6 @@
 
 import com.google.android.collect.Lists;
 
-import java.io.File;
 import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.util.ArrayList;
@@ -188,10 +184,7 @@
     private Drawable mChooserRowLayer;
     private int mChooserRowServiceSpacing;
 
-    private SharedPreferences mPinnedSharedPrefs;
-    private static final float PINNED_TARGET_SCORE_BOOST = 1000.f;
     private static final float CALLER_TARGET_SCORE_BOOST = 900.f;
-    private static final String PINNED_SHARED_PREFS_NAME = "chooser_pin_settings";
     private static final String TARGET_DETAILS_FRAGMENT_TAG = "targetDetailsFragment";
 
     private final List<ChooserTargetServiceConnection> mServiceConnections = new ArrayList<>();
@@ -236,7 +229,6 @@
                     mServiceConnections.remove(sri.connection);
                     if (mServiceConnections.isEmpty()) {
                         sendVoiceChoicesIfNeeded();
-                        mChooserListAdapter.setShowServiceTargets(true);
                     }
                     break;
 
@@ -250,7 +242,6 @@
                     unbindRemainingServices();
                     sendVoiceChoicesIfNeeded();
                     mChooserListAdapter.completeServiceTargetLoading();
-                    mChooserListAdapter.setShowServiceTargets(true);
                     break;
 
                 case SHORTCUT_MANAGER_SHARE_TARGET_RESULT:
@@ -265,7 +256,6 @@
 
                 case SHORTCUT_MANAGER_SHARE_TARGET_RESULT_COMPLETED:
                     sendVoiceChoicesIfNeeded();
-                    mChooserListAdapter.setShowServiceTargets(true);
                     break;
 
                 default:
@@ -321,9 +311,7 @@
         // Do not allow the title to be changed when sharing content
         CharSequence title = null;
         if (target != null) {
-            String targetAction = target.getAction();
-            if (!(Intent.ACTION_SEND.equals(targetAction) || Intent.ACTION_SEND_MULTIPLE.equals(
-                    targetAction))) {
+            if (!isSendAction(target)) {
                 title = intent.getCharSequenceExtra(Intent.EXTRA_TITLE);
             } else {
                 Log.w(TAG, "Ignoring intent's EXTRA_TITLE, deprecated in P. You may wish to set a"
@@ -390,7 +378,6 @@
             mCallerChooserTargets = targets;
         }
 
-        mPinnedSharedPrefs = getPinnedSharedPrefs(this);
         setRetainInOnStop(intent.getBooleanExtra(EXTRA_PRIVATE_RETAIN_IN_ON_STOP, false));
         super.onCreate(savedInstanceState, target, title, defaultTitleRes, initialIntents,
                 null, false);
@@ -446,6 +433,11 @@
         mChooserRowServiceSpacing = getResources()
                                         .getDimensionPixelSize(R.dimen.chooser_service_spacing);
 
+        // expand/shrink direct share 4 -> 8 viewgroup
+        if (mResolverDrawerLayout != null && isSendAction(target)) {
+            mResolverDrawerLayout.setOnScrollChangeListener(this::handleScroll);
+        }
+
         if (DEBUG) {
             Log.d(TAG, "System Time Cost is " + systemCost);
         }
@@ -461,34 +453,6 @@
                 .getUserInfo(UserHandle.myUserId()).isManagedProfile();
     }
 
-    /**
-     * Override method to add content preview area, specific to the chooser activity.
-     */
-    @Override
-    public void setHeader() {
-        super.setHeader();
-
-        Intent targetIntent = getTargetIntent();
-        if (targetIntent == null) {
-            return;
-        }
-
-        String action = targetIntent.getAction();
-        if (!(Intent.ACTION_SEND.equals(action) || Intent.ACTION_SEND_MULTIPLE.equals(action))) {
-            return;
-        }
-
-        if (mChooserListAdapter == null || mChooserListAdapter.getCount() == 0) {
-            return;
-        }
-
-        int previewType = findPreferredContentPreview(targetIntent, getContentResolver());
-
-        getMetricsLogger().write(new LogMaker(MetricsEvent.ACTION_SHARE_WITH_PREVIEW)
-                .setSubtype(previewType));
-        displayContentPreview(previewType, targetIntent);
-    }
-
     private void onCopyButtonClicked(View v) {
         Intent targetIntent = getTargetIntent();
         if (targetIntent == null) {
@@ -548,46 +512,56 @@
 
     private void updateLayoutWidth(int layoutResourceId, int width) {
         View view = findViewById(layoutResourceId);
-        LayoutParams params = view.getLayoutParams();
-        params.width = width;
-        view.setLayoutParams(params);
-    }
-
-    private void displayContentPreview(@ContentPreviewType int previewType, Intent targetIntent) {
-        switch (previewType) {
-            case CONTENT_PREVIEW_TEXT:
-                displayTextContentPreview(targetIntent);
-                break;
-            case CONTENT_PREVIEW_IMAGE:
-                displayImageContentPreview(targetIntent);
-                break;
-            case CONTENT_PREVIEW_FILE:
-                displayFileContentPreview(targetIntent);
-                break;
-            default:
-                Log.e(TAG, "Unexpected content preview type: " + previewType);
+        if (view != null && view.getLayoutParams() != null) {
+            LayoutParams params = view.getLayoutParams();
+            params.width = width;
+            view.setLayoutParams(params);
         }
     }
 
-    private void displayTextContentPreview(Intent targetIntent) {
-        ViewGroup contentPreviewLayout = findViewById(R.id.content_preview_text_area);
-        contentPreviewLayout.setVisibility(View.VISIBLE);
+    private ViewGroup displayContentPreview(@ContentPreviewType int previewType,
+            Intent targetIntent, LayoutInflater layoutInflater, ViewGroup convertView,
+            ViewGroup parent) {
+        switch (previewType) {
+            case CONTENT_PREVIEW_TEXT:
+                return displayTextContentPreview(targetIntent, layoutInflater, convertView, parent);
+            case CONTENT_PREVIEW_IMAGE:
+                return displayImageContentPreview(targetIntent, layoutInflater, convertView,
+                        parent);
+            case CONTENT_PREVIEW_FILE:
+                return displayFileContentPreview(targetIntent, layoutInflater, convertView, parent);
+            default:
+                Log.e(TAG, "Unexpected content preview type: " + previewType);
+        }
 
-        findViewById(R.id.copy_button).setOnClickListener(this::onCopyButtonClicked);
+        return null;
+    }
+
+    private ViewGroup displayTextContentPreview(Intent targetIntent, LayoutInflater layoutInflater,
+            ViewGroup convertView, ViewGroup parent) {
+        ViewGroup contentPreviewLayout =
+                convertView != null ? convertView : (ViewGroup) layoutInflater.inflate(
+                        R.layout.chooser_grid_preview_text, parent, false);
+
+        contentPreviewLayout.findViewById(R.id.copy_button).setOnClickListener(
+                this::onCopyButtonClicked);
 
         CharSequence sharingText = targetIntent.getCharSequenceExtra(Intent.EXTRA_TEXT);
         if (sharingText == null) {
-            findViewById(R.id.content_preview_text_layout).setVisibility(View.GONE);
+            contentPreviewLayout.findViewById(R.id.content_preview_text_layout).setVisibility(
+                    View.GONE);
         } else {
-            TextView textView = findViewById(R.id.content_preview_text);
+            TextView textView = contentPreviewLayout.findViewById(R.id.content_preview_text);
             textView.setText(sharingText);
         }
 
         String previewTitle = targetIntent.getStringExtra(Intent.EXTRA_TITLE);
         if (TextUtils.isEmpty(previewTitle)) {
-            findViewById(R.id.content_preview_title_layout).setVisibility(View.GONE);
+            contentPreviewLayout.findViewById(R.id.content_preview_title_layout).setVisibility(
+                    View.GONE);
         } else {
-            TextView previewTitleView = findViewById(R.id.content_preview_title);
+            TextView previewTitleView = contentPreviewLayout.findViewById(
+                    R.id.content_preview_title);
             previewTitleView.setText(previewTitle);
 
             ClipData previewData = targetIntent.getClipData();
@@ -599,7 +573,8 @@
                 }
             }
 
-            ImageView previewThumbnailView = findViewById(R.id.content_preview_thumbnail);
+            ImageView previewThumbnailView = contentPreviewLayout.findViewById(
+                    R.id.content_preview_thumbnail);
             if (previewThumbnail == null) {
                 previewThumbnailView.setVisibility(View.GONE);
             } else {
@@ -611,16 +586,20 @@
                 }
             }
         }
+
+        return contentPreviewLayout;
     }
 
-    private void displayImageContentPreview(Intent targetIntent) {
-        ViewGroup contentPreviewLayout = findViewById(R.id.content_preview_image_area);
-        contentPreviewLayout.setVisibility(View.VISIBLE);
+    private ViewGroup displayImageContentPreview(Intent targetIntent, LayoutInflater layoutInflater,
+            ViewGroup convertView, ViewGroup parent) {
+        ViewGroup contentPreviewLayout =
+                convertView != null ? convertView : (ViewGroup) layoutInflater.inflate(
+                        R.layout.chooser_grid_preview_image, parent, false);
 
         String action = targetIntent.getAction();
         if (Intent.ACTION_SEND.equals(action)) {
             Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM);
-            loadUriIntoView(R.id.content_preview_image_1_large, uri);
+            loadUriIntoView(R.id.content_preview_image_1_large, uri, contentPreviewLayout);
         } else {
             ContentResolver resolver = getContentResolver();
 
@@ -636,23 +615,28 @@
                 Log.i(TAG, "Attempted to display image preview area with zero"
                         + " available images detected in EXTRA_STREAM list");
                 contentPreviewLayout.setVisibility(View.GONE);
-                return;
+                return contentPreviewLayout;
             }
 
-            loadUriIntoView(R.id.content_preview_image_1_large, imageUris.get(0));
+            loadUriIntoView(R.id.content_preview_image_1_large, imageUris.get(0),
+                    contentPreviewLayout);
 
             if (imageUris.size() == 2) {
-                loadUriIntoView(R.id.content_preview_image_2_large, imageUris.get(1));
+                loadUriIntoView(R.id.content_preview_image_2_large, imageUris.get(1),
+                        contentPreviewLayout);
             } else if (imageUris.size() > 2) {
-                loadUriIntoView(R.id.content_preview_image_2_small, imageUris.get(1));
+                loadUriIntoView(R.id.content_preview_image_2_small, imageUris.get(1),
+                        contentPreviewLayout);
                 RoundedRectImageView imageView = loadUriIntoView(
-                        R.id.content_preview_image_3_small, imageUris.get(2));
+                        R.id.content_preview_image_3_small, imageUris.get(2), contentPreviewLayout);
 
                 if (imageUris.size() > 3) {
                     imageView.setExtraImageCount(imageUris.size() - 3);
                 }
             }
         }
+
+        return contentPreviewLayout;
     }
 
     private static class FileInfo {
@@ -711,18 +695,21 @@
         return new FileInfo(fileName, hasThumbnail);
     }
 
-    private void displayFileContentPreview(Intent targetIntent) {
-        ViewGroup contentPreviewLayout = findViewById(R.id.content_preview_file_area);
-        contentPreviewLayout.setVisibility(View.VISIBLE);
+    private ViewGroup displayFileContentPreview(Intent targetIntent, LayoutInflater layoutInflater,
+            ViewGroup convertView, ViewGroup parent) {
+
+        ViewGroup contentPreviewLayout =
+                convertView != null ? convertView : (ViewGroup) layoutInflater.inflate(
+                        R.layout.chooser_grid_preview_file, parent, false);
 
         // TODO(b/120417119): Disable file copy until after moving to sysui,
         // due to permissions issues
-        findViewById(R.id.file_copy_button).setVisibility(View.GONE);
+        contentPreviewLayout.findViewById(R.id.file_copy_button).setVisibility(View.GONE);
 
         String action = targetIntent.getAction();
         if (Intent.ACTION_SEND.equals(action)) {
             Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM);
-            loadFileUriIntoView(uri);
+            loadFileUriIntoView(uri, contentPreviewLayout);
         } else {
             List<Uri> uris = targetIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
             int uriCount = uris.size();
@@ -732,42 +719,46 @@
                 Log.i(TAG,
                         "Appears to be no uris available in EXTRA_STREAM, removing "
                                 + "preview area");
-                return;
+                return contentPreviewLayout;
             } else if (uriCount == 1) {
-                loadFileUriIntoView(uris.get(0));
+                loadFileUriIntoView(uris.get(0), contentPreviewLayout);
             } else {
                 FileInfo fileInfo = extractFileInfo(uris.get(0), getContentResolver());
                 int remUriCount = uriCount - 1;
                 String fileName = getResources().getQuantityString(R.plurals.file_count,
                         remUriCount, fileInfo.name, remUriCount);
 
-                TextView fileNameView = findViewById(R.id.content_preview_filename);
+                TextView fileNameView = contentPreviewLayout.findViewById(
+                        R.id.content_preview_filename);
                 fileNameView.setText(fileName);
 
-                ImageView fileIconView = findViewById(R.id.content_preview_file_icon);
+                ImageView fileIconView = contentPreviewLayout.findViewById(
+                        R.id.content_preview_file_icon);
                 fileIconView.setVisibility(View.VISIBLE);
                 fileIconView.setImageResource(R.drawable.ic_file_copy);
             }
         }
+
+        return contentPreviewLayout;
     }
 
-    private void loadFileUriIntoView(Uri uri) {
+    private void loadFileUriIntoView(Uri uri, View parent) {
         FileInfo fileInfo = extractFileInfo(uri, getContentResolver());
 
-        TextView fileNameView = findViewById(R.id.content_preview_filename);
+        TextView fileNameView = parent.findViewById(R.id.content_preview_filename);
         fileNameView.setText(fileInfo.name);
 
         if (fileInfo.hasThumbnail) {
-            loadUriIntoView(R.id.content_preview_file_thumbnail, uri);
+            loadUriIntoView(R.id.content_preview_file_thumbnail, uri, parent);
         } else {
-            ImageView fileIconView = findViewById(R.id.content_preview_file_icon);
+            ImageView fileIconView = parent.findViewById(R.id.content_preview_file_icon);
             fileIconView.setVisibility(View.VISIBLE);
             fileIconView.setImageResource(R.drawable.ic_doc_generic);
         }
     }
 
-    private RoundedRectImageView loadUriIntoView(int imageResourceId, Uri uri) {
-        RoundedRectImageView imageView = findViewById(imageResourceId);
+    private RoundedRectImageView loadUriIntoView(int imageResourceId, Uri uri, View parent) {
+        RoundedRectImageView imageView = parent.findViewById(imageResourceId);
         Bitmap bmp = loadThumbnail(uri, new Size(200, 200));
         if (bmp != null) {
             imageView.setVisibility(View.VISIBLE);
@@ -822,22 +813,6 @@
         return CONTENT_PREVIEW_TEXT;
     }
 
-    static SharedPreferences getPinnedSharedPrefs(Context context) {
-        // The code below is because in the android:ui process, no one can hear you scream.
-        // The package info in the context isn't initialized in the way it is for normal apps,
-        // so the standard, name-based context.getSharedPreferences doesn't work. Instead, we
-        // build the path manually below using the same policy that appears in ContextImpl.
-        // This fails silently under the hood if there's a problem, so if we find ourselves in
-        // the case where we don't have access to credential encrypted storage we just won't
-        // have our pinned target info.
-        final File prefsFile = new File(new File(
-                Environment.getDataUserCePackageDirectory(StorageManager.UUID_PRIVATE_INTERNAL,
-                        context.getUserId(), context.getPackageName()),
-                "shared_prefs"),
-                PINNED_SHARED_PREFS_NAME + ".xml");
-        return context.getSharedPreferences(prefsFile, MODE_PRIVATE);
-    }
-
     @Override
     protected void onDestroy() {
         super.onDestroy();
@@ -933,17 +908,14 @@
         }
 
         ComponentName name = ri.activityInfo.getComponentName();
-        boolean pinned = mPinnedSharedPrefs.getBoolean(name.flattenToString(), false);
         ResolverTargetActionsDialogFragment f =
                 new ResolverTargetActionsDialogFragment(ri.loadLabel(getPackageManager()),
-                        name, pinned);
+                        name);
         f.show(getFragmentManager(), TARGET_DETAILS_FRAGMENT_TAG);
     }
 
     private void modifyTargetIntent(Intent in) {
-        final String action = in.getAction();
-        if (Intent.ACTION_SEND.equals(action) ||
-                Intent.ACTION_SEND_MULTIPLE.equals(action)) {
+        if (isSendAction(in)) {
             in.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT |
                     Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
         }
@@ -998,15 +970,15 @@
             switch (mChooserListAdapter.getPositionTargetType(which)) {
                 case ChooserListAdapter.TARGET_CALLER:
                     cat = MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_APP_TARGET;
+                    value -= mChooserListAdapter.getSelectableServiceTargetCount();
                     break;
                 case ChooserListAdapter.TARGET_SERVICE:
                     cat = MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET;
-                    value -= mChooserListAdapter.getCallerTargetCount();
                     break;
                 case ChooserListAdapter.TARGET_STANDARD:
                     cat = MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_STANDARD_TARGET;
                     value -= mChooserListAdapter.getCallerTargetCount()
-                            + mChooserListAdapter.getServiceTargetCount();
+                            + mChooserListAdapter.getSelectableServiceTargetCount();
                     break;
             }
 
@@ -1392,11 +1364,6 @@
         }
 
         @Override
-        boolean isComponentPinned(ComponentName name) {
-            return mPinnedSharedPrefs.getBoolean(name.flattenToString(), false);
-        }
-
-        @Override
         boolean isComponentFiltered(ComponentName name) {
             if (mFilteredComponentNames == null) {
                 return false;
@@ -1414,11 +1381,8 @@
             if (target == null) {
                 return CALLER_TARGET_SCORE_BOOST;
             }
-            float score = super.getScore(target);
-            if (target.isPinned()) {
-                score += PINNED_TARGET_SCORE_BOOST;
-            }
-            return score;
+
+            return super.getScore(target);
         }
     }
 
@@ -1515,10 +1479,6 @@
             return null;
         }
 
-        public boolean isPinned() {
-            return false;
-        }
-
         public float getModifiedScore() {
             return 0.1f;
         }
@@ -1749,10 +1709,11 @@
             }
             return results;
         }
+    }
 
-        @Override
-        public boolean isPinned() {
-            return mSourceInfo != null ? mSourceInfo.isPinned() : false;
+    private void handleScroll(View view, int x, int y, int oldx, int oldy) {
+        if (mChooserRowAdapter != null) {
+            mChooserRowAdapter.handleScroll(view, y, oldy);
         }
     }
 
@@ -1762,12 +1723,14 @@
         public static final int TARGET_SERVICE = 1;
         public static final int TARGET_STANDARD = 2;
 
-        private static final int MAX_SERVICE_TARGETS = 4;
+        private static final int MAX_SUGGESTED_APP_TARGETS = 4;
         private static final int MAX_TARGETS_PER_SERVICE = 2;
 
+        private static final int MAX_SERVICE_TARGETS = 8;
+
         // Reserve spots for incoming direct share targets by adding placeholders
         private ChooserTargetInfo mPlaceHolderTargetInfo = new PlaceHolderTargetInfo();
-        private List<ChooserTargetInfo> mServiceTargets;
+        private final List<ChooserTargetInfo> mServiceTargets = new ArrayList<>();
         private final List<TargetInfo> mCallerTargets = new ArrayList<>();
         private boolean mShowServiceTargets;
 
@@ -1786,7 +1749,7 @@
             super(context, payloadIntents, null, rList, launchedFromUid, filterLastUsed,
                     resolverListController);
 
-            mServiceTargets = createPlaceHolders();
+            createPlaceHolders();
 
             if (initialIntents != null) {
                 final PackageManager pm = getPackageManager();
@@ -1840,12 +1803,11 @@
             }
         }
 
-        private List<ChooserTargetInfo> createPlaceHolders() {
-            List<ChooserTargetInfo> list = new ArrayList<>();
+        private void createPlaceHolders() {
+            mServiceTargets.clear();
             for (int i = 0; i < MAX_SERVICE_TARGETS; i++) {
-                list.add(mPlaceHolderTargetInfo);
+                mServiceTargets.add(mPlaceHolderTargetInfo);
             }
-            return list;
         }
 
         @Override
@@ -1855,11 +1817,6 @@
         }
 
         @Override
-        public boolean isComponentPinned(ComponentName name) {
-            return mPinnedSharedPrefs.getBoolean(name.flattenToString(), false);
-        }
-
-        @Override
         public View onCreateView(ViewGroup parent) {
             return mInflater.inflate(
                     com.android.internal.R.layout.resolve_grid_item, parent, false);
@@ -1913,7 +1870,7 @@
         }
 
         public int getCallerTargetCount() {
-            return mCallerTargets.size();
+            return Math.min(mCallerTargets.size(), MAX_SUGGESTED_APP_TARGETS);
         }
 
         /**
@@ -1930,7 +1887,11 @@
         }
 
         public int getServiceTargetCount() {
-            return Math.min(mServiceTargets.size(), MAX_SERVICE_TARGETS);
+            if (isSendAction(getTargetIntent())) {
+                return Math.min(mServiceTargets.size(), MAX_SERVICE_TARGETS);
+            }
+
+            return 0;
         }
 
         public int getStandardTargetCount() {
@@ -1940,18 +1901,18 @@
         public int getPositionTargetType(int position) {
             int offset = 0;
 
-            final int callerTargetCount = getCallerTargetCount();
-            if (position < callerTargetCount) {
-                return TARGET_CALLER;
-            }
-            offset += callerTargetCount;
-
             final int serviceTargetCount = getServiceTargetCount();
-            if (position - offset < serviceTargetCount) {
+            if (position < serviceTargetCount) {
                 return TARGET_SERVICE;
             }
             offset += serviceTargetCount;
 
+            final int callerTargetCount = getCallerTargetCount();
+            if (position - offset < callerTargetCount) {
+                return TARGET_CALLER;
+            }
+            offset += callerTargetCount;
+
             final int standardTargetCount = super.getCount();
             if (position - offset < standardTargetCount) {
                 return TARGET_STANDARD;
@@ -1969,19 +1930,19 @@
         public TargetInfo targetInfoForPosition(int position, boolean filtered) {
             int offset = 0;
 
-            final int callerTargetCount = getCallerTargetCount();
-            if (position < callerTargetCount) {
-                return mCallerTargets.get(position);
-            }
-            offset += callerTargetCount;
-
             final int serviceTargetCount = filtered ? getServiceTargetCount() :
                                                getSelectableServiceTargetCount();
-            if (position - offset < serviceTargetCount) {
-                return mServiceTargets.get(position - offset);
+            if (position < serviceTargetCount) {
+                return mServiceTargets.get(position);
             }
             offset += serviceTargetCount;
 
+            final int callerTargetCount = getCallerTargetCount();
+            if (position - offset < callerTargetCount) {
+                return mCallerTargets.get(position - offset);
+            }
+            offset += callerTargetCount;
+
             return filtered ? super.getItem(position - offset)
                     : getDisplayInfoAt(position - offset);
         }
@@ -1995,7 +1956,7 @@
             if (mTargetsNeedPruning && targets.size() > 0) {
                 // First proper update since we got an onListRebuilt() with (transient) 0 items.
                 // Clear out the target list and rebuild.
-                mServiceTargets = createPlaceHolders();
+                createPlaceHolders();
                 mTargetsNeedPruning = false;
 
                 // Add back any app-supplied direct share targets that may have been
@@ -2037,26 +1998,6 @@
         }
 
         /**
-         * Set to true to reveal all service targets at once.
-         */
-        public void setShowServiceTargets(boolean show) {
-            // mShowServiceTargets is only flipped once to show direct share targets. But after the
-            // initial display the list can be re-sorted and the user will see the target list
-            // change. This will log the initial show and the subsequent shuffle to help us get
-            // accurate timing of the UX.
-            if (show) {
-                getMetricsLogger().write(
-                        new LogMaker(MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN_DIRECT_TARGET)
-                                .setSubtype(mShowServiceTargets ? MetricsEvent.PREVIOUSLY_VISIBLE
-                                        : MetricsEvent.PREVIOUSLY_HIDDEN));
-            }
-            if (show != mShowServiceTargets) {
-                mShowServiceTargets = show;
-                notifyDataSetChanged();
-            }
-        }
-
-        /**
          * Calling this marks service target loading complete, and will attempt to no longer
          * update the direct share area.
          */
@@ -2099,12 +2040,34 @@
         }
     }
 
+    private boolean isSendAction(Intent targetIntent) {
+        if (targetIntent == null) {
+            return false;
+        }
+
+        String action = targetIntent.getAction();
+        if (action == null) {
+            return false;
+        }
+
+        if (Intent.ACTION_SEND.equals(action) || Intent.ACTION_SEND_MULTIPLE.equals(action)) {
+            return true;
+        }
+
+        return false;
+    }
+
     class ChooserRowAdapter extends BaseAdapter {
         private ChooserListAdapter mChooserListAdapter;
         private final LayoutInflater mLayoutInflater;
-        private final int mColumnCount = 4;
         private int mAnimationCount = 0;
 
+        private DirectShareViewHolder mDirectShareViewHolder;
+
+        private static final int VIEW_TYPE_DIRECT_SHARE = 0;
+        private static final int VIEW_TYPE_NORMAL = 1;
+        private static final int VIEW_TYPE_CONTENT_PREVIEW = 2;
+
         public ChooserRowAdapter(ChooserListAdapter wrappedAdapter) {
             mChooserListAdapter = wrappedAdapter;
             mLayoutInflater = LayoutInflater.from(ChooserActivity.this);
@@ -2124,24 +2087,47 @@
             });
         }
 
+        private int getMaxTargetsPerRow() {
+            // this will soon hold logic for portrait/landscape
+            return 4;
+        }
+
         @Override
         public int getCount() {
             return (int) (
-                    getCallerTargetRowCount()
+                    getContentPreviewRowCount()
+                            + getCallerTargetRowCount()
                             + getServiceTargetRowCount()
                             + Math.ceil(
-                            (float) mChooserListAdapter.getStandardTargetCount() / mColumnCount)
+                            (float) mChooserListAdapter.getStandardTargetCount()
+                                    / getMaxTargetsPerRow())
             );
         }
 
+        public int getContentPreviewRowCount() {
+            if (!isSendAction(getTargetIntent())) {
+                return 0;
+            }
+
+            if (mChooserListAdapter == null || mChooserListAdapter.getCount() == 0) {
+                return 0;
+            }
+
+            return 1;
+        }
+
         public int getCallerTargetRowCount() {
             return (int) Math.ceil(
-                    (float) mChooserListAdapter.getCallerTargetCount() / mColumnCount);
+                    (float) mChooserListAdapter.getCallerTargetCount() / getMaxTargetsPerRow());
         }
 
-        // There can be at most one row of service targets.
+        // There can be at most one row in the listview, that is internally
+        // a ViewGroup with 2 rows
         public int getServiceTargetRowCount() {
-            return 1;
+            if (isSendAction(getTargetIntent())) {
+                return 1;
+            }
+            return 0;
         }
 
         @Override
@@ -2158,29 +2144,70 @@
         @Override
         public View getView(int position, View convertView, ViewGroup parent) {
             final RowViewHolder holder;
+            int viewType = getItemViewType(position);
+
+            if (viewType == VIEW_TYPE_CONTENT_PREVIEW) {
+                return createContentPreviewView(convertView, parent);
+            }
+
             if (convertView == null) {
-                holder = createViewHolder(parent);
+                holder = createViewHolder(viewType, parent);
             } else {
                 holder = (RowViewHolder) convertView.getTag();
             }
-            bindViewHolder(position, holder);
 
-            return holder.row;
+            bindViewHolder(position, holder,
+                    viewType == VIEW_TYPE_DIRECT_SHARE
+                            ? ChooserListAdapter.MAX_SERVICE_TARGETS : getMaxTargetsPerRow());
+
+            return holder.getViewGroup();
         }
 
-        RowViewHolder createViewHolder(ViewGroup parent) {
-            final ViewGroup row = (ViewGroup) mLayoutInflater.inflate(R.layout.chooser_row,
-                    parent, false);
-            final RowViewHolder holder = new RowViewHolder(row, mColumnCount);
-            final int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+        @Override
+        public int getItemViewType(int position) {
+            if (position == 0 && getContentPreviewRowCount() == 1) {
+                return VIEW_TYPE_CONTENT_PREVIEW;
+            }
 
-            for (int i = 0; i < mColumnCount; i++) {
-                final View v = mChooserListAdapter.createView(row);
+            final int start = getFirstRowPosition(position);
+            final int startType = mChooserListAdapter.getPositionTargetType(start);
+
+            if (startType == ChooserListAdapter.TARGET_SERVICE) {
+                return VIEW_TYPE_DIRECT_SHARE;
+            }
+
+            return VIEW_TYPE_NORMAL;
+        }
+
+        @Override
+        public int getViewTypeCount() {
+            return 3;
+        }
+
+        private ViewGroup createContentPreviewView(View convertView, ViewGroup parent) {
+            Intent targetIntent = getTargetIntent();
+            int previewType = findPreferredContentPreview(targetIntent, getContentResolver());
+
+            if (convertView == null) {
+                getMetricsLogger().write(new LogMaker(MetricsEvent.ACTION_SHARE_WITH_PREVIEW)
+                        .setSubtype(previewType));
+            }
+
+            return displayContentPreview(previewType, targetIntent, mLayoutInflater,
+                    (ViewGroup) convertView, parent);
+        }
+
+        private RowViewHolder loadViewsIntoRow(RowViewHolder holder) {
+            final int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+            int columnCount = holder.getColumnCount();
+
+            for (int i = 0; i < columnCount; i++) {
+                final View v = mChooserListAdapter.createView(holder.getRow(i));
                 final int column = i;
                 v.setOnClickListener(new OnClickListener() {
                     @Override
                     public void onClick(View v) {
-                        startSelected(holder.itemIndices[column], false, true);
+                        startSelected(holder.getItemIndex(column), false, true);
                     }
                 });
                 v.setOnLongClickListener(new OnLongClickListener() {
@@ -2188,12 +2215,11 @@
                     public boolean onLongClick(View v) {
                         showTargetDetails(
                                 mChooserListAdapter.resolveInfoForPosition(
-                                        holder.itemIndices[column], true));
+                                        holder.getItemIndex(column), true));
                         return true;
                     }
                 });
-                row.addView(v);
-                holder.cells[i] = v;
+                ViewGroup row = holder.addView(i, v);
 
                 // Force height to be a given so we don't have visual disruption during scaling.
                 LayoutParams lp = v.getLayoutParams();
@@ -2204,47 +2230,75 @@
                 } else {
                     lp.height = v.getMeasuredHeight();
                 }
-                if (i != (mColumnCount - 1)) {
-                    row.addView(new Space(ChooserActivity.this),
-                            new LinearLayout.LayoutParams(0, 0, 1));
-                }
             }
 
+            final ViewGroup viewGroup = holder.getViewGroup();
+
             // Pre-measure so we can scale later.
             holder.measure();
-            LayoutParams lp = row.getLayoutParams();
+            LayoutParams lp = viewGroup.getLayoutParams();
             if (lp == null) {
-                lp = new LayoutParams(LayoutParams.MATCH_PARENT, holder.measuredRowHeight);
-                row.setLayoutParams(lp);
+                lp = new LayoutParams(LayoutParams.MATCH_PARENT, holder.getMeasuredRowHeight());
+                viewGroup.setLayoutParams(lp);
             } else {
-                lp.height = holder.measuredRowHeight;
+                lp.height = holder.getMeasuredRowHeight();
             }
-            row.setTag(holder);
+
+            viewGroup.setTag(holder);
+
             return holder;
         }
 
-        void bindViewHolder(int rowPosition, RowViewHolder holder) {
+        RowViewHolder createViewHolder(int viewType, ViewGroup parent) {
+            if (viewType == VIEW_TYPE_DIRECT_SHARE) {
+                ViewGroup parentGroup = (ViewGroup) mLayoutInflater.inflate(
+                        R.layout.chooser_row_direct_share, parent, false);
+                ViewGroup row1 = (ViewGroup) mLayoutInflater.inflate(R.layout.chooser_row,
+                        parentGroup, false);
+                ViewGroup row2 = (ViewGroup) mLayoutInflater.inflate(R.layout.chooser_row,
+                        parentGroup, false);
+                parentGroup.addView(row1);
+                parentGroup.addView(row2);
+
+                mDirectShareViewHolder = new DirectShareViewHolder(parentGroup,
+                        Lists.newArrayList(row1, row2), getMaxTargetsPerRow());
+                loadViewsIntoRow(mDirectShareViewHolder);
+
+                return mDirectShareViewHolder;
+            } else {
+                ViewGroup row = (ViewGroup) mLayoutInflater.inflate(R.layout.chooser_row, parent,
+                        false);
+                RowViewHolder holder = new SingleRowViewHolder(row, getMaxTargetsPerRow());
+                loadViewsIntoRow(holder);
+
+                return holder;
+            }
+        }
+
+        void bindViewHolder(int rowPosition, RowViewHolder holder, int columnCount) {
             final int start = getFirstRowPosition(rowPosition);
             final int startType = mChooserListAdapter.getPositionTargetType(start);
 
             final int lastStartType = mChooserListAdapter.getPositionTargetType(
                     getFirstRowPosition(rowPosition - 1));
 
-            if (startType != lastStartType || rowPosition == 0) {
-                holder.row.setBackground(mChooserRowLayer);
-                setVertPadding(holder, mChooserRowServiceSpacing, 0);
+            final ViewGroup row = holder.getViewGroup();
+
+            if (startType != lastStartType || rowPosition == getContentPreviewRowCount()) {
+                row.setBackground(mChooserRowLayer);
+                setVertPadding(row, mChooserRowServiceSpacing, 0);
             } else {
-                holder.row.setBackground(null);
-                setVertPadding(holder, 0, 0);
+                row.setBackground(null);
+                setVertPadding(row, 0, 0);
             }
 
-            int end = start + mColumnCount - 1;
+            int end = start + columnCount - 1;
             while (mChooserListAdapter.getPositionTargetType(end) != startType && end >= start) {
                 end--;
             }
 
             if (end == start && mChooserListAdapter.getItem(start) instanceof EmptyTargetInfo) {
-                final TextView textView = holder.row.findViewById(R.id.chooser_row_text_option);
+                final TextView textView = row.findViewById(R.id.chooser_row_text_option);
 
                 if (textView.getVisibility() != View.VISIBLE) {
                     textView.setAlpha(0.0f);
@@ -2269,12 +2323,12 @@
                 }
             }
 
-            for (int i = 0; i < mColumnCount; i++) {
-                final View v = holder.cells[i];
+            for (int i = 0; i < columnCount; i++) {
+                final View v = holder.getView(i);
                 if (start + i <= end) {
                     setCellVisibility(holder, i, View.VISIBLE);
-                    holder.itemIndices[i] = start + i;
-                    mChooserListAdapter.bindView(holder.itemIndices[i], v);
+                    holder.setItemIndex(i, start + i);
+                    mChooserListAdapter.bindView(holder.getItemIndex(i), v);
                 } else {
                     setCellVisibility(holder, i, View.INVISIBLE);
                 }
@@ -2282,13 +2336,13 @@
         }
 
         private void setCellVisibility(RowViewHolder holder, int i, int visibility) {
-            final View v = holder.cells[i];
+            final View v = holder.getView(i);
             if (visibility == View.VISIBLE) {
-                holder.cellVisibility[i] = true;
+                holder.setViewVisibility(i, true);
                 v.setVisibility(visibility);
                 v.setAlpha(1.0f);
-            } else if (visibility == View.INVISIBLE && holder.cellVisibility[i]) {
-                holder.cellVisibility[i] = false;
+            } else if (visibility == View.INVISIBLE && holder.getViewVisibility(i)) {
+                holder.setViewVisibility(i, false);
 
                 ValueAnimator fadeAnim = ObjectAnimator.ofFloat(v, "alpha", 1.0f, 0f);
                 fadeAnim.setDuration(NO_DIRECT_SHARE_ANIM_IN_MILLIS);
@@ -2302,49 +2356,222 @@
             }
         }
 
-        private void setVertPadding(RowViewHolder holder, int top, int bottom) {
-            holder.row.setPadding(holder.row.getPaddingLeft(), top,
-                    holder.row.getPaddingRight(), bottom);
+        private void setVertPadding(ViewGroup row, int top, int bottom) {
+            row.setPadding(row.getPaddingLeft(), top, row.getPaddingRight(), bottom);
         }
 
         int getFirstRowPosition(int row) {
-            final int callerCount = mChooserListAdapter.getCallerTargetCount();
-            final int callerRows = (int) Math.ceil((float) callerCount / mColumnCount);
-
-            if (row < callerRows) {
-                return row * mColumnCount;
-            }
+            row -= getContentPreviewRowCount();
 
             final int serviceCount = mChooserListAdapter.getServiceTargetCount();
-            final int serviceRows = (int) Math.ceil((float) serviceCount / mColumnCount);
+            final int serviceRows = (int) Math.ceil((float) serviceCount
+                    / ChooserListAdapter.MAX_SERVICE_TARGETS);
+            if (row < serviceRows) {
+                return row * getMaxTargetsPerRow();
+            }
 
+            final int callerCount = mChooserListAdapter.getCallerTargetCount();
+            final int callerRows = (int) Math.ceil((float) callerCount / getMaxTargetsPerRow());
             if (row < callerRows + serviceRows) {
-                return callerCount + (row - callerRows) * mColumnCount;
+                return serviceCount + (row - serviceRows) * getMaxTargetsPerRow();
             }
 
             return callerCount + serviceCount
-                    + (row - callerRows - serviceRows) * mColumnCount;
+                    + (row - callerRows - serviceRows) * getMaxTargetsPerRow();
+        }
+
+        public void handleScroll(View v, int y, int oldy) {
+            if (mDirectShareViewHolder != null) {
+                mDirectShareViewHolder.handleScroll(mAdapterView, y, oldy, getMaxTargetsPerRow());
+            }
         }
     }
 
-    static class RowViewHolder {
-        public final View[] cells;
-        public final boolean [] cellVisibility;
-        public final ViewGroup row;
-        int measuredRowHeight;
-        int[] itemIndices;
+    abstract class RowViewHolder {
+        protected int mMeasuredRowHeight;
+        private int[] mItemIndices;
+        protected final View[] mCells;
+        private final boolean[] mCellVisibility;
+        private final int mColumnCount;
 
-        public RowViewHolder(ViewGroup row, int cellCount) {
-            this.row = row;
-            this.cells = new View[cellCount];
-            this.cellVisibility = new boolean[cellCount];
-            this.itemIndices = new int[cellCount];
+        RowViewHolder(int cellCount) {
+            this.mCells = new View[cellCount];
+            this.mItemIndices = new int[cellCount];
+            this.mCellVisibility = new boolean[cellCount];
+            this.mColumnCount = cellCount;
+        }
+
+        abstract ViewGroup addView(int index, View v);
+
+        abstract ViewGroup getViewGroup();
+
+        abstract ViewGroup getRow(int index);
+
+        public int getColumnCount() {
+            return mColumnCount;
+        }
+
+        public void setViewVisibility(int index, boolean visibility) {
+            mCellVisibility[index] = visibility;
+        }
+
+        public boolean getViewVisibility(int index) {
+            return mCellVisibility[index];
         }
 
         public void measure() {
             final int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
-            row.measure(spec, spec);
-            measuredRowHeight = row.getMeasuredHeight();
+            getViewGroup().measure(spec, spec);
+            mMeasuredRowHeight = getViewGroup().getMeasuredHeight();
+        }
+
+        public int getMeasuredRowHeight() {
+            return mMeasuredRowHeight;
+        }
+
+        protected void addSpacer(ViewGroup row) {
+            row.addView(new Space(ChooserActivity.this),
+                    new LinearLayout.LayoutParams(0, 0, 1));
+        }
+
+        public void setItemIndex(int itemIndex, int listIndex) {
+            mItemIndices[itemIndex] = listIndex;
+        }
+
+        public int getItemIndex(int itemIndex) {
+            return mItemIndices[itemIndex];
+        }
+
+        public View getView(int index) {
+            return mCells[index];
+        }
+    }
+
+    class SingleRowViewHolder extends RowViewHolder {
+        private final ViewGroup mRow;
+
+        SingleRowViewHolder(ViewGroup row, int cellCount) {
+            super(cellCount);
+
+            this.mRow = row;
+        }
+
+        public ViewGroup getViewGroup() {
+            return mRow;
+        }
+
+        public ViewGroup getRow(int index) {
+            return mRow;
+        }
+
+        public ViewGroup addView(int index, View v) {
+            mRow.addView(v);
+            mCells[index] = v;
+
+            if (index != (mCells.length - 1)) {
+                addSpacer(mRow);
+            }
+
+            return mRow;
+        }
+    }
+
+    class DirectShareViewHolder extends RowViewHolder {
+        private final ViewGroup mParent;
+        private final List<ViewGroup> mRows;
+        private int mCellCountPerRow;
+
+        private boolean mHideDirectShareExpansion = false;
+        private int mDirectShareMinHeight = 0;
+        private int mDirectShareCurrHeight = 0;
+        private int mDirectShareMaxHeight = 0;
+
+        DirectShareViewHolder(ViewGroup parent, List<ViewGroup> rows, int cellCountPerRow) {
+            super(rows.size() * cellCountPerRow);
+
+            this.mParent = parent;
+            this.mRows = rows;
+            this.mCellCountPerRow = cellCountPerRow;
+        }
+
+        public ViewGroup addView(int index, View v) {
+            ViewGroup row = getRow(index);
+            row.addView(v);
+            mCells[index] = v;
+
+            if (index % mCellCountPerRow != (mCellCountPerRow - 1)) {
+                addSpacer(row);
+            }
+
+            return row;
+        }
+
+        public ViewGroup getViewGroup() {
+            return mParent;
+        }
+
+        public ViewGroup getRow(int index) {
+            return mRows.get(index / mCellCountPerRow);
+        }
+
+        public void measure() {
+            final int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+            getRow(0).measure(spec, spec);
+            getRow(1).measure(spec, spec);
+
+            // uses ChooserActiivty state variables to track height
+            mDirectShareMinHeight = getRow(0).getMeasuredHeight();
+            mDirectShareCurrHeight = mDirectShareCurrHeight > 0
+                                         ? mDirectShareCurrHeight : mDirectShareMinHeight;
+            mDirectShareMaxHeight = 2 * mDirectShareMinHeight;
+        }
+
+        public int getMeasuredRowHeight() {
+            return mDirectShareCurrHeight;
+        }
+
+        public void handleScroll(AbsListView view, int y, int oldy, int maxTargetsPerRow) {
+            // only expand if we have more than 4 targets, and delay that decision until
+            // they start to scroll
+            if (mHideDirectShareExpansion) {
+                return;
+            }
+
+            if (mChooserListAdapter.getSelectableServiceTargetCount() <= maxTargetsPerRow) {
+                mHideDirectShareExpansion = true;
+                return;
+            }
+
+            int yDiff = (int) ((oldy - y) * 0.7f);
+
+            int prevHeight = mDirectShareCurrHeight;
+            mDirectShareCurrHeight = Math.min(mDirectShareCurrHeight + yDiff,
+                    mDirectShareMaxHeight);
+            mDirectShareCurrHeight = Math.max(mDirectShareCurrHeight, mDirectShareMinHeight);
+            yDiff = mDirectShareCurrHeight - prevHeight;
+
+            if (view == null || view.getChildCount() == 0) {
+                return;
+            }
+
+            int index = mChooserRowAdapter.getContentPreviewRowCount();
+
+            ViewGroup expansionGroup = (ViewGroup) view.getChildAt(index);
+            int widthSpec = MeasureSpec.makeMeasureSpec(expansionGroup.getWidth(),
+                    MeasureSpec.EXACTLY);
+            int heightSpec = MeasureSpec.makeMeasureSpec(mDirectShareCurrHeight,
+                    MeasureSpec.EXACTLY);
+            expansionGroup.measure(widthSpec, heightSpec);
+            expansionGroup.getLayoutParams().height = expansionGroup.getMeasuredHeight();
+            expansionGroup.layout(expansionGroup.getLeft(), expansionGroup.getTop(),
+                    expansionGroup.getRight(),
+                    expansionGroup.getTop() + expansionGroup.getMeasuredHeight());
+
+            // reposition list items
+            int items = view.getChildCount();
+            for (int i = index + 1; i < items; i++) {
+                view.getChildAt(i).offsetTopAndBottom(yDiff);
+            }
         }
     }
 
@@ -2519,13 +2746,13 @@
             final int chooserTargetRows = mChooserRowAdapter.getServiceTargetRowCount();
             int offset = 0;
             for (int i = 0; i < chooserTargetRows; i++) {
-                final int pos = mChooserRowAdapter.getCallerTargetRowCount() + i;
+                final int pos = mChooserRowAdapter.getContentPreviewRowCount() + i;
                 final int vt = mChooserRowAdapter.getItemViewType(pos);
                 if (vt != mCachedViewType) {
                     mCachedView = null;
                 }
                 final View v = mChooserRowAdapter.getView(pos, mCachedView, mListView);
-                int height = ((RowViewHolder) (v.getTag())).measuredRowHeight;
+                int height = ((RowViewHolder) (v.getTag())).getMeasuredRowHeight();
 
                 offset += (int) (height);
 
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 011cc04..12942ab 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -42,6 +42,8 @@
 import android.content.pm.UserInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.AsyncTask;
@@ -49,6 +51,7 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.PatternMatcher;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.StrictMode;
 import android.os.UserHandle;
@@ -56,7 +59,6 @@
 import android.provider.MediaStore;
 import android.provider.Settings;
 import android.text.TextUtils;
-import android.util.IconDrawableFactory;
 import android.util.Log;
 import android.util.Slog;
 import android.view.LayoutInflater;
@@ -99,7 +101,7 @@
 
     protected ResolveListAdapter mAdapter;
     private boolean mSafeForwardingMode;
-    private AbsListView mAdapterView;
+    protected AbsListView mAdapterView;
     private Button mAlwaysButton;
     private Button mOnceButton;
     private Button mSettingsButton;
@@ -131,7 +133,7 @@
     /** See {@link #setRetainInOnStop}. */
     private boolean mRetainInOnStop;
 
-    IconDrawableFactory mIconFactory;
+    SimpleIconFactory mSimpleIconFactory;
 
     private final PackageMonitor mPackageMonitor = new PackageMonitor() {
         @Override public void onSomePackagesChanged() {
@@ -309,7 +311,11 @@
         // as to mitigate Intent Capturing vulnerability
         mSupportsAlwaysUseOption = supportsAlwaysUseOption && !mUseLayoutForBrowsables;
 
-        mIconFactory = IconDrawableFactory.newInstance(this, true);
+        final int iconSize = getResources().getDimensionPixelSize(R.dimen.resolver_icon_size);
+        final int badgeSize = getResources().getDimensionPixelSize(R.dimen.resolver_badge_size);
+        mSimpleIconFactory = new SimpleIconFactory(this, mIconDpi, iconSize, badgeSize);
+        mSimpleIconFactory.setWrapperBackgroundColor(Color.WHITE);
+
         if (configureContentView(mIntents, initialIntents, rList)) {
             return;
         }
@@ -494,6 +500,7 @@
         }
     }
 
+    @Nullable
     Drawable getIcon(Resources res, int resId) {
         Drawable result;
         try {
@@ -505,26 +512,52 @@
         return result;
     }
 
+    /**
+     * Loads the icon for the provided ResolveInfo. Defaults to using the application icon over
+     * any IntentFilter or Activity icon to increase user understanding, with an exception for
+     * applications that hold the right permission. Always attempts to use icon resources over
+     * PackageManager loading mechanisms so badging can be done by iconloader.
+     */
     Drawable loadIconForResolveInfo(ResolveInfo ri) {
-        Drawable dr;
-        try {
-            if (ri.resolvePackageName != null && ri.icon != 0) {
-                dr = getIcon(mPm.getResourcesForApplication(ri.resolvePackageName), ri.icon);
-                if (dr != null) {
-                    return mIconFactory.getShadowedIcon(dr);
+        Drawable dr = null;
+
+        // Allow for app icon override given the right permission
+        if (PackageManager.PERMISSION_GRANTED == mPm.checkPermission(
+                android.Manifest.permission.SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON,
+                ri.activityInfo.applicationInfo.packageName)) {
+            try {
+                if (ri.resolvePackageName != null && ri.icon != 0) {
+                    dr = getIcon(mPm.getResourcesForApplication(ri.resolvePackageName), ri.icon);
                 }
-            }
-            final int iconRes = ri.getIconResource();
-            if (iconRes != 0) {
-                dr = getIcon(mPm.getResourcesForApplication(ri.activityInfo.packageName), iconRes);
-                if (dr != null) {
-                    return mIconFactory.getShadowedIcon(dr);
+                if (dr == null) {
+                    final int iconRes = ri.getIconResource();
+                    if (iconRes != 0) {
+                        dr = getIcon(mPm.getResourcesForApplication(ri.activityInfo.packageName),
+                                iconRes);
+                    }
                 }
+            } catch (NameNotFoundException e) {
+                Log.e(TAG, "SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON permission granted but "
+                        + "couldn't find resources for package", e);
             }
-        } catch (NameNotFoundException e) {
-            Log.e(TAG, "Couldn't find resources for package", e);
         }
-        return mIconFactory.getBadgedIcon(ri.activityInfo.applicationInfo);
+
+        // Use app icons for better user association
+        if (dr == null) {
+            try {
+                dr = getIcon(mPm.getResourcesForApplication(ri.activityInfo.applicationInfo),
+                        ri.activityInfo.applicationInfo.icon);
+            } catch (NameNotFoundException ignore) {
+            }
+        }
+
+        // Fall back to ApplicationInfo#loadIcon if nothing has been loaded
+        if (dr == null) {
+            dr = ri.activityInfo.applicationInfo.loadIcon(mPm);
+        }
+
+        return new BitmapDrawable(this.getResources(),
+                mSimpleIconFactory.createUserBadgedIconBitmap(dr, Process.myUserHandle()));
     }
 
     @Override
@@ -1177,7 +1210,6 @@
         private final CharSequence mExtendedInfo;
         private final Intent mResolvedIntent;
         private final List<Intent> mSourceIntents = new ArrayList<>();
-        private boolean mPinned;
 
         public DisplayResolveInfo(Intent originalIntent, ResolveInfo pri, CharSequence pLabel,
                 CharSequence pInfo, Intent pOrigIntent) {
@@ -1204,7 +1236,6 @@
             mExtendedInfo = other.mExtendedInfo;
             mResolvedIntent = new Intent(other.mResolvedIntent);
             mResolvedIntent.fillIn(fillInIntent, flags);
-            mPinned = other.mPinned;
         }
 
         public ResolveInfo getResolveInfo() {
@@ -1304,15 +1335,6 @@
             activity.startActivityAsUser(mResolvedIntent, options, user);
             return false;
         }
-
-        @Override
-        public boolean isPinned() {
-            return mPinned;
-        }
-
-        public void setPinned(boolean pinned) {
-            mPinned = pinned;
-        }
     }
 
     /**
@@ -1414,11 +1436,6 @@
          * @return the list of supported source intents deduped against this single target
          */
         List<Intent> getAllSourceIntents();
-
-        /**
-         * @return true if this target should be pinned to the front by the request of the user
-         */
-        boolean isPinned();
     }
 
     public class ResolveListAdapter extends BaseAdapter {
@@ -1776,7 +1793,6 @@
             final Intent replaceIntent = getReplacementIntent(add.activityInfo, intent);
             final DisplayResolveInfo dri = new DisplayResolveInfo(intent, add, roLabel,
                     extraInfo, replaceIntent);
-            dri.setPinned(rci.isPinned());
             addResolveInfo(dri);
             if (replaceIntent == intent) {
                 // Only add alternates if we didn't get a specific replacement from
@@ -1921,10 +1937,6 @@
             return !TextUtils.isEmpty(info.getExtendedInfo());
         }
 
-        public boolean isComponentPinned(ComponentName name) {
-            return false;
-        }
-
         public final void bindView(int position, View view) {
             onBindView(view, getItem(position));
         }
@@ -1967,7 +1979,6 @@
     @VisibleForTesting
     public static final class ResolvedComponentInfo {
         public final ComponentName name;
-        private boolean mPinned;
         private final List<Intent> mIntents = new ArrayList<>();
         private final List<ResolveInfo> mResolveInfos = new ArrayList<>();
 
@@ -2010,14 +2021,6 @@
             }
             return -1;
         }
-
-        public boolean isPinned() {
-            return mPinned;
-        }
-
-        public void setPinned(boolean pinned) {
-            mPinned = pinned;
-        }
     }
 
     static class ViewHolder {
diff --git a/core/java/com/android/internal/app/ResolverComparator.java b/core/java/com/android/internal/app/ResolverComparator.java
index f61a03b..b9f67e6 100644
--- a/core/java/com/android/internal/app/ResolverComparator.java
+++ b/core/java/com/android/internal/app/ResolverComparator.java
@@ -325,30 +325,18 @@
             }
         }
 
-        final boolean lPinned = lhsp.isPinned();
-        final boolean rPinned = rhsp.isPinned();
+        if (mStats != null) {
+            final ResolverTarget lhsTarget = mTargetsDict.get(new ComponentName(
+                    lhs.activityInfo.packageName, lhs.activityInfo.name));
+            final ResolverTarget rhsTarget = mTargetsDict.get(new ComponentName(
+                    rhs.activityInfo.packageName, rhs.activityInfo.name));
 
-        if (lPinned && !rPinned) {
-            return -1;
-        } else if (!lPinned && rPinned) {
-            return 1;
-        }
-
-        // Pinned items stay stable within a normal lexical sort and ignore scoring.
-        if (!lPinned && !rPinned) {
-            if (mStats != null) {
-                final ResolverTarget lhsTarget = mTargetsDict.get(new ComponentName(
-                        lhs.activityInfo.packageName, lhs.activityInfo.name));
-                final ResolverTarget rhsTarget = mTargetsDict.get(new ComponentName(
-                        rhs.activityInfo.packageName, rhs.activityInfo.name));
-
-                if (lhsTarget != null && rhsTarget != null) {
-                    final int selectProbabilityDiff = Float.compare(
+            if (lhsTarget != null && rhsTarget != null) {
+                final int selectProbabilityDiff = Float.compare(
                         rhsTarget.getSelectProbability(), lhsTarget.getSelectProbability());
 
-                    if (selectProbabilityDiff != 0) {
-                        return selectProbabilityDiff > 0 ? 1 : -1;
-                    }
+                if (selectProbabilityDiff != 0) {
+                    return selectProbabilityDiff > 0 ? 1 : -1;
                 }
             }
         }
diff --git a/core/java/com/android/internal/app/ResolverListController.java b/core/java/com/android/internal/app/ResolverListController.java
index 61aeca6..f48102a 100644
--- a/core/java/com/android/internal/app/ResolverListController.java
+++ b/core/java/com/android/internal/app/ResolverListController.java
@@ -30,14 +30,13 @@
 import android.content.pm.ResolveInfo;
 import android.os.RemoteException;
 import android.util.Log;
-import com.android.internal.annotations.GuardedBy;
+
 import com.android.internal.annotations.VisibleForTesting;
 
-import java.lang.InterruptedException;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.concurrent.CountDownLatch;
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
 
 /**
  * A helper for the ResolverActivity that exposes methods to retrieve, filter and sort its list of
@@ -147,7 +146,6 @@
                         newInfo.activityInfo.packageName, newInfo.activityInfo.name);
                 final ResolverActivity.ResolvedComponentInfo rci =
                         new ResolverActivity.ResolvedComponentInfo(name, intent, newInfo);
-                rci.setPinned(isComponentPinned(name));
                 into.add(rci);
             }
         }
@@ -270,10 +268,6 @@
                 && ai.name.equals(b.name.getClassName());
     }
 
-    boolean isComponentPinned(ComponentName name) {
-        return false;
-    }
-
     boolean isComponentFiltered(ComponentName componentName) {
         return false;
     }
diff --git a/core/java/com/android/internal/app/ResolverTargetActionsDialogFragment.java b/core/java/com/android/internal/app/ResolverTargetActionsDialogFragment.java
index 8156f79..a49240c 100644
--- a/core/java/com/android/internal/app/ResolverTargetActionsDialogFragment.java
+++ b/core/java/com/android/internal/app/ResolverTargetActionsDialogFragment.java
@@ -23,7 +23,6 @@
 import android.content.ComponentName;
 import android.content.DialogInterface;
 import android.content.Intent;
-import android.content.SharedPreferences;
 import android.net.Uri;
 import android.os.Bundle;
 import android.provider.Settings;
@@ -36,34 +35,27 @@
 public class ResolverTargetActionsDialogFragment extends DialogFragment
         implements DialogInterface.OnClickListener {
     private static final String NAME_KEY = "componentName";
-    private static final String PINNED_KEY = "pinned";
     private static final String TITLE_KEY = "title";
 
     // Sync with R.array.resolver_target_actions_* resources
-    private static final int TOGGLE_PIN_INDEX = 0;
-    private static final int APP_INFO_INDEX = 1;
+    private static final int APP_INFO_INDEX = 0;
 
     public ResolverTargetActionsDialogFragment() {
     }
 
-    public ResolverTargetActionsDialogFragment(CharSequence title, ComponentName name,
-            boolean pinned) {
+    public ResolverTargetActionsDialogFragment(CharSequence title, ComponentName name) {
         Bundle args = new Bundle();
         args.putCharSequence(TITLE_KEY, title);
         args.putParcelable(NAME_KEY, name);
-        args.putBoolean(PINNED_KEY, pinned);
         setArguments(args);
     }
 
     @Override
     public Dialog onCreateDialog(Bundle savedInstanceState) {
         final Bundle args = getArguments();
-        final int itemRes = args.getBoolean(PINNED_KEY, false)
-                ? R.array.resolver_target_actions_unpin
-                : R.array.resolver_target_actions_pin;
         return new Builder(getContext())
                 .setCancelable(true)
-                .setItems(itemRes, this)
+                .setItems(R.array.resolver_target_actions, this)
                 .setTitle(args.getCharSequence(TITLE_KEY))
                 .create();
     }
@@ -73,19 +65,6 @@
         final Bundle args = getArguments();
         ComponentName name = args.getParcelable(NAME_KEY);
         switch (which) {
-            case TOGGLE_PIN_INDEX:
-                SharedPreferences sp = ChooserActivity.getPinnedSharedPrefs(getContext());
-                final String key = name.flattenToString();
-                boolean currentVal = sp.getBoolean(name.flattenToString(), false);
-                if (currentVal) {
-                    sp.edit().remove(key).apply();
-                } else {
-                    sp.edit().putBoolean(key, true).apply();
-                }
-
-                // Force the chooser to requery and resort things
-                getActivity().recreate();
-                break;
             case APP_INFO_INDEX:
                 Intent in = new Intent().setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
                         .setData(Uri.fromParts("package", name.getPackageName(), null))
diff --git a/core/java/com/android/internal/app/SimpleIconFactory.java b/core/java/com/android/internal/app/SimpleIconFactory.java
new file mode 100644
index 0000000..eb1530e
--- /dev/null
+++ b/core/java/com/android/internal/app/SimpleIconFactory.java
@@ -0,0 +1,609 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.app;
+
+import static android.graphics.Paint.DITHER_FLAG;
+import static android.graphics.Paint.FILTER_BITMAP_FLAG;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.graphics.Bitmap;
+import android.graphics.BlurMaskFilter;
+import android.graphics.BlurMaskFilter.Blur;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PaintFlagsDrawFilter;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.drawable.AdaptiveIconDrawable;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.DrawableWrapper;
+import android.os.Process;
+import android.os.UserHandle;
+import android.util.AttributeSet;
+
+import com.android.internal.R;
+
+import org.xmlpull.v1.XmlPullParser;
+
+import java.nio.ByteBuffer;
+
+
+/**
+ * @deprecated Use the Launcher3 Iconloaderlib at packages/apps/Launcher3/iconloaderlib. This class
+ * is a temporary fork of Iconloader. It combines all necessary methods to render app icons that are
+ * possibly badged. It is intended to be used only by Sharesheet for the Q release.
+ */
+@Deprecated
+public class SimpleIconFactory {
+
+    private static final int DEFAULT_WRAPPER_BACKGROUND = Color.WHITE;
+    private static final float BLUR_FACTOR = 0.5f / 48;
+
+    private Context mContext;
+    private Canvas mCanvas;
+    private PackageManager mPm;
+
+    private int mFillResIconDpi;
+    private int mIconBitmapSize;
+    private int mBadgeBitmapSize;
+    private int mWrapperBackgroundColor;
+
+    private Drawable mWrapperIcon;
+    private final Rect mOldBounds = new Rect();
+
+    /**
+     * @deprecated Do not use, functionality will be replaced by iconloader lib eventually.
+     */
+    @Deprecated
+    SimpleIconFactory(Context context, int fillResIconDpi, int iconBitmapSize,
+            int badgeBitmapSize) {
+        mContext = context.getApplicationContext();
+        mPm = mContext.getPackageManager();
+        mIconBitmapSize = iconBitmapSize;
+        mBadgeBitmapSize = badgeBitmapSize;
+        mFillResIconDpi = fillResIconDpi;
+
+        mCanvas = new Canvas();
+        mCanvas.setDrawFilter(new PaintFlagsDrawFilter(DITHER_FLAG, FILTER_BITMAP_FLAG));
+
+        // Normalizer init
+        // Use twice the icon size as maximum size to avoid scaling down twice.
+        mMaxSize = iconBitmapSize * 2;
+        mBitmap = Bitmap.createBitmap(mMaxSize, mMaxSize, Bitmap.Config.ALPHA_8);
+        mScaleCheckCanvas = new Canvas(mBitmap);
+        mPixels = new byte[mMaxSize * mMaxSize];
+        mLeftBorder = new float[mMaxSize];
+        mRightBorder = new float[mMaxSize];
+        mBounds = new Rect();
+        mAdaptiveIconBounds = new Rect();
+        mAdaptiveIconScale = SCALE_NOT_INITIALIZED;
+
+        // Shadow generator init
+        mDefaultBlurMaskFilter = new BlurMaskFilter(iconBitmapSize * BLUR_FACTOR,
+                Blur.NORMAL);
+    }
+
+    /**
+     * Sets the background color used for wrapped adaptive icon
+     *
+     * @deprecated Do not use, functionality will be replaced by iconloader lib eventually.
+     */
+    @Deprecated
+    void setWrapperBackgroundColor(int color) {
+        mWrapperBackgroundColor = (Color.alpha(color) < 255) ? DEFAULT_WRAPPER_BACKGROUND : color;
+    }
+
+    /**
+     * Creates bitmap using the source drawable and various parameters.
+     * The bitmap is visually normalized with other icons and has enough spacing to add shadow.
+     *
+     * @param icon                      source of the icon associated with a user that has no badge,
+     *                                  likely user 0
+     * @param user                      info can be used for a badge
+     * @return a bitmap suitable for disaplaying as an icon at various system UIs.
+     *
+     * @deprecated Do not use, functionality will be replaced by iconloader lib eventually.
+     */
+    @Deprecated
+    Bitmap createUserBadgedIconBitmap(@Nullable Drawable icon, UserHandle user) {
+        float [] scale = new float[1];
+
+        // If no icon is provided use the system default
+        if (icon == null) {
+            icon = getFullResDefaultActivityIcon(mFillResIconDpi);
+        }
+        icon = normalizeAndWrapToAdaptiveIcon(icon, null, scale);
+        Bitmap bitmap = createIconBitmap(icon, scale[0]);
+        if (icon instanceof AdaptiveIconDrawable) {
+            mCanvas.setBitmap(bitmap);
+            recreateIcon(Bitmap.createBitmap(bitmap), mCanvas);
+            mCanvas.setBitmap(null);
+        }
+
+        final Bitmap result;
+        if (user != null && !Process.myUserHandle().equals(user)) {
+            BitmapDrawable drawable = new FixedSizeBitmapDrawable(bitmap);
+            Drawable badged = mPm.getUserBadgedIcon(drawable, user);
+            if (badged instanceof BitmapDrawable) {
+                result = ((BitmapDrawable) badged).getBitmap();
+            } else {
+                result = createIconBitmap(badged, 1f);
+            }
+        } else {
+            result = bitmap;
+        }
+
+        return result;
+    }
+
+    /**
+     * Creates bitmap using the source drawable and flattened pre-rendered app icon.
+     * The bitmap is visually normalized with other icons and has enough spacing to add shadow.
+     *
+     * @param icon                      source of the icon associated with a user that has no badge
+     * @param renderedAppIcon           pre-rendered app icon to use as a badge, likely the output
+     *                                  of createUserBadgedIconBitmap for user 0
+     * @return a bitmap suitable for disaplaying as an icon at various system UIs.
+     *
+     * @deprecated Do not use, functionality will be replaced by iconloader lib eventually.
+     */
+    @Deprecated
+    public Bitmap createAppBadgedIconBitmap(@Nullable Drawable icon, Bitmap renderedAppIcon) {
+        // Flatten the passed in icon
+        float [] scale = new float[1];
+
+        // If no icon is provided use the system default
+        if (icon == null) {
+            icon = getFullResDefaultActivityIcon(mFillResIconDpi);
+        }
+        icon = normalizeAndWrapToAdaptiveIcon(icon, null, scale);
+        Bitmap bitmap = createIconBitmap(icon, scale[0]);
+        if (icon instanceof AdaptiveIconDrawable) {
+            mCanvas.setBitmap(bitmap);
+            recreateIcon(Bitmap.createBitmap(bitmap), mCanvas);
+            mCanvas.setBitmap(null);
+        }
+
+        // Now scale down and apply the badge to the bottom right corner of the flattened icon
+        renderedAppIcon = Bitmap.createScaledBitmap(renderedAppIcon, mBadgeBitmapSize,
+                mBadgeBitmapSize, false);
+
+        // Paint the provided badge on top of the flattened icon
+        mCanvas.setBitmap(bitmap);
+        mCanvas.drawBitmap(renderedAppIcon, mIconBitmapSize - mBadgeBitmapSize,
+                mIconBitmapSize - mBadgeBitmapSize, null);
+        mCanvas.setBitmap(null);
+
+        return bitmap;
+    }
+
+    private static Drawable getFullResDefaultActivityIcon(int iconDpi) {
+        return Resources.getSystem().getDrawableForDensity(android.R.mipmap.sym_def_app_icon,
+                iconDpi);
+    }
+
+    private Bitmap createIconBitmap(Drawable icon, float scale) {
+        return createIconBitmap(icon, scale, mIconBitmapSize);
+    }
+
+    /**
+     * @param icon drawable that should be flattened to a bitmap
+     * @param scale the scale to apply before drawing {@param icon} on the canvas
+     */
+    private Bitmap createIconBitmap(Drawable icon, float scale, int size) {
+        Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
+
+        mCanvas.setBitmap(bitmap);
+        mOldBounds.set(icon.getBounds());
+
+        if (icon instanceof AdaptiveIconDrawable) {
+            int offset = Math.max((int) Math.ceil(BLUR_FACTOR * size),
+                    Math.round(size * (1 - scale) / 2));
+            icon.setBounds(offset, offset, size - offset, size - offset);
+            icon.draw(mCanvas);
+        } else {
+            if (icon instanceof BitmapDrawable) {
+                BitmapDrawable bitmapDrawable = (BitmapDrawable) icon;
+                Bitmap b = bitmapDrawable.getBitmap();
+                if (bitmap != null && b.getDensity() == Bitmap.DENSITY_NONE) {
+                    bitmapDrawable.setTargetDensity(mContext.getResources().getDisplayMetrics());
+                }
+            }
+            int width = size;
+            int height = size;
+
+            int intrinsicWidth = icon.getIntrinsicWidth();
+            int intrinsicHeight = icon.getIntrinsicHeight();
+            if (intrinsicWidth > 0 && intrinsicHeight > 0) {
+                // Scale the icon proportionally to the icon dimensions
+                final float ratio = (float) intrinsicWidth / intrinsicHeight;
+                if (intrinsicWidth > intrinsicHeight) {
+                    height = (int) (width / ratio);
+                } else if (intrinsicHeight > intrinsicWidth) {
+                    width = (int) (height * ratio);
+                }
+            }
+            final int left = (size - width) / 2;
+            final int top = (size - height) / 2;
+            icon.setBounds(left, top, left + width, top + height);
+            mCanvas.save();
+            mCanvas.scale(scale, scale, size / 2, size / 2);
+            icon.draw(mCanvas);
+            mCanvas.restore();
+
+        }
+
+        icon.setBounds(mOldBounds);
+        mCanvas.setBitmap(null);
+        return bitmap;
+    }
+
+    private Drawable normalizeAndWrapToAdaptiveIcon(Drawable icon, RectF outIconBounds,
+            float[] outScale) {
+        float scale = 1f;
+
+        if (mWrapperIcon == null) {
+            mWrapperIcon = mContext.getDrawable(
+                    R.drawable.iconfactory_adaptive_icon_drawable_wrapper).mutate();
+        }
+
+        AdaptiveIconDrawable dr = (AdaptiveIconDrawable) mWrapperIcon;
+        dr.setBounds(0, 0, 1, 1);
+        scale = getScale(icon, outIconBounds);
+        if (!(icon instanceof AdaptiveIconDrawable)) {
+            FixedScaleDrawable fsd = ((FixedScaleDrawable) dr.getForeground());
+            fsd.setDrawable(icon);
+            fsd.setScale(scale);
+            icon = dr;
+            scale = getScale(icon, outIconBounds);
+
+            ((ColorDrawable) dr.getBackground()).setColor(mWrapperBackgroundColor);
+        }
+
+        outScale[0] = scale;
+        return icon;
+    }
+
+
+    /* Normalization block */
+
+    private static final float SCALE_NOT_INITIALIZED = 0;
+    // Ratio of icon visible area to full icon size for a square shaped icon
+    private static final float MAX_SQUARE_AREA_FACTOR = 375.0f / 576;
+    // Ratio of icon visible area to full icon size for a circular shaped icon
+    private static final float MAX_CIRCLE_AREA_FACTOR = 380.0f / 576;
+
+    private static final float CIRCLE_AREA_BY_RECT = (float) Math.PI / 4;
+
+    // Slope used to calculate icon visible area to full icon size for any generic shaped icon.
+    private static final float LINEAR_SCALE_SLOPE =
+            (MAX_CIRCLE_AREA_FACTOR - MAX_SQUARE_AREA_FACTOR) / (1 - CIRCLE_AREA_BY_RECT);
+
+    private static final int MIN_VISIBLE_ALPHA = 40;
+
+    private float mAdaptiveIconScale;
+    private final Rect mAdaptiveIconBounds;
+    private final Rect mBounds;
+    private final int mMaxSize;
+    private final byte[] mPixels;
+    private final float[] mLeftBorder;
+    private final float[] mRightBorder;
+    private final Bitmap mBitmap;
+    private final Canvas mScaleCheckCanvas;
+
+    /**
+     * Returns the amount by which the {@param d} should be scaled (in both dimensions) so that it
+     * matches the design guidelines for a launcher icon.
+     *
+     * We first calculate the convex hull of the visible portion of the icon.
+     * This hull then compared with the bounding rectangle of the hull to find how closely it
+     * resembles a circle and a square, by comparing the ratio of the areas. Note that this is not
+     * an ideal solution but it gives satisfactory result without affecting the performance.
+     *
+     * This closeness is used to determine the ratio of hull area to the full icon size.
+     * Refer {@link #MAX_CIRCLE_AREA_FACTOR} and {@link #MAX_SQUARE_AREA_FACTOR}
+     *
+     * @param outBounds optional rect to receive the fraction distance from each edge.
+     */
+    private synchronized float getScale(@NonNull Drawable d, @Nullable RectF outBounds) {
+        if (d instanceof AdaptiveIconDrawable) {
+            if (mAdaptiveIconScale != SCALE_NOT_INITIALIZED) {
+                if (outBounds != null) {
+                    outBounds.set(mAdaptiveIconBounds);
+                }
+                return mAdaptiveIconScale;
+            }
+        }
+        int width = d.getIntrinsicWidth();
+        int height = d.getIntrinsicHeight();
+        if (width <= 0 || height <= 0) {
+            width = width <= 0 || width > mMaxSize ? mMaxSize : width;
+            height = height <= 0 || height > mMaxSize ? mMaxSize : height;
+        } else if (width > mMaxSize || height > mMaxSize) {
+            int max = Math.max(width, height);
+            width = mMaxSize * width / max;
+            height = mMaxSize * height / max;
+        }
+
+        mBitmap.eraseColor(Color.TRANSPARENT);
+        d.setBounds(0, 0, width, height);
+        d.draw(mScaleCheckCanvas);
+
+        ByteBuffer buffer = ByteBuffer.wrap(mPixels);
+        buffer.rewind();
+        mBitmap.copyPixelsToBuffer(buffer);
+
+        // Overall bounds of the visible icon.
+        int topY = -1;
+        int bottomY = -1;
+        int leftX = mMaxSize + 1;
+        int rightX = -1;
+
+        // Create border by going through all pixels one row at a time and for each row find
+        // the first and the last non-transparent pixel. Set those values to mLeftBorder and
+        // mRightBorder and use -1 if there are no visible pixel in the row.
+
+        // buffer position
+        int index = 0;
+        // buffer shift after every row, width of buffer = mMaxSize
+        int rowSizeDiff = mMaxSize - width;
+        // first and last position for any row.
+        int firstX, lastX;
+
+        for (int y = 0; y < height; y++) {
+            firstX = lastX = -1;
+            for (int x = 0; x < width; x++) {
+                if ((mPixels[index] & 0xFF) > MIN_VISIBLE_ALPHA) {
+                    if (firstX == -1) {
+                        firstX = x;
+                    }
+                    lastX = x;
+                }
+                index++;
+            }
+            index += rowSizeDiff;
+
+            mLeftBorder[y] = firstX;
+            mRightBorder[y] = lastX;
+
+            // If there is at least one visible pixel, update the overall bounds.
+            if (firstX != -1) {
+                bottomY = y;
+                if (topY == -1) {
+                    topY = y;
+                }
+
+                leftX = Math.min(leftX, firstX);
+                rightX = Math.max(rightX, lastX);
+            }
+        }
+
+        if (topY == -1 || rightX == -1) {
+            // No valid pixels found. Do not scale.
+            return 1;
+        }
+
+        convertToConvexArray(mLeftBorder, 1, topY, bottomY);
+        convertToConvexArray(mRightBorder, -1, topY, bottomY);
+
+        // Area of the convex hull
+        float area = 0;
+        for (int y = 0; y < height; y++) {
+            if (mLeftBorder[y] <= -1) {
+                continue;
+            }
+            area += mRightBorder[y] - mLeftBorder[y] + 1;
+        }
+
+        // Area of the rectangle required to fit the convex hull
+        float rectArea = (bottomY + 1 - topY) * (rightX + 1 - leftX);
+        float hullByRect = area / rectArea;
+
+        float scaleRequired;
+        if (hullByRect < CIRCLE_AREA_BY_RECT) {
+            scaleRequired = MAX_CIRCLE_AREA_FACTOR;
+        } else {
+            scaleRequired = MAX_SQUARE_AREA_FACTOR + LINEAR_SCALE_SLOPE * (1 - hullByRect);
+        }
+        mBounds.left = leftX;
+        mBounds.right = rightX;
+
+        mBounds.top = topY;
+        mBounds.bottom = bottomY;
+
+        if (outBounds != null) {
+            outBounds.set(((float) mBounds.left) / width, ((float) mBounds.top) / height,
+                    1 - ((float) mBounds.right) / width,
+                    1 - ((float) mBounds.bottom) / height);
+        }
+        float areaScale = area / (width * height);
+        // Use sqrt of the final ratio as the images is scaled across both width and height.
+        float scale = areaScale > scaleRequired ? (float) Math.sqrt(scaleRequired / areaScale) : 1;
+        if (d instanceof AdaptiveIconDrawable && mAdaptiveIconScale == SCALE_NOT_INITIALIZED) {
+            mAdaptiveIconScale = scale;
+            mAdaptiveIconBounds.set(mBounds);
+        }
+        return scale;
+    }
+
+    /**
+     * Modifies {@param xCoordinates} to represent a convex border. Fills in all missing values
+     * (except on either ends) with appropriate values.
+     * @param xCoordinates map of x coordinate per y.
+     * @param direction 1 for left border and -1 for right border.
+     * @param topY the first Y position (inclusive) with a valid value.
+     * @param bottomY the last Y position (inclusive) with a valid value.
+     */
+    private static void convertToConvexArray(
+            float[] xCoordinates, int direction, int topY, int bottomY) {
+        int total = xCoordinates.length;
+        // The tangent at each pixel.
+        float[] angles = new float[total - 1];
+
+        int first = topY; // First valid y coordinate
+        int last = -1;    // Last valid y coordinate which didn't have a missing value
+
+        float lastAngle = Float.MAX_VALUE;
+
+        for (int i = topY + 1; i <= bottomY; i++) {
+            if (xCoordinates[i] <= -1) {
+                continue;
+            }
+            int start;
+
+            if (lastAngle == Float.MAX_VALUE) {
+                start = first;
+            } else {
+                float currentAngle = (xCoordinates[i] - xCoordinates[last]) / (i - last);
+                start = last;
+                // If this position creates a concave angle, keep moving up until we find a
+                // position which creates a convex angle.
+                if ((currentAngle - lastAngle) * direction < 0) {
+                    while (start > first) {
+                        start--;
+                        currentAngle = (xCoordinates[i] - xCoordinates[start]) / (i - start);
+                        if ((currentAngle - angles[start]) * direction >= 0) {
+                            break;
+                        }
+                    }
+                }
+            }
+
+            // Reset from last check
+            lastAngle = (xCoordinates[i] - xCoordinates[start]) / (i - start);
+            // Update all the points from start.
+            for (int j = start; j < i; j++) {
+                angles[j] = lastAngle;
+                xCoordinates[j] = xCoordinates[start] + lastAngle * (j - start);
+            }
+            last = i;
+        }
+    }
+
+    /* Shadow generator block */
+
+    private static final float KEY_SHADOW_DISTANCE = 1f / 48;
+    private static final int KEY_SHADOW_ALPHA = 61;
+    private static final int AMBIENT_SHADOW_ALPHA = 30;
+
+    private Paint mBlurPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
+    private Paint mDrawPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
+    private BlurMaskFilter mDefaultBlurMaskFilter;
+
+    private synchronized void recreateIcon(Bitmap icon, Canvas out) {
+        recreateIcon(icon, mDefaultBlurMaskFilter, AMBIENT_SHADOW_ALPHA, KEY_SHADOW_ALPHA, out);
+    }
+
+    private synchronized void recreateIcon(Bitmap icon, BlurMaskFilter blurMaskFilter,
+            int ambientAlpha, int keyAlpha, Canvas out) {
+        int[] offset = new int[2];
+        mBlurPaint.setMaskFilter(blurMaskFilter);
+        Bitmap shadow = icon.extractAlpha(mBlurPaint, offset);
+
+        // Draw ambient shadow
+        mDrawPaint.setAlpha(ambientAlpha);
+        out.drawBitmap(shadow, offset[0], offset[1], mDrawPaint);
+
+        // Draw key shadow
+        mDrawPaint.setAlpha(keyAlpha);
+        out.drawBitmap(shadow, offset[0], offset[1] + KEY_SHADOW_DISTANCE * mIconBitmapSize,
+                mDrawPaint);
+
+        // Draw the icon
+        mDrawPaint.setAlpha(255); // TODO if b/128609682 not fixed by launch use .setAlpha(254)
+        out.drawBitmap(icon, 0, 0, mDrawPaint);
+    }
+
+    /* Classes */
+
+    /**
+     * Extension of {@link DrawableWrapper} which scales the child drawables by a fixed amount.
+     */
+    public static class FixedScaleDrawable extends DrawableWrapper {
+
+        private static final float LEGACY_ICON_SCALE = .7f * .6667f;
+        private float mScaleX, mScaleY;
+
+        public FixedScaleDrawable() {
+            super(new ColorDrawable());
+            mScaleX = LEGACY_ICON_SCALE;
+            mScaleY = LEGACY_ICON_SCALE;
+        }
+
+        @Override
+        public void draw(@NonNull Canvas canvas) {
+            int saveCount = canvas.save();
+            canvas.scale(mScaleX, mScaleY,
+                    getBounds().exactCenterX(), getBounds().exactCenterY());
+            super.draw(canvas);
+            canvas.restoreToCount(saveCount);
+        }
+
+        @Override
+        public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs) { }
+
+        @Override
+        public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme) { }
+
+        /**
+         * Sets the scale associated with this drawable
+         * @param scale
+         */
+        public void setScale(float scale) {
+            float h = getIntrinsicHeight();
+            float w = getIntrinsicWidth();
+            mScaleX = scale * LEGACY_ICON_SCALE;
+            mScaleY = scale * LEGACY_ICON_SCALE;
+            if (h > w && w > 0) {
+                mScaleX *= w / h;
+            } else if (w > h && h > 0) {
+                mScaleY *= h / w;
+            }
+        }
+    }
+
+    /**
+     * An extension of {@link BitmapDrawable} which returns the bitmap pixel size as intrinsic size.
+     * This allows the badging to be done based on the action bitmap size rather than
+     * the scaled bitmap size.
+     */
+    private static class FixedSizeBitmapDrawable extends BitmapDrawable {
+
+        FixedSizeBitmapDrawable(Bitmap bitmap) {
+            super(null, bitmap);
+        }
+
+        @Override
+        public int getIntrinsicHeight() {
+            return getBitmap().getWidth();
+        }
+
+        @Override
+        public int getIntrinsicWidth() {
+            return getBitmap().getWidth();
+        }
+    }
+
+}
diff --git a/core/java/com/android/internal/infra/AbstractRemoteService.java b/core/java/com/android/internal/infra/AbstractRemoteService.java
index 2e709de..eb881de 100644
--- a/core/java/com/android/internal/infra/AbstractRemoteService.java
+++ b/core/java/com/android/internal/infra/AbstractRemoteService.java
@@ -614,6 +614,7 @@
                 if (remoteService != null) {
                     // TODO(b/117779333): we should probably ignore it if service is destroyed.
                     Slog.w(mTag, "timed out after " + service.getRemoteRequestMillis() + " ms");
+                    remoteService.finishRequest(this);
                     onTimeout(remoteService);
                 } else {
                     Slog.w(mTag, "timed out (no service)");
diff --git a/core/java/com/android/internal/os/KernelCpuThreadReader.java b/core/java/com/android/internal/os/KernelCpuThreadReader.java
index 6a9db10..248e026 100644
--- a/core/java/com/android/internal/os/KernelCpuThreadReader.java
+++ b/core/java/com/android/internal/os/KernelCpuThreadReader.java
@@ -198,8 +198,8 @@
      *
      * <p>This function will crawl through all process {@code proc} directories found by the pattern
      * {@code /proc/[0-9]*}, and then check the UID using {@code /proc/$PID/status}. This takes
-     * approximately 500ms on a Pixel 2. Therefore, this method can be computationally expensive,
-     * and should not be called more than once an hour.
+     * approximately 500ms on a 2017 device. Therefore, this method can be computationally
+     * expensive, and should not be called more than once an hour.
      *
      * <p>Data is only collected for UIDs passing the predicate supplied in {@link
      * #setUidPredicate}.
@@ -283,7 +283,7 @@
                 if (threadCpuUsage == null) {
                     continue;
                 }
-                if (mMinimumTotalCpuUsageMillis < totalCpuUsage(threadCpuUsage.usageTimesMillis)) {
+                if (mMinimumTotalCpuUsageMillis > totalCpuUsage(threadCpuUsage.usageTimesMillis)) {
                     if (filteredThreadsCpuUsage == null) {
                         filteredThreadsCpuUsage = new int[mFrequenciesKhz.length];
                     }
diff --git a/core/java/com/android/internal/os/KernelWakelockReader.java b/core/java/com/android/internal/os/KernelWakelockReader.java
index 2442d0b..8b25e2d 100644
--- a/core/java/com/android/internal/os/KernelWakelockReader.java
+++ b/core/java/com/android/internal/os/KernelWakelockReader.java
@@ -66,7 +66,7 @@
      */
     public final KernelWakelockStats readKernelWakelockStats(KernelWakelockStats staleStats) {
         byte[] buffer = new byte[32*1024];
-        int len;
+        int len = 0;
         boolean wakeup_sources;
         final long startTime = SystemClock.uptimeMillis();
 
@@ -87,7 +87,11 @@
                 }
             }
 
-            len = is.read(buffer);
+            int cnt;
+            while ((cnt = is.read(buffer, len, buffer.length - len)) > 0) {
+                len += cnt;
+            }
+
             is.close();
         } catch (java.io.IOException e) {
             Slog.wtf(TAG, "failed to read kernel wakelocks", e);
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 70d8b45..992ddd8 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -408,11 +408,11 @@
      * TODO (chriswailes): Cache the system property location in native code and then write a JNI
      *                     function to fetch it.
      */
-    public static String getSystemProperty(String propertyName, String defaultValue) {
+    public static String getConfigurationProperty(String propertyName, String defaultValue) {
         return SystemProperties.get(
                 String.join(".",
                         "persist.device_config",
-                        DeviceConfig.RuntimeNative.NAMESPACE,
+                        DeviceConfig.NAMESPACE_RUNTIME_NATIVE,
                         propertyName),
                 defaultValue);
     }
@@ -433,12 +433,14 @@
      *
      * TODO (chriswailes): Cache the system property location in native code and then write a JNI
      *                     function to fetch it.
+     * TODO (chriswailes): Move into ZygoteConfig.java once the necessary CL lands (go/ag/6580627)
      */
-    public static boolean getSystemPropertyBoolean(String propertyName, Boolean defaultValue) {
+    public static boolean getConfigurationPropertyBoolean(
+            String propertyName, Boolean defaultValue) {
         return SystemProperties.getBoolean(
                 String.join(".",
                         "persist.device_config",
-                        DeviceConfig.RuntimeNative.NAMESPACE,
+                        DeviceConfig.NAMESPACE_RUNTIME_NATIVE,
                         propertyName),
                 defaultValue);
     }
diff --git a/core/java/com/android/internal/os/ZygoteConfig.java b/core/java/com/android/internal/os/ZygoteConfig.java
new file mode 100644
index 0000000..c8ff51e
--- /dev/null
+++ b/core/java/com/android/internal/os/ZygoteConfig.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+/**
+ * Flag names for configuring the zygote.
+ *
+ * @hide
+ */
+public class ZygoteConfig {
+
+    /** If {@code true}, enables the unspecialized app process (USAP) pool feature */
+    public static final String USAP_POOL_ENABLED = "blastula_pool_enabled";
+
+    /** The threshold used to determine if the pool should be refilled */
+    public static final String USAP_POOL_REFILL_THRESHOLD = "blastula_refill_threshold";
+
+    /** The maximum number of processes to keep in the USAP pool */
+    public static final String USAP_POOL_SIZE_MAX = "blastula_pool_size_max";
+
+    /** The minimum number of processes to keep in the USAP pool */
+    public static final String USAP_POOL_SIZE_MIN = "blastula_pool_size_min";
+}
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 5f23719..07b82d0 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -122,6 +122,12 @@
 
     private static boolean sPreloadComplete;
 
+    /**
+     * Cached classloader to use for the system server. Will only be populated in the system
+     * server process.
+     */
+    private static ClassLoader sCachedSystemServerClassLoader = null;
+
     static void preload(TimingsTraceLog bootTimingsTraceLog) {
         Log.d(TAG, "begin preload");
         bootTimingsTraceLog.traceBegin("BeginPreload");
@@ -443,7 +449,13 @@
 
         final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
         if (systemServerClasspath != null) {
-            performSystemServerDexOpt(systemServerClasspath);
+            if (performSystemServerDexOpt(systemServerClasspath)) {
+                // Throw away the cached classloader. If we compiled here, the classloader would
+                // not have had AoT-ed artifacts.
+                // Note: This only works in a very special environment where selinux enforcement is
+                // disabled, e.g., Mac builds.
+                sCachedSystemServerClassLoader = null;
+            }
             // Capturing profiles is only supported for debug or eng builds since selinux normally
             // prevents it.
             boolean profileSystemServer = SystemProperties.getBoolean(
@@ -476,10 +488,9 @@
 
             throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");
         } else {
-            ClassLoader cl = null;
-            if (systemServerClasspath != null) {
-                cl = createPathClassLoader(systemServerClasspath, parsedArgs.mTargetSdkVersion);
-
+            createSystemServerClassLoader();
+            ClassLoader cl = sCachedSystemServerClassLoader;
+            if (cl != null) {
                 Thread.currentThread().setContextClassLoader(cl);
             }
 
@@ -494,6 +505,24 @@
     }
 
     /**
+     * Create the classloader for the system server and store it in
+     * {@link sCachedSystemServerClassLoader}. This function may be called through JNI in
+     * system server startup, when the runtime is in a critically low state. Do not do
+     * extended computation etc here.
+     */
+    private static void createSystemServerClassLoader() {
+        if (sCachedSystemServerClassLoader != null) {
+            return;
+        }
+        final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
+        // TODO: Should we run optimization here?
+        if (systemServerClasspath != null) {
+            sCachedSystemServerClassLoader = createPathClassLoader(systemServerClasspath,
+                    VMRuntime.SDK_VERSION_CUR_DEVELOPMENT);
+        }
+    }
+
+    /**
      * Note that preparing the profiles for system server does not require special selinux
      * permissions. From the installer perspective the system server is a regular package which can
      * capture profile information.
@@ -557,15 +586,16 @@
 
     /**
      * Performs dex-opt on the elements of {@code classPath}, if needed. We choose the instruction
-     * set of the current runtime.
+     * set of the current runtime. If something was compiled, return true.
      */
-    private static void performSystemServerDexOpt(String classPath) {
+    private static boolean performSystemServerDexOpt(String classPath) {
         final String[] classPathElements = classPath.split(":");
         final IInstalld installd = IInstalld.Stub
                 .asInterface(ServiceManager.getService("installd"));
         final String instructionSet = VMRuntime.getRuntime().vmInstructionSet();
 
         String classPathForElement = "";
+        boolean compiledSomething = false;
         for (String classPathElement : classPathElements) {
             // System server is fully AOTed and never profiled
             // for profile guided compilation.
@@ -607,6 +637,7 @@
                             uuid, classLoaderContext, seInfo, false /* downgrade */,
                             targetSdkVersion, /*profileName*/ null, /*dexMetadataPath*/ null,
                             "server-dexopt");
+                    compiledSomething = true;
                 } catch (RemoteException | ServiceSpecificException e) {
                     // Ignore (but log), we need this on the classpath for fallback mode.
                     Log.w(TAG, "Failed compiling classpath element for system server: "
@@ -617,6 +648,8 @@
             classPathForElement = encodeSystemServerClassPath(
                     classPathForElement, classPathElement);
         }
+
+        return compiledSomething;
     }
 
     /**
diff --git a/core/java/com/android/internal/os/ZygoteServer.java b/core/java/com/android/internal/os/ZygoteServer.java
index 6595317..3f3aba9 100644
--- a/core/java/com/android/internal/os/ZygoteServer.java
+++ b/core/java/com/android/internal/os/ZygoteServer.java
@@ -22,7 +22,6 @@
 import android.net.LocalSocket;
 import android.os.SystemClock;
 import android.os.Trace;
-import android.provider.DeviceConfig;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.system.StructPollfd;
@@ -242,52 +241,55 @@
 
     private void fetchUsapPoolPolicyProps() {
         if (mUsapPoolSupported) {
-            final String usapPoolSizeMaxPropString =
-                    Zygote.getSystemProperty(
-                            DeviceConfig.RuntimeNative.USAP_POOL_SIZE_MAX,
-                            USAP_POOL_SIZE_MAX_DEFAULT);
+            final String usapPoolSizeMaxPropString = Zygote.getConfigurationProperty(
+                    ZygoteConfig.USAP_POOL_SIZE_MAX, USAP_POOL_SIZE_MAX_DEFAULT);
 
             if (!usapPoolSizeMaxPropString.isEmpty()) {
-                mUsapPoolSizeMax =
-                        Integer.min(
-                                Integer.parseInt(usapPoolSizeMaxPropString),
-                                USAP_POOL_SIZE_MAX_LIMIT);
+                mUsapPoolSizeMax = Integer.min(Integer.parseInt(
+                        usapPoolSizeMaxPropString), USAP_POOL_SIZE_MAX_LIMIT);
             }
 
-            final String usapPoolSizeMinPropString =
-                    Zygote.getSystemProperty(
-                            DeviceConfig.RuntimeNative.USAP_POOL_SIZE_MIN,
-                            USAP_POOL_SIZE_MIN_DEFAULT);
+            final String usapPoolSizeMinPropString = Zygote.getConfigurationProperty(
+                    ZygoteConfig.USAP_POOL_SIZE_MIN, USAP_POOL_SIZE_MIN_DEFAULT);
 
             if (!usapPoolSizeMinPropString.isEmpty()) {
-                mUsapPoolSizeMin =
-                        Integer.max(
-                                Integer.parseInt(usapPoolSizeMinPropString),
-                                USAP_POOL_SIZE_MIN_LIMIT);
+                mUsapPoolSizeMin = Integer.max(
+                        Integer.parseInt(usapPoolSizeMinPropString), USAP_POOL_SIZE_MIN_LIMIT);
             }
 
-            final String usapPoolRefillThresholdPropString =
-                    Zygote.getSystemProperty(
-                            DeviceConfig.RuntimeNative.USAP_POOL_REFILL_THRESHOLD,
-                            Integer.toString(mUsapPoolSizeMax / 2));
+            final String usapPoolRefillThresholdPropString = Zygote.getConfigurationProperty(
+                    ZygoteConfig.USAP_POOL_REFILL_THRESHOLD,
+                    Integer.toString(mUsapPoolSizeMax / 2));
 
             if (!usapPoolRefillThresholdPropString.isEmpty()) {
-                mUsapPoolRefillThreshold =
-                        Integer.min(
-                                Integer.parseInt(usapPoolRefillThresholdPropString),
-                                mUsapPoolSizeMax);
+                mUsapPoolRefillThreshold = Integer.min(
+                        Integer.parseInt(usapPoolRefillThresholdPropString),
+                        mUsapPoolSizeMax);
+            }
+
+            // Sanity check
+            if (mUsapPoolSizeMin >= mUsapPoolSizeMax) {
+                Log.w(TAG, "The max size of the USAP pool must be greater than the minimum size."
+                        + "  Restoring default values.");
+
+                mUsapPoolSizeMax = Integer.parseInt(USAP_POOL_SIZE_MAX_DEFAULT);
+                mUsapPoolSizeMin = Integer.parseInt(USAP_POOL_SIZE_MIN_DEFAULT);
+                mUsapPoolRefillThreshold = mUsapPoolSizeMax / 2;
             }
         }
     }
 
+    private boolean mIsFirstPropertyCheck = true;
     private long mLastPropCheckTimestamp = 0;
 
     private void fetchUsapPoolPolicyPropsWithMinInterval() {
         final long currentTimestamp = SystemClock.elapsedRealtime();
 
-        if (currentTimestamp - mLastPropCheckTimestamp >= Zygote.PROPERTY_CHECK_INTERVAL) {
-            fetchUsapPoolPolicyProps();
+        if (mIsFirstPropertyCheck
+                || (currentTimestamp - mLastPropCheckTimestamp >= Zygote.PROPERTY_CHECK_INTERVAL)) {
+            mIsFirstPropertyCheck = false;
             mLastPropCheckTimestamp = currentTimestamp;
+            fetchUsapPoolPolicyProps();
         }
     }
 
@@ -304,6 +306,9 @@
     Runnable fillUsapPool(int[] sessionSocketRawFDs) {
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Zygote:FillUsapPool");
 
+        // Ensure that the pool properties have been fetched.
+        fetchUsapPoolPolicyPropsWithMinInterval();
+
         int usapPoolCount = Zygote.getUsapPoolCount();
         int numUsapsToSpawn = mUsapPoolSizeMax - usapPoolCount;
 
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index 42fb1f5..bb7423a 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -33,7 +33,6 @@
 import android.graphics.drawable.Drawable;
 import android.text.TextUtils;
 import android.util.Size;
-import android.util.TypedValue;
 import android.view.ContextThemeWrapper;
 import android.view.Gravity;
 import android.view.LayoutInflater;
@@ -593,7 +592,7 @@
             refreshCoordinatesAndOverflowDirection(contentRectOnScreen);
             preparePopupContent();
             // We need to specify the position in window coordinates.
-            // TODO: Consider to use PopupWindow.setLayoutInScreenEnabled(true) so that we can
+            // TODO: Consider to use PopupWindow.setIsLaidOutInScreen(true) so that we can
             // specify the popup position in screen coordinates.
             mPopupWindow.showAtLocation(
                     mParent, Gravity.NO_GRAVITY, mCoordsOnWindow.x, mCoordsOnWindow.y);
@@ -661,7 +660,7 @@
             refreshCoordinatesAndOverflowDirection(contentRectOnScreen);
             preparePopupContent();
             // We need to specify the position in window coordinates.
-            // TODO: Consider to use PopupWindow.setLayoutInScreenEnabled(true) so that we can
+            // TODO: Consider to use PopupWindow.setIsLaidOutInScreen(true) so that we can
             // specify the popup position in screen coordinates.
             mPopupWindow.update(
                     mCoordsOnWindow.x, mCoordsOnWindow.y,
@@ -755,7 +754,7 @@
             // and screen coordiantes, where the offset between them should be equal to the window
             // origin, and 2) we can use an arbitrary for this calculation while calculating the
             // location of the rootview is supposed to be least expensive.
-            // TODO: Consider to use PopupWindow.setLayoutInScreenEnabled(true) so that we can avoid
+            // TODO: Consider to use PopupWindow.setIsLaidOutInScreen(true) so that we can avoid
             // the following calculation.
             mParent.getRootView().getLocationOnScreen(mTmpCoords);
             int rootViewLeftOnScreen = mTmpCoords[0];
@@ -1722,7 +1721,7 @@
     private static PopupWindow createPopupWindow(ViewGroup content) {
         ViewGroup popupContentHolder = new LinearLayout(content.getContext());
         PopupWindow popupWindow = new PopupWindow(popupContentHolder);
-        // TODO: Use .setLayoutInScreenEnabled(true) instead of .setClippingEnabled(false)
+        // TODO: Use .setIsLaidOutInScreen(true) instead of .setClippingEnabled(false)
         // unless FLAG_LAYOUT_IN_SCREEN has any unintentional side-effects.
         popupWindow.setClippingEnabled(false);
         popupWindow.setWindowLayoutType(
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index 3be7c3e..41e2fc8 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -62,6 +62,7 @@
     void systemReady();
     void userPresent(int userId);
     int getStrongAuthForUser(int userId);
+    boolean hasPendingEscrowToken(int userId);
 
     // Keystore RecoveryController methods.
     // {@code ServiceSpecificException} may be thrown to signal an error, which caller can
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index c095376..1965609 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -1638,7 +1638,7 @@
     }
 
     /**
-     * @see StrongAuthTracker#isFingerprintAllowedForUser
+     * @see StrongAuthTracker#isBiometricAllowedForUser(int)
      */
     public boolean isBiometricAllowedForUser(int userId) {
         return (getStrongAuthForUser(userId) & ~StrongAuthTracker.ALLOWING_BIOMETRIC) == 0;
@@ -1980,6 +1980,18 @@
     }
 
     /**
+     * Returns whether the given user has pending escrow tokens
+     */
+    public boolean hasPendingEscrowToken(int userId) {
+        try {
+            return getLockSettings().hasPendingEscrowToken(userId);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+        return false;
+    }
+
+    /**
      * Return true if the device supports the lock screen feature, false otherwise.
      */
     public boolean hasSecureLockScreen() {
diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
index ee8637d8..9722fcb 100644
--- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java
+++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
@@ -502,6 +502,7 @@
                         new LogMaker(MetricsEvent.ACTION_SHARESHEET_COLLAPSED_CHANGED)
                         .setSubtype(isCollapsedNew ? 1 : 0));
             }
+            onScrollChanged(0, (int) newPos, 0, (int) (newPos - dy));
             postInvalidateOnAnimation();
             return dy;
         }
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index 958bb18..561dcad 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -938,6 +938,7 @@
                         } else {
                             mBugreportWhitelistedPackages.add(pkgname);
                         }
+                        XmlUtils.skipCurrentTag(parser);
                     } break;
                     default: {
                         Slog.w(TAG, "Tag " + name + " is unknown in "
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 8f00759..e0b7629 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -206,13 +206,14 @@
     // The caller needs to have already set the alpha type properly, so the
     // native SkBitmap stays in sync with the Java Bitmap.
     assert_premultiplied(bitmap->info(), isPremultiplied);
+    bool fromMalloc = bitmap->pixelStorageType() == PixelStorageType::Heap;
     BitmapWrapper* bitmapWrapper = new BitmapWrapper(bitmap);
     if (!isMutable) {
         bitmapWrapper->bitmap().setImmutable();
     }
     jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
             reinterpret_cast<jlong>(bitmapWrapper), bitmap->width(), bitmap->height(), density,
-            isPremultiplied, ninePatchChunk, ninePatchInsets);
+            isPremultiplied, ninePatchChunk, ninePatchInsets, fromMalloc);
 
     if (env->ExceptionCheck() != 0) {
         ALOGE("*** Uncaught exception returned from Java call!\n");
@@ -1224,7 +1225,7 @@
 {
     gBitmap_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Bitmap"));
     gBitmap_nativePtr = GetFieldIDOrDie(env, gBitmap_class, "mNativePtr", "J");
-    gBitmap_constructorMethodID = GetMethodIDOrDie(env, gBitmap_class, "<init>", "(JIIIZ[BLandroid/graphics/NinePatch$InsetStruct;)V");
+    gBitmap_constructorMethodID = GetMethodIDOrDie(env, gBitmap_class, "<init>", "(JIIIZ[BLandroid/graphics/NinePatch$InsetStruct;Z)V");
     gBitmap_reinitMethodID = GetMethodIDOrDie(env, gBitmap_class, "reinit", "(IIZ)V");
     gBitmap_getAllocationByteCountMethodID = GetMethodIDOrDie(env, gBitmap_class, "getAllocationByteCount", "()I");
     return android::RegisterMethodsOrDie(env, "android/graphics/Bitmap", gBitmapMethods,
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 4ba4540..47b1548 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -507,18 +507,9 @@
                 ninePatchChunk, ninePatchInsets, -1);
     }
 
-    // Speculative fix for b/112551574. It doesn't seem like |b| can be null. If it is, print some
-    // info that might be helpful to diagnose.
-    Bitmap* b = defaultAllocator.getStorageObjAndReset();
-    if (!b) {
-        ALOGW("defaultAllocator has no storage object!");
-        ALOGW("\tjavaBitmap: %s", (javaBitmap == nullptr ? "null" : "present"));
-        ALOGW("\tisHardware: %s", (isHardware ? "true" : "false"));
-        ALOGW("\twillScale: %s", (willScale ? "true" : "false"));
-        return nullptr;
-    }
     // now create the java bitmap
-    return bitmap::createBitmap(env, b, bitmapCreateFlags, ninePatchChunk, ninePatchInsets, -1);
+    return bitmap::createBitmap(env, defaultAllocator.getStorageObjAndReset(),
+            bitmapCreateFlags, ninePatchChunk, ninePatchInsets, -1);
 }
 
 static jobject nativeDecodeStream(JNIEnv* env, jobject clazz, jobject is, jbyteArray storage,
diff --git a/core/jni/android/graphics/HarfBuzzNGFaceSkia.h b/core/jni/android/graphics/HarfBuzzNGFaceSkia.h
deleted file mode 100644
index 3308d5d..0000000
--- a/core/jni/android/graphics/HarfBuzzNGFaceSkia.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2011, The Android Open Source Project
- * Copyright 2011, Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _ANDROID_GRAPHICS_HARF_BUZZ_NG_FACE_SKIA_H_
-#define _ANDROID_GRAPHICS_HARF_BUZZ_NG_FACE_SKIA_H_
-
-#include <SkScalar.h>
-#include <SkPaint.h>
-
-#include <hb.h>
-
-namespace android {
-
-static inline float
-HBFixedToFloat (hb_position_t v)
-{
-    return scalbnf (v, -8);
-}
-
-static inline hb_position_t
-HBFloatToFixed (float v)
-{
-    return scalbnf (v, +8);
-}
-
-static inline hb_position_t SkScalarToHBFixed(SkScalar value) {
-    return HBFloatToFixed(SkScalarToFloat(value));
-}
-
-hb_blob_t* harfbuzzSkiaReferenceTable(hb_face_t* face, hb_tag_t tag, void* userData);
-
-hb_font_t* createFont(hb_face_t* face, SkPaint* paint, float sizeX, float sizeY);
-
-}  // namespace android
-
-#endif  // _ANDROID_GRAPHICS_HARF_BUZZ_NG_FACE_SKIA_H_
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 85f1159..cd5c734 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -723,13 +723,17 @@
         obj->setStyle(style);
     }
 
-    static void setColor(jlong paintHandle, jlong colorSpaceHandle,
-            jfloat r, jfloat g, jfloat b, jfloat a) {
+    static void setColorLong(jlong paintHandle, jlong colorSpaceHandle,
+            jlong colorLong) {
+        SkColor4f color = GraphicsJNI::convertColorLong(colorLong);
         sk_sp<SkColorSpace> cs = GraphicsJNI::getNativeColorSpace(colorSpaceHandle);
-        SkColor4f color = SkColor4f{r, g, b, a};
         reinterpret_cast<Paint*>(paintHandle)->setColor4f(color, cs.get());
     }
 
+    static void setColor(jlong paintHandle, jint color) {
+        reinterpret_cast<Paint*>(paintHandle)->setColor(color);
+    }
+
     static void setAlpha(jlong paintHandle, jint a) {
         reinterpret_cast<Paint*>(paintHandle)->setAlpha(a);
     }
@@ -923,14 +927,24 @@
         paint->setWordSpacing(wordSpacing);
     }
 
-    static jint getHyphenEdit(jlong paintHandle, jint hyphen) {
+    static jint getStartHyphenEdit(jlong paintHandle, jint hyphen) {
         Paint* paint = reinterpret_cast<Paint*>(paintHandle);
-        return paint->getHyphenEdit();
+        return static_cast<jint>(paint->getStartHyphenEdit());
     }
 
-    static void setHyphenEdit(jlong paintHandle, jint hyphen) {
+    static jint getEndHyphenEdit(jlong paintHandle, jint hyphen) {
         Paint* paint = reinterpret_cast<Paint*>(paintHandle);
-        paint->setHyphenEdit((uint32_t)hyphen);
+        return static_cast<jint>(paint->getEndHyphenEdit());
+    }
+
+    static void setStartHyphenEdit(jlong paintHandle, jint hyphen) {
+        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
+        paint->setStartHyphenEdit((uint32_t)hyphen);
+    }
+
+    static void setEndHyphenEdit(jlong paintHandle, jint hyphen) {
+        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
+        paint->setEndHyphenEdit((uint32_t)hyphen);
     }
 
     static jfloat ascent(jlong paintHandle) {
@@ -981,9 +995,9 @@
 
     static void setShadowLayer(jlong paintHandle, jfloat radius,
                                jfloat dx, jfloat dy, jlong colorSpaceHandle,
-                               jfloat r, jfloat g, jfloat b, jfloat a) {
+                               jlong colorLong) {
+        SkColor4f color = GraphicsJNI::convertColorLong(colorLong);
         sk_sp<SkColorSpace> cs = GraphicsJNI::getNativeColorSpace(colorSpaceHandle);
-        SkColor4f color = SkColor4f{r, g, b, a};
 
         Paint* paint = reinterpret_cast<Paint*>(paintHandle);
         if (radius <= 0) {
@@ -1072,7 +1086,8 @@
     {"nSetDither","(JZ)V", (void*) PaintGlue::setDither},
     {"nGetStyle","(J)I", (void*) PaintGlue::getStyle},
     {"nSetStyle","(JI)V", (void*) PaintGlue::setStyle},
-    {"nSetColor","(JJFFFF)V", (void*) PaintGlue::setColor},
+    {"nSetColor","(JI)V", (void*) PaintGlue::setColor},
+    {"nSetColor","(JJJ)V", (void*) PaintGlue::setColorLong},
     {"nSetAlpha","(JI)V", (void*) PaintGlue::setAlpha},
     {"nGetStrokeWidth","(J)F", (void*) PaintGlue::getStrokeWidth},
     {"nSetStrokeWidth","(JF)V", (void*) PaintGlue::setStrokeWidth},
@@ -1105,15 +1120,17 @@
     {"nSetLetterSpacing","(JF)V", (void*) PaintGlue::setLetterSpacing},
     {"nGetWordSpacing","(J)F", (void*) PaintGlue::getWordSpacing},
     {"nSetWordSpacing","(JF)V", (void*) PaintGlue::setWordSpacing},
-    {"nGetHyphenEdit", "(J)I", (void*) PaintGlue::getHyphenEdit},
-    {"nSetHyphenEdit", "(JI)V", (void*) PaintGlue::setHyphenEdit},
+    {"nGetStartHyphenEdit", "(J)I", (void*) PaintGlue::getStartHyphenEdit},
+    {"nGetEndHyphenEdit", "(J)I", (void*) PaintGlue::getEndHyphenEdit},
+    {"nSetStartHyphenEdit", "(JI)V", (void*) PaintGlue::setStartHyphenEdit},
+    {"nSetEndHyphenEdit", "(JI)V", (void*) PaintGlue::setEndHyphenEdit},
     {"nAscent","(J)F", (void*) PaintGlue::ascent},
     {"nDescent","(J)F", (void*) PaintGlue::descent},
     {"nGetUnderlinePosition","(J)F", (void*) PaintGlue::getUnderlinePosition},
     {"nGetUnderlineThickness","(J)F", (void*) PaintGlue::getUnderlineThickness},
     {"nGetStrikeThruPosition","(J)F", (void*) PaintGlue::getStrikeThruPosition},
     {"nGetStrikeThruThickness","(J)F", (void*) PaintGlue::getStrikeThruThickness},
-    {"nSetShadowLayer", "(JFFFJFFFF)V", (void*)PaintGlue::setShadowLayer},
+    {"nSetShadowLayer", "(JFFFJJ)V", (void*)PaintGlue::setShadowLayer},
     {"nHasShadowLayer", "(J)Z", (void*)PaintGlue::hasShadowLayer},
     {"nEqualsForTextMeasurement", "(JJ)Z", (void*)PaintGlue::equalsForTextMeasurement},
 };
diff --git a/core/jni/android/graphics/text/LineBreaker.cpp b/core/jni/android/graphics/text/LineBreaker.cpp
index c23f1e9..a23f99a 100644
--- a/core/jni/android/graphics/text/LineBreaker.cpp
+++ b/core/jni/android/graphics/text/LineBreaker.cpp
@@ -80,13 +80,13 @@
         jfloat firstWidth,
         jint firstWidthLineCount,
         jfloat restWidth,
-        jintArray variableTabStops,
-        jint defaultTabStop,
+        jfloatArray variableTabStops,
+        jfloat defaultTabStop,
         jint indentsOffset) {
     minikin::android::StaticLayoutNative* builder = toNative(nativePtr);
 
     ScopedCharArrayRO text(env, javaText);
-    ScopedNullableIntArrayRO tabStops(env, variableTabStops);
+    ScopedNullableFloatArrayRO tabStops(env, variableTabStops);
 
     minikin::U16StringPiece u16Text(text.get(), length);
     minikin::MeasuredText* measuredText = reinterpret_cast<minikin::MeasuredText*>(measuredTextPtr);
@@ -151,8 +151,8 @@
         "F"  // firstWidth
         "I"  // firstWidthLineCount
         "F"  // restWidth
-        "[I"  // variableTabStops
-        "I"  // defaultTabStop
+        "[F"  // variableTabStops
+        "F"  // defaultTabStop
         "I"  // indentsOffset
         ")J", (void*) nComputeLineBreaks},
 
diff --git a/core/jni/android_hardware_input_InputWindowHandle.cpp b/core/jni/android_hardware_input_InputWindowHandle.cpp
index eb71052..a1d1d4f 100644
--- a/core/jni/android_hardware_input_InputWindowHandle.cpp
+++ b/core/jni/android_hardware_input_InputWindowHandle.cpp
@@ -31,6 +31,11 @@
 
 namespace android {
 
+struct WeakRefHandleField {
+    jfieldID handle;
+    jmethodID get;
+};
+
 static struct {
     jfieldID ptr;
     jfieldID inputApplicationHandle;
@@ -57,6 +62,8 @@
     jfieldID inputFeatures;
     jfieldID displayId;
     jfieldID portalToDisplayId;
+    jfieldID replaceTouchableRegionWithCrop;
+    WeakRefHandleField touchableRegionCropHandle;
 } gInputWindowHandleClassInfo;
 
 static Mutex gHandleMutex;
@@ -90,6 +97,7 @@
     jobject tokenObj = env->GetObjectField(obj, gInputWindowHandleClassInfo.token);
     if (tokenObj) {
         mInfo.token = ibinderForJavaObject(env, tokenObj);
+        env->DeleteLocalRef(tokenObj);
     } else {
         mInfo.token.clear();
     }
@@ -161,6 +169,24 @@
         env->DeleteLocalRef(inputApplicationHandleObj);
     }
 
+    mInfo.replaceTouchableRegionWithCrop = env->GetBooleanField(obj,
+            gInputWindowHandleClassInfo.replaceTouchableRegionWithCrop);
+
+    jobject handleObj = env->GetObjectField(obj,
+            gInputWindowHandleClassInfo.touchableRegionCropHandle.handle);
+    if (handleObj) {
+        // Promote java weak reference.
+        jobject strongHandleObj = env->CallObjectMethod(handleObj,
+                gInputWindowHandleClassInfo.touchableRegionCropHandle.get);
+        if (strongHandleObj) {
+            mInfo.touchableRegionCropHandle = ibinderForJavaObject(env, strongHandleObj);
+            env->DeleteLocalRef(strongHandleObj);
+        } else {
+            mInfo.touchableRegionCropHandle.clear();
+        }
+        env->DeleteLocalRef(handleObj);
+    }
+
     env->DeleteLocalRef(obj);
     return true;
 }
@@ -220,6 +246,10 @@
         var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
         LOG_FATAL_IF(! (var), "Unable to find field " fieldName);
 
+#define GET_METHOD_ID(var, clazz, methodName, methodSignature) \
+        var = env->GetMethodID(clazz, methodName, methodSignature); \
+        LOG_FATAL_IF(! (var), "Unable to find method " methodName);
+
 int register_android_view_InputWindowHandle(JNIEnv* env) {
     int res = jniRegisterNativeMethods(env, "android/view/InputWindowHandle",
             gInputWindowHandleMethods, NELEM(gInputWindowHandleMethods));
@@ -303,6 +333,18 @@
 
     GET_FIELD_ID(gInputWindowHandleClassInfo.portalToDisplayId, clazz,
             "portalToDisplayId", "I");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.replaceTouchableRegionWithCrop, clazz,
+            "replaceTouchableRegionWithCrop", "Z");
+
+    jclass weakRefClazz;
+    FIND_CLASS(weakRefClazz, "java/lang/ref/Reference");
+
+    GET_METHOD_ID(gInputWindowHandleClassInfo.touchableRegionCropHandle.get, weakRefClazz,
+             "get", "()Ljava/lang/Object;")
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.touchableRegionCropHandle.handle, clazz,
+            "touchableRegionCropHandle", "Ljava/lang/ref/WeakReference;");
     return 0;
 }
 
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index ce5512b..c4c16ee 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -31,6 +31,7 @@
 #include <renderthread/CanvasContext.h>
 #include <TreeInfo.h>
 #include <hwui/Paint.h>
+#include <utils/TraceUtils.h>
 
 #include "core_jni_helpers.h"
 
@@ -338,6 +339,19 @@
     return renderNode->stagingProperties().hasOverlappingRendering();
 }
 
+static jboolean android_view_RenderNode_getAnimationMatrix(jlong renderNodePtr, jlong outMatrixPtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    SkMatrix* outMatrix = reinterpret_cast<SkMatrix*>(outMatrixPtr);
+
+    const SkMatrix* animationMatrix = renderNode->stagingProperties().getAnimationMatrix();
+
+    if (animationMatrix) {
+        *outMatrix = *animationMatrix;
+        return JNI_TRUE;
+    }
+    return JNI_FALSE;
+}
+
 static jboolean android_view_RenderNode_getClipToBounds(jlong renderNodePtr) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     return renderNode->stagingProperties().getClipToBounds();
@@ -649,6 +663,7 @@
     { "nSetLayerPaint",        "(JJ)Z",  (void*) android_view_RenderNode_setLayerPaint },
     { "nSetStaticMatrix",      "(JJ)Z",  (void*) android_view_RenderNode_setStaticMatrix },
     { "nSetAnimationMatrix",   "(JJ)Z",  (void*) android_view_RenderNode_setAnimationMatrix },
+    { "nGetAnimationMatrix",   "(JJ)Z",  (void*) android_view_RenderNode_getAnimationMatrix },
     { "nSetClipToBounds",      "(JZ)Z",  (void*) android_view_RenderNode_setClipToBounds },
     { "nGetClipToBounds",      "(J)Z",   (void*) android_view_RenderNode_getClipToBounds },
     { "nSetClipBounds",        "(JIIII)Z", (void*) android_view_RenderNode_setClipBounds },
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 89d908b..4a6c72b 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -1164,6 +1164,25 @@
     }
 }
 
+static jboolean nativeGetDisplayBrightnessSupport(JNIEnv* env, jclass clazz,
+        jobject displayTokenObject) {
+    sp<IBinder> displayToken(ibinderForJavaObject(env, displayTokenObject));
+    if (displayToken == nullptr) {
+        return JNI_FALSE;
+    }
+    return static_cast<jboolean>(SurfaceComposerClient::getDisplayBrightnessSupport(displayToken));
+}
+
+static jboolean nativeSetDisplayBrightness(JNIEnv* env, jclass clazz, jobject displayTokenObject,
+        jfloat brightness) {
+    sp<IBinder> displayToken(ibinderForJavaObject(env, displayTokenObject));
+    if (displayToken == nullptr) {
+        return JNI_FALSE;
+    }
+    status_t error = SurfaceComposerClient::setDisplayBrightness(displayToken, brightness);
+    return error == OK ? JNI_TRUE : JNI_FALSE;
+}
+
 // ----------------------------------------------------------------------------
 
 static const JNINativeMethod sSurfaceControlMethods[] = {
@@ -1308,7 +1327,11 @@
     {"nativeSetGeometry", "(JJLandroid/graphics/Rect;Landroid/graphics/Rect;J)V",
             (void*)nativeSetGeometry },
     {"nativeSyncInputWindows", "(J)V",
-            (void*)nativeSyncInputWindows }
+            (void*)nativeSyncInputWindows },
+    {"nativeGetDisplayBrightnessSupport", "(Landroid/os/IBinder;)Z",
+            (void*)nativeGetDisplayBrightnessSupport },
+    {"nativeSetDisplayBrightness", "(Landroid/os/IBinder;F)Z",
+            (void*)nativeSetDisplayBrightness },
 };
 
 int register_android_view_SurfaceControl(JNIEnv* env)
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index c6f62ca..cde1884 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -24,6 +24,7 @@
 #endif
 
 #define LOG_TAG "Zygote"
+#define ATRACE_TAG ATRACE_TAG_DALVIK
 
 #include <async_safe/log.h>
 
@@ -73,6 +74,7 @@
 #include <cutils/multiuser.h>
 #include <private/android_filesystem_config.h>
 #include <utils/String8.h>
+#include <utils/Trace.h>
 #include <selinux/android.h>
 #include <seccomp_policy.h>
 #include <stats_event_list.h>
@@ -111,11 +113,16 @@
 
 static const char kIsolatedStorage[] = "persist.sys.isolated_storage";
 static const char kIsolatedStorageSnapshot[] = "sys.isolated_storage_snapshot";
-static const char kZygoteClassName[] = "com/android/internal/os/Zygote";
+
+static constexpr const char* kZygoteClassName = "com/android/internal/os/Zygote";
 static jclass gZygoteClass;
 static jmethodID gCallPostForkSystemServerHooks;
 static jmethodID gCallPostForkChildHooks;
 
+static constexpr const char* kZygoteInitClassName = "com/android/internal/os/ZygoteInit";
+static jclass gZygoteInitClass;
+static jmethodID gCreateSystemServerClassLoader;
+
 static bool g_is_security_enforced = true;
 
 /**
@@ -352,7 +359,7 @@
   }
 
   if (usaps_removed > 0) {
-    if (write(gUsapPoolEventFD, &usaps_removed, sizeof(usaps_removed)) == -1) {
+    if (TEMP_FAILURE_RETRY(write(gUsapPoolEventFD, &usaps_removed, sizeof(usaps_removed))) == -1) {
       // If this write fails something went terribly wrong.  We will now kill
       // the zygote and let the system bring it back up.
       async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG,
@@ -585,6 +592,8 @@
 }
 
 static int UnmountTree(const char* path) {
+  ATRACE_CALL();
+
   size_t path_len = strlen(path);
 
   FILE* fp = setmntent("/proc/mounts", "r");
@@ -627,6 +636,8 @@
 }
 
 static void CreatePkgSandboxTarget(userid_t user_id, fail_fn_t fail_fn) {
+  ATRACE_CALL();
+
   // Create /mnt/user/0/package
   std::string pkg_sandbox_dir = StringPrintf("/mnt/user/%d", user_id);
   CreateDir(pkg_sandbox_dir, 0751, AID_ROOT, AID_ROOT, fail_fn);
@@ -650,6 +661,8 @@
                                 uid_t uid,
                                 const char* dir_name,
                                 fail_fn_t fail_fn) {
+  ATRACE_CALL();
+
   std::string mnt_source_dir = StringPrintf("%s/Android/%s/%s",
       mnt_source_root.c_str(), dir_name, package_name.c_str());
 
@@ -662,6 +675,8 @@
 static void CreateSubDirs(int parent_fd, const std::string& parent_path,
                           const std::vector<std::string>& sub_dirs,
                           fail_fn_t fail_fn) {
+  ATRACE_CALL();
+
   for (auto& dir_name : sub_dirs) {
     struct stat sb;
     if (TEMP_FAILURE_RETRY(fstatat(parent_fd, dir_name.c_str(), &sb, 0)) == 0) {
@@ -686,6 +701,8 @@
                                   const std::vector<std::string>& package_names,
                                   bool create_sandbox_dir,
                                   fail_fn_t fail_fn) {
+  ATRACE_CALL();
+
   std::string android_dir = StringPrintf("%s/Android", path.c_str());
   android::base::unique_fd android_fd(open(android_dir.c_str(),
                                            O_RDONLY | O_DIRECTORY | O_CLOEXEC));
@@ -729,6 +746,7 @@
 }
 
 static void CreatePkgSandboxSource(const std::string& sandbox_source, fail_fn_t fail_fn) {
+  ATRACE_CALL();
 
   struct stat sb;
   if (TEMP_FAILURE_RETRY(stat(sandbox_source.c_str(), &sb)) == 0) {
@@ -751,6 +769,8 @@
 static void PreparePkgSpecificDirs(const std::vector<std::string>& package_names,
                                    bool mount_all_obbs, const std::string& sandbox_id,
                                    userid_t user_id, uid_t uid, fail_fn_t fail_fn) {
+  ATRACE_CALL();
+
   std::unique_ptr<DIR, decltype(&closedir)> dirp(opendir("/storage"), closedir);
   if (!dirp) {
     fail_fn(CREATE_ERROR("Failed to opendir /storage: %s", strerror(errno)));
@@ -807,6 +827,8 @@
                                      userid_t user_id,
                                      const std::string& sandbox_id,
                                      fail_fn_t fail_fn) {
+  ATRACE_CALL();
+
   std::string obb_mount_dir = StringPrintf("/mnt/user/%d/obb_mount", user_id);
   std::string obb_mount_file = StringPrintf("%s/%s", obb_mount_dir.c_str(), sandbox_id.c_str());
   if (mount_mode == MOUNT_EXTERNAL_INSTALLER) {
@@ -844,6 +866,7 @@
         const std::string& sandbox_id,
         fail_fn_t fail_fn) {
   // See storage config details at http://source.android.com/tech/storage/
+  ATRACE_CALL();
 
   String8 storage_source;
   if (mount_mode == MOUNT_EXTERNAL_DEFAULT) {
@@ -1420,6 +1443,15 @@
       fail_fn("Error calling post fork system server hooks.");
     }
 
+    // Prefetch the classloader for the system server. This is done early to
+    // allow a tie-down of the proper system server selinux domain.
+    env->CallStaticVoidMethod(gZygoteInitClass, gCreateSystemServerClassLoader);
+    if (env->ExceptionCheck()) {
+      // Be robust here. The Java code will attempt to create the classloader
+      // at a later point (but may not have rights to use AoT artifacts).
+      env->ExceptionClear();
+    }
+
     // TODO(oth): Remove hardcoded label here (b/117874058).
     static const char* kSystemServerLabel = "u:r:system_server:s0";
     if (selinux_android_setcon(kSystemServerLabel) != 0) {
@@ -1986,6 +2018,13 @@
   gCallPostForkChildHooks = GetStaticMethodIDOrDie(env, gZygoteClass, "callPostForkChildHooks",
                                                    "(IZZLjava/lang/String;)V");
 
-  return RegisterMethodsOrDie(env, "com/android/internal/os/Zygote", gMethods, NELEM(gMethods));
+  gZygoteInitClass = MakeGlobalRefOrDie(env, FindClassOrDie(env, kZygoteInitClassName));
+  gCreateSystemServerClassLoader = GetStaticMethodIDOrDie(env, gZygoteInitClass,
+                                                          "createSystemServerClassLoader",
+                                                          "()V");
+
+  RegisterMethodsOrDie(env, "com/android/internal/os/Zygote", gMethods, NELEM(gMethods));
+
+  return JNI_OK;
 }
 }  // namespace android
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index 927c85f2..7ad9223 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -2302,4 +2302,7 @@
 
     // Panel for Wifi
     PANEL_WIFI = 1687;
+
+    // Open: Settings > Special App Access > Do not disturb control for app
+    ZEN_ACCESS_DETAIL = 1692;
 }
diff --git a/core/proto/android/server/connectivity/data_stall_event.proto b/core/proto/android/server/connectivity/data_stall_event.proto
index 21717d8..a82326f 100644
--- a/core/proto/android/server/connectivity/data_stall_event.proto
+++ b/core/proto/android/server/connectivity/data_stall_event.proto
@@ -25,6 +25,7 @@
     VALID = 1;
     INVALID = 2;
     PORTAL = 3;
+    PARTIAL = 4;
 }
 
 enum ApBand {
@@ -86,4 +87,4 @@
     repeated int32 dns_return_code = 1;
     // Indicate the timestamp of the dns event.
     repeated int64 dns_time = 2;
-}
\ No newline at end of file
+}
diff --git a/core/proto/android/server/powermanagerservice.proto b/core/proto/android/server/powermanagerservice.proto
index 8fce94e..9bf1825 100644
--- a/core/proto/android/server/powermanagerservice.proto
+++ b/core/proto/android/server/powermanagerservice.proto
@@ -318,6 +318,16 @@
     // Whether battery saver is enabled.
     optional bool enabled = 1;
 
+    enum StateEnum {
+        STATE_UNKNOWN = 0;
+        STATE_OFF = 1;
+        STATE_MANUAL_ON = 2;
+        STATE_AUTOMATIC_ON = 3;
+        STATE_OFF_AUTOMATIC_SNOOZED = 4;
+        STATE_PENDING_STICKY_ON = 5;
+    }
+    optional StateEnum state = 18;
+
     // Whether full battery saver is enabled.
     optional bool is_full_enabled = 14;
 
@@ -337,8 +347,7 @@
     // Whether battery status has been set at least once.
     optional bool battery_status_set = 4;
 
-    // Whether automatic battery saver has been canceled by the user.
-    optional bool battery_saver_snoozing = 5;
+    reserved 5; // battery_saver_snoozing
 
     // Whether the device is connected to any power source.
     optional bool is_powered = 6;
@@ -373,5 +382,5 @@
     // using elapsed realtime as the timebase.
     optional int64 last_adaptive_battery_saver_changed_externally_elapsed = 17;
 
-    // Next tag: 18
+    // Next tag: 19
 }
diff --git a/core/proto/android/stats/devicepolicy/device_policy_enums.proto b/core/proto/android/stats/devicepolicy/device_policy_enums.proto
index 49221b4..589a6a7 100644
--- a/core/proto/android/stats/devicepolicy/device_policy_enums.proto
+++ b/core/proto/android/stats/devicepolicy/device_policy_enums.proto
@@ -136,11 +136,13 @@
 
   SEPARATE_PROFILE_CHALLENGE_CHANGED = 110;
   SET_GLOBAL_SETTING = 111;
-  PM_IS_INSTALLER_DEVICE_OWNER_OR_AFFILIATED_PROFILE_OWNER = 112;
-  PM_UNINSTALL = 113;
+  INSTALL_PACKAGE = 112;
+  UNINSTALL_PACKAGE = 113;
   WIFI_SERVICE_ADD_NETWORK_SUGGESTIONS = 114;
   WIFI_SERVICE_ADD_OR_UPDATE_NETWORK = 115;
   QUERY_SUMMARY_FOR_DEVICE = 116;
   REMOVE_CROSS_PROFILE_WIDGET_PROVIDER = 117;
   ESTABLISH_VPN = 118;
+  SET_NETWORK_LOGGING_ENABLED = 119;
+  RETRIEVE_NETWORK_LOGS = 120;
 }
diff --git a/core/java/android/net/ProxyInfoParcelable.aidl b/core/proto/android/stats/storage/storage_enums.proto
similarity index 74%
rename from core/java/android/net/ProxyInfoParcelable.aidl
rename to core/proto/android/stats/storage/storage_enums.proto
index 59fd846..6892e28 100644
--- a/core/java/android/net/ProxyInfoParcelable.aidl
+++ b/core/proto/android/stats/storage/storage_enums.proto
@@ -5,20 +5,22 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *     http://www.apache.org/licenses/LICENSE-2.0
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
-*/
+ */
 
-package android.net;
+syntax = "proto2";
 
-parcelable ProxyInfoParcelable {
-    String host;
-    int port;
-    String[] exclusionList;
-    String pacFileUrl;
+package android.stats.storage;
+
+enum ExternalStorageType {
+  UNKNOWN = 0;
+  SD_CARD = 1;
+  USB = 2;
+  OTHER = 3;
 }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index ea300aa..c7417bf 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -867,6 +867,7 @@
         android:label="@string/permgrouplab_visual"
         android:description="@string/permgroupdesc_visual"
         android:request="@string/permgrouprequest_visual"
+        android:requestDetail="@string/permgrouprequestdetail_visual"
         android:priority="920" />
 
     <!-- Allows an application to read the user's shared images collection. -->
@@ -1516,6 +1517,13 @@
     <permission android:name="android.permission.MANAGE_IPSEC_TUNNELS"
         android:protectionLevel="signature|appop" />
 
+    <!-- @hide Allows apps to create and manage Test Networks.
+         <p>Granted only to shell. CTS tests will use
+         UiAutomation.AdoptShellPermissionIdentity() to gain access.
+    -->
+    <permission android:name="android.permission.MANAGE_TEST_NETWORKS"
+        android:protectionLevel="signature" />
+
     <!-- @SystemApi @hide Allows applications to read Wi-Fi credential.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.READ_WIFI_CREDENTIAL"
diff --git a/packages/SystemUI/res/layout/assistant_handle.xml b/core/res/res/drawable/iconfactory_adaptive_icon_drawable_wrapper.xml
similarity index 68%
rename from packages/SystemUI/res/layout/assistant_handle.xml
rename to core/res/res/drawable/iconfactory_adaptive_icon_drawable_wrapper.xml
index a952ca5..3dd276d 100644
--- a/packages/SystemUI/res/layout/assistant_handle.xml
+++ b/core/res/res/drawable/iconfactory_adaptive_icon_drawable_wrapper.xml
@@ -15,11 +15,10 @@
   ~ limitations under the License
   -->
 
-<com.android.systemui.statusbar.phone.NavigationHandle
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/assistant_handle"
-    android:layout_width="@dimen/navigation_assistant_handle_width"
-    android:layout_height="match_parent"
-    android:layout_weight="0"
-/>
-
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@color/white"/>
+    <foreground>
+        <drawable
+            class="com.android.internal.app.SimpleIconFactory$FixedScaleDrawable"/>
+    </foreground>
+</adaptive-icon>
\ No newline at end of file
diff --git a/core/res/res/drawable/sym_def_app_icon_background.xml b/core/res/res/drawable/sym_def_app_icon_background.xml
index 5755210..17b592f 100644
--- a/core/res/res/drawable/sym_def_app_icon_background.xml
+++ b/core/res/res/drawable/sym_def_app_icon_background.xml
@@ -5,7 +5,7 @@
     android:viewportHeight="108.0"
     android:viewportWidth="108.0"
     xmlns:android="http://schemas.android.com/apk/res/android">
-    <path android:fillColor="@android:color/material_deep_teal_500"
+    <path android:fillColor="@android:color/accent_device_default_light"
         android:pathData="M0,0h108v108h-108z"
         android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
     <path android:fillColor="#00000000" android:pathData="M19,0L19,108"
diff --git a/core/res/res/layout/chooser_grid.xml b/core/res/res/layout/chooser_grid.xml
index 10798ad..2860ee4 100644
--- a/core/res/res/layout/chooser_grid.xml
+++ b/core/res/res/layout/chooser_grid.xml
@@ -70,209 +70,6 @@
                   android:layout_centerHorizontal="true"/>
     </RelativeLayout>
 
-    <!-- The following 3 layouts are mutually exclusive. One of them will be
-         set VISIBLE programatically, when the optimal preview type can be 
-         determined by inspecting the data being shared. This path was chosen
-         b/c inflating layouts in code had sizing problems with this widget. -->
-
-    <!-- Layout Option 1: Supporting up to 3 images for preview -->
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="vertical"
-        android:background="?attr/colorBackgroundFloating">
-        <RelativeLayout
-            android:id="@+id/content_preview_image_area"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center_horizontal"
-            android:paddingBottom="@dimen/chooser_view_spacing"
-            android:visibility="gone"
-            android:background="?attr/colorBackgroundFloating">
-
-            <view class="com.android.internal.app.ChooserActivity$RoundedRectImageView"
-                  android:id="@+id/content_preview_image_1_large"
-                  android:visibility="gone"
-                  android:layout_width="120dp"
-                  android:layout_height="140dp"
-                  android:layout_alignParentTop="true"
-                  android:adjustViewBounds="true"
-                  android:gravity="center"
-                  android:scaleType="centerCrop"/>
-
-            <view class="com.android.internal.app.ChooserActivity$RoundedRectImageView"
-                  android:id="@+id/content_preview_image_2_large"
-                  android:visibility="gone"
-                  android:layout_width="120dp"
-                  android:layout_height="140dp"
-                  android:layout_alignParentTop="true"
-                  android:layout_toRightOf="@id/content_preview_image_1_large"
-                  android:layout_marginLeft="10dp"
-                  android:adjustViewBounds="true"
-                  android:gravity="center"
-                  android:scaleType="centerCrop"/>
-
-            <view class="com.android.internal.app.ChooserActivity$RoundedRectImageView"
-                  android:id="@+id/content_preview_image_2_small"
-                  android:visibility="gone"
-                  android:layout_width="120dp"
-                  android:layout_height="65dp"
-                  android:layout_alignParentTop="true"
-                  android:layout_toRightOf="@id/content_preview_image_1_large"
-                  android:layout_marginLeft="10dp"
-                  android:adjustViewBounds="true"
-                  android:gravity="center"
-                  android:scaleType="centerCrop"/>
-
-            <view class="com.android.internal.app.ChooserActivity$RoundedRectImageView"
-                  android:id="@+id/content_preview_image_3_small"
-                  android:visibility="gone"
-                  android:layout_width="120dp"
-                  android:layout_height="65dp"
-                  android:layout_below="@id/content_preview_image_2_small"
-                  android:layout_toRightOf="@id/content_preview_image_1_large"
-                  android:layout_marginLeft="10dp"
-                  android:layout_marginTop="10dp"
-                  android:adjustViewBounds="true"
-                  android:gravity="center"
-                  android:scaleType="centerCrop"/>
-
-        </RelativeLayout>
-    </LinearLayout>
-
-    <!-- Layout Option 2: Text preview, with optional title and thumbnail -->
-    <LinearLayout
-        android:id="@+id/content_preview_text_area"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="vertical"
-        android:paddingBottom="@dimen/chooser_view_spacing"
-        android:visibility="gone"
-        android:background="?attr/colorBackgroundFloating">
-
-        <LinearLayout
-            android:layout_width="@dimen/chooser_preview_width"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center"
-            android:orientation="horizontal"
-            android:paddingLeft="@dimen/chooser_edge_margin_normal"
-            android:paddingRight="@dimen/chooser_edge_margin_normal"
-            android:layout_marginBottom="@dimen/chooser_view_spacing"
-            android:id="@+id/content_preview_text_layout">
-            <TextView
-                android:id="@+id/content_preview_text"
-                android:layout_width="0dp"
-                android:layout_weight="1"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center_vertical"
-                android:ellipsize="end"
-                android:gravity="start|top"
-                android:paddingRight="24dp"
-                android:maxLines="2"/>
-            <Button
-                android:id="@+id/copy_button"
-                android:layout_width="24dp"
-                android:layout_height="24dp"
-                android:gravity="center"
-                android:layout_gravity="center_vertical"
-                android:background="@drawable/ic_content_copy_gm2"/>
-        </LinearLayout>
-
-        <!-- Required sub-layout so we can get the nice rounded corners-->
-        <!-- around this section -->
-        <LinearLayout
-            android:layout_width="@dimen/chooser_preview_width"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center"
-            android:orientation="horizontal"
-            android:layout_marginLeft="@dimen/chooser_edge_margin_thin"
-            android:layout_marginRight="@dimen/chooser_edge_margin_thin"
-            android:minHeight="80dp"
-            android:background="@drawable/chooser_content_preview_rounded"
-            android:id="@+id/content_preview_title_layout">
-
-            <view class="com.android.internal.app.ChooserActivity$RoundedRectImageView"
-                  android:id="@+id/content_preview_thumbnail"
-                  android:layout_width="75dp"
-                  android:layout_height="75dp"
-                  android:layout_marginRight="16dp"
-                  android:adjustViewBounds="true"
-                  android:layout_gravity="center_vertical"
-                  android:gravity="center"
-                  android:scaleType="centerCrop"/>
-
-            <TextView
-                android:id="@+id/content_preview_title"
-                android:layout_width="0dp"
-                android:layout_weight="1"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center_vertical"
-                android:ellipsize="end"
-                android:maxLines="2"
-                android:textAppearance="?attr/textAppearanceMedium"/>
-        </LinearLayout>
-    </LinearLayout>
-
-    <!-- Layout Option 3: File preview, icon, filename, copy-->
-    <LinearLayout
-        android:id="@+id/content_preview_file_area"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="vertical"
-        android:paddingBottom="@dimen/chooser_view_spacing"
-        android:visibility="gone"
-        android:background="?attr/colorBackgroundFloating">
-
-        <LinearLayout
-            android:layout_width="@dimen/chooser_preview_width"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center"
-            android:orientation="horizontal"
-            android:paddingLeft="@dimen/chooser_edge_margin_normal"
-            android:paddingRight="@dimen/chooser_edge_margin_normal"
-            android:layout_marginBottom="@dimen/chooser_view_spacing"
-            android:id="@+id/content_preview_file_layout">
-
-            <view class="com.android.internal.app.ChooserActivity$RoundedRectImageView"
-                  android:id="@+id/content_preview_file_thumbnail"
-                  android:layout_width="75dp"
-                  android:layout_height="75dp"
-                  android:layout_marginRight="16dp"
-                  android:adjustViewBounds="true"
-                  android:layout_gravity="center_vertical"
-                  android:gravity="center"
-                  android:scaleType="centerCrop"
-                  android:visibility="gone"/>
-            <ImageView
-                  android:id="@+id/content_preview_file_icon"
-                  android:layout_width="36dp"
-                  android:layout_height="36dp"
-                  android:layout_marginRight="16dp"
-                  android:adjustViewBounds="true"
-                  android:layout_gravity="center_vertical"
-                  android:gravity="center"
-                  android:scaleType="fitCenter"
-                  android:visibility="gone"/>
-            <TextView
-                android:id="@+id/content_preview_filename"
-                android:layout_width="0dp"
-                android:layout_weight="1"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center_vertical"
-                android:ellipsize="middle"
-                android:gravity="start|top"
-                android:paddingRight="24dp"
-                android:singleLine="true"/>
-            <Button
-                android:id="@+id/file_copy_button"
-                android:layout_width="24dp"
-                android:layout_height="24dp"
-                android:gravity="center"
-                android:layout_gravity="center_vertical"
-                android:background="@drawable/ic_content_copy_gm2"/>
-        </LinearLayout>
-    </LinearLayout>
-
     <ListView
         android:layout_width="match_parent"
         android:layout_height="match_parent"
diff --git a/core/res/res/layout/chooser_grid_preview_file.xml b/core/res/res/layout/chooser_grid_preview_file.xml
new file mode 100644
index 0000000..27c6041
--- /dev/null
+++ b/core/res/res/layout/chooser_grid_preview_file.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright 2019, 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.
+*/
+-->
+<!-- Layout Option: File preview, icon, filename, copy-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/content_preview_file_area"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:paddingBottom="@dimen/chooser_view_spacing"
+    android:background="?attr/colorBackgroundFloating">
+
+  <LinearLayout
+      android:layout_width="@dimen/chooser_preview_width"
+      android:layout_height="wrap_content"
+      android:layout_gravity="center"
+      android:orientation="horizontal"
+      android:paddingLeft="@dimen/chooser_edge_margin_normal"
+      android:paddingRight="@dimen/chooser_edge_margin_normal"
+      android:layout_marginBottom="@dimen/chooser_view_spacing"
+      android:id="@+id/content_preview_file_layout">
+
+    <view class="com.android.internal.app.ChooserActivity$RoundedRectImageView"
+          android:id="@+id/content_preview_file_thumbnail"
+          android:layout_width="75dp"
+          android:layout_height="75dp"
+          android:layout_marginRight="16dp"
+          android:adjustViewBounds="true"
+          android:layout_gravity="center_vertical"
+          android:gravity="center"
+          android:scaleType="centerCrop"
+          android:visibility="gone"/>
+    <ImageView
+        android:id="@+id/content_preview_file_icon"
+        android:layout_width="36dp"
+        android:layout_height="36dp"
+        android:layout_marginRight="16dp"
+        android:adjustViewBounds="true"
+        android:layout_gravity="center_vertical"
+        android:gravity="center"
+        android:scaleType="fitCenter"
+        android:visibility="gone"/>
+    <TextView
+        android:id="@+id/content_preview_filename"
+        android:layout_width="0dp"
+        android:layout_weight="1"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        android:ellipsize="middle"
+        android:gravity="start|top"
+        android:paddingRight="24dp"
+        android:singleLine="true"/>
+    <Button
+        android:id="@+id/file_copy_button"
+        android:layout_width="24dp"
+        android:layout_height="24dp"
+        android:gravity="center"
+        android:layout_gravity="center_vertical"
+        android:background="@drawable/ic_content_copy_gm2"/>
+  </LinearLayout>
+</LinearLayout>
+
diff --git a/core/res/res/layout/chooser_grid_preview_image.xml b/core/res/res/layout/chooser_grid_preview_image.xml
new file mode 100644
index 0000000..ad31e0d
--- /dev/null
+++ b/core/res/res/layout/chooser_grid_preview_image.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright 2019, 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.
+*/
+-->
+<!-- Layout Option: Supporting up to 3 images for preview -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:background="?attr/colorBackgroundFloating">
+  <RelativeLayout
+      android:id="@+id/content_preview_image_area"
+      android:layout_width="wrap_content"
+      android:layout_height="wrap_content"
+      android:layout_gravity="center_horizontal"
+      android:paddingBottom="@dimen/chooser_view_spacing"
+      android:background="?attr/colorBackgroundFloating">
+
+    <view class="com.android.internal.app.ChooserActivity$RoundedRectImageView"
+          android:id="@+id/content_preview_image_1_large"
+          android:visibility="gone"
+          android:layout_width="120dp"
+          android:layout_height="140dp"
+          android:layout_alignParentTop="true"
+          android:adjustViewBounds="true"
+          android:gravity="center"
+          android:scaleType="centerCrop"/>
+
+    <view class="com.android.internal.app.ChooserActivity$RoundedRectImageView"
+          android:id="@+id/content_preview_image_2_large"
+          android:visibility="gone"
+          android:layout_width="120dp"
+          android:layout_height="140dp"
+          android:layout_alignParentTop="true"
+          android:layout_toRightOf="@id/content_preview_image_1_large"
+          android:layout_marginLeft="10dp"
+          android:adjustViewBounds="true"
+          android:gravity="center"
+          android:scaleType="centerCrop"/>
+
+    <view class="com.android.internal.app.ChooserActivity$RoundedRectImageView"
+          android:id="@+id/content_preview_image_2_small"
+          android:visibility="gone"
+          android:layout_width="120dp"
+          android:layout_height="65dp"
+          android:layout_alignParentTop="true"
+          android:layout_toRightOf="@id/content_preview_image_1_large"
+          android:layout_marginLeft="10dp"
+          android:adjustViewBounds="true"
+          android:gravity="center"
+          android:scaleType="centerCrop"/>
+
+    <view class="com.android.internal.app.ChooserActivity$RoundedRectImageView"
+          android:id="@+id/content_preview_image_3_small"
+          android:visibility="gone"
+          android:layout_width="120dp"
+          android:layout_height="65dp"
+          android:layout_below="@id/content_preview_image_2_small"
+          android:layout_toRightOf="@id/content_preview_image_1_large"
+          android:layout_marginLeft="10dp"
+          android:layout_marginTop="10dp"
+          android:adjustViewBounds="true"
+          android:gravity="center"
+          android:scaleType="centerCrop"/>
+
+  </RelativeLayout>
+</LinearLayout>
+
diff --git a/core/res/res/layout/chooser_grid_preview_text.xml b/core/res/res/layout/chooser_grid_preview_text.xml
new file mode 100644
index 0000000..7cfbb1b
--- /dev/null
+++ b/core/res/res/layout/chooser_grid_preview_text.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright 2019, 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.
+*/
+-->
+<!-- Layout Option: Text preview, with optional title and thumbnail -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/content_preview_text_area"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:paddingBottom="@dimen/chooser_view_spacing"
+    android:background="?attr/colorBackgroundFloating">
+
+  <LinearLayout
+      android:layout_width="@dimen/chooser_preview_width"
+      android:layout_height="wrap_content"
+      android:layout_gravity="center"
+      android:orientation="horizontal"
+      android:paddingLeft="@dimen/chooser_edge_margin_normal"
+      android:paddingRight="@dimen/chooser_edge_margin_normal"
+      android:layout_marginBottom="@dimen/chooser_view_spacing"
+      android:id="@+id/content_preview_text_layout">
+    <TextView
+        android:id="@+id/content_preview_text"
+        android:layout_width="0dp"
+        android:layout_weight="1"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        android:ellipsize="end"
+        android:gravity="start|top"
+        android:paddingRight="24dp"
+        android:maxLines="2"/>
+    <Button
+        android:id="@+id/copy_button"
+        android:layout_width="24dp"
+        android:layout_height="24dp"
+        android:gravity="center"
+        android:layout_gravity="center_vertical"
+        android:background="@drawable/ic_content_copy_gm2"/>
+  </LinearLayout>
+
+  <!-- Required sub-layout so we can get the nice rounded corners-->
+  <!-- around this section -->
+  <LinearLayout
+      android:layout_width="@dimen/chooser_preview_width"
+      android:layout_height="wrap_content"
+      android:layout_gravity="center"
+      android:orientation="horizontal"
+      android:layout_marginLeft="@dimen/chooser_edge_margin_thin"
+      android:layout_marginRight="@dimen/chooser_edge_margin_thin"
+      android:minHeight="80dp"
+      android:background="@drawable/chooser_content_preview_rounded"
+      android:id="@+id/content_preview_title_layout">
+
+    <view class="com.android.internal.app.ChooserActivity$RoundedRectImageView"
+          android:id="@+id/content_preview_thumbnail"
+          android:layout_width="75dp"
+          android:layout_height="75dp"
+          android:layout_marginRight="16dp"
+          android:adjustViewBounds="true"
+          android:layout_gravity="center_vertical"
+          android:gravity="center"
+          android:scaleType="centerCrop"/>
+
+    <TextView
+        android:id="@+id/content_preview_title"
+        android:layout_width="0dp"
+        android:layout_weight="1"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        android:ellipsize="end"
+        android:maxLines="2"
+        android:textAppearance="?attr/textAppearanceMedium"/>
+  </LinearLayout>
+</LinearLayout>
+
diff --git a/core/java/android/net/NetworkParcelable.aidl b/core/res/res/layout/chooser_row_direct_share.xml
similarity index 62%
rename from core/java/android/net/NetworkParcelable.aidl
rename to core/res/res/layout/chooser_row_direct_share.xml
index c26352e..d7e36ee 100644
--- a/core/java/android/net/NetworkParcelable.aidl
+++ b/core/res/res/layout/chooser_row_direct_share.xml
@@ -1,6 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
 /*
-**
-** Copyright (C) 2019 The Android Open Source Project
+** Copyright 2019, 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,9 +15,12 @@
 ** 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:orientation="vertical"
+                android:layout_width="match_parent"
+                android:layout_height="200dp">
 
-package android.net;
+</LinearLayout>
 
-parcelable NetworkParcelable {
-    long networkHandle;
-}
+
diff --git a/core/res/res/layout/resolve_list_item.xml b/core/res/res/layout/resolve_list_item.xml
index 5d52832..0bdb25a 100644
--- a/core/res/res/layout/resolve_list_item.xml
+++ b/core/res/res/layout/resolve_list_item.xml
@@ -29,8 +29,8 @@
     <!-- Activity icon when presenting dialog
          Size will be filled in by ResolverActivity -->
     <ImageView android:id="@+id/icon"
-               android:layout_width="24dp"
-               android:layout_height="24dp"
+               android:layout_width="@dimen/resolver_icon_size"
+               android:layout_height="@dimen/resolver_icon_size"
                android:layout_gravity="start|center_vertical"
                android:layout_marginStart="?attr/listPreferredItemPaddingStart"
                android:layout_marginTop="12dp"
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index 8f2d6c3..f058985 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -175,13 +175,7 @@
     </array>
 
     <!-- Used in ResolverTargetActionsDialogFragment -->
-    <string-array name="resolver_target_actions_pin">
-        <item>@string/pin_target</item>
-        <item>@string/app_info</item>
-    </string-array>
-
-    <string-array name="resolver_target_actions_unpin">
-        <item>@string/unpin_target</item>
+    <string-array name="resolver_target_actions">
         <item>@string/app_info</item>
     </string-array>
 
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index bfb6d24..71e071c 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3306,6 +3306,9 @@
          where the user can launch other applications from.  -->
     <bool name="config_noHomeScreen">false</bool>
 
+    <!-- True if the device supports system decorations on secondary displays. -->
+    <bool name="config_supportsSystemDecorsOnSecondaryDisplays">true</bool>
+
     <!-- True if the device requires AppWidgetService even if it does not have
          the PackageManager.FEATURE_APP_WIDGETS feature -->
     <bool name="config_enableAppWidgetService">false</bool>
@@ -3513,6 +3516,12 @@
     -->
     <string name="config_defaultAttentionService" translatable="false"></string>
 
+    <!-- The component name for the system-wide captions service.
+         This service must be trusted, as it controls part of the UI of the volume bar.
+         Example: "com.android.captions/.SystemCaptionsService"
+    -->
+    <string name="config_defaultSystemCaptionsService" translatable="false"></string>
+
     <!-- The package name for the incident report approver app.
         This app is usually PermissionController or an app that replaces it.  When
         a bugreport or incident report with EXPLICT-level sharing flags is going to be
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index fafd8fe..7134eed 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -723,4 +723,6 @@
     <dimen name="chooser_edge_margin_normal">24dp</dimen>
     <dimen name="chooser_preview_image_font_size">20sp</dimen>
     <dimen name="chooser_preview_width">-1px</dimen>
+    <dimen name="resolver_icon_size">42dp</dimen>
+    <dimen name="resolver_badge_size">18dp</dimen>
 </resources>
diff --git a/core/res/res/values/dimens_car.xml b/core/res/res/values/dimens_car.xml
index 5014a29..d2cf40a 100644
--- a/core/res/res/values/dimens_car.xml
+++ b/core/res/res/values/dimens_car.xml
@@ -102,4 +102,7 @@
     <!-- Progress Bar -->
     <dimen name="car_progress_bar_height">@dimen/car_seekbar_height</dimen>
 
+    <!-- TextView -->
+    <dimen name="car_textview_fading_edge_length">40dp</dimen>
+
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index a69655a..74970e8 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -525,8 +525,8 @@
     <!-- label for screenshot item in power menu -->
     <string name="global_action_screenshot">Screenshot</string>
 
-    <!-- Take bug report menu title [CHAR LIMIT=NONE] -->
-    <string name="bugreport_title">Take bug report</string>
+    <!-- Take bug report menu title [CHAR LIMIT=20] -->
+    <string name="bugreport_title">Bug report</string>
     <!-- Message in bugreport dialog describing what it does [CHAR LIMIT=NONE] -->
     <!-- TODO: remove if not used anymore -->
     <string name="bugreport_message">This will collect information about your
@@ -800,7 +800,9 @@
     <string name="permgroupdesc_visual">access your photos &amp; videos</string>
     <!-- Message shown to the user when the apps requests permission from this group. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
     <string name="permgrouprequest_visual">Allow
-        &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your photos and videos, including tagged locations?</string>
+        &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your photos and videos?</string>
+    <!-- Subtitle of the message shown to the user when the apps requests permission to access photos and videos [CHAR LIMIT=150]-->
+    <string name="permgrouprequestdetail_visual">Locations and other people in your photos and videos can be identified by the app</string>
 
     <!-- Title for the capability of an accessibility service to retrieve window content. -->
     <string name="capability_title_canRetrieveWindowContent">Retrieve window content</string>
@@ -1536,43 +1538,45 @@
     <string name="permdesc_useFaceAuthentication">Allows the app to use face authentication hardware for authentication</string>
 
     <!-- Message shown during face acquisition when the face cannot be recognized [CHAR LIMIT=50] -->
-    <string name="face_acquired_insufficient">Couldn\u2019t process face. Please try again.</string>
+    <string name="face_acquired_insufficient">Couldn\u2019t capture accurate face data. Try again.</string>
     <!-- Message shown during face acquisition when the image is too bright [CHAR LIMIT=50] -->
-    <string name="face_acquired_too_bright">Face is too bright. Please try in lower light.</string>
+    <string name="face_acquired_too_bright">Too bright. Try gentler lighting.</string>
     <!-- Message shown during face acquisition when the image is too dark [CHAR LIMIT=50] -->
-    <string name="face_acquired_too_dark">Face is too dark. Please uncover light source.</string>
+    <string name="face_acquired_too_dark">Too dark. Try brighter lighting.</string>
     <!-- Message shown during face acquisition when the user is too close to sensor [CHAR LIMIT=50] -->
-    <string name="face_acquired_too_close">Please move sensor farther from face.</string>
+    <string name="face_acquired_too_close">Move phone farther away.</string>
     <!-- Message shown during face acquisition when the user is too far from sensor [CHAR LIMIT=50] -->
-    <string name="face_acquired_too_far">Please bring sensor closer to face.</string>
+    <string name="face_acquired_too_far">Move phone closer.</string>
     <!-- Message shown during face acquisition when the user is too high relatively to sensor [CHAR LIMIT=50] -->
-    <string name="face_acquired_too_high">Please move sensor higher.</string>
+    <string name="face_acquired_too_high">Move phone higher.</string>
     <!-- Message shown during face acquisition when the user is too low relatively to sensor [CHAR LIMIT=50] -->
-    <string name="face_acquired_too_low">Please move sensor lower.</string>
+    <string name="face_acquired_too_low">Move phone lower.</string>
     <!-- Message shown during face acquisition when the user is too right relatively to sensor [CHAR LIMIT=50] -->
-    <string name="face_acquired_too_right">Please move sensor to the right.</string>
+    <string name="face_acquired_too_right">Move phone to the right.</string>
     <!-- Message shown during face acquisition when the user is too left relatively to sensor [CHAR LIMIT=50] -->
-    <string name="face_acquired_too_left">Please move sensor to the left.</string>
+    <string name="face_acquired_too_left">Move phone to the left.</string>
     <!-- Message shown during face acquisition when the user is not front facing the sensor [CHAR LIMIT=50] -->
-    <string name="face_acquired_poor_gaze">Please look at the sensor.</string>
+    <string name="face_acquired_poor_gaze">Look at the screen with your eyes open.</string>
     <!-- Message shown during face acquisition when the user is not detected [CHAR LIMIT=50] -->
-    <string name="face_acquired_not_detected">No face detected.</string>
+    <string name="face_acquired_not_detected">Can\u2019t see your face. Look at the phone.</string>
     <!-- Message shown during face acquisition when the device is not steady [CHAR LIMIT=50] -->
-    <string name="face_acquired_too_much_motion">Too much motion.</string>
+    <string name="face_acquired_too_much_motion">Too much motion. Hold phone steady.</string>
     <!-- Message shown during face acquisition when the sensor needs to be recalibrated [CHAR LIMIT=50] -->
     <string name="face_acquired_recalibrate">Please re-enroll your face.</string>
     <!-- Message shown during face enrollment when a different person's face is detected [CHAR LIMIT=50] -->
-    <string name="face_acquired_too_different">Different face detected.</string>
+    <string name="face_acquired_too_different">No longer able to recognize face. Try again.</string>
     <!-- Message shown during face enrollment when the face is too similar to a previous acquisition [CHAR LIMIT=50] -->
     <string name="face_acquired_too_similar">Too similar, please change your pose.</string>
     <!-- Message shown during acqusition when the user's face is turned too far left or right [CHAR LIMIT=50] -->
-    <string name="face_acquired_pan_too_extreme">Please look more directly at the camera.</string>
+    <string name="face_acquired_pan_too_extreme">Please look more directly at the screen.</string>
     <!-- Message shown during acqusition when the user's face is tilted too high or too low [CHAR LIMIT=50] -->
-    <string name="face_acquired_tilt_too_extreme">Please look more directly at the camera.</string>
+    <string name="face_acquired_tilt_too_extreme">Please look more directly at the screen.</string>
     <!-- Message shown during acquisiton when the user's face is tilted too far left or right [CHAR LIMIT=50] -->
     <string name="face_acquired_roll_too_extreme">Please straighten your head vertically.</string>
     <!-- Message shown during acquisition when the user's face is obscured [CHAR LIMIT=50] -->
-    <string name="face_acquired_obscured">Please uncover your face.</string>
+    <string name="face_acquired_obscured">Clear the space between your head and the phone.</string>
+    <!-- Message shown during acquisition when the sensor is dirty [CHAR LIMIT=50] -->
+    <string name="face_acquired_sensor_dirty">Please clean the camera.</string>
     <!-- Array containing custom messages shown during face acquisition from vendor.  Vendor is expected to add and translate these strings -->
     <string-array name="face_acquired_vendor">
     </string-array>
@@ -3372,9 +3376,9 @@
     <string name="wifi_available_action_all_networks">All networks</string>
 
     <!-- Notification title for a connection to a app suggested wireless network.-->
-    <string name="wifi_suggestion_title">A Wi\u2011Fi network proposed by <xliff:g id="name" example="App123">%s</xliff:g> is available</string>
+    <string name="wifi_suggestion_title">Connect to Wi\u2011Fi networks?</string>
     <!-- Notification content for a connection to a app suggested wireless network.-->
-    <string name="wifi_suggestion_content">Do you want to connect to networks proposed by <xliff:g id="name" example="App123">%s</xliff:g>?</string>
+    <string name="wifi_suggestion_content">Suggested by <xliff:g id="name" example="App123">%s</xliff:g></string>
     <!-- Notification action for allowing app specified in the notification body.-->
     <string name="wifi_suggestion_action_allow_app">Yes</string>
     <!-- Notification action for disallowing app specified in the notification body.-->
@@ -3600,6 +3604,11 @@
     <string name="adb_active_notification_message">Tap to turn off USB debugging</string>
     <string name="adb_active_notification_message" product="tv">Select to disable USB debugging.</string>
 
+    <!-- Title of notification shown when Test Harness Mode is enabled. [CHAR LIMIT=NONE] -->
+    <string name="test_harness_mode_notification_title">Test Harness Mode enabled</string>
+    <!-- Message of notification shown when Test Harness Mode is enabled. [CHAR LIMIT=NONE] -->
+    <string name="test_harness_mode_notification_message">Perform a factory reset to disable Test Harness Mode.</string>
+
     <!-- Title of notification shown when contaminant is detected on the USB port. [CHAR LIMIT=NONE] -->
     <string name="usb_contaminant_detected_title">Liquid or debris in USB port</string>
     <!-- Message of notification shown when contaminant is detected on the USB port. [CHAR LIMIT=NONE] -->
@@ -5046,12 +5055,6 @@
     <string name="usb_mtp_launch_notification_description">Tap to view files</string>
 
     <!-- Resolver target actions strings -->
-
-    <!-- Pin (as in to a bulletin board with a pushpin) a resolver
-         target to the front of the list. -->
-    <string name="pin_target">Pin</string>
-    <!-- Unpin a resolver target such that it sorts normally. -->
-    <string name="unpin_target">Unpin</string>
     <!-- View application info for a target. -->
     <string name="app_info">App info</string>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 69def5b..17ccc31 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -390,6 +390,7 @@
   <java-symbol type="bool" name="config_supportsSplitScreenMultiWindow" />
   <java-symbol type="bool" name="config_supportsMultiDisplay" />
   <java-symbol type="bool" name="config_noHomeScreen" />
+  <java-symbol type="bool" name="config_supportsSystemDecorsOnSecondaryDisplays" />
   <java-symbol type="bool" name="config_guestUserEphemeral" />
   <java-symbol type="bool" name="config_localDisplaysMirrorContent" />
   <java-symbol type="bool" name="config_localDisplaysPrivate" />
@@ -2060,6 +2061,8 @@
   <java-symbol type="string" name="accessibility_binding_label" />
   <java-symbol type="string" name="adb_active_notification_message" />
   <java-symbol type="string" name="adb_active_notification_title" />
+  <java-symbol type="string" name="test_harness_mode_notification_title" />
+  <java-symbol type="string" name="test_harness_mode_notification_message" />
   <java-symbol type="string" name="taking_remote_bugreport_notification_title" />
   <java-symbol type="string" name="share_remote_bugreport_notification_title" />
   <java-symbol type="string" name="sharing_remote_bugreport_notification_title" />
@@ -2543,6 +2546,7 @@
   <java-symbol type="string" name="face_acquired_tilt_too_extreme" />
   <java-symbol type="string" name="face_acquired_roll_too_extreme" />
   <java-symbol type="string" name="face_acquired_obscured" />
+  <java-symbol type="string" name="face_acquired_sensor_dirty" />
   <java-symbol type="array" name="face_acquired_vendor" />
   <java-symbol type="string" name="face_name_template" />
   <java-symbol type="string" name="face_authenticated_no_confirmation_required" />
@@ -2762,6 +2766,9 @@
   <java-symbol type="dimen" name="chooser_preview_image_font_size"/>
   <java-symbol type="dimen" name="chooser_preview_width" />
   <java-symbol type="layout" name="chooser_grid" />
+  <java-symbol type="layout" name="chooser_grid_preview_text" />
+  <java-symbol type="layout" name="chooser_grid_preview_image" />
+  <java-symbol type="layout" name="chooser_grid_preview_file" />
   <java-symbol type="id" name="chooser_row_text_option" />
   <java-symbol type="dimen" name="chooser_row_text_option_translate" />
   <java-symbol type="layout" name="resolve_grid_item" />
@@ -2770,6 +2777,7 @@
   <java-symbol type="drawable" name="scroll_indicator_material" />
 
   <java-symbol type="layout" name="chooser_row" />
+  <java-symbol type="layout" name="chooser_row_direct_share" />
   <java-symbol type="id" name="target_badge" />
   <java-symbol type="bool" name="config_supportDoubleTapWake" />
   <java-symbol type="drawable" name="ic_perm_device_info" />
@@ -2989,8 +2997,7 @@
   <java-symbol type="color" name="notification_material_background_color" />
 
   <!-- Resolver target actions -->
-  <java-symbol type="array" name="resolver_target_actions_pin" />
-  <java-symbol type="array" name="resolver_target_actions_unpin" />
+  <java-symbol type="array" name="resolver_target_actions" />
 
   <java-symbol type="array" name="non_removable_euicc_slots" />
 
@@ -3382,6 +3389,7 @@
   <java-symbol type="string" name="config_defaultAppPredictionService" />
   <java-symbol type="string" name="config_defaultContentSuggestionsService" />
   <java-symbol type="string" name="config_defaultAttentionService" />
+  <java-symbol type="string" name="config_defaultSystemCaptionsService" />
 
   <java-symbol type="string" name="notification_channel_foreground_service" />
   <java-symbol type="string" name="foreground_service_app_in_background" />
@@ -3674,6 +3682,7 @@
   <java-symbol type="array" name="config_displayWhiteBalanceAmbientColorTemperatures" />
   <java-symbol type="array" name="config_displayWhiteBalanceDisplayColorTemperatures" />
   <java-symbol type="drawable" name="ic_action_open" />
+  <java-symbol type="drawable" name="ic_menu_copy_material" />
 
   <!-- MIME types -->
   <java-symbol type="string" name="mime_type_folder" />
@@ -3700,4 +3709,9 @@
 
   <!-- For Auto-Brightness -->
   <java-symbol type="string" name="config_displayLightSensorType" />
+
+  <java-symbol type="drawable" name="iconfactory_adaptive_icon_drawable_wrapper"/>
+  <java-symbol type="dimen" name="resolver_icon_size"/>
+  <java-symbol type="dimen" name="resolver_badge_size"/>
+
 </resources>
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index 3791305..9955c51 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -55,6 +55,7 @@
     <uses-permission android:name="android.permission.GET_PACKAGE_SIZE" />
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.INJECT_EVENTS" />
+    <uses-permission android:name="android.permission.MANAGE_APP_PREDICTIONS"/>
     <uses-permission android:name="android.permission.READ_CONTACTS" />
     <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
     <uses-permission android:name="android.permission.READ_DREAM_STATE" />
diff --git a/core/tests/coretests/src/android/content/pm/AndroidHidlUpdaterTest.java b/core/tests/coretests/src/android/content/pm/AndroidHidlUpdaterTest.java
index 9b360db..cc48239 100644
--- a/core/tests/coretests/src/android/content/pm/AndroidHidlUpdaterTest.java
+++ b/core/tests/coretests/src/android/content/pm/AndroidHidlUpdaterTest.java
@@ -42,8 +42,17 @@
         PackageBuilder before = builder()
                 .targetSdkVersion(Build.VERSION_CODES.P);
 
+        // no change, not system
+        checkBackwardsCompatibility(before, before);
+    }
+
+    @Test
+    public void targeted_at_P_system() {
+        PackageBuilder before = builder().asSystemApp()
+                .targetSdkVersion(Build.VERSION_CODES.P);
+
         // Should add both HIDL libraries
-        PackageBuilder after = builder()
+        PackageBuilder after = builder().asSystemApp()
                 .targetSdkVersion(Build.VERSION_CODES.P)
                 .requiredLibraries(ANDROID_HIDL_MANAGER, ANDROID_HIDL_BASE);
 
@@ -56,9 +65,19 @@
                 .targetSdkVersion(Build.VERSION_CODES.P)
                 .requiredLibraries(OTHER_LIBRARY);
 
+        // no change, not system
+        checkBackwardsCompatibility(before, before);
+    }
+
+    @Test
+    public void targeted_at_P_not_empty_usesLibraries_system() {
+        PackageBuilder before = builder().asSystemApp()
+                .targetSdkVersion(Build.VERSION_CODES.P)
+                .requiredLibraries(OTHER_LIBRARY);
+
         // The hidl jars should be added at the start of the list because it
         // is not on the bootclasspath and the package targets pre-P.
-        PackageBuilder after = builder()
+        PackageBuilder after = builder().asSystemApp()
                 .targetSdkVersion(Build.VERSION_CODES.P)
                 .requiredLibraries(ANDROID_HIDL_MANAGER, ANDROID_HIDL_BASE, OTHER_LIBRARY);
 
@@ -71,8 +90,21 @@
                 .targetSdkVersion(Build.VERSION_CODES.P)
                 .requiredLibraries(ANDROID_HIDL_MANAGER, ANDROID_HIDL_BASE);
 
-        // No change is required because although the HIDL libraries has been removed from
-        // the bootclasspath the package explicitly requests it.
+        PackageBuilder after = builder()
+                .targetSdkVersion(Build.VERSION_CODES.P);
+
+        // Libraries are removed because they are not available for non-system apps
+        checkBackwardsCompatibility(before, after);
+    }
+
+    @Test
+    public void targeted_at_P_in_usesLibraries_system() {
+        PackageBuilder before = builder().asSystemApp()
+                .targetSdkVersion(Build.VERSION_CODES.P)
+                .requiredLibraries(ANDROID_HIDL_MANAGER, ANDROID_HIDL_BASE);
+
+        // No change is required because the package explicitly requests the HIDL libraries
+        // and is targeted at the current version so does not need backwards compatibility.
         checkBackwardsCompatibility(before, before);
     }
 
@@ -83,8 +115,7 @@
         // Dependency is removed, it is not available.
         PackageBuilder after = builder();
 
-        // No change is required because the package explicitly requests the HIDL libraries
-        // and is targeted at the current version so does not need backwards compatibility.
+        // Libraries are removed because they are not available for apps targetting Q+
         checkBackwardsCompatibility(before, after);
     }
 
@@ -95,8 +126,7 @@
         // Dependency is removed, it is not available.
         PackageBuilder after = builder();
 
-        // No change is required because the package explicitly requests the HIDL libraries
-        // and is targeted at the current version so does not need backwards compatibility.
+        // Libraries are removed because they are not available for apps targetting Q+
         checkBackwardsCompatibility(before, after);
     }
 
diff --git a/core/tests/coretests/src/android/content/pm/PackageBuilder.java b/core/tests/coretests/src/android/content/pm/PackageBuilder.java
index c5db962..f7544af 100644
--- a/core/tests/coretests/src/android/content/pm/PackageBuilder.java
+++ b/core/tests/coretests/src/android/content/pm/PackageBuilder.java
@@ -31,6 +31,8 @@
 
     private int mTargetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
 
+    private int mFlags = 0;
+
     private ArrayList<String> mRequiredLibraries;
 
     private ArrayList<String> mOptionalLibraries;
@@ -42,6 +44,7 @@
     public PackageParser.Package build() {
         PackageParser.Package pkg = new PackageParser.Package("org.package.name");
         pkg.applicationInfo.targetSdkVersion = mTargetSdkVersion;
+        pkg.applicationInfo.flags = mFlags;
         pkg.usesLibraries = mRequiredLibraries;
         pkg.usesOptionalLibraries = mOptionalLibraries;
         return pkg;
@@ -52,6 +55,11 @@
         return this;
     }
 
+    PackageBuilder asSystemApp() {
+        this.mFlags |= ApplicationInfo.FLAG_SYSTEM;
+        return this;
+    }
+
     PackageBuilder requiredLibraries(String... names) {
         this.mRequiredLibraries = arrayListOrNull(names);
         return this;
diff --git a/core/tests/coretests/src/android/provider/DeviceConfigTest.java b/core/tests/coretests/src/android/provider/DeviceConfigTest.java
index 04fa524..7a4fa3a 100644
--- a/core/tests/coretests/src/android/provider/DeviceConfigTest.java
+++ b/core/tests/coretests/src/android/provider/DeviceConfigTest.java
@@ -61,6 +61,26 @@
     }
 
     @Test
+    public void getProperty_nullNamespace() {
+        try {
+            DeviceConfig.getProperty(null, sKey);
+            Assert.fail("Null namespace should have resulted in an NPE.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void getProperty_nullName() {
+        try {
+            DeviceConfig.getProperty(sNamespace, null);
+            Assert.fail("Null name should have resulted in an NPE.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    @Test
     public void getString_empty() {
         final String default_value = "default_value";
         final String result = DeviceConfig.getString(sNamespace, sKey, default_value);
@@ -68,6 +88,12 @@
     }
 
     @Test
+    public void getString_nullDefault() {
+        final String result = DeviceConfig.getString(sNamespace, sKey, null);
+        assertThat(result).isNull();
+    }
+
+    @Test
     public void getString_nonEmpty() {
         final String value = "new_value";
         final String default_value = "default";
@@ -78,6 +104,26 @@
     }
 
     @Test
+    public void getString_nullNamespace() {
+        try {
+            DeviceConfig.getString(null, sKey, "default_value");
+            Assert.fail("Null namespace should have resulted in an NPE.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void getString_nullName() {
+        try {
+            DeviceConfig.getString(sNamespace, null, "default_value");
+            Assert.fail("Null name should have resulted in an NPE.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    @Test
     public void getBoolean_empty() {
         final boolean default_value = true;
         final boolean result = DeviceConfig.getBoolean(sNamespace, sKey, default_value);
@@ -105,6 +151,26 @@
     }
 
     @Test
+    public void getBoolean_nullNamespace() {
+        try {
+            DeviceConfig.getBoolean(null, sKey, false);
+            Assert.fail("Null namespace should have resulted in an NPE.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void getBoolean_nullName() {
+        try {
+            DeviceConfig.getBoolean(sNamespace, null, false);
+            Assert.fail("Null name should have resulted in an NPE.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    @Test
     public void getInt_empty() {
         final int default_value = 999;
         final int result = DeviceConfig.getInt(sNamespace, sKey, default_value);
@@ -132,6 +198,26 @@
     }
 
     @Test
+    public void getInt_nullNamespace() {
+        try {
+            DeviceConfig.getInt(null, sKey, 0);
+            Assert.fail("Null namespace should have resulted in an NPE.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void getInt_nullName() {
+        try {
+            DeviceConfig.getInt(sNamespace, null, 0);
+            Assert.fail("Null name should have resulted in an NPE.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    @Test
     public void getLong_empty() {
         final long default_value = 123456;
         final long result = DeviceConfig.getLong(sNamespace, sKey, default_value);
@@ -159,6 +245,26 @@
     }
 
     @Test
+    public void getLong_nullNamespace() {
+        try {
+            DeviceConfig.getLong(null, sKey, 0);
+            Assert.fail("Null namespace should have resulted in an NPE.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void getLong_nullName() {
+        try {
+            DeviceConfig.getLong(sNamespace, null, 0);
+            Assert.fail("Null name should have resulted in an NPE.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    @Test
     public void getFloat_empty() {
         final float default_value = 123.456f;
         final float result = DeviceConfig.getFloat(sNamespace, sKey, default_value);
@@ -186,6 +292,46 @@
     }
 
     @Test
+    public void getFloat_nullNamespace() {
+        try {
+            DeviceConfig.getFloat(null, sKey, 0);
+            Assert.fail("Null namespace should have resulted in an NPE.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void getFloat_nullName() {
+        try {
+            DeviceConfig.getFloat(sNamespace, null, 0);
+            Assert.fail("Null name should have resulted in an NPE.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void setProperty_nullNamespace() {
+        try {
+            DeviceConfig.setProperty(null, sKey, sValue, false);
+            Assert.fail("Null namespace should have resulted in an NPE.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void setProperty_nullName() {
+        try {
+            DeviceConfig.setProperty(sNamespace, null, sValue, false);
+            Assert.fail("Null name should have resulted in an NPE.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    @Test
     public void setAndGetProperty_sameNamespace() {
         DeviceConfig.setProperty(sNamespace, sKey, sValue, false);
         String result = DeviceConfig.getProperty(sNamespace, sKey);
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 43f8db1..7322a54 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -655,6 +655,7 @@
                  Settings.Secure.NIGHT_DISPLAY_ACTIVATED,
                  Settings.Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME,
                  Settings.Secure.NUM_ROTATION_SUGGESTIONS_ACCEPTED,
+                 Settings.Secure.ODI_CAPTIONS_ENABLED,
                  Settings.Secure.PACKAGE_VERIFIER_STATE,
                  Settings.Secure.PACKAGE_VERIFIER_USER_CONSENT,
                  Settings.Secure.PARENTAL_CONTROL_LAST_UPDATE,
diff --git a/core/tests/coretests/src/android/text/StaticLayoutTest.java b/core/tests/coretests/src/android/text/StaticLayoutTest.java
index b1c896e..0ebf03f 100644
--- a/core/tests/coretests/src/android/text/StaticLayoutTest.java
+++ b/core/tests/coretests/src/android/text/StaticLayoutTest.java
@@ -22,6 +22,7 @@
 import static org.junit.Assert.assertTrue;
 
 import android.graphics.Canvas;
+import android.graphics.Paint;
 import android.graphics.Paint.FontMetricsInt;
 import android.os.LocaleList;
 import android.platform.test.annotations.Presubmit;
@@ -799,11 +800,13 @@
     @Test
     public void testLayoutDoesntModifyPaint() {
         final TextPaint paint = new TextPaint();
-        paint.setHyphenEdit(31);
+        paint.setStartHyphenEdit(Paint.START_HYPHEN_EDIT_INSERT_HYPHEN);
+        paint.setEndHyphenEdit(Paint.END_HYPHEN_EDIT_INSERT_HYPHEN);
         final StaticLayout layout = StaticLayout.Builder.obtain("", 0, 0, paint, 100).build();
         final Canvas canvas = new Canvas();
         layout.drawText(canvas, 0, 0);
-        assertEquals(31, paint.getHyphenEdit());
+        assertEquals(Paint.START_HYPHEN_EDIT_INSERT_HYPHEN, paint.getStartHyphenEdit());
+        assertEquals(Paint.END_HYPHEN_EDIT_INSERT_HYPHEN, paint.getEndHyphenEdit());
     }
 
     @Test
diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureContextTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureContextTest.java
new file mode 100644
index 0000000..4680a64
--- /dev/null
+++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureContextTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.view.contentcapture;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.ComponentName;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Unit test for {@link ContentCaptureEvent}.
+ *
+ * <p>To run it:
+ * {@code atest FrameworksCoreTests:android.view.contentcapture.ContentCaptureContextTest}
+ */
+@RunWith(JUnit4.class)
+public class ContentCaptureContextTest {
+
+    @Test
+    public void testConstructorAdditionalFlags() {
+        final ComponentName componentName = new ComponentName("component", "name");
+        final ContentCaptureContext ctx = new ContentCaptureContext(/* clientContext= */ null,
+                componentName, /* taskId= */ 666, /* displayId= */ 42, /* flags= */ 1);
+        final ContentCaptureContext newCtx = new ContentCaptureContext(ctx, /* extraFlags= */ 2);
+        assertThat(newCtx.getFlags()).isEqualTo(3);
+
+        assertThat(newCtx.getActivityComponent()).isEqualTo(componentName);
+        assertThat(newCtx.getTaskId()).isEqualTo(666);
+        assertThat(newCtx.getDisplayId()).isEqualTo(42);
+        assertThat(newCtx.getExtras()).isNull();
+        assertThat(newCtx.getLocusId()).isNull();
+        assertThat(newCtx.getParentSessionId()).isNull();
+    }
+}
diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java
index de2edc3..2416de1 100644
--- a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java
+++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java
@@ -19,6 +19,7 @@
 import static android.view.contentcapture.ContentCaptureEvent.TYPE_SESSION_FINISHED;
 import static android.view.contentcapture.ContentCaptureEvent.TYPE_SESSION_STARTED;
 import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_DISAPPEARED;
+import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_TEXT_CHANGED;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -230,6 +231,68 @@
         assertContextUpdatedEvent(clone);
     }
 
+    @Test
+    public void testMergeEvent_typeViewTextChanged() {
+        final ContentCaptureEvent event = new ContentCaptureEvent("42", TYPE_VIEW_TEXT_CHANGED)
+                .setText("test");
+        final ContentCaptureEvent event2 = new ContentCaptureEvent("43", TYPE_VIEW_TEXT_CHANGED)
+                .setText("empty");
+
+        event.mergeEvent(event2);
+        assertThat(event.getText()).isEqualTo(event2.getText());
+    }
+
+    @Test
+    public void testMergeEvent_typeViewDisappeared() {
+        final ContentCaptureEvent event = new ContentCaptureEvent("42", TYPE_VIEW_DISAPPEARED)
+                .setAutofillId(new AutofillId(1));
+        final ContentCaptureEvent event2 = new ContentCaptureEvent("43", TYPE_VIEW_DISAPPEARED)
+                .setAutofillId(new AutofillId(2));
+        final ArrayList<AutofillId> autofillIds = new ArrayList<>();
+        autofillIds.add(new AutofillId(3));
+        autofillIds.add(new AutofillId(4));
+        final ContentCaptureEvent event3 = new ContentCaptureEvent("17", TYPE_VIEW_DISAPPEARED)
+                .setAutofillIds(autofillIds);
+
+        event.mergeEvent(event2);
+        assertThat(event.getIds()).containsExactly(new AutofillId(1), new AutofillId(2));
+
+        event2.mergeEvent(event3);
+        assertThat(event2.getIds()).containsExactly(new AutofillId(2), new AutofillId(3),
+                new AutofillId(4));
+    }
+
+    @Test
+    public void testMergeEvent_typeViewDisappeared_noIds() {
+        final ContentCaptureEvent event = new ContentCaptureEvent("42", TYPE_VIEW_DISAPPEARED)
+                .setAutofillId(new AutofillId(1));
+        final ContentCaptureEvent event2 = new ContentCaptureEvent("43", TYPE_VIEW_DISAPPEARED);
+
+        assertThrows(IllegalArgumentException.class, () -> event.mergeEvent(event2));
+    }
+
+    @Test
+    public void testMergeEvent_nullArgument() {
+        final ContentCaptureEvent event = new ContentCaptureEvent("42", TYPE_VIEW_DISAPPEARED);
+        assertThrows(NullPointerException.class, () -> event.mergeEvent(null));
+    }
+
+    @Test
+    public void testMergeEvent_differentEventTypes() {
+        final ContentCaptureEvent event = new ContentCaptureEvent("42", TYPE_VIEW_DISAPPEARED)
+                .setText("test").setAutofillId(new AutofillId(1));
+        final ContentCaptureEvent event2 = new ContentCaptureEvent("17", TYPE_VIEW_TEXT_CHANGED)
+                .setText("empty").setAutofillId(new AutofillId(2));
+
+        event.mergeEvent(event2);
+        assertThat(event.getText()).isEqualTo("test");
+        assertThat(event.getId()).isEqualTo(new AutofillId(1));
+
+        event2.mergeEvent(event);
+        assertThat(event2.getText()).isEqualTo("empty");
+        assertThat(event2.getId()).isEqualTo(new AutofillId(2));
+    }
+
     private void assertContextUpdatedEvent(ContentCaptureEvent event) {
         assertThat(event.getType()).isEqualTo(TYPE_CONTEXT_UPDATED);
         assertThat(event.getEventTime()).isAtLeast(MY_EPOCH);
diff --git a/core/tests/coretests/src/android/view/textclassifier/ActionsSuggestionsHelperTest.java b/core/tests/coretests/src/android/view/textclassifier/ActionsSuggestionsHelperTest.java
index f440953..5c7287f 100644
--- a/core/tests/coretests/src/android/view/textclassifier/ActionsSuggestionsHelperTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/ActionsSuggestionsHelperTest.java
@@ -27,13 +27,17 @@
 import android.content.ComponentName;
 import android.content.Intent;
 import android.graphics.drawable.Icon;
+import android.net.Uri;
 import android.os.Bundle;
+import android.view.textclassifier.intent.LabeledIntent;
+import android.view.textclassifier.intent.TemplateIntentFactory;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.google.android.textclassifier.ActionsSuggestionsModel;
+import com.google.android.textclassifier.RemoteActionTemplate;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -204,6 +208,77 @@
         assertThat(conversationActions.get(2).getAction()).isNull();
     }
 
+    public void createLabeledIntentResult_null() {
+        ActionsSuggestionsModel.ActionSuggestion nativeSuggestion =
+                new ActionsSuggestionsModel.ActionSuggestion(
+                        "text",
+                        ConversationAction.TYPE_OPEN_URL,
+                        1.0f,
+                        null,
+                        null
+                );
+
+        LabeledIntent.Result labeledIntentResult =
+                ActionsSuggestionsHelper.createLabeledIntentResult(
+                        InstrumentationRegistry.getTargetContext(),
+                        new TemplateIntentFactory(),
+                        nativeSuggestion);
+
+        assertThat(labeledIntentResult).isNull();
+    }
+
+    @Test
+    public void createLabeledIntentResult_emptyList() {
+        ActionsSuggestionsModel.ActionSuggestion nativeSuggestion =
+                new ActionsSuggestionsModel.ActionSuggestion(
+                        "text",
+                        ConversationAction.TYPE_OPEN_URL,
+                        1.0f,
+                        null,
+                        new RemoteActionTemplate[0]
+                );
+
+        LabeledIntent.Result labeledIntentResult =
+                ActionsSuggestionsHelper.createLabeledIntentResult(
+                        InstrumentationRegistry.getTargetContext(),
+                        new TemplateIntentFactory(),
+                        nativeSuggestion);
+
+        assertThat(labeledIntentResult).isNull();
+    }
+
+    @Test
+    public void createLabeledIntentResult() {
+        ActionsSuggestionsModel.ActionSuggestion nativeSuggestion =
+                new ActionsSuggestionsModel.ActionSuggestion(
+                        "text",
+                        ConversationAction.TYPE_OPEN_URL,
+                        1.0f,
+                        null,
+                        new RemoteActionTemplate[]{
+                                new RemoteActionTemplate(
+                                        "title",
+                                        null,
+                                        "description",
+                                        Intent.ACTION_VIEW,
+                                        Uri.parse("http://www.android.com").toString(),
+                                        null,
+                                        0,
+                                        null,
+                                        null,
+                                        null,
+                                        0)});
+
+        LabeledIntent.Result labeledIntentResult =
+                ActionsSuggestionsHelper.createLabeledIntentResult(
+                        InstrumentationRegistry.getTargetContext(),
+                        new TemplateIntentFactory(),
+                        nativeSuggestion);
+
+        assertThat(labeledIntentResult.remoteAction.getTitle()).isEqualTo("title");
+        assertThat(labeledIntentResult.resolvedIntent.getAction()).isEqualTo(Intent.ACTION_VIEW);
+    }
+
     private ZonedDateTime createZonedDateTimeFromMsUtc(long msUtc) {
         return ZonedDateTime.ofInstant(Instant.ofEpochMilli(msUtc), ZoneId.of("UTC"));
     }
@@ -215,7 +290,7 @@
             long referenceTimeInMsUtc) {
         assertThat(nativeMessage.getText()).isEqualTo(text.toString());
         assertThat(nativeMessage.getUserId()).isEqualTo(userId);
-        assertThat(nativeMessage.getLocales()).isEqualTo(LOCALE_TAG);
+        assertThat(nativeMessage.getDetectedTextLanguageTags()).isEqualTo(LOCALE_TAG);
         assertThat(nativeMessage.getReferenceTimeMsUtc()).isEqualTo(referenceTimeInMsUtc);
     }
 }
diff --git a/core/tests/coretests/src/android/view/textclassifier/FakeContextBuilder.java b/core/tests/coretests/src/android/view/textclassifier/FakeContextBuilder.java
index fef6583..2674e37 100644
--- a/core/tests/coretests/src/android/view/textclassifier/FakeContextBuilder.java
+++ b/core/tests/coretests/src/android/view/textclassifier/FakeContextBuilder.java
@@ -44,8 +44,7 @@
 /**
  * A builder used to build a fake context for testing.
  */
-// TODO: Consider making public.
-final class FakeContextBuilder {
+public final class FakeContextBuilder {
 
     /**
      * A component name that can be used for tests.
@@ -57,7 +56,7 @@
     private final Map<String, ComponentName> mComponents = new HashMap<>();
     private @Nullable ComponentName mAllIntentComponent;
 
-    FakeContextBuilder() {
+    public FakeContextBuilder() {
         mPackageManager = mock(PackageManager.class);
         when(mPackageManager.resolveActivity(any(Intent.class), anyInt())).thenReturn(null);
         mContext = new ContextWrapper(InstrumentationRegistry.getTargetContext()) {
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationConstantsTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationConstantsTest.java
index fe2a660..f6bb1bf 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassificationConstantsTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationConstantsTest.java
@@ -21,6 +21,7 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import org.junit.Assert;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -48,7 +49,8 @@
                 + "entity_list_editable=date:datetime,"
                 + "in_app_conversation_action_types_default=text_reply,"
                 + "notification_conversation_action_types_default=send_email:call_phone,"
-                + "lang_id_threshold_override=0.3";
+                + "lang_id_threshold_override=0.3,"
+                + "lang_id_context_settings=10:1:0.5";
         final TextClassificationConstants constants =
                 TextClassificationConstants.loadFromString(s);
 
@@ -91,6 +93,8 @@
                 .containsExactly("send_email", "call_phone");
         assertWithMessage("lang_id_threshold_override")
                 .that(constants.getLangIdThresholdOverride()).isWithin(EPSILON).of(0.3f);
+        Assert.assertArrayEquals("lang_id_context_settings",
+                constants.getLangIdContextSettings(), new float[]{10, 1, 0.5f}, EPSILON);
     }
 
     @Test
@@ -111,7 +115,8 @@
                 + "entity_list_editable=flight,"
                 + "in_app_conversation_action_types_default=view_map:track_flight,"
                 + "notification_conversation_action_types_default=share_location,"
-                + "lang_id_threshold_override=2";
+                + "lang_id_threshold_override=2,"
+                + "lang_id_context_settings=30:0.5:0.3";
         final TextClassificationConstants constants =
                 TextClassificationConstants.loadFromString(s);
 
@@ -154,6 +159,8 @@
                 .containsExactly("share_location");
         assertWithMessage("lang_id_threshold_override")
                 .that(constants.getLangIdThresholdOverride()).isWithin(EPSILON).of(2f);
+        Assert.assertArrayEquals("lang_id_context_settings",
+                constants.getLangIdContextSettings(), new float[]{30, 0.5f, 0.3f}, EPSILON);
     }
 
     @Test
@@ -196,13 +203,15 @@
                 .that(constants.getInAppConversationActionTypes())
                 .containsExactly("text_reply", "create_reminder", "call_phone", "open_url",
                         "send_email", "send_sms", "track_flight", "view_calendar", "view_map",
-                        "add_contact");
+                        "add_contact", "copy");
         assertWithMessage("notification_conversation_action_types_default")
                 .that(constants.getNotificationConversationActionTypes())
                 .containsExactly("text_reply", "create_reminder", "call_phone", "open_url",
                         "send_email", "send_sms", "track_flight", "view_calendar", "view_map",
-                        "add_contact");
+                        "add_contact", "copy");
         assertWithMessage("lang_id_threshold_override")
                 .that(constants.getLangIdThresholdOverride()).isWithin(EPSILON).of(-1f);
+        Assert.assertArrayEquals("lang_id_context_settings",
+                constants.getLangIdContextSettings(), new float[]{20, 1, 0.4f}, EPSILON);
     }
 }
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
index bcaf663..8de5f13 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
@@ -32,6 +32,7 @@
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.google.common.truth.Truth;
 
@@ -41,7 +42,6 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
 
 import java.util.Arrays;
 import java.util.Collections;
@@ -53,22 +53,10 @@
  * Tests are skipped if such a textclassifier does not exist.
  */
 @SmallTest
-@RunWith(Parameterized.class)
+@RunWith(AndroidJUnit4.class)
 public class TextClassifierTest {
-    private static final String LOCAL = "local";
-    private static final String SYSTEM = "system";
 
-    @Parameterized.Parameters(name = "{0}")
-    public static Iterable<Object> textClassifierTypes() {
-        return Arrays.asList(LOCAL);
-
-        // TODO: The following will fail on any device that specifies a no-op TextClassifierService.
-        // Enable when we can set a specified TextClassifierService for testing.
-        // return Arrays.asList(LOCAL, SYSTEM);
-    }
-
-    @Parameterized.Parameter
-    public String mTextClassifierType;
+    // TODO: Implement TextClassifierService testing.
 
     private static final TextClassificationConstants TC_CONSTANTS =
             TextClassificationConstants.loadFromString("");
@@ -83,8 +71,7 @@
     public void setup() {
         mContext = InstrumentationRegistry.getTargetContext();
         mTcm = mContext.getSystemService(TextClassificationManager.class);
-        mClassifier = mTcm.getTextClassifier(
-                mTextClassifierType.equals(LOCAL) ? TextClassifier.LOCAL : TextClassifier.SYSTEM);
+        mClassifier = mTcm.getTextClassifier(TextClassifier.LOCAL);
     }
 
     @Test
@@ -278,6 +265,8 @@
         assertEquals("ja", ExtrasUtils.getEntityType(foreignLanguageInfo));
         assertTrue(ExtrasUtils.getScore(foreignLanguageInfo) >= 0);
         assertTrue(ExtrasUtils.getScore(foreignLanguageInfo) <= 1);
+        assertTrue(intent.hasExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER));
+        assertEquals("ja", ExtrasUtils.getTopLanguage(intent).getLanguage());
 
         LocaleList.setDefault(originalLocales);
     }
@@ -468,6 +457,34 @@
         Truth.assertThat(actionIntent.getData()).isEqualTo(Uri.parse("https://www.android.com"));
     }
 
+    @Test
+    public void testSuggestConversationActions_copy() {
+        if (isTextClassifierDisabled()) return;
+        ConversationActions.Message message =
+                new ConversationActions.Message.Builder(
+                        ConversationActions.Message.PERSON_USER_OTHERS)
+                        .setText("Authentication code: 12345")
+                        .build();
+        TextClassifier.EntityConfig typeConfig =
+                new TextClassifier.EntityConfig.Builder().includeTypesFromTextClassifier(false)
+                        .setIncludedTypes(
+                                Collections.singletonList(ConversationAction.TYPE_COPY))
+                        .build();
+        ConversationActions.Request request =
+                new ConversationActions.Request.Builder(Collections.singletonList(message))
+                        .setMaxSuggestions(1)
+                        .setTypeConfig(typeConfig)
+                        .build();
+
+        ConversationActions conversationActions = mClassifier.suggestConversationActions(request);
+        Truth.assertThat(conversationActions.getConversationActions()).hasSize(1);
+        ConversationAction conversationAction = conversationActions.getConversationActions().get(0);
+        Truth.assertThat(conversationAction.getType()).isEqualTo(ConversationAction.TYPE_COPY);
+        Truth.assertThat(conversationAction.getTextReply()).isAnyOf(null, "");
+        Truth.assertThat(conversationAction.getAction()).isNull();
+        String code = ExtrasUtils.getCopyText(conversationAction.getExtras());
+        Truth.assertThat(code).isEqualTo("12345");
+    }
 
     private boolean isTextClassifierDisabled() {
         return mClassifier == null || mClassifier == TextClassifier.NO_OP;
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassifierUtilsTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassifierUtilsTest.java
new file mode 100644
index 0000000..011866d
--- /dev/null
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassifierUtilsTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.textclassifier;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.assertThrows;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class TextClassifierUtilsTest {
+
+    @Test
+    public void testGetSubString() {
+        final String text = "Yakuza call themselves 任侠団体";
+        int start;
+        int end;
+        int minimumLength;
+
+        // End index at end of text.
+        start = text.indexOf("任侠団体");
+        end = text.length();
+        minimumLength = 20;
+        assertThat(TextClassifier.Utils.getSubString(text, start, end, minimumLength))
+                .isEqualTo("call themselves 任侠団体");
+
+        // Start index at beginning of text.
+        start = 0;
+        end = "Yakuza".length();
+        minimumLength = 15;
+        assertThat(TextClassifier.Utils.getSubString(text, start, end, minimumLength))
+                .isEqualTo("Yakuza call themselves");
+
+        // Text in the middle
+        start = text.indexOf("all");
+        end = start + 1;
+        minimumLength = 10;
+        assertThat(TextClassifier.Utils.getSubString(text, start, end, minimumLength))
+                .isEqualTo("Yakuza call themselves");
+
+        // Selection >= minimumLength.
+        start = text.indexOf("themselves");
+        end = start + "themselves".length();
+        minimumLength = end - start;
+        assertThat(TextClassifier.Utils.getSubString(text, start, end, minimumLength))
+                .isEqualTo("themselves");
+
+        // text.length < minimumLength.
+        minimumLength = text.length() + 1;
+        assertThat(TextClassifier.Utils.getSubString(text, start, end, minimumLength))
+                .isEqualTo(text);
+    }
+
+    @Test
+    public void testGetSubString_invalidParams() {
+        final String text = "The Yoruba regard Olodumare as the principal agent of creation";
+        final int length = text.length();
+        final int minimumLength = 10;
+
+        // Null text
+        assertThrows(() -> TextClassifier.Utils.getSubString(null, 0, 1, minimumLength));
+        // start > end
+        assertThrows(() -> TextClassifier.Utils.getSubString(text, 6, 5, minimumLength));
+        // start < 0
+        assertThrows(() -> TextClassifier.Utils.getSubString(text, -1, 5, minimumLength));
+        // end > text.length
+        assertThrows(() -> TextClassifier.Utils.getSubString(text, 6, length + 1, minimumLength));
+    }
+}
diff --git a/core/tests/coretests/src/android/view/textclassifier/LabeledIntentTest.java b/core/tests/coretests/src/android/view/textclassifier/intent/LabeledIntentTest.java
similarity index 79%
rename from core/tests/coretests/src/android/view/textclassifier/LabeledIntentTest.java
rename to core/tests/coretests/src/android/view/textclassifier/intent/LabeledIntentTest.java
index 6520c8f..857408f 100644
--- a/core/tests/coretests/src/android/view/textclassifier/LabeledIntentTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/intent/LabeledIntentTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.view.textclassifier;
+package android.view.textclassifier.intent;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -23,8 +23,10 @@
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
+import android.os.Bundle;
+import android.view.textclassifier.FakeContextBuilder;
+import android.view.textclassifier.TextClassifier;
 
-import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
@@ -41,11 +43,15 @@
     private static final Intent INTENT =
             new Intent(Intent.ACTION_VIEW).setDataAndNormalize(Uri.parse("http://www.android.com"));
     private static final int REQUEST_CODE = 42;
+    private static final Bundle TEXT_LANGUAGES_BUNDLE = Bundle.EMPTY;
+
     private Context mContext;
 
     @Before
     public void setup() {
-        mContext = InstrumentationRegistry.getTargetContext();
+        mContext = new FakeContextBuilder()
+                .setIntentComponent(Intent.ACTION_VIEW, FakeContextBuilder.DEFAULT_COMPONENT)
+                .build();
     }
 
     @Test
@@ -58,8 +64,8 @@
                 REQUEST_CODE
         );
 
-        LabeledIntent.Result result =
-                labeledIntent.resolve(mContext, /*titleChooser*/ null);
+        LabeledIntent.Result result = labeledIntent.resolve(
+                mContext, /*titleChooser*/ null, TEXT_LANGUAGES_BUNDLE);
 
         assertThat(result).isNotNull();
         assertThat(result.remoteAction.getTitle()).isEqualTo(TITLE_WITH_ENTITY);
@@ -67,6 +73,7 @@
         Intent intent = result.resolvedIntent;
         assertThat(intent.getAction()).isEqualTo(intent.getAction());
         assertThat(intent.getComponent()).isNotNull();
+        assertThat(intent.hasExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER)).isTrue();
     }
 
     @Test
@@ -79,8 +86,8 @@
                 REQUEST_CODE
         );
 
-        LabeledIntent.Result result =
-                labeledIntent.resolve(mContext, /*titleChooser*/ null);
+        LabeledIntent.Result result = labeledIntent.resolve(
+                mContext, /*titleChooser*/ null, TEXT_LANGUAGES_BUNDLE);
 
         assertThat(result).isNotNull();
         assertThat(result.remoteAction.getTitle()).isEqualTo(TITLE_WITHOUT_ENTITY);
@@ -100,8 +107,8 @@
                 REQUEST_CODE
         );
 
-        LabeledIntent.Result result =
-                labeledIntent.resolve(mContext, (labeledIntent1, resolveInfo) -> "chooser");
+        LabeledIntent.Result result = labeledIntent.resolve(
+                mContext, (labeledIntent1, resolveInfo) -> "chooser", TEXT_LANGUAGES_BUNDLE);
 
         assertThat(result).isNotNull();
         assertThat(result.remoteAction.getTitle()).isEqualTo("chooser");
@@ -121,8 +128,8 @@
                 REQUEST_CODE
         );
 
-        LabeledIntent.Result result =
-                labeledIntent.resolve(mContext, (labeledIntent1, resolveInfo) -> null);
+        LabeledIntent.Result result = labeledIntent.resolve(
+                mContext, (labeledIntent1, resolveInfo) -> null, TEXT_LANGUAGES_BUNDLE);
 
         assertThat(result).isNotNull();
         assertThat(result.remoteAction.getTitle()).isEqualTo(TITLE_WITHOUT_ENTITY);
@@ -148,15 +155,16 @@
 
     @Test
     public void resolve_noIntentHandler() {
-        Intent intent = new Intent("some.thing.does.not.exist");
+        // See setup(). mContext can only resolve Intent.ACTION_VIEW.
+        Intent unresolvableIntent = new Intent(Intent.ACTION_TRANSLATE);
         LabeledIntent labeledIntent = new LabeledIntent(
                 TITLE_WITHOUT_ENTITY,
                 null,
                 DESCRIPTION,
-                intent,
+                unresolvableIntent,
                 REQUEST_CODE);
 
-        LabeledIntent.Result result = labeledIntent.resolve(mContext, null);
+        LabeledIntent.Result result = labeledIntent.resolve(mContext, null, null);
 
         assertThat(result).isNull();
     }
diff --git a/core/tests/coretests/src/android/view/textclassifier/LegacyIntentFactoryTest.java b/core/tests/coretests/src/android/view/textclassifier/intent/LegacyIntentClassificationFactoryTest.java
similarity index 83%
rename from core/tests/coretests/src/android/view/textclassifier/LegacyIntentFactoryTest.java
rename to core/tests/coretests/src/android/view/textclassifier/intent/LegacyIntentClassificationFactoryTest.java
index 743818c..19e5b0a 100644
--- a/core/tests/coretests/src/android/view/textclassifier/LegacyIntentFactoryTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/intent/LegacyIntentClassificationFactoryTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2019 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,11 +14,12 @@
  * limitations under the License.
  */
 
-package android.view.textclassifier;
+package android.view.textclassifier.intent;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import android.content.Intent;
+import android.view.textclassifier.TextClassifier;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
@@ -34,15 +35,15 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class LegacyIntentFactoryTest {
+public class LegacyIntentClassificationFactoryTest {
 
     private static final String TEXT = "text";
 
-    private LegacyIntentFactory mLegacyIntentFactory;
+    private LegacyClassificationIntentFactory mLegacyIntentClassificationFactory;
 
     @Before
     public void setup() {
-        mLegacyIntentFactory = new LegacyIntentFactory();
+        mLegacyIntentClassificationFactory = new LegacyClassificationIntentFactory();
     }
 
     @Test
@@ -61,9 +62,10 @@
                         null,
                         null,
                         null,
+                        null,
                         null);
 
-        List<LabeledIntent> intents = mLegacyIntentFactory.create(
+        List<LabeledIntent> intents = mLegacyIntentClassificationFactory.create(
                 InstrumentationRegistry.getContext(),
                 TEXT,
                 /* foreignText */ false,
@@ -75,8 +77,6 @@
         Intent intent = labeledIntent.intent;
         assertThat(intent.getAction()).isEqualTo(Intent.ACTION_DEFINE);
         assertThat(intent.getStringExtra(Intent.EXTRA_TEXT)).isEqualTo(TEXT);
-        assertThat(
-                intent.getBooleanExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER, false)).isTrue();
     }
 
     @Test
@@ -95,9 +95,10 @@
                         null,
                         null,
                         null,
+                        null,
                         null);
 
-        List<LabeledIntent> intents = mLegacyIntentFactory.create(
+        List<LabeledIntent> intents = mLegacyIntentClassificationFactory.create(
                 InstrumentationRegistry.getContext(),
                 TEXT,
                 /* foreignText */ true,
diff --git a/core/tests/coretests/src/android/view/textclassifier/TemplateClassificationIntentFactoryTest.java b/core/tests/coretests/src/android/view/textclassifier/intent/TemplateClassificationIntentFactoryTest.java
similarity index 66%
rename from core/tests/coretests/src/android/view/textclassifier/TemplateClassificationIntentFactoryTest.java
rename to core/tests/coretests/src/android/view/textclassifier/intent/TemplateClassificationIntentFactoryTest.java
index 9fd9e8e..eaef0a0 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TemplateClassificationIntentFactoryTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/intent/TemplateClassificationIntentFactoryTest.java
@@ -14,11 +14,19 @@
  * limitations under the License.
  */
 
-package android.view.textclassifier;
+package android.view.textclassifier.intent;
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.same;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
 import android.content.Intent;
+import android.view.textclassifier.TextClassifier;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
@@ -45,7 +53,7 @@
     private static final String ACTION = Intent.ACTION_VIEW;
 
     @Mock
-    private IntentFactory mFallback;
+    private ClassificationIntentFactory mFallback;
     private TemplateClassificationIntentFactory mTemplateClassificationIntentFactory;
 
     @Before
@@ -72,6 +80,7 @@
                         null,
                         null,
                         null,
+                        null,
                         createRemoteActionTemplates());
 
         List<LabeledIntent> intents =
@@ -87,12 +96,10 @@
         assertThat(labeledIntent.titleWithoutEntity).isEqualTo(TITLE_WITHOUT_ENTITY);
         Intent intent = labeledIntent.intent;
         assertThat(intent.getAction()).isEqualTo(ACTION);
-        assertThat(intent.hasExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER)).isTrue();
 
         labeledIntent = intents.get(1);
         intent = labeledIntent.intent;
         assertThat(intent.getAction()).isEqualTo(Intent.ACTION_TRANSLATE);
-        assertThat(intent.hasExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER)).isTrue();
     }
 
     @Test
@@ -111,6 +118,7 @@
                         null,
                         null,
                         null,
+                        null,
                         createRemoteActionTemplates());
 
         List<LabeledIntent> intents =
@@ -126,9 +134,73 @@
         assertThat(labeledIntent.titleWithoutEntity).isEqualTo(TITLE_WITHOUT_ENTITY);
         Intent intent = labeledIntent.intent;
         assertThat(intent.getAction()).isEqualTo(ACTION);
-        assertThat(intent.hasExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER)).isTrue();
     }
 
+    @Test
+    public void create_nullTemplate() {
+        AnnotatorModel.ClassificationResult classificationResult =
+                new AnnotatorModel.ClassificationResult(
+                        TextClassifier.TYPE_ADDRESS,
+                        1.0f,
+                        null,
+                        null,
+                        null,
+                        null,
+                        null,
+                        null,
+                        null,
+                        null,
+                        null,
+                        null,
+                        null,
+                        null);
+
+        mTemplateClassificationIntentFactory.create(
+                InstrumentationRegistry.getContext(),
+                TEXT,
+                /* foreignText */ false,
+                null,
+                classificationResult);
+
+
+        verify(mFallback).create(
+                same(InstrumentationRegistry.getContext()), eq(TEXT), eq(false), eq(null),
+                same(classificationResult));
+    }
+
+    @Test
+    public void create_emptyResult() {
+        AnnotatorModel.ClassificationResult classificationResult =
+                new AnnotatorModel.ClassificationResult(
+                        TextClassifier.TYPE_ADDRESS,
+                        1.0f,
+                        null,
+                        null,
+                        null,
+                        null,
+                        null,
+                        null,
+                        null,
+                        null,
+                        null,
+                        null,
+                        null,
+                        new RemoteActionTemplate[0]);
+
+        mTemplateClassificationIntentFactory.create(
+                InstrumentationRegistry.getContext(),
+                TEXT,
+                /* foreignText */ false,
+                null,
+                classificationResult);
+
+
+        verify(mFallback, never()).create(
+                any(Context.class), eq(TEXT), eq(false), eq(null),
+                any(AnnotatorModel.ClassificationResult.class));
+    }
+
+
     private static RemoteActionTemplate[] createRemoteActionTemplates() {
         return new RemoteActionTemplate[]{
                 new RemoteActionTemplate(
diff --git a/core/tests/coretests/src/android/view/textclassifier/TemplateIntentFactoryTest.java b/core/tests/coretests/src/android/view/textclassifier/intent/TemplateIntentFactoryTest.java
similarity index 97%
rename from core/tests/coretests/src/android/view/textclassifier/TemplateIntentFactoryTest.java
rename to core/tests/coretests/src/android/view/textclassifier/intent/TemplateIntentFactoryTest.java
index 1860734..6e3de2d 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TemplateIntentFactoryTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/intent/TemplateIntentFactoryTest.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.view.textclassifier;
+package android.view.textclassifier.intent;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -101,7 +101,6 @@
         assertThat(intent.getPackage()).isNull();
         assertThat(intent.getStringExtra(KEY_ONE)).isEqualTo(VALUE_ONE);
         assertThat(intent.getIntExtra(KEY_TWO, 0)).isEqualTo(VALUE_TWO);
-        assertThat(intent.hasExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER)).isTrue();
     }
 
     @Test
@@ -160,7 +159,6 @@
         assertThat(intent.getFlags()).isEqualTo(0);
         assertThat(intent.getCategories()).isNull();
         assertThat(intent.getPackage()).isNull();
-        assertThat(intent.hasExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER)).isTrue();
     }
 
     @Test
diff --git a/core/tests/coretests/src/android/widget/TextViewTest.java b/core/tests/coretests/src/android/widget/TextViewTest.java
index 585360f..0617caf 100644
--- a/core/tests/coretests/src/android/widget/TextViewTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewTest.java
@@ -209,7 +209,8 @@
         int lineCount = layout.getLineCount();
         boolean hyphenationHappend = false;
         for (int i = 0; i < lineCount; ++i) {
-            if (layout.getHyphen(i) == 0) {
+            if (layout.getStartHyphenEdit(i) == Paint.START_HYPHEN_EDIT_NO_EDIT
+                    && layout.getEndHyphenEdit(i) == Paint.END_HYPHEN_EDIT_NO_EDIT) {
                 continue;  // Hyphantion does not happen.
             }
             hyphenationHappend = true;
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index 3578bc0..185fa07 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -97,9 +97,12 @@
         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
                 Mockito.anyBoolean(),
                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
-        mActivityRule.launchActivity(Intent.createChooser(viewIntent, "chooser test"));
+        final ChooserWrapperActivity activity = mActivityRule.launchActivity(
+                Intent.createChooser(viewIntent, "chooser test"));
 
         waitForIdle();
+        assertThat(activity.getAdapter().getCount(), is(2));
+        assertThat(activity.getAdapter().getServiceTargetCount(), is(0));
         onView(withId(R.id.title)).check(matches(withText("chooser test")));
     }
 
@@ -596,7 +599,7 @@
 
         mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
         waitForIdle();
-        verify(mockLogger, Mockito.times(3)).write(logMakerCaptor.capture());
+        verify(mockLogger, Mockito.times(2)).write(logMakerCaptor.capture());
         // First invocation is from onCreate
         assertThat(logMakerCaptor.getAllValues().get(1).getCategory(),
                 is(MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
@@ -626,16 +629,12 @@
         ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
         mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
         waitForIdle();
-        verify(mockLogger, Mockito.times(3)).write(logMakerCaptor.capture());
+        verify(mockLogger, Mockito.times(2)).write(logMakerCaptor.capture());
         // First invocation is from onCreate
         assertThat(logMakerCaptor.getAllValues().get(1).getCategory(),
                 is(MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
         assertThat(logMakerCaptor.getAllValues().get(1).getSubtype(),
                 is(CONTENT_PREVIEW_IMAGE));
-        assertThat(logMakerCaptor.getAllValues().get(2).getCategory(),
-                is(MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
-        assertThat(logMakerCaptor.getAllValues().get(2).getSubtype(),
-                is(CONTENT_PREVIEW_IMAGE));
     }
 
     @Test
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
index a8dd69a..5e71129 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
@@ -39,8 +39,8 @@
     static final OverrideData sOverrides = new OverrideData();
     private UsageStatsManager mUsm;
 
-    ResolveListAdapter getAdapter() {
-        return mAdapter;
+    ChooserListAdapter getAdapter() {
+        return (ChooserListAdapter) mAdapter;
     }
 
     boolean getIsSelected() { return mIsSuccessfullySelected; }
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 2e56e09..4bd344f 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -122,13 +122,22 @@
     }
 
     /**
-     * Private constructor that must received an already allocated native bitmap
+     * Private constructor that must receive an already allocated native bitmap
      * int (pointer).
      */
-    // called from JNI
-    @UnsupportedAppUsage
-    Bitmap(long nativeBitmap, int width, int height, int density, boolean requestPremultiplied,
-            byte[] ninePatchChunk, NinePatch.InsetStruct ninePatchInsets) {
+    // JNI now calls the version below this one. This is preserved due to UnsupportedAppUsage.
+    @UnsupportedAppUsage(maxTargetSdk = 28)
+    Bitmap(long nativeBitmap, int width, int height, int density,
+            boolean requestPremultiplied, byte[] ninePatchChunk,
+            NinePatch.InsetStruct ninePatchInsets) {
+        this(nativeBitmap, width, height, density, requestPremultiplied, ninePatchChunk,
+                ninePatchInsets, true);
+    }
+
+    // called from JNI and Bitmap_Delegate.
+    Bitmap(long nativeBitmap, int width, int height, int density,
+            boolean requestPremultiplied, byte[] ninePatchChunk,
+            NinePatch.InsetStruct ninePatchInsets, boolean fromMalloc) {
         if (nativeBitmap == 0) {
             throw new RuntimeException("internal error: native bitmap is 0");
         }
@@ -144,13 +153,21 @@
         }
 
         mNativePtr = nativeBitmap;
-        long nativeSize = NATIVE_ALLOCATION_SIZE + getAllocationByteCount();
-        NativeAllocationRegistry registry = new NativeAllocationRegistry(
-            Bitmap.class.getClassLoader(), nativeGetNativeFinalizer(), nativeSize);
+
+        final int allocationByteCount = getAllocationByteCount();
+        NativeAllocationRegistry registry;
+        if (fromMalloc) {
+            registry = NativeAllocationRegistry.createMalloced(
+                    Bitmap.class.getClassLoader(), nativeGetNativeFinalizer(), allocationByteCount);
+        } else {
+            registry = NativeAllocationRegistry.createNonmalloced(
+                    Bitmap.class.getClassLoader(), nativeGetNativeFinalizer(), allocationByteCount);
+        }
         registry.registerNativeAllocation(this, nativeBitmap);
 
         if (ResourcesImpl.TRACE_FOR_DETAILED_PRELOAD) {
             sPreloadTracingNumInstantiatedBitmaps++;
+            long nativeSize = NATIVE_ALLOCATION_SIZE + allocationByteCount;
             sPreloadTracingTotalBitmapsSize += nativeSize;
         }
     }
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 8f46e1a..7b3f3da 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -76,14 +76,11 @@
     // (see SkCanvas.cpp, SkDraw.cpp)
     private static final int MAXMIMUM_BITMAP_SIZE = 32766;
 
-    // The approximate size of the native allocation associated with
-    // a Canvas object.
-    private static final long NATIVE_ALLOCATION_SIZE = 525;
-
     // Use a Holder to allow static initialization of Canvas in the boot image.
     private static class NoImagePreloadHolder {
-        public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
-                Canvas.class.getClassLoader(), nGetNativeFinalizer(), NATIVE_ALLOCATION_SIZE);
+        public static final NativeAllocationRegistry sRegistry =
+                NativeAllocationRegistry.createMalloced(
+                Canvas.class.getClassLoader(), nGetNativeFinalizer());
     }
 
     // This field is used to finalize the native Canvas properly
diff --git a/graphics/java/android/graphics/ColorFilter.java b/graphics/java/android/graphics/ColorFilter.java
index b24b988..4c2ef84 100644
--- a/graphics/java/android/graphics/ColorFilter.java
+++ b/graphics/java/android/graphics/ColorFilter.java
@@ -26,8 +26,9 @@
 public class ColorFilter {
 
     private static class NoImagePreloadHolder {
-        public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
-                ColorFilter.class.getClassLoader(), nativeGetFinalizer(), 50);
+        public static final NativeAllocationRegistry sRegistry =
+                NativeAllocationRegistry.createMalloced(
+                ColorFilter.class.getClassLoader(), nativeGetFinalizer());
     }
 
     /**
diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java
index 5d8ba93..5af0da8 100644
--- a/graphics/java/android/graphics/FontFamily.java
+++ b/graphics/java/android/graphics/FontFamily.java
@@ -44,13 +44,15 @@
 
     private static String TAG = "FontFamily";
 
-    private static final NativeAllocationRegistry sBuilderRegistry = new NativeAllocationRegistry(
-            FontFamily.class.getClassLoader(), nGetBuilderReleaseFunc(), 64);
+    private static final NativeAllocationRegistry sBuilderRegistry =
+            NativeAllocationRegistry.createMalloced(
+            FontFamily.class.getClassLoader(), nGetBuilderReleaseFunc());
 
     private @Nullable Runnable mNativeBuilderCleaner;
 
-    private static final NativeAllocationRegistry sFamilyRegistry = new NativeAllocationRegistry(
-            FontFamily.class.getClassLoader(), nGetFamilyReleaseFunc(), 64);
+    private static final NativeAllocationRegistry sFamilyRegistry =
+            NativeAllocationRegistry.createMalloced(
+            FontFamily.class.getClassLoader(), nGetFamilyReleaseFunc());
 
     /**
      * @hide
diff --git a/graphics/java/android/graphics/Matrix.java b/graphics/java/android/graphics/Matrix.java
index f8cb366..22b6401 100644
--- a/graphics/java/android/graphics/Matrix.java
+++ b/graphics/java/android/graphics/Matrix.java
@@ -16,12 +16,13 @@
 
 package android.graphics;
 
+import android.annotation.UnsupportedAppUsage;
+
 import dalvik.annotation.optimization.CriticalNative;
 import dalvik.annotation.optimization.FastNative;
 
 import libcore.util.NativeAllocationRegistry;
 
-import android.annotation.UnsupportedAppUsage;
 import java.io.PrintWriter;
 
 /**
@@ -222,12 +223,10 @@
         }
     };
 
-    // sizeof(SkMatrix) is 9 * sizeof(float) + uint32_t
-    private static final long NATIVE_ALLOCATION_SIZE = 40;
-
     private static class NoImagePreloadHolder {
-        public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
-                Matrix.class.getClassLoader(), nGetNativeFinalizer(), NATIVE_ALLOCATION_SIZE);
+        public static final NativeAllocationRegistry sRegistry =
+                NativeAllocationRegistry.createMalloced(
+                Matrix.class.getClassLoader(), nGetNativeFinalizer());
     }
 
     /**
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 9eeb43b..346c7ab 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -58,13 +58,11 @@
     private long mNativeShader;
     private long mNativeColorFilter;
 
-    // The approximate size of a native paint object.
-    private static final long NATIVE_PAINT_SIZE = 98;
-
     // Use a Holder to allow static initialization of Paint in the boot image.
     private static class NoImagePreloadHolder {
-        public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
-                Paint.class.getClassLoader(), nGetNativeFinalizer(), NATIVE_PAINT_SIZE);
+        public static final NativeAllocationRegistry sRegistry =
+                NativeAllocationRegistry.createMalloced(
+                Paint.class.getClassLoader(), nGetNativeFinalizer());
     }
 
     @ColorLong private long mColor;
@@ -364,19 +362,79 @@
      */
     private static final int CURSOR_OPT_MAX_VALUE = CURSOR_AT;
 
-    /**
-     * Mask for hyphen edits that happen at the end of a line. Keep in sync with the definition in
-     * Minikin's Hyphenator.h.
-     * @hide
-     */
-    public static final int HYPHENEDIT_MASK_END_OF_LINE = 0x07;
+    /** @hide */
+    @IntDef(prefix = { "START_HYPHEN_EDIT_" }, value = {
+        START_HYPHEN_EDIT_NO_EDIT,
+        START_HYPHEN_EDIT_INSERT_HYPHEN,
+        START_HYPHEN_EDIT_INSERT_ZWJ
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface StartHyphenEdit {}
 
     /**
-     * Mask for hyphen edits that happen at the start of a line. Keep in sync with the definition in
-     * Minikin's Hyphenator.h.
-     * @hide
+     * An integer representing the starting of the line has no modification for hyphenation.
      */
-    public static final int HYPHENEDIT_MASK_START_OF_LINE = 0x03 << 3;
+    public static final int START_HYPHEN_EDIT_NO_EDIT = 0x00;
+
+    /**
+     * An integer representing the starting of the line has normal hyphen character (U+002D).
+     */
+    public static final int START_HYPHEN_EDIT_INSERT_HYPHEN = 0x01;
+
+    /**
+     * An integer representing the starting of the line has Zero-Width-Joiner (U+200D).
+     */
+    public static final int START_HYPHEN_EDIT_INSERT_ZWJ = 0x02;
+
+    /** @hide */
+    @IntDef(prefix = { "END_HYPHEN_EDIT_" }, value = {
+        END_HYPHEN_EDIT_NO_EDIT,
+        END_HYPHEN_EDIT_REPLACE_WITH_HYPHEN,
+        END_HYPHEN_EDIT_INSERT_HYPHEN,
+        END_HYPHEN_EDIT_INSERT_ARMENIAN_HYPHEN,
+        END_HYPHEN_EDIT_INSERT_MAQAF,
+        END_HYPHEN_EDIT_INSERT_UCAS_HYPHEN,
+        END_HYPHEN_EDIT_INSERT_ZWJ_AND_HYPHEN
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface EndHyphenEdit {}
+
+    /**
+     * An integer representing the end of the line has no modification for hyphenation.
+     */
+    public static final int END_HYPHEN_EDIT_NO_EDIT = 0x00;
+
+    /**
+     * An integer representing the character at the end of the line is replaced with hyphen
+     * character (U+002D).
+     */
+    public static final int END_HYPHEN_EDIT_REPLACE_WITH_HYPHEN = 0x01;
+
+    /**
+     * An integer representing the end of the line has normal hyphen character (U+002D).
+     */
+    public static final int END_HYPHEN_EDIT_INSERT_HYPHEN = 0x02;
+
+    /**
+     * An integer representing the end of the line has Armentian hyphen (U+058A).
+     */
+    public static final int END_HYPHEN_EDIT_INSERT_ARMENIAN_HYPHEN = 0x03;
+
+    /**
+     * An integer representing the end of the line has maqaf (Hebrew hyphen, U+05BE).
+     */
+    public static final int END_HYPHEN_EDIT_INSERT_MAQAF = 0x04;
+
+    /**
+     * An integer representing the end of the line has Canadian Syllabics hyphen (U+1400).
+     */
+    public static final int END_HYPHEN_EDIT_INSERT_UCAS_HYPHEN = 0x05;
+
+    /**
+     * An integer representing the end of the line has Zero-Width-Joiner (U+200D) followed by normal
+     * hyphen character (U+002D).
+     */
+    public static final int END_HYPHEN_EDIT_INSERT_ZWJ_AND_HYPHEN = 0x06;
 
     /**
      * The Style specifies if the primitive being drawn is filled, stroked, or
@@ -988,7 +1046,8 @@
      * @param color The new color (including alpha) to set in the paint.
      */
     public void setColor(@ColorInt int color) {
-        setColor(Color.pack(color));
+        nSetColor(mNativePaint, color);
+        mColor = Color.pack(color);
     }
 
     /**
@@ -1005,12 +1064,8 @@
      */
     public void setColor(@ColorLong long color) {
         ColorSpace cs = Color.colorSpace(color);
-        float r = Color.red(color);
-        float g = Color.green(color);
-        float b = Color.blue(color);
-        float a = Color.alpha(color);
 
-        nSetColor(mNativePaint, cs.getNativeInstance(), r, g, b, a);
+        nSetColor(mNativePaint, cs.getNativeInstance(), color);
         mColor = color;
     }
 
@@ -1440,11 +1495,7 @@
      */
     public void setShadowLayer(float radius, float dx, float dy, @ColorLong long shadowColor) {
         ColorSpace cs = Color.colorSpace(shadowColor);
-        float r = Color.red(shadowColor);
-        float g = Color.green(shadowColor);
-        float b = Color.blue(shadowColor);
-        float a = Color.alpha(shadowColor);
-        nSetShadowLayer(mNativePaint, radius, dx, dy, cs.getNativeInstance(), r, g, b, a);
+        nSetShadowLayer(mNativePaint, radius, dx, dy, cs.getNativeInstance(), shadowColor);
 
         mShadowLayerRadius = radius;
         mShadowLayerDx = dx;
@@ -1472,6 +1523,7 @@
     /**
      * Returns the blur radius of the shadow layer.
      * @see #setShadowLayer(float,float,float,int)
+     * @see #setShadowLayer(float,float,float,long)
      */
     public float getShadowLayerRadius() {
         return mShadowLayerRadius;
@@ -1480,6 +1532,7 @@
     /**
      * Returns the x offset of the shadow layer.
      * @see #setShadowLayer(float,float,float,int)
+     * @see #setShadowLayer(float,float,float,long)
      */
     public float getShadowLayerDx() {
         return mShadowLayerDx;
@@ -1488,6 +1541,7 @@
     /**
      * Returns the y offset of the shadow layer.
      * @see #setShadowLayer(float,float,float,int)
+     * @see #setShadowLayer(float,float,float,long)
      */
     public float getShadowLayerDy() {
         return mShadowLayerDy;
@@ -1873,54 +1927,80 @@
     }
 
     /**
-     * Get the current value of packed hyphen edit.
+     * Get the current value of start hyphen edit.
      *
-     * You can extract start hyphen edit and end hyphen edit by using
-     * {@link android.text.Hyphenator#unpackStartHyphenEdit(int)} and
-     * {@link android.text.Hyphenator#unpackEndHyphenEdit(int)}.
+     * The default value is 0 which is equivalent to {@link #START_HYPHEN_EDIT_NO_EDIT}.
      *
-     * The default value is 0 which is equivalent to packed value of
-     * {@link android.text.Hyphenator#START_HYPHEN_EDIT_NO_EDIT} and
-     * {@link android.text.Hyphenator#END_HYPHEN_EDIT_NO_EDIT}.
-     *
-     * @return the current hyphen edit value
-     * @see #setHyphenEdit(int)
+     * @return the current starting hyphen edit value
+     * @see #setStartHyphenEdit(int)
      */
-    public int getHyphenEdit() {
-        return nGetHyphenEdit(mNativePaint);
+    public @StartHyphenEdit int getStartHyphenEdit() {
+        return nGetStartHyphenEdit(mNativePaint);
     }
 
     /**
-     * Set a packed hyphen edit on the paint.
+     * Get the current value of end hyphen edit.
      *
-     * By setting hyphen edit, the measurement and drawing is performed with modifying hyphenation
-     * at the start of line and end of line. For example, by passing
-     * {@link android.text.Hyphenator#END_HYPHEN_EDIT_INSERT_HYPHEN} like as follows, HYPHEN(U+2010)
+     * The default value is 0 which is equivalent to {@link #END_HYPHEN_EDIT_NO_EDIT}.
+     *
+     * @return the current starting hyphen edit value
+     * @see #setStartHyphenEdit(int)
+     */
+    public @EndHyphenEdit int getEndHyphenEdit() {
+        return nGetEndHyphenEdit(mNativePaint);
+    }
+
+    /**
+     * Set a start hyphen edit on the paint.
+     *
+     * By setting start hyphen edit, the measurement and drawing is performed with modifying
+     * hyphenation at the start of line. For example, by passing
+     * {@link #START_HYPHEN_EDIT_INSERT_HYPHEN} like as follows, HYPHEN(U+2010)
+     * character is appended at the start of line.
+     *
+     * <pre>
+     * <code>
+     *   Paint paint = new Paint();
+     *   paint.setStartHyphenEdit(Paint.START_HYPHEN_EDIT_INSERT_HYPHEN);
+     *   paint.measureText("abc", 0, 3);  // Returns the width of "‐abc"
+     *   Canvas.drawText("abc", 0, 3, 0f, 0f, paint);  // Draws "‐abc"
+     * </code>
+     * </pre>
+     *
+     * The default value is 0 which is equivalent to
+     * {@link #START_HYPHEN_EDIT_NO_EDIT}.
+     *
+     * @param startHyphen a start hyphen edit value.
+     * @see #getStartHyphenEdit()
+     */
+    public void setStartHyphenEdit(@StartHyphenEdit int startHyphen) {
+        nSetStartHyphenEdit(mNativePaint, startHyphen);
+    }
+
+    /**
+     * Set a end hyphen edit on the paint.
+     *
+     * By setting end hyphen edit, the measurement and drawing is performed with modifying
+     * hyphenation at the end of line. For example, by passing
+     * {@link #END_HYPHEN_EDIT_INSERT_HYPHEN} like as follows, HYPHEN(U+2010)
      * character is appended at the end of line.
      *
      * <pre>
      * <code>
      *   Paint paint = new Paint();
-     *   paint.setHyphenEdit(Hyphenator.packHyphenEdit(
-     *       Hyphenator.START_HYPHEN_EDIT_NO_EDIT,
-     *       Hyphenator.END_HYPHEN_EDIT_INSERT_HYPHEN));
+     *   paint.setEndHyphenEdit(Paint.END_HYPHEN_EDIT_INSERT_HYPHEN);
      *   paint.measureText("abc", 0, 3);  // Returns the width of "abc‐"
      *   Canvas.drawText("abc", 0, 3, 0f, 0f, paint);  // Draws "abc‐"
      * </code>
      * </pre>
      *
-     * You can pack start hyphen edit and end hyphen edit by
-     * {@link android.text.Hyphenator#packHyphenEdit(int,int)}
+     * The default value is 0 which is equivalent to {@link #END_HYPHEN_EDIT_NO_EDIT}.
      *
-     * The default value is 0 which is equivalent to packed value of
-     * {@link android.text.Hyphenator#START_HYPHEN_EDIT_NO_EDIT} and
-     * {@link android.text.Hyphenator#END_HYPHEN_EDIT_NO_EDIT}.
-     *
-     * @param hyphen a packed hyphen edit value.
-     * @see #getHyphenEdit()
+     * @param endHyphen a end hyphen edit value.
+     * @see #getEndHyphenEdit()
      */
-    public void setHyphenEdit(int hyphen) {
-        nSetHyphenEdit(mNativePaint, hyphen);
+    public void setEndHyphenEdit(@EndHyphenEdit int endHyphen) {
+        nSetEndHyphenEdit(mNativePaint, endHyphen);
     }
 
     /**
@@ -3051,7 +3131,7 @@
     @CriticalNative
     private static native void nSetShadowLayer(long paintPtr,
             float radius, float dx, float dy, long colorSpaceHandle,
-            float r, float g, float b, float a);
+            @ColorLong long shadowColor);
     @CriticalNative
     private static native boolean nHasShadowLayer(long paintPtr);
     @CriticalNative
@@ -3063,9 +3143,13 @@
     @CriticalNative
     private static native void nSetWordSpacing(long paintPtr, float wordSpacing);
     @CriticalNative
-    private static native int nGetHyphenEdit(long paintPtr);
+    private static native int nGetStartHyphenEdit(long paintPtr);
     @CriticalNative
-    private static native void nSetHyphenEdit(long paintPtr, int hyphen);
+    private static native int nGetEndHyphenEdit(long paintPtr);
+    @CriticalNative
+    private static native void nSetStartHyphenEdit(long paintPtr, int hyphen);
+    @CriticalNative
+    private static native void nSetEndHyphenEdit(long paintPtr, int hyphen);
     @CriticalNative
     private static native void nSetStrokeMiter(long paintPtr, float miter);
     @CriticalNative
@@ -3100,7 +3184,9 @@
     private static native void nSetFilterBitmap(long paintPtr, boolean filter);
     @CriticalNative
     private static native void nSetColor(long paintPtr, long colorSpaceHandle,
-            float r, float g, float b, float a);
+            @ColorLong long color);
+    @CriticalNative
+    private static native void nSetColor(long paintPtr, @ColorInt int color);
     @CriticalNative
     private static native void nSetStrikeThruText(long paintPtr, boolean strikeThruText);
     @CriticalNative
diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java
index 405ab0b..7282d52 100644
--- a/graphics/java/android/graphics/Path.java
+++ b/graphics/java/android/graphics/Path.java
@@ -36,8 +36,9 @@
  */
 public class Path {
 
-    private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
-                Path.class.getClassLoader(), nGetFinalizer(), 48 /* dummy size */);
+    private static final NativeAllocationRegistry sRegistry =
+            NativeAllocationRegistry.createMalloced(
+                Path.class.getClassLoader(), nGetFinalizer());
 
     /**
      * @hide
diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java
index 5e48ea1..9b4f2c1 100644
--- a/graphics/java/android/graphics/RenderNode.java
+++ b/graphics/java/android/graphics/RenderNode.java
@@ -70,8 +70,7 @@
  *         canvas.drawRect(...);
  *     } finally {
  *         renderNode.endRecording();
- *     }
- * </pre>
+ *     }</pre>
  *
  * <h3>Drawing a RenderNode in a View</h3>
  * <pre class="prettyprint">
@@ -84,8 +83,7 @@
  *             // Draw the RenderNode into this canvas.
  *             canvas.drawRenderNode(myRenderNode);
  *         }
- *     }
- * </pre>
+ *     }</pre>
  *
  * <h3>Releasing resources</h3>
  * <p>This step is not mandatory but recommended if you want to release resources
@@ -93,8 +91,7 @@
  * <pre class="prettyprint">
  *     // Discards the display list content allowing for any held resources to be released.
  *     // After calling this
- *     renderNode.discardDisplayList();
- * </pre>
+ *     renderNode.discardDisplayList();</pre>
  *
  *
  * <h3>Properties</h3>
@@ -132,8 +129,7 @@
  *          // will be invoked and will execute very quickly
  *          mRenderNode.offsetLeftAndRight(x);
  *          invalidate();
- *     }
- * </pre>
+ *     }</pre>
  *
  * <p>A few of the properties may at first appear redundant, such as {@link #setElevation(float)}
  * and {@link #setTranslationZ(float)}. The reason for these duplicates are to allow for a
@@ -146,24 +142,26 @@
  * overlap with {@link #setPosition(Rect)}.
  *
  * <p>The RenderNode's transform matrix is computed at render time as follows:
- * First a setTranslate(getTranslationX(), getTranslationY()) is applied to a {@link Matrix}.
- * Second a preRotate(getRotationZ(), getPivotX(), getPivotY()) is applied to the matrix. And
- * finally a preScale(getScaleX(), getScaleY(), getPivotX(), getPivotY()) is applied. The current
- * canvas transform matrix, which is translated to the RenderNode's position,
- * is then multiplied by the RenderNode's transform matrix. Therefore there is no implicit
- * ordering in setting various RenderNode properties. That is to say that:
+ * <pre class="prettyprint">
+ *     Matrix transform = new Matrix();
+ *     transform.setTranslate(renderNode.getTranslationX(), renderNode.getTranslationY());
+ *     transform.preRotate(renderNode.getRotationZ(),
+ *             renderNode.getPivotX(), renderNode.getPivotY());
+ *     transform.preScale(renderNode.getScaleX(), renderNode.getScaleY(),
+ *             renderNode.getPivotX(), renderNode.getPivotY());</pre>
+ * The current canvas transform matrix, which is translated to the RenderNode's position,
+ * is then multiplied by the RenderNode's transform matrix. Therefore the ordering of calling
+ * property setters does not affect the result. That is to say that:
  *
  * <pre class="prettyprint">
  *     renderNode.setTranslationX(100);
- *     renderNode.setScaleX(100);
- * </pre>
+ *     renderNode.setScaleX(100);</pre>
  *
- * is equivalent to
+ * is equivalent to:
  *
  * <pre class="prettyprint">
  *     renderNode.setScaleX(100);
- *     renderNode.setTranslationX(100);
- * </pre>
+ *     renderNode.setTranslationX(100);</pre>
  *
  * <h3>Threading</h3>
  * <p>RenderNode may be created and used on any thread but they are not thread-safe. Only
@@ -182,8 +180,7 @@
  *         if (needsUpdate) {
  *             myOwningView.invalidate();
  *         }
- *     }
- * </pre>
+ *     }</pre>
  * This is marginally faster than doing a more explicit up-front check if the value changed by
  * comparing the desired value against {@link #getTranslationX()} as it minimizes JNI transitions.
  * The actual mechanism of requesting a new frame to be rendered will depend on how this
@@ -198,8 +195,9 @@
 
     // Use a Holder to allow static initialization in the boot image.
     private static class NoImagePreloadHolder {
-        public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
-                RenderNode.class.getClassLoader(), nGetNativeFinalizer(), 1024);
+        public static final NativeAllocationRegistry sRegistry =
+                NativeAllocationRegistry.createMalloced(
+                RenderNode.class.getClassLoader(), nGetNativeFinalizer());
     }
 
     /**
@@ -808,14 +806,37 @@
      * for the matrix parameter.
      *
      * @param matrix The matrix, null indicates that the matrix should be cleared.
+     * @see #getAnimationMatrix()
+     *
      * @hide TODO Do we want this?
      */
-    public boolean setAnimationMatrix(Matrix matrix) {
+    public boolean setAnimationMatrix(@Nullable Matrix matrix) {
         return nSetAnimationMatrix(mNativeRenderNode,
                 (matrix != null) ? matrix.native_instance : 0);
     }
 
     /**
+     * Returns the previously set Animation matrix. This matrix exists if an Animation is
+     * currently playing on a View, and is set on the display list during at draw() time.
+     * Returns <code>null</code> when there is no transformation provided by
+     * {@link #setAnimationMatrix(Matrix)}.
+     *
+     * @return the current Animation matrix.
+     * @see #setAnimationMatrix(Matrix)
+     *
+     * @hide
+     */
+    @Nullable
+    public Matrix getAnimationMatrix() {
+        Matrix output = new Matrix();
+        if (nGetAnimationMatrix(mNativeRenderNode, output.native_instance)) {
+            return output;
+        } else {
+            return null;
+        }
+    }
+
+    /**
      * Sets the translucency level for the display list.
      *
      * @param alpha The translucency of the display list, must be a value between 0.0f and 1.0f
@@ -1660,6 +1681,9 @@
     private static native boolean nHasOverlappingRendering(long renderNode);
 
     @CriticalNative
+    private static native boolean nGetAnimationMatrix(long renderNode, long animationMatrix);
+
+    @CriticalNative
     private static native boolean nGetClipToOutline(long renderNode);
 
     @CriticalNative
diff --git a/graphics/java/android/graphics/Shader.java b/graphics/java/android/graphics/Shader.java
index d555128..3050d1d 100644
--- a/graphics/java/android/graphics/Shader.java
+++ b/graphics/java/android/graphics/Shader.java
@@ -33,8 +33,9 @@
 public class Shader {
 
     private static class NoImagePreloadHolder {
-        public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
-                Shader.class.getClassLoader(), nativeGetFinalizer(), 50);
+        public static final NativeAllocationRegistry sRegistry =
+                NativeAllocationRegistry.createMalloced(
+                Shader.class.getClassLoader(), nativeGetFinalizer());
     }
 
     /**
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 9518714..9995f1e 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -75,8 +75,9 @@
 
     private static String TAG = "Typeface";
 
-    private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
-            Typeface.class.getClassLoader(), nativeGetReleaseFunc(), 64);
+    private static final NativeAllocationRegistry sRegistry =
+            NativeAllocationRegistry.createMalloced(
+            Typeface.class.getClassLoader(), nativeGetReleaseFunc());
 
     /** The default NORMAL typeface object */
     public static final Typeface DEFAULT;
diff --git a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
index bb6bf24..82f5870 100644
--- a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
@@ -313,7 +313,7 @@
                     extended, cropRect), inputStream, afd);
 
         final long nativeSize = nNativeByteSize(mState.mNativePtr);
-        NativeAllocationRegistry registry = new NativeAllocationRegistry(
+        NativeAllocationRegistry registry = NativeAllocationRegistry.createMalloced(
                 AnimatedImageDrawable.class.getClassLoader(), nGetNativeFinalizer(), nativeSize);
         registry.registerNativeAllocation(mState, mState.mNativePtr);
     }
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index d7aee77..d9dab98 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -1253,7 +1253,6 @@
         private boolean mInitialized = false;
         private boolean mIsReversible = false;
         private boolean mIsInfinite = false;
-        // TODO: Consider using NativeAllocationRegistery to track native allocation
         private final VirtualRefBasePtr mSetRefBasePtr;
         private WeakReference<RenderNode> mLastSeenTarget = null;
         private int mLastListenerId = 0;
diff --git a/graphics/java/android/graphics/fonts/Font.java b/graphics/java/android/graphics/fonts/Font.java
index f715f43..552088f 100644
--- a/graphics/java/android/graphics/fonts/Font.java
+++ b/graphics/java/android/graphics/fonts/Font.java
@@ -54,13 +54,13 @@
      * A builder class for creating new Font.
      */
     public static final class Builder {
-        private static final NativeAllocationRegistry sAssetByteBufferRegistroy =
-                new NativeAllocationRegistry(ByteBuffer.class.getClassLoader(),
-                    nGetReleaseNativeAssetFunc(), 64);
+        private static final NativeAllocationRegistry sAssetByteBufferRegistry =
+                NativeAllocationRegistry.createMalloced(ByteBuffer.class.getClassLoader(),
+                    nGetReleaseNativeAssetFunc());
 
-        private static final NativeAllocationRegistry sFontRegistory =
-                new NativeAllocationRegistry(Font.class.getClassLoader(),
-                    nGetReleaseNativeFont(), 64);
+        private static final NativeAllocationRegistry sFontRegistry =
+                NativeAllocationRegistry.createMalloced(Font.class.getClassLoader(),
+                    nGetReleaseNativeFont());
 
         private @Nullable ByteBuffer mBuffer;
         private @Nullable File mFile;
@@ -171,7 +171,7 @@
                 return;
             }
             final ByteBuffer b = nGetAssetBuffer(nativeAsset);
-            sAssetByteBufferRegistroy.registerNativeAllocation(b, nativeAsset);
+            sAssetByteBufferRegistry.registerNativeAllocation(b, nativeAsset);
             if (b == null) {
                 mException = new FileNotFoundException(path + " not found");
                 return;
@@ -206,7 +206,7 @@
                 return;
             }
             final ByteBuffer b = nGetAssetBuffer(nativeAsset);
-            sAssetByteBufferRegistroy.registerNativeAllocation(b, nativeAsset);
+            sAssetByteBufferRegistry.registerNativeAllocation(b, nativeAsset);
             if (b == null) {
                 mException = new FileNotFoundException(str + " not found");
                 return;
@@ -356,7 +356,7 @@
          * Creates the font based on the configured values.
          * @return the Font object
          */
-        public @Nullable Font build() throws IOException {
+        public @NonNull Font build() throws IOException {
             if (mException != null) {
                 throw new IOException("Failed to read font contents", mException);
             }
@@ -391,7 +391,7 @@
                     mTtcIndex);
             final Font font = new Font(ptr, readonlyBuffer, mFile,
                     new FontStyle(mWeight, slant), mTtcIndex, mAxes, mLocaleList);
-            sFontRegistory.registerNativeAllocation(font, ptr);
+            sFontRegistry.registerNativeAllocation(font, ptr);
             return font;
         }
 
diff --git a/graphics/java/android/graphics/fonts/FontFamily.java b/graphics/java/android/graphics/fonts/FontFamily.java
index 4772c1c..75ea120 100644
--- a/graphics/java/android/graphics/fonts/FontFamily.java
+++ b/graphics/java/android/graphics/fonts/FontFamily.java
@@ -63,8 +63,8 @@
      */
     public static final class Builder {
         private static final NativeAllocationRegistry sFamilyRegistory =
-                new NativeAllocationRegistry(FontFamily.class.getClassLoader(),
-                    nGetReleaseNativeFamily(), 64);
+                NativeAllocationRegistry.createMalloced(FontFamily.class.getClassLoader(),
+                    nGetReleaseNativeFamily());
 
         private final ArrayList<Font> mFonts = new ArrayList<>();
         private final HashSet<Integer> mStyleHashSet = new HashSet<>();
diff --git a/graphics/java/android/graphics/text/LineBreaker.java b/graphics/java/android/graphics/text/LineBreaker.java
index 046bbcf..54622c5 100644
--- a/graphics/java/android/graphics/text/LineBreaker.java
+++ b/graphics/java/android/graphics/text/LineBreaker.java
@@ -69,7 +69,7 @@
  * }
  *
  * // Draw text to the canvas
- * Bitmap bmp = new Bitmap.createBitmap(240, totalHeight, Bitmap.Config.ARGB_8888);
+ * Bitmap bmp = Bitmap.createBitmap(240, totalHeight, Bitmap.Config.ARGB_8888);
  * Canvas c = new Canvas(bmp);
  * float yOffset = 0f;
  * int prevOffset = 0;
@@ -248,8 +248,8 @@
         private @FloatRange(from = 0.0f) float mWidth = 0;
         private @FloatRange(from = 0.0f) float mFirstWidth = 0;
         private @IntRange(from = 0) int mFirstWidthLineCount = 0;
-        private @Nullable int[] mVariableTabStops = null;
-        private @IntRange(from = 0) int mDefaultTabStop = 0;
+        private @Nullable float[] mVariableTabStops = null;
+        private @FloatRange(from = 0) float mDefaultTabStop = 0;
 
         public ParagraphConstraints() {}
 
@@ -284,8 +284,8 @@
          * @see #getTabStops()
          * @see #getDefaultTabStop()
          */
-        public void setTabStops(@Nullable int[] tabStops,
-                @Px @IntRange(from = 0) int defaultTabStop) {
+        public void setTabStops(@Nullable float[] tabStops,
+                @Px @FloatRange(from = 0) float defaultTabStop) {
             mVariableTabStops = tabStops;
             mDefaultTabStop = defaultTabStop;
         }
@@ -320,18 +320,18 @@
         /**
          * Returns the array of tab stops in pixels.
          *
-         * @see #setTabStops(int[], int)
+         * @see #setTabStops(float[], int)
          */
-        public @Nullable int[] getTabStops() {
+        public @Nullable float[] getTabStops() {
             return mVariableTabStops;
         }
 
         /**
          * Returns the default tab stops in pixels.
          *
-         * @see #setTabStop(int[], int)
+         * @see #setTabStop(float[], int)
          */
-        public @Px @IntRange(from = 0) int getDefaultTabStop() {
+        public @Px @FloatRange(from = 0) float getDefaultTabStop() {
             return mDefaultTabStop;
         }
     }
@@ -342,11 +342,16 @@
      */
     public static class Result {
         // Following two contstant must be synced with minikin's line breaker.
+        // TODO(nona): Remove these constatns by introducing native methods.
         private static final int TAB_MASK = 0x20000000;
         private static final int HYPHEN_MASK = 0xFF;
+        private static final int START_HYPHEN_MASK = 0x18;  // 0b11000
+        private static final int END_HYPHEN_MASK = 0x7;  // 0b00111
+        private static final int START_HYPHEN_BITS_SHIFT = 3;
 
-        private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
-                Result.class.getClassLoader(), nGetReleaseResultFunc(), 32);
+        private static final NativeAllocationRegistry sRegistry =
+                NativeAllocationRegistry.createMalloced(
+                Result.class.getClassLoader(), nGetReleaseResultFunc());
         private final long mPtr;
 
         private Result(long ptr) {
@@ -414,22 +419,35 @@
         }
 
         /**
-         * Returns a packed hyphen edit for the line.
+         * Returns a start hyphen edit for the line.
          *
          * @param lineIndex an index of the line.
-         * @return a packed hyphen edit for the line.
+         * @return a start hyphen edit for the line.
          *
-         * @see android.text.Hyphenator#unpackStartHyphenEdit(int)
-         * @see android.text.Hyphenator#unpackEndHyphenEdit(int)
-         * @see android.text.Hyphenator#packHyphenEdit(int,int)
+         * @see android.graphics.Paint#setStartHyphenEdit
+         * @see android.graphics.Paint#getStartHyphenEdit
          */
-        public int getLineHyphenEdit(int lineIndex) {
-            return (nGetLineFlag(mPtr, lineIndex) & HYPHEN_MASK);
+        public int getStartLineHyphenEdit(int lineIndex) {
+            return (nGetLineFlag(mPtr, lineIndex) & START_HYPHEN_MASK) >> START_HYPHEN_BITS_SHIFT;
+        }
+
+        /**
+         * Returns an end hyphen edit for the line.
+         *
+         * @param lineIndex an index of the line.
+         * @return an end hyphen edit for the line.
+         *
+         * @see android.graphics.Paint#setEndHyphenEdit
+         * @see android.graphics.Paint#getEndHyphenEdit
+         */
+        public int getEndLineHyphenEdit(int lineIndex) {
+            return nGetLineFlag(mPtr, lineIndex) & END_HYPHEN_MASK;
         }
     }
 
-    private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
-            LineBreaker.class.getClassLoader(), nGetReleaseFunc(), 64);
+    private static final NativeAllocationRegistry sRegistry =
+            NativeAllocationRegistry.createMalloced(
+            LineBreaker.class.getClassLoader(), nGetReleaseFunc());
 
     private final long mNativePtr;
 
@@ -497,8 +515,8 @@
             @FloatRange(from = 0.0f) float firstWidth,
             @IntRange(from = 0) int firstWidthLineCount,
             @FloatRange(from = 0.0f) float restWidth,
-            @Nullable int[] variableTabStops,
-            int defaultTabStop,
+            @Nullable float[] variableTabStops,
+            float defaultTabStop,
             @IntRange(from = 0) int indentsOffset);
 
     // Result accessors
diff --git a/graphics/java/android/graphics/text/MeasuredText.java b/graphics/java/android/graphics/text/MeasuredText.java
index 480aff2..9db7533 100644
--- a/graphics/java/android/graphics/text/MeasuredText.java
+++ b/graphics/java/android/graphics/text/MeasuredText.java
@@ -65,6 +65,7 @@
 
     /**
      * Returns the characters in the paragraph used to compute this MeasuredText instance.
+     * @hide
      */
     public @NonNull char[] getChars() {
         return mChars;
@@ -169,8 +170,9 @@
      * Note: The appendStyle and appendReplacementRun should be called to cover the text length.
      */
     public static final class Builder {
-        private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
-                MeasuredText.class.getClassLoader(), nGetReleaseFunc(), 1024);
+        private static final NativeAllocationRegistry sRegistry =
+                NativeAllocationRegistry.createMalloced(
+                MeasuredText.class.getClassLoader(), nGetReleaseFunc());
 
         private long mNativePtr;
 
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
index 105af6e..51c4252 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
@@ -16,7 +16,6 @@
 
 package android.security.keystore;
 
-import libcore.util.EmptyArray;
 import android.security.Credentials;
 import android.security.GateKeeper;
 import android.security.KeyStore;
@@ -31,6 +30,8 @@
 import android.security.keystore.WrappedKeyEntry;
 import android.util.Log;
 
+import libcore.util.EmptyArray;
+
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -123,7 +124,14 @@
 
         final Certificate[] caList;
 
-        final byte[] caBytes = mKeyStore.get(Credentials.CA_CERTIFICATE + alias, mUid);
+        // Suppress the key not found warning for this call. It seems that this error is exclusively
+        // being thrown when there is a self signed certificate chain, so when the keystore service
+        // attempts to query for the CA details, it obviously fails to find them and returns a
+        // key not found exception. This is WAI, and throwing a stack trace here can be very
+        // misleading since the trace is not clear.
+        final byte[] caBytes = mKeyStore.get(Credentials.CA_CERTIFICATE + alias,
+                                             mUid,
+                                             true /* suppressKeyNotFoundWarning */);
         if (caBytes != null) {
             final Collection<X509Certificate> caChain = toCertificates(caBytes);
 
diff --git a/libs/androidfw/Asset.cpp b/libs/androidfw/Asset.cpp
index c512a6b..9a95fdf 100644
--- a/libs/androidfw/Asset.cpp
+++ b/libs/androidfw/Asset.cpp
@@ -292,8 +292,10 @@
 
     pAsset = new _FileAsset;
     result = pAsset->openChunk(dataMap);
-    if (result != NO_ERROR)
+    if (result != NO_ERROR) {
+        delete pAsset;
         return NULL;
+    }
 
     pAsset->mAccessMode = mode;
     return pAsset;
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 4f1b2a4..ebba4cb 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -191,7 +191,7 @@
         "surfacetexture/EGLConsumer.cpp",
         "surfacetexture/ImageConsumer.cpp",
         "surfacetexture/SurfaceTexture.cpp",
-        "thread/TaskManager.cpp",
+        "thread/CommonPool.cpp",
         "utils/Blur.cpp",
         "utils/Color.cpp",
         "utils/GLUtils.cpp",
@@ -308,6 +308,7 @@
         "tests/unit/main.cpp",
         "tests/unit/CacheManagerTests.cpp",
         "tests/unit/CanvasContextTests.cpp",
+        "tests/unit/CommonPoolTests.cpp",
         "tests/unit/DamageAccumulatorTests.cpp",
         "tests/unit/DeferredLayerUpdaterTests.cpp",
         "tests/unit/FatVectorTests.cpp",
@@ -381,7 +382,6 @@
         "tests/microbench/LinearAllocatorBench.cpp",
         "tests/microbench/PathParserBench.cpp",
         "tests/microbench/RenderNodeBench.cpp",
-        "tests/microbench/TaskManagerBench.cpp",
     ],
 }
 
diff --git a/libs/hwui/FrameInfoVisualizer.cpp b/libs/hwui/FrameInfoVisualizer.cpp
index b04c774..3a8e559 100644
--- a/libs/hwui/FrameInfoVisualizer.cpp
+++ b/libs/hwui/FrameInfoVisualizer.cpp
@@ -17,6 +17,7 @@
 
 #include "IProfileRenderer.h"
 #include "utils/Color.h"
+#include "utils/TimeUtils.h"
 
 #include <cutils/compiler.h>
 #include <array>
@@ -26,22 +27,24 @@
 #define RETURN_IF_DISABLED() \
     if (CC_LIKELY(mType == ProfileType::None && !mShowDirtyRegions)) return
 
-#define PROFILE_DRAW_WIDTH 3
-#define PROFILE_DRAW_THRESHOLD_STROKE_WIDTH 2
-#define PROFILE_DRAW_DP_PER_MS 7
-
 namespace android {
 namespace uirenderer {
 
-// Must be NUM_ELEMENTS in size
-static const SkColor THRESHOLD_COLOR = Color::Green_500;
-static const SkColor BAR_FAST_MASK = 0x8FFFFFFF;
-static const SkColor BAR_JANKY_MASK = 0xDFFFFFFF;
+static constexpr auto PROFILE_DRAW_THRESHOLD_STROKE_WIDTH = 2;
+static constexpr auto PROFILE_DRAW_DP_PER_MS = 7;
 
-// We could get this from TimeLord and use the actual frame interval, but
-// this is good enough
-#define FRAME_THRESHOLD 16
-#define FRAME_THRESHOLD_NS 16000000
+struct Threshold {
+    SkColor color;
+    float percentFrametime;
+};
+
+static constexpr std::array<Threshold, 3> THRESHOLDS{
+        Threshold{.color = Color::Green_500, .percentFrametime = 0.8f},
+        Threshold{.color = Color::Lime_500, .percentFrametime = 1.0f},
+        Threshold{.color = Color::Red_500, .percentFrametime = 1.5f},
+};
+static constexpr SkColor BAR_FAST_MASK = 0x8FFFFFFF;
+static constexpr SkColor BAR_JANKY_MASK = 0xDFFFFFFF;
 
 struct BarSegment {
     FrameInfoIndex start;
@@ -64,7 +67,8 @@
     return (int)(dp * density + 0.5f);
 }
 
-FrameInfoVisualizer::FrameInfoVisualizer(FrameInfoSource& source) : mFrameSource(source) {
+FrameInfoVisualizer::FrameInfoVisualizer(FrameInfoSource& source, nsecs_t frameInterval)
+        : mFrameSource(source), mFrameInterval(frameInterval) {
     setDensity(1);
     consumeProperties();
 }
@@ -76,7 +80,10 @@
 void FrameInfoVisualizer::setDensity(float density) {
     if (CC_UNLIKELY(mDensity != density)) {
         mDensity = density;
-        mVerticalUnit = dpToPx(PROFILE_DRAW_DP_PER_MS, density);
+        // We want the vertical units to scale height relative to a baseline 16ms.
+        // This keeps the threshold lines consistent across varying refresh rates
+        mVerticalUnit = static_cast<int>(dpToPx(PROFILE_DRAW_DP_PER_MS, density) * (float)16_ms /
+                                         (float)mFrameInterval);
         mThresholdStroke = dpToPx(PROFILE_DRAW_THRESHOLD_STROKE_WIDTH, density);
     }
 }
@@ -148,7 +155,7 @@
         float* rect;
         int ri;
         // Rects are LTRB
-        if (mFrameSource[fi].totalDuration() <= FRAME_THRESHOLD_NS) {
+        if (mFrameSource[fi].totalDuration() <= mFrameInterval) {
             rect = mFastRects.get();
             ri = fast_i;
             fast_i += 4;
@@ -181,7 +188,7 @@
         float* rect;
         int ri;
         // Rects are LTRB
-        if (mFrameSource[fi].totalDuration() <= FRAME_THRESHOLD_NS) {
+        if (mFrameSource[fi].totalDuration() <= mFrameInterval) {
             rect = mFastRects.get();
             ri = fast_i;
             fast_i -= 4;
@@ -211,10 +218,13 @@
 
 void FrameInfoVisualizer::drawThreshold(IProfileRenderer& renderer) {
     SkPaint paint;
-    paint.setColor(THRESHOLD_COLOR);
-    float yLocation = renderer.getViewportHeight() - (FRAME_THRESHOLD * mVerticalUnit);
-    renderer.drawRect(0.0f, yLocation - mThresholdStroke / 2, renderer.getViewportWidth(),
-                      yLocation + mThresholdStroke / 2, paint);
+    for (auto& t : THRESHOLDS) {
+        paint.setColor(t.color);
+        float yLocation = renderer.getViewportHeight() -
+                          (ns2ms(mFrameInterval) * t.percentFrametime * mVerticalUnit);
+        renderer.drawRect(0.0f, yLocation - mThresholdStroke / 2, renderer.getViewportWidth(),
+                          yLocation + mThresholdStroke / 2, paint);
+    }
 }
 
 bool FrameInfoVisualizer::consumeProperties() {
diff --git a/libs/hwui/FrameInfoVisualizer.h b/libs/hwui/FrameInfoVisualizer.h
index b98f501..3040a77 100644
--- a/libs/hwui/FrameInfoVisualizer.h
+++ b/libs/hwui/FrameInfoVisualizer.h
@@ -39,7 +39,7 @@
 
 class FrameInfoVisualizer {
 public:
-    explicit FrameInfoVisualizer(FrameInfoSource& source);
+    explicit FrameInfoVisualizer(FrameInfoSource& source, nsecs_t frameInterval);
     ~FrameInfoVisualizer();
 
     bool consumeProperties();
@@ -71,6 +71,7 @@
 
     FrameInfoSource& mFrameSource;
 
+    nsecs_t mFrameInterval;
     int mVerticalUnit = 0;
     int mThresholdStroke = 0;
 
diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp
index fe633e9..fb60a96 100644
--- a/libs/hwui/Readback.cpp
+++ b/libs/hwui/Readback.cpp
@@ -28,6 +28,7 @@
 #include "hwui/Bitmap.h"
 #include "utils/Color.h"
 #include "utils/MathUtils.h"
+#include "utils/TraceUtils.h"
 
 using namespace android::uirenderer::renderthread;
 
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index 3bbee18..219d040 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -287,6 +287,8 @@
     switch (mPixelStorageType) {
         case PixelStorageType::Heap:
             return mPixelStorage.heap.size;
+        case PixelStorageType::Ashmem:
+            return mPixelStorage.ashmem.size;
         default:
             return rowBytes() * height();
     }
diff --git a/libs/hwui/hwui/Bitmap.h b/libs/hwui/hwui/Bitmap.h
index 01e4516..dd98b25 100644
--- a/libs/hwui/hwui/Bitmap.h
+++ b/libs/hwui/hwui/Bitmap.h
@@ -103,6 +103,8 @@
 
     bool isHardware() const { return mPixelStorageType == PixelStorageType::Hardware; }
 
+    PixelStorageType pixelStorageType() const { return mPixelStorageType; }
+
     GraphicBuffer* graphicBuffer();
 
     /**
diff --git a/libs/hwui/hwui/MinikinUtils.cpp b/libs/hwui/hwui/MinikinUtils.cpp
index 733f8e4..5f6b53a 100644
--- a/libs/hwui/hwui/MinikinUtils.cpp
+++ b/libs/hwui/hwui/MinikinUtils.cpp
@@ -58,9 +58,8 @@
     const minikin::U16StringPiece textBuf(buf, bufSize);
     const minikin::Range range(start, start + count);
     const minikin::Range contextRange(contextStart, contextStart + contextCount);
-    const minikin::HyphenEdit hyphenEdit = static_cast<minikin::HyphenEdit>(paint->getHyphenEdit());
-    const minikin::StartHyphenEdit startHyphen = minikin::startHyphenEdit(hyphenEdit);
-    const minikin::EndHyphenEdit endHyphen = minikin::endHyphenEdit(hyphenEdit);
+    const minikin::StartHyphenEdit startHyphen = paint->getStartHyphenEdit();
+    const minikin::EndHyphenEdit endHyphen = paint->getEndHyphenEdit();
 
     if (mt == nullptr) {
         return minikin::Layout(textBuf.substr(contextRange), range - contextStart, bidiFlags,
@@ -76,9 +75,8 @@
     minikin::MinikinPaint minikinPaint = prepareMinikinPaint(paint, typeface);
     const minikin::U16StringPiece textBuf(buf, bufSize);
     const minikin::Range range(start, start + count);
-    const minikin::HyphenEdit hyphenEdit = static_cast<minikin::HyphenEdit>(paint->getHyphenEdit());
-    const minikin::StartHyphenEdit startHyphen = minikin::startHyphenEdit(hyphenEdit);
-    const minikin::EndHyphenEdit endHyphen = minikin::endHyphenEdit(hyphenEdit);
+    const minikin::StartHyphenEdit startHyphen = paint->getStartHyphenEdit();
+    const minikin::EndHyphenEdit endHyphen = paint->getEndHyphenEdit();
 
     return minikin::Layout::measureText(textBuf, range, bidiFlags, minikinPaint, startHyphen,
                                         endHyphen, advances);
diff --git a/libs/hwui/hwui/Paint.h b/libs/hwui/hwui/Paint.h
index 601b3c2..9b2fa9d 100644
--- a/libs/hwui/hwui/Paint.h
+++ b/libs/hwui/hwui/Paint.h
@@ -27,6 +27,7 @@
 
 #include <minikin/FontFamily.h>
 #include <minikin/FamilyVariant.h>
+#include <minikin/Hyphenator.h>
 
 namespace android {
 
@@ -89,9 +90,25 @@
 
     minikin::FamilyVariant getFamilyVariant() const { return mFamilyVariant; }
 
-    void setHyphenEdit(uint32_t hyphen) { mHyphenEdit = hyphen; }
+    void setStartHyphenEdit(uint32_t startHyphen) {
+        mHyphenEdit = minikin::packHyphenEdit(
+            static_cast<minikin::StartHyphenEdit>(startHyphen),
+            minikin::endHyphenEdit(mHyphenEdit));
+    }
 
-    uint32_t getHyphenEdit() const { return mHyphenEdit; }
+    void setEndHyphenEdit(uint32_t endHyphen) {
+        mHyphenEdit = minikin::packHyphenEdit(
+            minikin::startHyphenEdit(mHyphenEdit),
+            static_cast<minikin::EndHyphenEdit>(endHyphen));
+    }
+
+    minikin::StartHyphenEdit getStartHyphenEdit() const {
+        return minikin::startHyphenEdit(mHyphenEdit);
+    }
+
+    minikin::EndHyphenEdit getEndHyphenEdit() const {
+        return minikin::endHyphenEdit(mHyphenEdit);
+    }
 
     void setAndroidTypeface(Typeface* typeface) { mTypeface = typeface; }
 
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index a00a36f..721a115 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -25,6 +25,7 @@
 #include <SkPictureRecorder.h>
 #include "TreeInfo.h"
 #include "VectorDrawable.h"
+#include "thread/CommonPool.h"
 #include "utils/TraceUtils.h"
 
 #include <unistd.h>
@@ -49,10 +50,6 @@
     unpinImages();
 }
 
-TaskManager* SkiaPipeline::getTaskManager() {
-    return mRenderThread.cacheManager().getTaskManager();
-}
-
 void SkiaPipeline::onDestroyHardwareResources() {
     unpinImages();
     mRenderThread.cacheManager().trimStaleResources();
@@ -225,42 +222,21 @@
     }
 }
 
-class SkiaPipeline::SavePictureProcessor : public TaskProcessor<bool> {
-public:
-    explicit SavePictureProcessor(TaskManager* taskManager) : TaskProcessor<bool>(taskManager) {}
-
-    struct SavePictureTask : public Task<bool> {
-        sk_sp<SkData> data;
-        std::string filename;
-    };
-
-    void savePicture(const sk_sp<SkData>& data, const std::string& filename) {
-        sp<SavePictureTask> task(new SavePictureTask());
-        task->data = data;
-        task->filename = filename;
-        TaskProcessor<bool>::add(task);
-    }
-
-    virtual void onProcess(const sp<Task<bool>>& task) override {
-        ATRACE_NAME("SavePictureTask");
-        SavePictureTask* t = static_cast<SavePictureTask*>(task.get());
-
-        if (0 == access(t->filename.c_str(), F_OK)) {
-            task->setResult(false);
+static void savePictureAsync(const sk_sp<SkData>& data, const std::string& filename) {
+    CommonPool::post([data, filename] {
+        if (0 == access(filename.c_str(), F_OK)) {
             return;
         }
 
-        SkFILEWStream stream(t->filename.c_str());
+        SkFILEWStream stream(filename.c_str());
         if (stream.isValid()) {
-            stream.write(t->data->data(), t->data->size());
+            stream.write(data->data(), data->size());
             stream.flush();
             SkDebugf("SKP Captured Drawing Output (%d bytes) for frame. %s", stream.bytesWritten(),
-                     t->filename.c_str());
+                     filename.c_str());
         }
-
-        task->setResult(true);
-    }
-};
+    });
+}
 
 SkCanvas* SkiaPipeline::tryCapture(SkSurface* surface) {
     if (CC_UNLIKELY(Properties::skpCaptureEnabled)) {
@@ -297,16 +273,10 @@
                 ATRACE_END();
 
                 // offload saving to file in a different thread
-                if (!mSavePictureProcessor.get()) {
-                    TaskManager* taskManager = getTaskManager();
-                    mSavePictureProcessor = new SavePictureProcessor(
-                            taskManager->canRunTasks() ? taskManager : nullptr);
-                }
                 if (1 == mCaptureSequence) {
-                    mSavePictureProcessor->savePicture(data, mCapturedFile);
+                    savePictureAsync(data, mCapturedFile);
                 } else {
-                    mSavePictureProcessor->savePicture(
-                            data,
+                    savePictureAsync(data,
                             mCapturedFile + "_" + std::to_string(mCaptureSequence));
                 }
                 mCaptureSequence--;
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.h b/libs/hwui/pipeline/skia/SkiaPipeline.h
index 7381e04..41d8646 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.h
@@ -33,8 +33,6 @@
     explicit SkiaPipeline(renderthread::RenderThread& thread);
     virtual ~SkiaPipeline();
 
-    TaskManager* getTaskManager() override;
-
     void onDestroyHardwareResources() override;
 
     bool pinImages(std::vector<SkImage*>& mutableImages) override;
@@ -157,11 +155,7 @@
      *  mCaptureSequence counts how many frames are left to take in the sequence.
      */
     int mCaptureSequence = 0;
-    /**
-     *  mSavePictureProcessor is used to run the file saving code in a separate thread.
-     */
-    class SavePictureProcessor;
-    sp<SavePictureProcessor> mSavePictureProcessor;
+
     /**
      *  mRecorder holds the current picture recorder. We could store it on the stack to support
      *  parallel tryCapture calls (not really needed).
diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp
index 6c04232..8b02c11 100644
--- a/libs/hwui/renderthread/CacheManager.cpp
+++ b/libs/hwui/renderthread/CacheManager.cpp
@@ -23,6 +23,7 @@
 #include "pipeline/skia/SkiaMemoryTracer.h"
 #include "Properties.h"
 #include "renderstate/RenderState.h"
+#include "thread/CommonPool.h"
 
 #include <GrContextOptions.h>
 #include <SkExecutor.h>
@@ -76,29 +77,15 @@
     mGrContext->setResourceCacheLimits(mMaxResources, mMaxResourceBytes);
 }
 
-class CacheManager::SkiaTaskProcessor : public TaskProcessor<bool>, public SkExecutor {
+class CommonPoolExecutor : public SkExecutor {
 public:
-    explicit SkiaTaskProcessor(TaskManager* taskManager) : TaskProcessor<bool>(taskManager) {}
-
-    // This is really a Task<void> but that doesn't really work when Future<>
-    // expects to be able to get/set a value
-    struct SkiaTask : public Task<bool> {
-        std::function<void()> func;
-    };
-
     virtual void add(std::function<void(void)> func) override {
-        sp<SkiaTask> task(new SkiaTask());
-        task->func = func;
-        TaskProcessor<bool>::add(task);
-    }
-
-    virtual void onProcess(const sp<Task<bool> >& task) override {
-        SkiaTask* t = static_cast<SkiaTask*>(task.get());
-        t->func();
-        task->setResult(true);
+        CommonPool::post(std::move(func));
     }
 };
 
+static CommonPoolExecutor sDefaultExecutor;
+
 void CacheManager::configureContext(GrContextOptions* contextOptions, const void* identity, ssize_t size) {
     contextOptions->fAllowPathMaskCaching = true;
 
@@ -107,12 +94,7 @@
     // provided to Skia.
     contextOptions->fGlyphCacheTextureMaximumBytes = GrNextSizePow2(mMaxSurfaceArea);
 
-    if (mTaskManager.canRunTasks()) {
-        if (!mTaskProcessor.get()) {
-            mTaskProcessor = new SkiaTaskProcessor(&mTaskManager);
-        }
-        contextOptions->fExecutor = mTaskProcessor.get();
-    }
+    contextOptions->fExecutor = &sDefaultExecutor;
 
     auto& cache = skiapipeline::ShaderCache::get();
     cache.initShaderDiskCache(identity, size);
diff --git a/libs/hwui/renderthread/CacheManager.h b/libs/hwui/renderthread/CacheManager.h
index 66f04f1..b0286e8 100644
--- a/libs/hwui/renderthread/CacheManager.h
+++ b/libs/hwui/renderthread/CacheManager.h
@@ -24,8 +24,6 @@
 #include <vector>
 
 #include "pipeline/skia/VectorDrawableAtlas.h"
-#include "thread/TaskManager.h"
-#include "thread/TaskProcessor.h"
 
 namespace android {
 
@@ -54,8 +52,6 @@
     size_t getCacheSize() const { return mMaxResourceBytes; }
     size_t getBackgroundCacheSize() const { return mBackgroundResourceBytes; }
 
-    TaskManager* getTaskManager() { return &mTaskManager; }
-
 private:
     friend class RenderThread;
 
@@ -78,10 +74,6 @@
     };
 
     sp<skiapipeline::VectorDrawableAtlas> mVectorDrawableAtlas;
-
-    class SkiaTaskProcessor;
-    sp<SkiaTaskProcessor> mTaskProcessor;
-    TaskManager mTaskManager;
 };
 
 } /* namespace renderthread */
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 091775dbe7..baa41c1 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -27,8 +27,10 @@
 #include "pipeline/skia/SkiaOpenGLPipeline.h"
 #include "pipeline/skia/SkiaPipeline.h"
 #include "pipeline/skia/SkiaVulkanPipeline.h"
+#include "thread/CommonPool.h"
 #include "utils/GLUtils.h"
 #include "utils/TimeUtils.h"
+#include "utils/TraceUtils.h"
 #include "../Properties.h"
 
 #include <cutils/properties.h>
@@ -103,7 +105,7 @@
         , mOpaque(!translucent)
         , mAnimationContext(contextFactory->createAnimationContext(mRenderThread.timeLord()))
         , mJankTracker(&thread.globalProfileData(), thread.mainDisplayInfo())
-        , mProfiler(mJankTracker.frames())
+        , mProfiler(mJankTracker.frames(), thread.timeLord().frameIntervalNanos())
         , mContentDrawBounds(0, 0, 0, 0)
         , mRenderPipeline(std::move(renderPipeline)) {
     rootRenderNode->makeRoot();
@@ -603,31 +605,14 @@
     if (mFrameFences.size()) {
         ATRACE_CALL();
         for (auto& fence : mFrameFences) {
-            fence->getResult();
+            fence.get();
         }
         mFrameFences.clear();
     }
 }
 
-class CanvasContext::FuncTaskProcessor : public TaskProcessor<bool> {
-public:
-    explicit FuncTaskProcessor(TaskManager* taskManager) : TaskProcessor<bool>(taskManager) {}
-
-    virtual void onProcess(const sp<Task<bool> >& task) override {
-        FuncTask* t = static_cast<FuncTask*>(task.get());
-        t->func();
-        task->setResult(true);
-    }
-};
-
 void CanvasContext::enqueueFrameWork(std::function<void()>&& func) {
-    if (!mFrameWorkProcessor.get()) {
-        mFrameWorkProcessor = new FuncTaskProcessor(mRenderPipeline->getTaskManager());
-    }
-    sp<FuncTask> task(new FuncTask());
-    task->func = func;
-    mFrameFences.push_back(task);
-    mFrameWorkProcessor->add(task);
+    mFrameFences.push_back(CommonPool::async(std::move(func)));
 }
 
 int64_t CanvasContext::getFrameNumber() {
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 4da0eac..abca342 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -28,8 +28,6 @@
 #include "ReliableSurface.h"
 #include "renderthread/RenderTask.h"
 #include "renderthread/RenderThread.h"
-#include "thread/Task.h"
-#include "thread/TaskProcessor.h"
 
 #include <EGL/egl.h>
 #include <SkBitmap.h>
@@ -42,6 +40,7 @@
 #include <set>
 #include <string>
 #include <vector>
+#include <future>
 
 namespace android {
 namespace uirenderer {
@@ -274,15 +273,7 @@
     // Stores the bounds of the main content.
     Rect mContentDrawBounds;
 
-    // TODO: This is really a Task<void> but that doesn't really work
-    // when Future<> expects to be able to get/set a value
-    struct FuncTask : public Task<bool> {
-        std::function<void()> func;
-    };
-    class FuncTaskProcessor;
-
-    std::vector<sp<FuncTask>> mFrameFences;
-    sp<TaskProcessor<bool>> mFrameWorkProcessor;
+    std::vector<std::future<void>> mFrameFences;
     std::unique_ptr<IRenderPipeline> mRenderPipeline;
 
     std::vector<std::function<void(int64_t)>> mFrameCompleteCallbacks;
diff --git a/libs/hwui/renderthread/IRenderPipeline.h b/libs/hwui/renderthread/IRenderPipeline.h
index 2cfc8df3..0502eb8 100644
--- a/libs/hwui/renderthread/IRenderPipeline.h
+++ b/libs/hwui/renderthread/IRenderPipeline.h
@@ -75,7 +75,6 @@
     virtual void renderLayers(const LightGeometry& lightGeometry,
                               LayerUpdateQueue* layerUpdateQueue, bool opaque,
                               const LightInfo& lightInfo) = 0;
-    virtual TaskManager* getTaskManager() = 0;
     virtual bool createOrUpdateLayer(RenderNode* node, const DamageAccumulator& damageAccumulator,
                                      ErrorHandler* errorHandler) = 0;
     virtual bool pinImages(std::vector<SkImage*>& mutableImages) = 0;
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 34f76d9..1bcb819 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -31,6 +31,7 @@
 #include "renderthread/RenderThread.h"
 #include "utils/Macros.h"
 #include "utils/TimeUtils.h"
+#include "utils/TraceUtils.h"
 
 #include <ui/GraphicBuffer.h>
 
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 08edd20..def805a 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -28,6 +28,7 @@
 #include "renderstate/RenderState.h"
 #include "utils/FatVector.h"
 #include "utils/TimeUtils.h"
+#include "utils/TraceUtils.h"
 
 #ifdef HWUI_GLES_WRAP_ENABLED
 #include "debug/GlesDriver.h"
@@ -52,9 +53,6 @@
 // using just a few large reads.
 static const size_t EVENT_BUFFER_SIZE = 100;
 
-// Slight delay to give the UI time to push us a new frame before we replay
-static const nsecs_t DISPATCH_FRAME_CALLBACKS_DELAY = milliseconds_to_nanoseconds(4);
-
 static bool gHasRenderThreadInstance = false;
 
 static JVMAttachHook gOnStartHook = nullptr;
@@ -171,6 +169,7 @@
     mDisplayInfo = DeviceInfo::get()->displayInfo();
     nsecs_t frameIntervalNanos = static_cast<nsecs_t>(1000000000 / mDisplayInfo.fps);
     mTimeLord.setFrameInterval(frameIntervalNanos);
+    mDispatchFrameDelay = static_cast<nsecs_t>(frameIntervalNanos * .25f);
     initializeDisplayEventReceiver();
     mEglManager = new EglManager();
     mRenderState = new RenderState(*this);
@@ -311,7 +310,7 @@
         if (mTimeLord.vsyncReceived(vsyncEvent) && !mFrameCallbackTaskPending) {
             ATRACE_NAME("queue mFrameCallbackTask");
             mFrameCallbackTaskPending = true;
-            nsecs_t runAt = (vsyncEvent + DISPATCH_FRAME_CALLBACKS_DELAY);
+            nsecs_t runAt = (vsyncEvent + mDispatchFrameDelay);
             queue().postAt(runAt, [this]() { dispatchFrameCallbacks(); });
         }
     }
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 329b4b9..9298be6 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -24,6 +24,7 @@
 #include "TimeLord.h"
 #include "thread/ThreadBase.h"
 #include "WebViewFunctorManager.h"
+#include "utils/TimeUtils.h"
 
 #include <GrContext.h>
 #include <SkBitmap.h>
@@ -164,6 +165,7 @@
     bool mFrameCallbackTaskPending;
 
     TimeLord mTimeLord;
+    nsecs_t mDispatchFrameDelay = 4_ms;
     RenderState* mRenderState;
     EglManager* mEglManager;
     WebViewFunctorManager& mFunctorManager;
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 6dacc7a..9916da5 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -23,6 +23,7 @@
 #include "RenderThread.h"
 #include "renderstate/RenderState.h"
 #include "utils/FatVector.h"
+#include "utils/TraceUtils.h"
 
 #include <GrBackendSemaphore.h>
 #include <GrBackendSurface.h>
diff --git a/libs/hwui/tests/macrobench/TestSceneRunner.cpp b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
index 0e61899e..b45dbc8 100644
--- a/libs/hwui/tests/macrobench/TestSceneRunner.cpp
+++ b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
@@ -21,6 +21,7 @@
 #include "tests/common/TestContext.h"
 #include "tests/common/TestScene.h"
 #include "tests/common/scenes/TestSceneBase.h"
+#include "utils/TraceUtils.h"
 
 #include <benchmark/benchmark.h>
 #include <gui/Surface.h>
diff --git a/libs/hwui/tests/microbench/TaskManagerBench.cpp b/libs/hwui/tests/microbench/TaskManagerBench.cpp
deleted file mode 100644
index 4153bae..0000000
--- a/libs/hwui/tests/microbench/TaskManagerBench.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#include <benchmark/benchmark.h>
-
-#include "thread/Task.h"
-#include "thread/TaskManager.h"
-#include "thread/TaskProcessor.h"
-#include "thread/ThreadBase.h"
-
-#include <atomic>
-#include <vector>
-
-using namespace android;
-using namespace android::uirenderer;
-
-class TrivialTask : public Task<char> {};
-
-class TrivialProcessor : public TaskProcessor<char> {
-public:
-    explicit TrivialProcessor(TaskManager* manager) : TaskProcessor(manager) {}
-    virtual ~TrivialProcessor() {}
-    virtual void onProcess(const sp<Task<char>>& task) override {
-        TrivialTask* t = static_cast<TrivialTask*>(task.get());
-        t->setResult(reinterpret_cast<intptr_t>(t) % 16 == 0 ? 'a' : 'b');
-    }
-};
-
-class TestThread : public ThreadBase, public virtual RefBase {};
-
-void BM_TaskManager_allocateTask(benchmark::State& state) {
-    std::vector<sp<TrivialTask>> tasks;
-    tasks.reserve(state.max_iterations);
-
-    while (state.KeepRunning()) {
-        tasks.emplace_back(new TrivialTask);
-        benchmark::DoNotOptimize(tasks.back());
-    }
-}
-BENCHMARK(BM_TaskManager_allocateTask);
-
-void BM_TaskManager_enqueueTask(benchmark::State& state) {
-    TaskManager taskManager;
-    sp<TrivialProcessor> processor(new TrivialProcessor(&taskManager));
-    std::vector<sp<TrivialTask>> tasks;
-    tasks.reserve(state.max_iterations);
-
-    while (state.KeepRunning()) {
-        tasks.emplace_back(new TrivialTask);
-        benchmark::DoNotOptimize(tasks.back());
-        processor->add(tasks.back());
-    }
-
-    for (sp<TrivialTask>& task : tasks) {
-        task->getResult();
-    }
-}
-BENCHMARK(BM_TaskManager_enqueueTask);
-
-void BM_TaskManager_enqueueRunDeleteTask(benchmark::State& state) {
-    TaskManager taskManager;
-    sp<TrivialProcessor> processor(new TrivialProcessor(&taskManager));
-    std::vector<sp<TrivialTask>> tasks;
-    tasks.reserve(state.max_iterations);
-
-    while (state.KeepRunning()) {
-        tasks.emplace_back(new TrivialTask);
-        benchmark::DoNotOptimize(tasks.back());
-        processor->add(tasks.back());
-    }
-    state.ResumeTiming();
-    for (sp<TrivialTask>& task : tasks) {
-        benchmark::DoNotOptimize(task->getResult());
-    }
-    tasks.clear();
-    state.PauseTiming();
-}
-BENCHMARK(BM_TaskManager_enqueueRunDeleteTask);
-
-void BM_Thread_enqueueTask(benchmark::State& state) {
-    sp<TestThread> thread{new TestThread};
-    thread->start();
-
-    atomic_int counter(0);
-    int expected = 0;
-    while (state.KeepRunning()) {
-        expected++;
-        thread->queue().post([&counter]() { counter++; });
-    }
-    thread->queue().runSync([]() {});
-
-    thread->requestExit();
-    thread->join();
-    if (counter != expected) {
-        printf("Ran %d lambads, should have been %d\n", counter.load(), expected);
-    }
-}
-BENCHMARK(BM_Thread_enqueueTask);
-
-void BM_Thread_enqueueRunDeleteTask(benchmark::State& state) {
-    sp<TestThread> thread{new TestThread};
-    thread->start();
-    std::vector<std::future<int>> tasks;
-    tasks.reserve(state.max_iterations);
-
-    int expected = 0;
-    while (state.KeepRunning()) {
-        tasks.emplace_back(thread->queue().async([expected]() -> int { return expected + 1; }));
-        expected++;
-    }
-    state.ResumeTiming();
-    expected = 0;
-    for (auto& future : tasks) {
-        if (future.get() != ++expected) {
-            printf("Mismatch expected %d vs. observed %d\n", expected, future.get());
-        }
-    }
-    tasks.clear();
-    state.PauseTiming();
-}
-BENCHMARK(BM_Thread_enqueueRunDeleteTask);
\ No newline at end of file
diff --git a/libs/hwui/tests/scripts/prep_generic.sh b/libs/hwui/tests/scripts/prep_generic.sh
new file mode 100755
index 0000000..223bf37
--- /dev/null
+++ b/libs/hwui/tests/scripts/prep_generic.sh
@@ -0,0 +1,249 @@
+#
+# 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.
+#
+
+#################################################################
+###
+###  DO NOT MODIFY THIS FILE
+###  This is a copy of androidx's benchmark/lockClocks.sh
+###  Make changes there instead then copy here!
+###
+#################################################################
+
+# This script can be used to lock device clocks to stable levels for comparing
+# different versions of software.  Since the clock levels are not necessarily
+# indicative of real world behavior, this should **never** be used to compare
+# performance between different device models.
+
+# Fun notes for maintaining this file:
+#      `expr` can deal with ints > INT32_MAX, but if compares cannot. This is why we use MHz.
+#      `expr` can sometimes evaluate right-to-left. This is why we use parens.
+#      Everything below the initial host-check isn't bash - Android uses mksh
+#      mksh allows `\n` in an echo, bash doesn't
+#      can't use `awk`
+
+CPU_TARGET_FREQ_PERCENT=50
+GPU_TARGET_FREQ_PERCENT=50
+
+if [ "`command -v getprop`" == "" ]; then
+    if [ -n "`command -v adb`" ]; then
+        echo ""
+        echo "Pushing $0 and running it on device..."
+        dest=/data/local/tmp/`basename $0`
+        adb push $0 ${dest}
+        adb shell ${dest}
+        adb shell rm ${dest}
+        exit
+    else
+        echo "Could not find adb. Options are:"
+        echo "  1. Ensure adb is on your \$PATH"
+        echo "  2. Use './gradlew lockClocks'"
+        echo "  3. Manually adb push this script to your device, and run it there"
+        exit -1
+    fi
+fi
+
+# require root
+if [ "`id -u`" -ne "0" ]; then
+    echo "Not running as root, cannot lock clocks, aborting"
+    exit -1
+fi
+
+DEVICE=`getprop ro.product.device`
+MODEL=`getprop ro.product.model`
+
+# Find CPU max frequency, and lock big cores to an available frequency
+# that's >= $CPU_TARGET_FREQ_PERCENT% of max. Disable other cores.
+function_lock_cpu() {
+    CPU_BASE=/sys/devices/system/cpu
+    GOV=cpufreq/scaling_governor
+
+    # Find max CPU freq, and associated list of available freqs
+    cpuMaxFreq=0
+    cpuAvailFreqCmpr=0
+    cpuAvailFreq=0
+    enableIndices=''
+    disableIndices=''
+    cpu=0
+    while [ -f ${CPU_BASE}/cpu${cpu}/online ]; do
+        # enable core, so we can find its frequencies
+        echo 1 > ${CPU_BASE}/cpu${cpu}/online
+
+        maxFreq=`cat ${CPU_BASE}/cpu$cpu/cpufreq/cpuinfo_max_freq`
+        availFreq=`cat ${CPU_BASE}/cpu$cpu/cpufreq/scaling_available_frequencies`
+        availFreqCmpr=${availFreq// /-}
+
+        if [ ${maxFreq} -gt ${cpuMaxFreq} ]; then
+            # new highest max freq, look for cpus with same max freq and same avail freq list
+            cpuMaxFreq=${maxFreq}
+            cpuAvailFreq=${availFreq}
+            cpuAvailFreqCmpr=${availFreqCmpr}
+
+            if [ -z ${disableIndices} ]; then
+                disableIndices="$enableIndices"
+            else
+                disableIndices="$disableIndices $enableIndices"
+            fi
+            enableIndices=${cpu}
+        elif [ ${maxFreq} == ${cpuMaxFreq} ] && [ ${availFreqCmpr} == ${cpuAvailFreqCmpr} ]; then
+            enableIndices="$enableIndices $cpu"
+        else
+            disableIndices="$disableIndices $cpu"
+        fi
+        cpu=$(($cpu + 1))
+    done
+
+    # Chose a frequency to lock to that's >= $CPU_TARGET_FREQ_PERCENT% of max
+    # (below, 100M = 1K for KHz->MHz * 100 for %)
+    TARGET_FREQ_MHZ=`expr \( ${cpuMaxFreq} \* ${CPU_TARGET_FREQ_PERCENT} \) \/ 100000`
+    chosenFreq=0
+    for freq in ${cpuAvailFreq}; do
+        freqMhz=`expr ${freq} \/ 1000`
+        if [ ${freqMhz} -ge ${TARGET_FREQ_MHZ} ]; then
+            chosenFreq=${freq}
+            break
+        fi
+    done
+
+    # enable 'big' CPUs
+    for cpu in ${enableIndices}; do
+        freq=${CPU_BASE}/cpu$cpu/cpufreq
+
+        echo 1 > ${CPU_BASE}/cpu${cpu}/online
+        echo userspace > ${CPU_BASE}/cpu${cpu}/${GOV}
+        echo ${chosenFreq} > ${freq}/scaling_max_freq
+        echo ${chosenFreq} > ${freq}/scaling_min_freq
+        echo ${chosenFreq} > ${freq}/scaling_setspeed
+
+        # validate setting the freq worked
+        obsCur=`cat ${freq}/scaling_cur_freq`
+        obsMin=`cat ${freq}/scaling_min_freq`
+        obsMax=`cat ${freq}/scaling_max_freq`
+        if [ obsCur -ne ${chosenFreq} ] || [ obsMin -ne ${chosenFreq} ] || [ obsMax -ne ${chosenFreq} ]; then
+            echo "Failed to set CPU$cpu to $chosenFreq Hz! Aborting..."
+            echo "scaling_cur_freq = $obsCur"
+            echo "scaling_min_freq = $obsMin"
+            echo "scaling_max_freq = $obsMax"
+            exit -1
+        fi
+    done
+
+    # disable other CPUs (Note: important to enable big cores first!)
+    for cpu in ${disableIndices}; do
+      echo 0 > ${CPU_BASE}/cpu${cpu}/online
+    done
+
+    echo "\nLocked CPUs ${enableIndices// /,} to $chosenFreq / $maxFreq KHz"
+    echo "Disabled CPUs ${disableIndices// /,}"
+}
+
+# If we have a Qualcomm GPU, find its max frequency, and lock to
+# an available frequency that's >= GPU_TARGET_FREQ_PERCENT% of max.
+function_lock_gpu_kgsl() {
+    if [ ! -d /sys/class/kgsl/kgsl-3d0/ ]; then
+        # not kgsl, abort
+        echo "\nCurrently don't support locking GPU clocks of $MODEL ($DEVICE)"
+        return -1
+    fi
+    if [ ${DEVICE} == "walleye" ] || [ ${DEVICE} == "taimen" ]; then
+        # Workaround crash
+        echo "\nUnable to lock GPU clocks of $MODEL ($DEVICE)"
+        return -1
+    fi
+
+    GPU_BASE=/sys/class/kgsl/kgsl-3d0
+
+    gpuMaxFreq=0
+    gpuAvailFreq=`cat $GPU_BASE/devfreq/available_frequencies`
+    for freq in ${gpuAvailFreq}; do
+        if [ ${freq} -gt ${gpuMaxFreq} ]; then
+            gpuMaxFreq=${freq}
+        fi
+    done
+
+    # (below, 100M = 1M for MHz * 100 for %)
+    TARGET_FREQ_MHZ=`expr \( ${gpuMaxFreq} \* ${GPU_TARGET_FREQ_PERCENT} \) \/ 100000000`
+
+    chosenFreq=${gpuMaxFreq}
+    index=0
+    chosenIndex=0
+    for freq in ${gpuAvailFreq}; do
+        freqMhz=`expr ${freq} \/ 1000000`
+        if [ ${freqMhz} -ge ${TARGET_FREQ_MHZ} ] && [ ${chosenFreq} -ge ${freq} ]; then
+            # note avail freq are generally in reverse order, so we don't break out of this loop
+            chosenFreq=${freq}
+            chosenIndex=${index}
+        fi
+        index=$(($index + 1))
+    done
+    lastIndex=$(($index - 1))
+
+    firstFreq=`echo $gpuAvailFreq | cut -d" " -f1`
+
+    if [ ${gpuMaxFreq} != ${firstFreq} ]; then
+        # pwrlevel is index of desired freq among available frequencies, from highest to lowest.
+        # If gpuAvailFreq appears to be in-order, reverse the index
+        chosenIndex=$(($lastIndex - $chosenIndex))
+    fi
+
+    echo 0 > ${GPU_BASE}/bus_split
+    echo 1 > ${GPU_BASE}/force_clk_on
+    echo 10000 > ${GPU_BASE}/idle_timer
+
+    echo performance > ${GPU_BASE}/devfreq/governor
+
+    # NOTE: we store in min/max twice, because we don't know if we're increasing
+    # or decreasing, and it's invalid to try and set min > max, or max < min
+    echo ${chosenFreq} > ${GPU_BASE}/devfreq/min_freq
+    echo ${chosenFreq} > ${GPU_BASE}/devfreq/max_freq
+    echo ${chosenFreq} > ${GPU_BASE}/devfreq/min_freq
+    echo ${chosenFreq} > ${GPU_BASE}/devfreq/max_freq
+    echo ${chosenIndex} > ${GPU_BASE}/min_pwrlevel
+    echo ${chosenIndex} > ${GPU_BASE}/max_pwrlevel
+    echo ${chosenIndex} > ${GPU_BASE}/min_pwrlevel
+    echo ${chosenIndex} > ${GPU_BASE}/max_pwrlevel
+
+    obsCur=`cat ${GPU_BASE}/devfreq/cur_freq`
+    obsMin=`cat ${GPU_BASE}/devfreq/min_freq`
+    obsMax=`cat ${GPU_BASE}/devfreq/max_freq`
+    if [ obsCur -ne ${chosenFreq} ] || [ obsMin -ne ${chosenFreq} ] || [ obsMax -ne ${chosenFreq} ]; then
+        echo "Failed to set GPU to $chosenFreq Hz! Aborting..."
+        echo "cur_freq = $obsCur"
+        echo "min_freq = $obsMin"
+        echo "max_freq = $obsMax"
+        echo "index = $chosenIndex"
+        exit -1
+    fi
+    echo "\nLocked GPU to $chosenFreq / $gpuMaxFreq Hz"
+}
+
+# kill processes that manage thermals / scaling
+stop thermal-engine
+stop perfd
+stop vendor.thermal-engine
+stop vendor.perfd
+
+function_lock_cpu
+
+function_lock_gpu_kgsl
+
+# Memory bus - hardcoded per-device for now
+if [ ${DEVICE} == "marlin" ] || [ ${DEVICE} == "sailfish" ]; then
+    echo 13763 > /sys/class/devfreq/soc:qcom,gpubw/max_freq
+else
+    echo "\nUnable to lock memory bus of $MODEL ($DEVICE)."
+fi
+
+echo "\n$DEVICE clocks have been locked - to reset, reboot the device\n"
\ No newline at end of file
diff --git a/libs/hwui/tests/scripts/prep_ryu.sh b/libs/hwui/tests/scripts/prep_ryu.sh
old mode 100644
new mode 100755
diff --git a/libs/hwui/tests/unit/CommonPoolTests.cpp b/libs/hwui/tests/unit/CommonPoolTests.cpp
new file mode 100644
index 0000000..c564ed6
--- /dev/null
+++ b/libs/hwui/tests/unit/CommonPoolTests.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include <gtest/gtest.h>
+
+#include "thread/CommonPool.h"
+
+#include <array>
+#include <condition_variable>
+#include <set>
+#include <thread>
+#include "unistd.h"
+
+using namespace android;
+using namespace android::uirenderer;
+
+TEST(CommonPool, post) {
+    std::atomic_bool ran(false);
+    CommonPool::post([&ran] { ran = true; });
+    for (int i = 0; !ran && i < 1000; i++) {
+        usleep(1);
+    }
+    EXPECT_TRUE(ran) << "Failed to flip atomic after 1 second";
+}
+
+TEST(CommonPool, threadCount) {
+    std::set<pid_t> threads;
+    std::array<std::future<pid_t>, 64> futures;
+    for (int i = 0; i < futures.size(); i++) {
+        futures[i] = CommonPool::async([] {
+            usleep(10);
+            return gettid();
+        });
+    }
+    for (auto& f : futures) {
+        threads.insert(f.get());
+    }
+    EXPECT_EQ(threads.size(), CommonPool::THREAD_COUNT);
+    EXPECT_EQ(0, threads.count(gettid()));
+}
+
+TEST(CommonPool, singleThread) {
+    std::mutex mutex;
+    std::condition_variable fence;
+    bool isProcessing = false;
+    bool queuedSecond = false;
+
+    auto f1 = CommonPool::async([&] {
+        {
+            std::unique_lock lock{mutex};
+            isProcessing = true;
+            fence.notify_all();
+            while (!queuedSecond) {
+                fence.wait(lock);
+            }
+        }
+        return gettid();
+    });
+
+    {
+        std::unique_lock lock{mutex};
+        while (!isProcessing) {
+            fence.wait(lock);
+        }
+    }
+
+    auto f2 = CommonPool::async([] {
+        return gettid();
+    });
+
+    {
+        std::unique_lock lock{mutex};
+        queuedSecond = true;
+        fence.notify_all();
+    }
+
+    auto tid1 = f1.get();
+    auto tid2 = f2.get();
+    EXPECT_EQ(tid1, tid2);
+    EXPECT_NE(gettid(), tid1);
+}
+
+TEST(CommonPool, fullQueue) {
+    std::mutex lock;
+    std::condition_variable fence;
+    bool signaled = false;
+    static constexpr auto QUEUE_COUNT = CommonPool::THREAD_COUNT + CommonPool::QUEUE_SIZE + 10;
+    std::atomic_int queuedCount{0};
+    std::array<std::future<void>, QUEUE_COUNT> futures;
+
+    std::thread queueThread{[&] {
+        for (int i = 0; i < QUEUE_COUNT; i++) {
+            futures[i] = CommonPool::async([&] {
+                std::unique_lock _lock{lock};
+                while (!signaled) {
+                    fence.wait(_lock);
+                }
+            });
+            queuedCount++;
+        }
+    }};
+
+    int previous;
+    do {
+        previous = queuedCount.load();
+        usleep(10000);
+    } while (previous != queuedCount.load());
+
+    EXPECT_GT(queuedCount.load(), CommonPool::QUEUE_SIZE);
+    EXPECT_LT(queuedCount.load(), QUEUE_COUNT);
+
+    {
+        std::unique_lock _lock{lock};
+        signaled = true;
+        fence.notify_all();
+    }
+
+    queueThread.join();
+    EXPECT_EQ(queuedCount.load(), QUEUE_COUNT);
+
+    // Ensure all our tasks are finished before return as they have references to the stack
+    for (auto& f : futures) {
+        f.get();
+    }
+}
\ No newline at end of file
diff --git a/libs/hwui/tests/unit/main.cpp b/libs/hwui/tests/unit/main.cpp
index 63d1540..83d888c 100644
--- a/libs/hwui/tests/unit/main.cpp
+++ b/libs/hwui/tests/unit/main.cpp
@@ -22,9 +22,6 @@
 #include "debug/NullGlesDriver.h"
 #include "hwui/Typeface.h"
 #include "tests/common/LeakChecker.h"
-#include "thread/Task.h"
-#include "thread/TaskManager.h"
-#include "thread/TaskProcessor.h"
 
 #include <signal.h>
 
diff --git a/libs/hwui/thread/Barrier.h b/libs/hwui/thread/Barrier.h
deleted file mode 100644
index bb750ca..0000000
--- a/libs/hwui/thread/Barrier.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#ifndef ANDROID_HWUI_BARRIER_H
-#define ANDROID_HWUI_BARRIER_H
-
-#include <utils/Condition.h>
-
-namespace android {
-namespace uirenderer {
-
-class Barrier {
-public:
-    explicit Barrier(Condition::WakeUpType type = Condition::WAKE_UP_ALL)
-            : mType(type), mOpened(false) {}
-    ~Barrier() {}
-
-    void open() {
-        Mutex::Autolock l(mLock);
-        mOpened = true;
-        mCondition.signal(mType);
-    }
-
-    void wait() const {
-        Mutex::Autolock l(mLock);
-        while (!mOpened) {
-            mCondition.wait(mLock);
-        }
-    }
-
-private:
-    Condition::WakeUpType mType;
-    volatile bool mOpened;
-    mutable Mutex mLock;
-    mutable Condition mCondition;
-};
-
-}  // namespace uirenderer
-}  // namespace android
-
-#endif  // ANDROID_HWUI_BARRIER_H
diff --git a/libs/hwui/thread/CommonPool.cpp b/libs/hwui/thread/CommonPool.cpp
new file mode 100644
index 0000000..7f94a15
--- /dev/null
+++ b/libs/hwui/thread/CommonPool.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include "CommonPool.h"
+
+#include <sys/resource.h>
+#include <utils/Trace.h>
+#include "renderthread/RenderThread.h"
+
+#include <array>
+
+namespace android {
+namespace uirenderer {
+
+CommonPool::CommonPool() {
+    ATRACE_CALL();
+
+    CommonPool* pool = this;
+    // Create 2 workers
+    for (int i = 0; i < THREAD_COUNT; i++) {
+        std::thread worker([pool, i] {
+            {
+                std::array<char, 20> name{"hwuiTask"};
+                snprintf(name.data(), name.size(), "hwuiTask%d", i);
+                auto self = pthread_self();
+                pthread_setname_np(self, name.data());
+                setpriority(PRIO_PROCESS, 0, PRIORITY_FOREGROUND);
+                auto startHook = renderthread::RenderThread::getOnStartHook();
+                if (startHook) {
+                    startHook(name.data());
+                }
+            }
+            pool->workerLoop();
+        });
+        worker.detach();
+    }
+}
+
+void CommonPool::post(Task&& task) {
+    static CommonPool pool;
+    pool.enqueue(std::move(task));
+}
+
+void CommonPool::enqueue(Task&& task) {
+    std::unique_lock lock(mLock);
+    while (!mWorkQueue.hasSpace()) {
+        lock.unlock();
+        usleep(100);
+        lock.lock();
+    }
+    mWorkQueue.push(std::move(task));
+    if (mWaitingThreads == THREAD_COUNT || (mWaitingThreads > 0 && mWorkQueue.size() > 1)) {
+        mCondition.notify_one();
+    }
+}
+
+void CommonPool::workerLoop() {
+    std::unique_lock lock(mLock);
+    while (true) {
+        if (!mWorkQueue.hasWork()) {
+            mWaitingThreads++;
+            mCondition.wait(lock);
+            mWaitingThreads--;
+        }
+        // Need to double-check that work is still available now that we have the lock
+        // It may have already been grabbed by a different thread
+        while (mWorkQueue.hasWork()) {
+            auto work = mWorkQueue.pop();
+            lock.unlock();
+            work();
+            lock.lock();
+        }
+    }
+}
+
+}  // namespace uirenderer
+}  // namespace android
\ No newline at end of file
diff --git a/libs/hwui/thread/CommonPool.h b/libs/hwui/thread/CommonPool.h
new file mode 100644
index 0000000..aef2990
--- /dev/null
+++ b/libs/hwui/thread/CommonPool.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#ifndef FRAMEWORKS_BASE_COMMONPOOL_H
+#define FRAMEWORKS_BASE_COMMONPOOL_H
+
+#include "utils/Macros.h"
+
+#include <log/log.h>
+
+#include <condition_variable>
+#include <functional>
+#include <future>
+#include <mutex>
+
+namespace android {
+namespace uirenderer {
+
+template <class T, int SIZE>
+class ArrayQueue {
+    PREVENT_COPY_AND_ASSIGN(ArrayQueue);
+    static_assert(SIZE > 0, "Size must be positive");
+
+public:
+    ArrayQueue() = default;
+    ~ArrayQueue() = default;
+
+    constexpr size_t capacity() const { return SIZE; }
+    constexpr bool hasWork() const { return mHead != mTail; }
+    constexpr bool hasSpace() const { return ((mHead + 1) % SIZE) != mTail; }
+    constexpr int size() const {
+        if (mHead > mTail) {
+            return mHead - mTail;
+        } else {
+            return mTail - mHead + SIZE;
+        }
+    }
+
+    constexpr void push(T&& t) {
+        int newHead = (mHead + 1) % SIZE;
+        LOG_ALWAYS_FATAL_IF(newHead == mTail, "no space");
+
+        mBuffer[mHead] = std::move(t);
+        mHead = newHead;
+    }
+
+    constexpr T&& pop() {
+        LOG_ALWAYS_FATAL_IF(mTail == mHead, "empty");
+        int index = mTail;
+        mTail = (mTail + 1) % SIZE;
+        return std::move(mBuffer[index]);
+    }
+
+private:
+    T mBuffer[SIZE];
+    int mHead = 0;
+    int mTail = 0;
+};
+
+class CommonPool {
+    PREVENT_COPY_AND_ASSIGN(CommonPool);
+
+public:
+    using Task = std::function<void()>;
+    static constexpr auto THREAD_COUNT = 2;
+    static constexpr auto QUEUE_SIZE = 128;
+
+    static void post(Task&& func);
+
+    template <class F>
+    static auto async(F&& func) -> std::future<decltype(func())> {
+        typedef std::packaged_task<decltype(func())()> task_t;
+        auto task = std::make_shared<task_t>(std::forward<F>(func));
+        post([task]() { std::invoke(*task); });
+        return task->get_future();
+    }
+
+    template <class F>
+    static auto runSync(F&& func) -> decltype(func()) {
+        std::packaged_task<decltype(func())()> task{std::forward<F>(func)};
+        post([&task]() { std::invoke(task); });
+        return task.get_future().get();
+    };
+
+private:
+    CommonPool();
+    ~CommonPool() {}
+
+    void enqueue(Task&&);
+
+    void workerLoop();
+
+    std::mutex mLock;
+    std::condition_variable mCondition;
+    int mWaitingThreads = 0;
+    ArrayQueue<Task, QUEUE_SIZE> mWorkQueue;
+};
+
+}  // namespace uirenderer
+}  // namespace android
+
+#endif  // FRAMEWORKS_BASE_COMMONPOOL_H
diff --git a/libs/hwui/thread/Future.h b/libs/hwui/thread/Future.h
deleted file mode 100644
index df53348e..0000000
--- a/libs/hwui/thread/Future.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#ifndef ANDROID_HWUI_FUTURE_H
-#define ANDROID_HWUI_FUTURE_H
-
-#include <utils/RefBase.h>
-
-#include "Barrier.h"
-
-namespace android {
-namespace uirenderer {
-
-template <typename T>
-class Future : public LightRefBase<Future<T> > {
-public:
-    explicit Future(Condition::WakeUpType type = Condition::WAKE_UP_ONE)
-            : mBarrier(type), mResult() {}
-    ~Future() {}
-
-    /**
-     * Returns the result of this future, blocking if
-     * the result is not available yet.
-     */
-    T get() const {
-        mBarrier.wait();
-        return mResult;
-    }
-
-    /**
-     * This method must be called only once.
-     */
-    void produce(T result) {
-        mResult = result;
-        mBarrier.open();
-    }
-
-private:
-    Barrier mBarrier;
-    T mResult;
-};
-
-}  // namespace uirenderer
-}  // namespace android
-
-#endif  // ANDROID_HWUI_FUTURE_H
diff --git a/libs/hwui/thread/Signal.h b/libs/hwui/thread/Signal.h
deleted file mode 100644
index 6d33ac4..0000000
--- a/libs/hwui/thread/Signal.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#ifndef ANDROID_HWUI_SIGNAL_H
-#define ANDROID_HWUI_SIGNAL_H
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <utils/threads.h>
-
-namespace android {
-namespace uirenderer {
-
-class Signal {
-public:
-    explicit Signal(Condition::WakeUpType type = Condition::WAKE_UP_ALL)
-            : mType(type), mSignaled(false) {}
-    ~Signal() {}
-
-    void signal() {
-        {
-            Mutex::Autolock l(mLock);
-            mSignaled = true;
-        }
-        mCondition.signal(mType);
-    }
-
-    void wait() {
-        Mutex::Autolock l(mLock);
-        while (!mSignaled) {
-            mCondition.wait(mLock);
-        }
-        mSignaled = false;
-    }
-
-private:
-    Condition::WakeUpType mType;
-    volatile bool mSignaled;
-    mutable Mutex mLock;
-    mutable Condition mCondition;
-};
-
-}  // namespace uirenderer
-}  // namespace android
-
-#endif  // ANDROID_HWUI_SIGNAL_H
diff --git a/libs/hwui/thread/Task.h b/libs/hwui/thread/Task.h
deleted file mode 100644
index 228ce19..0000000
--- a/libs/hwui/thread/Task.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#ifndef ANDROID_HWUI_TASK_H
-#define ANDROID_HWUI_TASK_H
-
-#include <utils/RefBase.h>
-#include <utils/Trace.h>
-
-#include "Future.h"
-
-namespace android {
-namespace uirenderer {
-
-class TaskBase : public RefBase {
-public:
-    TaskBase() {}
-    virtual ~TaskBase() {}
-};
-
-template <typename T>
-class Task : public TaskBase {
-public:
-    Task() : mFuture(new Future<T>()) {}
-    virtual ~Task() {}
-
-    T getResult() const { return mFuture->get(); }
-
-    void setResult(T result) { mFuture->produce(result); }
-
-protected:
-    const sp<Future<T> >& future() const { return mFuture; }
-
-private:
-    sp<Future<T> > mFuture;
-};
-
-}  // namespace uirenderer
-}  // namespace android
-
-#endif  // ANDROID_HWUI_TASK_H
diff --git a/libs/hwui/thread/TaskManager.cpp b/libs/hwui/thread/TaskManager.cpp
deleted file mode 100644
index de10ff1..0000000
--- a/libs/hwui/thread/TaskManager.cpp
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#include <sys/resource.h>
-#include <sys/sysinfo.h>
-
-#include "Task.h"
-#include "TaskManager.h"
-#include "TaskProcessor.h"
-#include "utils/MathUtils.h"
-#include "renderthread/RenderThread.h"
-
-namespace android {
-namespace uirenderer {
-
-///////////////////////////////////////////////////////////////////////////////
-// Manager
-///////////////////////////////////////////////////////////////////////////////
-
-TaskManager::TaskManager() {
-    // Get the number of available CPUs. This value does not change over time.
-    int cpuCount = sysconf(_SC_NPROCESSORS_CONF);
-
-    // Really no point in making more than 2 of these worker threads, but
-    // we do want to limit ourselves to 1 worker thread on dual-core devices.
-    int workerCount = cpuCount > 2 ? 2 : 1;
-    for (int i = 0; i < workerCount; i++) {
-        String8 name;
-        name.appendFormat("hwuiTask%d", i + 1);
-        mThreads.push_back(new WorkerThread(name));
-    }
-}
-
-TaskManager::~TaskManager() {
-    for (size_t i = 0; i < mThreads.size(); i++) {
-        mThreads[i]->exit();
-    }
-}
-
-bool TaskManager::canRunTasks() const {
-    return mThreads.size() > 0;
-}
-
-void TaskManager::stop() {
-    for (size_t i = 0; i < mThreads.size(); i++) {
-        mThreads[i]->exit();
-    }
-}
-
-bool TaskManager::addTaskBase(const sp<TaskBase>& task, const sp<TaskProcessorBase>& processor) {
-    if (mThreads.size() > 0) {
-        TaskWrapper wrapper(task, processor);
-
-        size_t minQueueSize = INT_MAX;
-        sp<WorkerThread> thread;
-
-        for (size_t i = 0; i < mThreads.size(); i++) {
-            if (mThreads[i]->getTaskCount() < minQueueSize) {
-                thread = mThreads[i];
-                minQueueSize = mThreads[i]->getTaskCount();
-            }
-        }
-
-        return thread->addTask(wrapper);
-    }
-    return false;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Thread
-///////////////////////////////////////////////////////////////////////////////
-
-status_t TaskManager::WorkerThread::readyToRun() {
-    setpriority(PRIO_PROCESS, 0, PRIORITY_FOREGROUND);
-    auto onStartHook = renderthread::RenderThread::getOnStartHook();
-    if (onStartHook) {
-        onStartHook(mName.c_str());
-    }
-
-    return NO_ERROR;
-}
-
-bool TaskManager::WorkerThread::threadLoop() {
-    mSignal.wait();
-    std::vector<TaskWrapper> tasks;
-    {
-        Mutex::Autolock l(mLock);
-        tasks.swap(mTasks);
-    }
-
-    for (size_t i = 0; i < tasks.size(); i++) {
-        const TaskWrapper& task = tasks[i];
-        task.mProcessor->process(task.mTask);
-    }
-
-    return true;
-}
-
-bool TaskManager::WorkerThread::addTask(const TaskWrapper& task) {
-    if (!isRunning()) {
-        run(mName.string(), PRIORITY_DEFAULT);
-    } else if (exitPending()) {
-        return false;
-    }
-
-    {
-        Mutex::Autolock l(mLock);
-        mTasks.push_back(task);
-    }
-    mSignal.signal();
-
-    return true;
-}
-
-size_t TaskManager::WorkerThread::getTaskCount() const {
-    Mutex::Autolock l(mLock);
-    return mTasks.size();
-}
-
-void TaskManager::WorkerThread::exit() {
-    requestExit();
-    mSignal.signal();
-}
-
-}  // namespace uirenderer
-}  // namespace android
diff --git a/libs/hwui/thread/TaskManager.h b/libs/hwui/thread/TaskManager.h
deleted file mode 100644
index 6c67222..0000000
--- a/libs/hwui/thread/TaskManager.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#ifndef ANDROID_HWUI_TASK_MANAGER_H
-#define ANDROID_HWUI_TASK_MANAGER_H
-
-#include <utils/Mutex.h>
-#include <utils/String8.h>
-#include <utils/Thread.h>
-
-#include "Signal.h"
-
-#include <vector>
-
-namespace android {
-namespace uirenderer {
-
-template <typename T>
-class Task;
-class TaskBase;
-
-template <typename T>
-class TaskProcessor;
-class TaskProcessorBase;
-
-class TaskManager {
-public:
-    TaskManager();
-    ~TaskManager();
-
-    /**
-     * Returns true if this task  manager can run tasks,
-     * false otherwise. This method will typically return
-     * false on a single CPU core device.
-     */
-    bool canRunTasks() const;
-
-    /**
-     * Stops all allocated threads. Adding tasks will start
-     * the threads again as necessary.
-     */
-    void stop();
-
-private:
-    template <typename T>
-    friend class TaskProcessor;
-
-    template <typename T>
-    bool addTask(const sp<Task<T> >& task, const sp<TaskProcessor<T> >& processor) {
-        return addTaskBase(sp<TaskBase>(task), sp<TaskProcessorBase>(processor));
-    }
-
-    bool addTaskBase(const sp<TaskBase>& task, const sp<TaskProcessorBase>& processor);
-
-    struct TaskWrapper {
-        TaskWrapper() : mTask(), mProcessor() {}
-
-        TaskWrapper(const sp<TaskBase>& task, const sp<TaskProcessorBase>& processor)
-                : mTask(task), mProcessor(processor) {}
-
-        sp<TaskBase> mTask;
-        sp<TaskProcessorBase> mProcessor;
-    };
-
-    class WorkerThread : public Thread {
-    public:
-        explicit WorkerThread(const String8& name)
-                : Thread(false), mSignal(Condition::WAKE_UP_ONE), mName(name) {}
-
-        bool addTask(const TaskWrapper& task);
-        size_t getTaskCount() const;
-        void exit();
-
-    private:
-        virtual status_t readyToRun() override;
-        virtual bool threadLoop() override;
-
-        // Lock for the list of tasks
-        mutable Mutex mLock;
-        std::vector<TaskWrapper> mTasks;
-
-        // Signal used to wake up the thread when a new
-        // task is available in the list
-        mutable Signal mSignal;
-
-        const String8 mName;
-    };
-
-    std::vector<sp<WorkerThread> > mThreads;
-};
-
-}  // namespace uirenderer
-}  // namespace android
-
-#endif  // ANDROID_HWUI_TASK_MANAGER_H
diff --git a/libs/hwui/thread/TaskProcessor.h b/libs/hwui/thread/TaskProcessor.h
deleted file mode 100644
index 8117ae6..0000000
--- a/libs/hwui/thread/TaskProcessor.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#ifndef ANDROID_HWUI_TASK_PROCESSOR_H
-#define ANDROID_HWUI_TASK_PROCESSOR_H
-
-#include <utils/RefBase.h>
-
-#include "Task.h"
-#include "TaskManager.h"
-
-namespace android {
-namespace uirenderer {
-
-class TaskProcessorBase : public RefBase {
-public:
-    TaskProcessorBase() {}
-    virtual ~TaskProcessorBase(){};
-
-    virtual void process(const sp<TaskBase>& task) = 0;
-};
-
-template <typename T>
-class TaskProcessor : public TaskProcessorBase {
-public:
-    explicit TaskProcessor(TaskManager* manager) : mManager(manager) {}
-    virtual ~TaskProcessor() {}
-
-    void add(const sp<Task<T> >& task) {
-        if (!addImpl(task)) {
-            // fall back to immediate execution
-            process(task);
-        }
-    }
-
-    virtual void onProcess(const sp<Task<T> >& task) = 0;
-
-private:
-    bool addImpl(const sp<Task<T> >& task);
-
-    virtual void process(const sp<TaskBase>& task) override {
-        sp<Task<T> > realTask = static_cast<Task<T>*>(task.get());
-        // This is the right way to do it but sp<> doesn't play nice
-        // sp<Task<T> > realTask = static_cast<sp<Task<T> > >(task);
-        onProcess(realTask);
-    }
-
-    TaskManager* mManager;
-};
-
-template <typename T>
-bool TaskProcessor<T>::addImpl(const sp<Task<T> >& task) {
-    if (mManager) {
-        sp<TaskProcessor<T> > self(this);
-        return mManager->addTask(task, self);
-    }
-    return false;
-}
-
-};  // namespace uirenderer
-};  // namespace android
-
-#endif  // ANDROID_HWUI_TASK_PROCESSOR_H
diff --git a/libs/hwui/thread/WorkQueue.h b/libs/hwui/thread/WorkQueue.h
index 7a6e638..42f8503 100644
--- a/libs/hwui/thread/WorkQueue.h
+++ b/libs/hwui/thread/WorkQueue.h
@@ -26,7 +26,6 @@
 #include <functional>
 #include <future>
 #include <mutex>
-#include <variant>
 #include <vector>
 
 namespace android::uirenderer {
diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java
index 446ea85..9013a96 100644
--- a/location/java/android/location/GnssMeasurement.java
+++ b/location/java/android/location/GnssMeasurement.java
@@ -49,8 +49,7 @@
     private int mMultipathIndicator;
     private double mSnrInDb;
     private double mAutomaticGainControlLevelInDb;
-    private int mCodeType;
-    private String mOtherCodeTypeName;
+    @NonNull private String mCodeType;
 
     // The following enumerations must be in sync with the values declared in gps.h
 
@@ -209,113 +208,6 @@
     public static final int ADR_STATE_HALF_CYCLE_REPORTED = (1<<4);
 
     /**
-     * GNSS measurement code type.
-     * @hide
-     */
-    @IntDef(prefix = { "CODE_TYPE_" }, value = {
-            CODE_TYPE_UNKNOWN, CODE_TYPE_A, CODE_TYPE_B, CODE_TYPE_C, CODE_TYPE_I, CODE_TYPE_L,
-            CODE_TYPE_M, CODE_TYPE_N, CODE_TYPE_P, CODE_TYPE_Q, CODE_TYPE_S, CODE_TYPE_W,
-            CODE_TYPE_X, CODE_TYPE_Y, CODE_TYPE_Z, CODE_TYPE_OTHER
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface CodeType {}
-
-    /** The GNSS Measurement's code type is unknown. */
-    public static final int CODE_TYPE_UNKNOWN = -1;
-
-    /**
-     * The GNSS Measurement's code type is one of the following: GALILEO E1A, GALILEO E6A, IRNSS
-     * L5A, IRNSS SA.
-     */
-    public static final int CODE_TYPE_A = 0;
-
-    /**
-     * The GNSS Measurement's code type is one of the following: GALILEO E1B, GALILEO E6B, IRNSS
-     * L5B, IRNSS SB.
-     */
-    public static final int CODE_TYPE_B = 1;
-
-    /**
-     * The GNSS Measurement's code type is one of the following: GPS L1 C/A,  GPS L2 C/A, GLONASS G1
-     * C/A, GLONASS G2 C/A, GALILEO E1C, GALILEO E6C, SBAS L1 C/A, QZSS L1 C/A, IRNSS L5C.
-     */
-    public static final int CODE_TYPE_C = 2;
-
-    /**
-     * The GNSS Measurement's code type is one of the following: GPS L5 I, GLONASS G3 I, GALILEO E5a
-     * I, GALILEO E5b I, GALILEO E5a+b I, SBAS L5 I, QZSS L5 I, BDS B1 I, BDS B2 I, BDS B3 I.
-     */
-    public static final int CODE_TYPE_I = 3;
-
-    /**
-     * The GNSS Measurement's code type is one of the following: GPS L1C (P), GPS L2C (L), QZSS L1C
-     * (P), QZSS L2C (L), LEX(6) L.
-     */
-    public static final int CODE_TYPE_L = 4;
-
-    /**
-     * The GNSS Measurement's code type is one of the following: GPS L1M, GPS L2M.
-     */
-    public static final int CODE_TYPE_M = 5;
-
-    /**
-     * The GNSS Measurement's code type is one of the following: GPS L1P, GPS L2P, GLONASS G1P,
-     * GLONASS G2P.
-     */
-    public static final int CODE_TYPE_P = 6;
-
-    /**
-     * The GNSS Measurement's code type is one of the following: GPS L5 Q, GLONASS G3 Q, GALILEO E5a
-     * Q, GALILEO E5b Q, GALILEO E5a+b Q, SBAS L5 Q, QZSS L5 Q, BDS B1 Q, BDS B2 Q, BDS B3 Q.
-     */
-    public static final int CODE_TYPE_Q = 7;
-
-    /**
-     * The GNSS Measurement's code type is one of the following: GPS L1C (D), GPS L2C (M), QZSS L1C
-     * (D), QZSS L2C (M), LEX(6) S.
-     */
-    public static final int CODE_TYPE_S = 8;
-
-    /**
-     * The GNSS Measurement's code type is one of the following: GPS L1 Z-tracking, GPS L2
-     * Z-tracking.
-     */
-    public static final int CODE_TYPE_W = 9;
-
-    /**
-     * The GNSS Measurement's code type is one of the following: GPS L1C (D+P), GPS L2C (M+L), GPS
-     * L5 (I+Q), GLONASS G3 (I+Q), GALILEO E1 (B+C), GALILEO E5a (I+Q), GALILEO E5b (I+Q), GALILEO
-     * E5a+b(I+Q), GALILEO E6 (B+C), SBAS L5 (I+Q), QZSS L1C (D+P), QZSS L2C (M+L), QZSS L5 (I+Q),
-     * LEX(6) (S+L), BDS B1 (I+Q), BDS B2 (I+Q), BDS B3 (I+Q), IRNSS L5 (B+C).
-     */
-    public static final int CODE_TYPE_X = 10;
-
-    /**
-     * The GNSS Measurement's code type is one of the following: GPS L1Y, GPS L2Y.
-     */
-    public static final int CODE_TYPE_Y = 11;
-
-    /**
-     * The GNSS Measurement's code type is one of the following: GALILEO E1 (A+B+C), GALILEO E6
-     * (A+B+C), QZSS L1-SAIF.
-     */
-    public static final int CODE_TYPE_Z = 12;
-
-    /**
-     * The GNSS Measurement's code type is one of the following: GPS L1 codeless, GPS L2 codeless.
-     */
-    public static final int CODE_TYPE_N = 13;
-
-    /**
-     * Other code type that does not belong to any of the above code types.
-     *
-     * This code type is used in the case that the code type being tracked in this measurement, as
-     * classified by RINEX standards, does not fit into one of the existing enumerated values. When
-     * this code type is set, the field otherCodeTypeName must specify the new code type.
-     */
-    public static final int CODE_TYPE_OTHER = 255;
-
-    /**
      * All the 'Accumulated Delta Range' flags.
      * @hide
      */
@@ -363,7 +255,6 @@
         mSnrInDb = measurement.mSnrInDb;
         mAutomaticGainControlLevelInDb = measurement.mAutomaticGainControlLevelInDb;
         mCodeType = measurement.mCodeType;
-        mOtherCodeTypeName = measurement.mOtherCodeTypeName;
     }
 
     /**
@@ -1414,9 +1305,50 @@
      *
      * <p>Similar to the Attribute field described in RINEX 3.03, e.g., in Tables 4-10, and Table
      * A2 at the RINEX 3.03 Update 1 Document.
+     *
+     * <p>Returns "A" for GALILEO E1A, GALILEO E6A, IRNSS L5A, IRNSS SA.
+     *
+     * <p>Returns "B" for GALILEO E1B, GALILEO E6B, IRNSS L5B, IRNSS SB.
+     *
+     * <p>Returns "C" for GPS L1 C/A,  GPS L2 C/A, GLONASS G1 C/A, GLONASS G2 C/A, GALILEO E1C,
+     * GALILEO E6C, SBAS L1 C/A, QZSS L1 C/A, IRNSS L5C.
+     *
+     * <p>Returns "I" for GPS L5 I, GLONASS G3 I, GALILEO E5a I, GALILEO E5b I, GALILEO E5a+b I,
+     * SBAS L5 I, QZSS L5 I, BDS B1 I, BDS B2 I, BDS B3 I.
+     *
+     * <p>Returns "L" for GPS L1C (P), GPS L2C (L), QZSS L1C (P), QZSS L2C (L), LEX(6) L.
+     *
+     * <p>Returns "M" for GPS L1M, GPS L2M.
+     *
+     * <p>Returns "N" for GPS L1 codeless, GPS L2 codeless.
+     *
+     * <p>Returns "P" for GPS L1P, GPS L2P, GLONASS G1P, GLONASS G2P.
+     *
+     * <p>Returns "Q" for GPS L5 Q, GLONASS G3 Q, GALILEO E5a Q, GALILEO E5b Q, GALILEO E5a+b Q,
+     * SBAS L5 Q, QZSS L5 Q, BDS B1 Q, BDS B2 Q, BDS B3 Q.
+     *
+     * <p>Returns "S" for GPS L1C (D), GPS L2C (M), QZSS L1C (D), QZSS L2C (M), LEX(6) S.
+     *
+     * <p>Returns "W" for GPS L1 Z-tracking, GPS L2 Z-tracking.
+     *
+     * <p>Returns "X" for GPS L1C (D+P), GPS L2C (M+L), GPS L5 (I+Q), GLONASS G3 (I+Q), GALILEO
+     * E1 (B+C), GALILEO E5a (I+Q), GALILEO E5b (I+Q), GALILEO E5a+b(I+Q), GALILEO E6 (B+C), SBAS
+     * L5 (I+Q), QZSS L1C (D+P), QZSS L2C (M+L), QZSS L5 (I+Q), LEX(6) (S+L), BDS B1 (I+Q), BDS
+     * B2 (I+Q), BDS B3 (I+Q), IRNSS L5 (B+C).
+     *
+     * <p>Returns "Y" for GPS L1Y, GPS L2Y.
+     *
+     * <p>Returns "Z" for GALILEO E1 (A+B+C), GALILEO E6 (A+B+C), QZSS L1-SAIF.
+     *
+     * <p>Returns "UNKNOWN" if the GNSS Measurement's code type is unknown.
+     *
+     * <p>This is used to specify the observation descriptor defined in GNSS Observation Data File
+     * Header Section Description in the RINEX standard (Version 3.XX), in cases where the code type
+     * does not align with the above listed values. For example, if a code type "G" is added, this
+     * string shall be set to "G".
      */
-    @CodeType
-    public int getCodeType() {
+    @NonNull
+    public String getCodeType() {
         return mCodeType;
     }
 
@@ -1426,7 +1358,7 @@
      * @hide
      */
     @TestApi
-    public void setCodeType(@CodeType int codeType) {
+    public void setCodeType(@NonNull String codeType) {
         setFlag(HAS_CODE_TYPE);
         mCodeType = codeType;
     }
@@ -1439,74 +1371,7 @@
     @TestApi
     public void resetCodeType() {
         resetFlag(HAS_CODE_TYPE);
-        mCodeType = CODE_TYPE_UNKNOWN;
-    }
-
-    /**
-     * Gets the GNSS measurement's code type name when the code type is {@link #CODE_TYPE_OTHER}.
-     *
-     * <p>This is used to specify the observation descriptor defined in GNSS Observation Data File
-     * Header Section Description in the RINEX standard (Version 3.XX), in cases where the code type
-     * does not align with an existing Android enumerated value. For example, if a code type "G" is
-     * added, this string shall be set to "G".
-     */
-    @NonNull
-    public String getOtherCodeTypeName() {
-        return mOtherCodeTypeName;
-    }
-
-    /**
-     * Sets the GNSS measurement's code type name when the code type is {@link #CODE_TYPE_OTHER}.
-     *
-     * @hide
-     */
-    @TestApi
-    public void setOtherCodeTypeName(@NonNull String otherCodeTypeName) {
-        mOtherCodeTypeName = otherCodeTypeName;
-    }
-
-    /**
-     * Gets a string representation of the 'code type'.
-     *
-     * <p>For internal and logging use only.
-     */
-    private String getCodeTypeString() {
-        switch (mCodeType) {
-            case CODE_TYPE_UNKNOWN:
-                return "CODE_TYPE_UNKNOWN";
-            case CODE_TYPE_A:
-                return "CODE_TYPE_A";
-            case CODE_TYPE_B:
-                return "CODE_TYPE_B";
-            case CODE_TYPE_C:
-                return "CODE_TYPE_C";
-            case CODE_TYPE_I:
-                return "CODE_TYPE_I";
-            case CODE_TYPE_L:
-                return "CODE_TYPE_L";
-            case CODE_TYPE_M:
-                return "CODE_TYPE_M";
-            case CODE_TYPE_N:
-                return "CODE_TYPE_N";
-            case CODE_TYPE_P:
-                return "CODE_TYPE_P";
-            case CODE_TYPE_Q:
-                return "CODE_TYPE_Q";
-            case CODE_TYPE_S:
-                return "CODE_TYPE_S";
-            case CODE_TYPE_W:
-                return "CODE_TYPE_W";
-            case CODE_TYPE_X:
-                return "CODE_TYPE_X";
-            case CODE_TYPE_Y:
-                return "CODE_TYPE_Y";
-            case CODE_TYPE_Z:
-                return "CODE_TYPE_Z";
-            case CODE_TYPE_OTHER:
-                return "CODE_TYPE_OTHER";
-            default:
-                return "<Invalid: " + mCodeType + ">";
-        }
+        mCodeType = "UNKNOWN";
     }
 
     public static final @android.annotation.NonNull Creator<GnssMeasurement> CREATOR = new Creator<GnssMeasurement>() {
@@ -1534,8 +1399,7 @@
             gnssMeasurement.mMultipathIndicator = parcel.readInt();
             gnssMeasurement.mSnrInDb = parcel.readDouble();
             gnssMeasurement.mAutomaticGainControlLevelInDb = parcel.readDouble();
-            gnssMeasurement.mCodeType = parcel.readInt();
-            gnssMeasurement.mOtherCodeTypeName = parcel.readString();
+            gnssMeasurement.mCodeType = parcel.readString();
 
             return gnssMeasurement;
         }
@@ -1568,8 +1432,7 @@
         parcel.writeInt(mMultipathIndicator);
         parcel.writeDouble(mSnrInDb);
         parcel.writeDouble(mAutomaticGainControlLevelInDb);
-        parcel.writeInt(mCodeType);
-        parcel.writeString(mOtherCodeTypeName);
+        parcel.writeString(mCodeType);
     }
 
     @Override
@@ -1647,10 +1510,7 @@
         builder.append(String.format(
                 format,
                 "CodeType",
-                hasCodeType() ? getCodeTypeString() : null));
-        builder.append(String.format(
-                format,
-                "OtherCodeTypeName", mOtherCodeTypeName));
+                hasCodeType() ? mCodeType : null));
 
         return builder.toString();
     }
@@ -1676,7 +1536,6 @@
         resetSnrInDb();
         resetAutomaticGainControlLevel();
         resetCodeType();
-        setOtherCodeTypeName("");
     }
 
     private void setFlag(int flag) {
diff --git a/location/java/android/location/GpsStatus.java b/location/java/android/location/GpsStatus.java
index 4e37654..609a15e 100644
--- a/location/java/android/location/GpsStatus.java
+++ b/location/java/android/location/GpsStatus.java
@@ -30,7 +30,6 @@
  * <p>This class is used in conjunction with the {@link Listener} interface.
  *
  * @deprecated use {@link GnssStatus} and {@link GnssStatus.Callback}.
- * @removed
  */
 @Deprecated
 public final class GpsStatus {
@@ -113,7 +112,6 @@
     /**
      * Used for receiving notifications when GPS status has changed.
      * @deprecated use {@link GnssStatus.Callback} instead.
-     * @removed
      */
     @Deprecated
     public interface Listener {
@@ -144,7 +142,6 @@
      * You can implement this interface and call {@link LocationManager#addNmeaListener}
      * to receive NMEA data from the GPS engine.
      * @deprecated use {@link OnNmeaMessageListener} instead.
-     * @removed
      */
     @Deprecated
     public interface NmeaListener {
diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java
index ed74333..673b411 100644
--- a/location/java/android/location/Location.java
+++ b/location/java/android/location/Location.java
@@ -150,7 +150,7 @@
     private Bundle mExtras = null;
 
     // A bitmask of fields present in this object (see HAS_* constants defined above).
-    private byte mFieldsMask = 0;
+    private int mFieldsMask = 0;
 
     /**
      * Construct a new Location with a named provider.
@@ -1137,7 +1137,7 @@
             l.mTime = in.readLong();
             l.mElapsedRealtimeNanos = in.readLong();
             l.mElapsedRealtimeUncertaintyNanos = in.readLong();
-            l.mFieldsMask = in.readByte();
+            l.mFieldsMask = in.readInt();
             l.mLatitude = in.readDouble();
             l.mLongitude = in.readDouble();
             l.mAltitude = in.readDouble();
@@ -1168,7 +1168,7 @@
         parcel.writeLong(mTime);
         parcel.writeLong(mElapsedRealtimeNanos);
         parcel.writeLong(mElapsedRealtimeUncertaintyNanos);
-        parcel.writeByte(mFieldsMask);
+        parcel.writeInt(mFieldsMask);
         parcel.writeDouble(mLatitude);
         parcel.writeDouble(mLongitude);
         parcel.writeDouble(mAltitude);
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index db6a4d0..050b2ec 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -167,11 +167,21 @@
 
     /**
      * Broadcast intent action when the set of enabled location providers changes. To check the
-     * status of a provider, use {@link #isProviderEnabled(String)}.
+     * status of a provider, use {@link #isProviderEnabled(String)}. Depending on API level, may
+     * include a string intent extra, {@link #EXTRA_PROVIDER_NAME}, with the name of the provider
+     * whose state has changed. See {@link #EXTRA_PROVIDER_NAME} for the supported API level.
+     *
+     * @see #EXTRA_PROVIDER_NAME
      */
     public static final String PROVIDERS_CHANGED_ACTION = "android.location.PROVIDERS_CHANGED";
 
     /**
+     * Intent extra included with {@link #PROVIDERS_CHANGED_ACTION} broadcasts, containing the name
+     * of the location provider that has changed, to be used with location provider APIs.
+     */
+    public static final String EXTRA_PROVIDER_NAME = "android.location.extra.PROVIDER_NAME";
+
+    /**
      * Broadcast intent action when the device location mode changes. To check the location mode,
      * use {@link #isLocationEnabled()}.
      */
@@ -1360,10 +1370,10 @@
             @NonNull String provider, boolean enabled, @NonNull UserHandle userHandle) {
         checkProvider(provider);
 
-        return Settings.Secure.setLocationProviderEnabledForUser(
+        return Settings.Secure.putStringForUser(
                 mContext.getContentResolver(),
-                provider,
-                enabled,
+                Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
+                (enabled ? "+" : "-") + provider,
                 userHandle.getIdentifier());
     }
 
@@ -1749,7 +1759,6 @@
      *
      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
      * @deprecated use {@link #registerGnssStatusCallback(GnssStatus.Callback)} instead.
-     * @removed
      */
     @Deprecated
     @RequiresPermission(ACCESS_FINE_LOCATION)
@@ -1762,7 +1771,6 @@
      *
      * @param listener GPS status listener object to remove
      * @deprecated use {@link #unregisterGnssStatusCallback(GnssStatus.Callback)} instead.
-     * @removed
      */
     @Deprecated
     public void removeGpsStatusListener(GpsStatus.Listener listener) {}
@@ -2088,7 +2096,6 @@
      *
      * @param status object containing GPS status details, or null.
      * @return status object containing updated GPS status.
-     * @removed
      */
     @Deprecated
     @RequiresPermission(ACCESS_FINE_LOCATION)
diff --git a/location/java/android/location/SettingInjectorService.java b/location/java/android/location/SettingInjectorService.java
index c201770..d6f8a7c 100644
--- a/location/java/android/location/SettingInjectorService.java
+++ b/location/java/android/location/SettingInjectorService.java
@@ -16,6 +16,7 @@
 
 package android.location;
 
+import android.annotation.NonNull;
 import android.app.Service;
 import android.content.Context;
 import android.content.Intent;
@@ -58,17 +59,17 @@
  * </pre>
  * Here:
  * <ul>
- *     <li>title: The {@link android.preference.Preference#getTitle()} value. The title should make
- *     it clear which apps are affected by the setting, typically by including the name of the
- *     developer. For example, "Acme Corp. ads preferences." </li>
+ * <li>title: The {@link android.preference.Preference#getTitle()} value. The title should make
+ * it clear which apps are affected by the setting, typically by including the name of the
+ * developer. For example, "Acme Corp. ads preferences." </li>
  *
- *     <li>icon: The {@link android.preference.Preference#getIcon()} value. Typically this will be a
- *     generic icon for the developer rather than the icon for an individual app.</li>
+ * <li>icon: The {@link android.preference.Preference#getIcon()} value. Typically this will be a
+ * generic icon for the developer rather than the icon for an individual app.</li>
  *
- *     <li>settingsActivity: the activity which is launched to allow the user to modify the setting
- *     value.  The activity must be in the same package as the subclass of
- *     {@link SettingInjectorService}. The activity should use your own branding to help emphasize
- *     to the user that it is not part of the system settings.</li>
+ * <li>settingsActivity: the activity which is launched to allow the user to modify the setting
+ * value.  The activity must be in the same package as the subclass of
+ * {@link SettingInjectorService}. The activity should use your own branding to help emphasize
+ * to the user that it is not part of the system settings.</li>
  * </ul>
  *
  * To ensure a good user experience, your {@link android.app.Application#onCreate()},
@@ -206,6 +207,8 @@
      * Returns the {@link android.preference.Preference#getSummary()} value (allowed to be null or
      * empty). Should not perform unpredictably-long operations such as network access--see the
      * running-time comments in the class-level javadoc.
+     * <p/>
+     * This method is called on KitKat, and Q+ devices.
      *
      * @return the {@link android.preference.Preference#getSummary()} value
      */
@@ -234,7 +237,7 @@
     /**
      * Sends a broadcast to refresh the injected settings on location settings page.
      */
-    public static final void refreshSettings(Context context) {
+    public static final void refreshSettings(@NonNull Context context) {
         Intent intent = new Intent(ACTION_INJECTED_SETTING_CHANGED);
         context.sendBroadcast(intent);
     }
diff --git a/media/OWNERS b/media/OWNERS
index eb26367..72c8952 100644
--- a/media/OWNERS
+++ b/media/OWNERS
@@ -3,7 +3,9 @@
 elaurent@google.com
 etalvala@google.com
 gkasten@google.com
+hdmoon@google.com
 hunga@google.com
+insun@google.com
 jaewan@google.com
 jmtrivi@google.com
 jsharkey@android.com
diff --git a/media/apex/java/android/media/MediaSession2.java b/media/apex/java/android/media/MediaSession2.java
index 09ac9ca..d63de09 100644
--- a/media/apex/java/android/media/MediaSession2.java
+++ b/media/apex/java/android/media/MediaSession2.java
@@ -511,7 +511,8 @@
         }
 
         /**
-         * Set extras for the session token.
+         * Set extras for the session token. If null or not set, {@link Session2Token#getExtras()}
+         * will return {@link Bundle#EMPTY}.
          *
          * @return The Builder to allow chaining
          * @see Session2Token#getExtras()
diff --git a/media/apex/java/android/media/Session2Token.java b/media/apex/java/android/media/Session2Token.java
index dc970ae..d7cb978 100644
--- a/media/apex/java/android/media/Session2Token.java
+++ b/media/apex/java/android/media/Session2Token.java
@@ -216,10 +216,11 @@
 
     /**
      * @return extras of the token
+     * @see MediaSession2.Builder#setExtras(Bundle)
      */
-    @Nullable
+    @NonNull
     public Bundle getExtras() {
-        return mExtras;
+        return mExtras == null ? Bundle.EMPTY : mExtras;
     }
 
     Session2Link getSessionLink() {
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 7783a4d..6a595d2 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -3308,6 +3308,7 @@
 
     /**
      * @hide
+     * Unregisters an {@link AudioPolicy} asynchronously.
      * @param policy the non-null {@link AudioPolicy} to unregister.
      */
     @SystemApi
@@ -3329,6 +3330,27 @@
         }
     }
 
+    /**
+     * @hide
+     * Unregisters an {@link AudioPolicy} synchronously.
+     * This method also invalidates all {@link AudioRecord} and {@link AudioTrack} objects
+     * associated with mixes of this policy.
+     * @param policy the non-null {@link AudioPolicy} to unregister.
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+    public void unregisterAudioPolicy(@NonNull AudioPolicy policy) {
+        Preconditions.checkNotNull(policy, "Illegal null AudioPolicy argument");
+        final IAudioService service = getService();
+        try {
+            policy.invalidateCaptorsAndInjectors();
+            service.unregisterAudioPolicy(policy.cb());
+            policy.setRegistration(null);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     //====================================================================
     // Notification of playback activity & playback configuration
     /**
@@ -4144,6 +4166,10 @@
      /**
      * Indicate A2DP source or sink active device change and eventually suppress
      * the {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent.
+     * This operation is asynchronous but its execution will still be sequentially scheduled
+     * relative to calls to {@link #setBluetoothHearingAidDeviceConnectionState(BluetoothDevice,
+     * int, boolean, int)} and
+     * {@link #handleBluetoothA2dpDeviceConfigChange(BluetoothDevice)}.
      * @param device Bluetooth device connected/disconnected
      * @param state  new connection state (BluetoothProfile.STATE_xxx)
      * @param profile profile for the A2DP device
@@ -4157,18 +4183,16 @@
      * BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED intent.
      * {@hide}
      */
-    public int handleBluetoothA2dpActiveDeviceChange(
+    public void handleBluetoothA2dpActiveDeviceChange(
                 BluetoothDevice device, int state, int profile,
                 boolean suppressNoisyIntent, int a2dpVolume) {
         final IAudioService service = getService();
-        int delay = 0;
         try {
-            delay = service.handleBluetoothA2dpActiveDeviceChange(device,
+            service.handleBluetoothA2dpActiveDeviceChange(device,
                 state, profile, suppressNoisyIntent, a2dpVolume);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
-        return delay;
     }
 
     /** {@hide} */
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 09cfa95..41e059b 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -1014,9 +1014,9 @@
      * frame indicates the number of samples per channel, e.g. 100 frames for a stereo compressed
      * stream corresponds to 200 decoded interleaved PCM samples.
      * @param delayInFrames number of frames to be ignored at the beginning of the stream. A value
-     *     of 0 indicates no padding is to be applied.
-     * @param paddingInFrames number of frames to be ignored at the end of the stream. A value of 0
      *     of 0 indicates no delay is to be applied.
+     * @param paddingInFrames number of frames to be ignored at the end of the stream. A value of 0
+     *     of 0 indicates no padding is to be applied.
      */
     public void setOffloadDelayPadding(@IntRange(from = 0) int delayInFrames,
             @IntRange(from = 0) int paddingInFrames) {
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 4cd8971..23db27d 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -1359,7 +1359,7 @@
         if (file == null) {
             throw new NullPointerException("file cannot be null");
         }
-        initForFilename(file.getName());
+        initForFilename(file.getAbsolutePath());
     }
 
     /**
diff --git a/media/java/android/media/ExternalRingtonesCursorWrapper.java b/media/java/android/media/ExternalRingtonesCursorWrapper.java
index dd4c77a..ea63a3a 100644
--- a/media/java/android/media/ExternalRingtonesCursorWrapper.java
+++ b/media/java/android/media/ExternalRingtonesCursorWrapper.java
@@ -16,7 +16,6 @@
 
 package android.media;
 
-import android.content.ContentProvider;
 import android.database.Cursor;
 import android.database.CursorWrapper;
 import android.net.Uri;
@@ -28,19 +27,18 @@
  * @hide
  */
 public class ExternalRingtonesCursorWrapper extends CursorWrapper {
+    private Uri mUri;
 
-    private int mUserId;
-
-    public ExternalRingtonesCursorWrapper(Cursor cursor, int userId) {
+    public ExternalRingtonesCursorWrapper(Cursor cursor, Uri uri) {
         super(cursor);
-        mUserId = userId;
+        mUri = uri;
     }
 
     public String getString(int index) {
-        String result = super.getString(index);
         if (index == RingtoneManager.URI_COLUMN_INDEX) {
-            result = ContentProvider.maybeAddUserId(Uri.parse(result), mUserId).toString();
+            return mUri.toString();
+        } else {
+            return super.getString(index);
         }
-        return result;
     }
 }
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 0285667..c29f355 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -171,7 +171,7 @@
 
     void handleBluetoothA2dpDeviceConfigChange(in BluetoothDevice device);
 
-    int handleBluetoothA2dpActiveDeviceChange(in BluetoothDevice device,
+    void handleBluetoothA2dpActiveDeviceChange(in BluetoothDevice device,
             int state, int profile, boolean suppressNoisyIntent, int a2dpVolume);
 
     @UnsupportedAppUsage
@@ -199,6 +199,8 @@
 
     oneway void unregisterAudioPolicyAsync(in IAudioPolicyCallback pcb);
 
+    void unregisterAudioPolicy(in IAudioPolicyCallback pcb);
+
     int addMixForPolicy(in AudioPolicyConfig policyConfig, in IAudioPolicyCallback pcb);
 
     int removeMixForPolicy(in AudioPolicyConfig policyConfig, in IAudioPolicyCallback pcb);
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 4bc3897..2ec9355 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -3223,14 +3223,83 @@
         // These constants were originally in-line with OMX values, but this
         // correspondence is no longer maintained.
 
+        // Profiles and levels for AVC Codec, corresponding to the definitions in
+        // "SERIES H: AUDIOVISUAL AND MULTIMEDIA SYSTEMS,
+        // Infrastructure of audiovisual services – Coding of moving video
+        // Advanced video coding for generic audiovisual services"
+        // found at
+        // https://www.itu.int/rec/T-REC-H.264-201704-I
+
+        /**
+         * AVC Baseline profile.
+         * See definition in
+         * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>,
+         * Annex A.
+         */
         public static final int AVCProfileBaseline = 0x01;
+
+        /**
+         * AVC Main profile.
+         * See definition in
+         * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>,
+         * Annex A.
+         */
         public static final int AVCProfileMain     = 0x02;
+
+        /**
+         * AVC Extended profile.
+         * See definition in
+         * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>,
+         * Annex A.
+         */
         public static final int AVCProfileExtended = 0x04;
+
+        /**
+         * AVC High profile.
+         * See definition in
+         * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>,
+         * Annex A.
+         */
         public static final int AVCProfileHigh     = 0x08;
+
+        /**
+         * AVC High 10 profile.
+         * See definition in
+         * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>,
+         * Annex A.
+         */
         public static final int AVCProfileHigh10   = 0x10;
+
+        /**
+         * AVC High 4:2:2 profile.
+         * See definition in
+         * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>,
+         * Annex A.
+         */
         public static final int AVCProfileHigh422  = 0x20;
+
+        /**
+         * AVC High 4:4:4 profile.
+         * See definition in
+         * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>,
+         * Annex A.
+         */
         public static final int AVCProfileHigh444  = 0x40;
+
+        /**
+         * AVC Constrained Baseline profile.
+         * See definition in
+         * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>,
+         * Annex A.
+         */
         public static final int AVCProfileConstrainedBaseline = 0x10000;
+
+        /**
+         * AVC Constrained High profile.
+         * See definition in
+         * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>,
+         * Annex A.
+         */
         public static final int AVCProfileConstrainedHigh     = 0x80000;
 
         public static final int AVCLevel1       = 0x01;
@@ -3420,8 +3489,34 @@
         public static final int DolbyVisionLevelUhd48   = 0x80;
         public static final int DolbyVisionLevelUhd60   = 0x100;
 
+        // Profiles and levels for AV1 Codec, corresponding to the
+        // definitions in
+        // "AV1 Bitstream & Decoding Process Specification", Annex A
+        // found at
+        // https://aomedia.org/av1-bitstream-and-decoding-process-specification/
+
+        /**
+         * AV1 Main profile.
+         * See definition in
+         * <a href="https://aomedia.org/av1-bitstream-and-decoding-process-specification/"> AV1 Bitstream and Decoding Process Specification</a>
+         * Annex A.
+         */
         public static final int AV1Profile0     = 0x1;
+
+        /**
+         * AV1 High profile.
+         * See definition in
+         * <a href="https://aomedia.org/av1-bitstream-and-decoding-process-specification/"> AV1 Bitstream and Decoding Process Specification</a>
+         * Annex A.
+         */
         public static final int AV1Profile1     = 0x2;
+
+        /**
+         * AV1 Professional profile.
+         * See definition in
+         * <a href="https://aomedia.org/av1-bitstream-and-decoding-process-specification/"> AV1 Bitstream and Decoding Process Specification</a>
+         * Annex A.
+         */
         public static final int AV1Profile2     = 0x4;
 
         public static final int AV1Level2       = 0x1;
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index 9258b85..aeb77cf 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -24,6 +25,7 @@
 import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityThread;
 import android.os.Handler;
+import android.os.HandlerExecutor;
 import android.os.Looper;
 import android.os.Message;
 import android.os.Parcel;
@@ -36,8 +38,13 @@
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Consumer;
+import java.util.function.Function;
 
 
 /**
@@ -131,21 +138,6 @@
 
     private static final String PERMISSION = android.Manifest.permission.ACCESS_DRM_CERTIFICATES;
 
-    private EventHandler mEventHandler;
-    private EventHandler mKeyStatusChangeHandler;
-    private EventHandler mExpirationUpdateHandler;
-    private EventHandler mSessionLostStateHandler;
-
-    private OnEventListener mOnEventListener;
-    private OnKeyStatusChangeListener mOnKeyStatusChangeListener;
-    private OnExpirationUpdateListener mOnExpirationUpdateListener;
-    private OnSessionLostStateListener mOnSessionLostStateListener;
-
-    private final Object mEventLock = new Object();
-    private final Object mKeyStatusChangeLock = new Object();
-    private final Object mExpirationUpdateLock = new Object();
-    private final Object mSessionLostStateLock = new Object();
-
     private long mNativeContext;
 
     /**
@@ -227,35 +219,19 @@
     private static final native boolean isCryptoSchemeSupportedNative(
             @NonNull byte[] uuid, @Nullable String mimeType, @SecurityLevel int securityLevel);
 
-    private EventHandler createHandler() {
+    private Handler createHandler() {
         Looper looper;
-        EventHandler handler;
+        Handler handler;
         if ((looper = Looper.myLooper()) != null) {
-            handler = new EventHandler(this, looper);
+            handler = new Handler(looper);
         } else if ((looper = Looper.getMainLooper()) != null) {
-            handler = new EventHandler(this, looper);
+            handler = new Handler(looper);
         } else {
             handler = null;
         }
         return handler;
     }
 
-    private EventHandler updateHandler(Handler handler) {
-        Looper looper;
-        EventHandler newHandler = null;
-        if (handler != null) {
-            looper = handler.getLooper();
-        } else {
-            looper = Looper.myLooper();
-        }
-        if (looper != null) {
-            if (handler == null || handler.getLooper() != looper) {
-                newHandler = new EventHandler(this, looper);
-            }
-        }
-        return newHandler;
-    }
-
     /**
      * Instantiate a MediaDrm object
      *
@@ -265,11 +241,6 @@
      * specified scheme UUID
      */
     public MediaDrm(@NonNull UUID uuid) throws UnsupportedSchemeException {
-        mEventHandler = createHandler();
-        mKeyStatusChangeHandler = createHandler();
-        mExpirationUpdateHandler = createHandler();
-        mSessionLostStateHandler = createHandler();
-
         /* Native setup requires a weak reference to our object.
          * It's easier to create it here than in C++.
          */
@@ -368,12 +339,30 @@
      */
     public void setOnExpirationUpdateListener(
             @Nullable OnExpirationUpdateListener listener, @Nullable Handler handler) {
-        synchronized(mExpirationUpdateLock) {
-            if (listener != null) {
-                mExpirationUpdateHandler = updateHandler(handler);
-            }
-            mOnExpirationUpdateListener = listener;
-        }
+        setListenerWithHandler(EXPIRATION_UPDATE, handler, listener,
+                this::createOnExpirationUpdateListener);
+    }
+    /**
+     * Register a callback to be invoked when a session expiration update
+     * occurs.
+     *
+     * @see #setOnExpirationUpdateListener(OnExpirationUpdateListener, Handler)
+     *
+     * @param executor the executor through which the listener should be invoked
+     * @param listener the callback that will be run.
+     */
+    public void setOnExpirationUpdateListener(
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull OnExpirationUpdateListener listener) {
+        setListenerWithExecutor(EXPIRATION_UPDATE, executor, listener,
+                this::createOnExpirationUpdateListener);
+    }
+
+    /**
+     * Clear the {@link OnExpirationUpdateListener}.
+     */
+    public void clearOnExpirationUpdateListener() {
+        clearGenericListener(EXPIRATION_UPDATE);
     }
 
     /**
@@ -407,12 +396,31 @@
      */
     public void setOnKeyStatusChangeListener(
             @Nullable OnKeyStatusChangeListener listener, @Nullable Handler handler) {
-        synchronized(mKeyStatusChangeLock) {
-            if (listener != null) {
-                mKeyStatusChangeHandler = updateHandler(handler);
-            }
-            mOnKeyStatusChangeListener = listener;
-        }
+        setListenerWithHandler(KEY_STATUS_CHANGE, handler, listener,
+                this::createOnKeyStatusChangeListener);
+    }
+
+    /**
+     * Register a callback to be invoked when the state of keys in a session
+     * change.
+     *
+     * @see #setOnKeyStatusChangeListener(OnKeyStatusChangeListener, Handler)
+     *
+     * @param listener the callback that will be run when key status changes.
+     * @param executor the executor on which the listener should be invoked.
+     */
+    public void setOnKeyStatusChangeListener(
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull OnKeyStatusChangeListener listener) {
+        setListenerWithExecutor(KEY_STATUS_CHANGE, executor, listener,
+                this::createOnKeyStatusChangeListener);
+    }
+
+    /**
+     * Clear the {@link OnKeyStatusChangeListener}.
+     */
+    public void clearOnKeyStatusChangeListener() {
+        clearGenericListener(KEY_STATUS_CHANGE);
     }
 
     /**
@@ -453,12 +461,31 @@
      */
     public void setOnSessionLostStateListener(
             @Nullable OnSessionLostStateListener listener, @Nullable Handler handler) {
-        synchronized(mSessionLostStateLock) {
-            if (listener != null) {
-                mSessionLostStateHandler = updateHandler(handler);
-            }
-            mOnSessionLostStateListener = listener;
-        }
+        setListenerWithHandler(SESSION_LOST_STATE, handler, listener,
+                this::createOnSessionLostStateListener);
+    }
+
+    /**
+     * Register a callback to be invoked when session state has been
+     * lost.
+     *
+     * @see #setOnSessionLostStateListener(OnSessionLostStateListener, Handler)
+     *
+     * @param listener the callback that will be run.
+     * @param executor the executor on which the listener should be invoked.
+     */
+    public void setOnSessionLostStateListener(
+            @NonNull @CallbackExecutor Executor executor,
+            @Nullable OnSessionLostStateListener listener) {
+        setListenerWithExecutor(SESSION_LOST_STATE, executor, listener,
+                this::createOnSessionLostStateListener);
+    }
+
+    /**
+     * Clear the {@link OnSessionLostStateListener}.
+     */
+    public void clearOnSessionLostStateListener() {
+        clearGenericListener(SESSION_LOST_STATE);
     }
 
     /**
@@ -552,14 +579,48 @@
     /**
      * Register a callback to be invoked when an event occurs
      *
+     * @see #setOnEventListener(OnEventListener, Handler)
+     *
      * @param listener the callback that will be run.  Use {@code null} to
      *        stop receiving event callbacks.
      */
     public void setOnEventListener(@Nullable OnEventListener listener)
     {
-        synchronized(mEventLock) {
-            mOnEventListener = listener;
-        }
+        setOnEventListener(listener, null);
+    }
+
+    /**
+     * Register a callback to be invoked when an event occurs
+     *
+     * @param listener the callback that will be run.  Use {@code null} to
+     *        stop receiving event callbacks.
+     * @param handler the handler on which the listener should be invoked, or
+     *        null if the listener should be invoked on the calling thread's looper.
+     */
+
+    public void setOnEventListener(@Nullable OnEventListener listener, @Nullable Handler handler)
+    {
+        setListenerWithHandler(DRM_EVENT, handler, listener, this::createOnEventListener);
+    }
+
+    /**
+     * Register a callback to be invoked when an event occurs
+     *
+     * @see #setOnEventListener(OnEventListener)
+     *
+     * @param executor the executor through which the listener should be invoked
+     * @param listener the callback that will be run.
+     */
+    public void setOnEventListener(@NonNull @CallbackExecutor Executor executor,
+            @NonNull OnEventListener listener) {
+        setListenerWithExecutor(DRM_EVENT, executor, listener, this::createOnEventListener);
+    }
+
+    /**
+     * Clear the {@link OnEventListener}.
+     */
+    public void clearOnEventListener() {
+        clearGenericListener(DRM_EVENT);
     }
 
     /**
@@ -637,99 +698,112 @@
     private static final int KEY_STATUS_CHANGE = 202;
     private static final int SESSION_LOST_STATE = 203;
 
-    private class EventHandler extends Handler
-    {
-        private MediaDrm mMediaDrm;
+    // Use ConcurrentMap to support concurrent read/write to listener settings.
+    // ListenerWithExecutor is immutable so we shouldn't need further locks.
+    private final Map<Integer, ListenerWithExecutor> mListenerMap = new ConcurrentHashMap<>();
 
-        public EventHandler(@NonNull MediaDrm md, @NonNull Looper looper) {
-            super(looper);
-            mMediaDrm = md;
+    // called by old-style set*Listener APIs using Handlers; listener & handler are Nullable
+    private <T> void setListenerWithHandler(int what, Handler handler, T listener,
+            Function<T, Consumer<ListenerArgs>> converter) {
+        if (listener == null) {
+            clearGenericListener(what);
+        } else {
+            handler = handler == null ? createHandler() : handler;
+            final HandlerExecutor executor = new HandlerExecutor(handler);
+            setGenericListener(what, executor, listener, converter);
         }
+    }
 
-        @Override
-        public void handleMessage(@NonNull Message msg) {
-            if (mMediaDrm.mNativeContext == 0) {
-                Log.w(TAG, "MediaDrm went away with unhandled events");
-                return;
+    // called by new-style set*Listener APIs using Executors; listener & executor must be NonNull
+    private <T> void setListenerWithExecutor(int what, Executor executor, T listener,
+            Function<T, Consumer<ListenerArgs>> converter) {
+        if (executor == null || listener == null) {
+            final String errMsg = String.format("executor %s listener %s", executor, listener);
+            throw new IllegalArgumentException(errMsg);
+        }
+        setGenericListener(what, executor, listener, converter);
+    }
+
+    private <T> void setGenericListener(int what, Executor executor, T listener,
+            Function<T, Consumer<ListenerArgs>> converter) {
+        mListenerMap.put(what, new ListenerWithExecutor(executor, converter.apply(listener)));
+    }
+
+    private void clearGenericListener(int what) {
+        mListenerMap.remove(what);
+    }
+
+    private Consumer<ListenerArgs> createOnEventListener(OnEventListener listener) {
+        return args -> {
+            byte[] sessionId = args.parcel.createByteArray();
+            if (sessionId.length == 0) {
+                sessionId = null;
             }
-            switch(msg.what) {
-
-            case DRM_EVENT:
-                synchronized(mEventLock) {
-                    if (mOnEventListener != null) {
-                        if (msg.obj != null && msg.obj instanceof Parcel) {
-                            Parcel parcel = (Parcel)msg.obj;
-                            byte[] sessionId = parcel.createByteArray();
-                            if (sessionId.length == 0) {
-                                sessionId = null;
-                            }
-                            byte[] data = parcel.createByteArray();
-                            if (data.length == 0) {
-                                data = null;
-                            }
-
-                            Log.i(TAG, "Drm event (" + msg.arg1 + "," + msg.arg2 + ")");
-                            mOnEventListener.onEvent(mMediaDrm, sessionId, msg.arg1, msg.arg2, data);
-                        }
-                    }
-                }
-                return;
-
-            case KEY_STATUS_CHANGE:
-                synchronized(mKeyStatusChangeLock) {
-                    if (mOnKeyStatusChangeListener != null) {
-                        if (msg.obj != null && msg.obj instanceof Parcel) {
-                            Parcel parcel = (Parcel)msg.obj;
-                            byte[] sessionId = parcel.createByteArray();
-                            if (sessionId.length > 0) {
-                                List<KeyStatus> keyStatusList = keyStatusListFromParcel(parcel);
-                                boolean hasNewUsableKey = (parcel.readInt() != 0);
-
-                                Log.i(TAG, "Drm key status changed");
-                                mOnKeyStatusChangeListener.onKeyStatusChange(mMediaDrm, sessionId,
-                                        keyStatusList, hasNewUsableKey);
-                            }
-                        }
-                    }
-                }
-                return;
-
-            case EXPIRATION_UPDATE:
-                synchronized(mExpirationUpdateLock) {
-                    if (mOnExpirationUpdateListener != null) {
-                        if (msg.obj != null && msg.obj instanceof Parcel) {
-                            Parcel parcel = (Parcel)msg.obj;
-                            byte[] sessionId = parcel.createByteArray();
-                            if (sessionId.length > 0) {
-                                long expirationTime = parcel.readLong();
-
-                                Log.i(TAG, "Drm key expiration update: " + expirationTime);
-                                mOnExpirationUpdateListener.onExpirationUpdate(mMediaDrm, sessionId,
-                                        expirationTime);
-                            }
-                        }
-                    }
-                }
-                return;
-
-            case SESSION_LOST_STATE:
-                synchronized(mSessionLostStateLock) {
-                    if (mOnSessionLostStateListener != null) {
-                        if (msg.obj != null && msg.obj instanceof Parcel) {
-                            Parcel parcel = (Parcel)msg.obj;
-                            byte[] sessionId = parcel.createByteArray();
-                            Log.i(TAG, "Drm session lost state event: ");
-                            mOnSessionLostStateListener.onSessionLostState(mMediaDrm,
-                                    sessionId);
-                        }
-                    }
-                }
-                return;
-
-            default:
-                Log.e(TAG, "Unknown message type " + msg.what);
-                return;
+            byte[] data = args.parcel.createByteArray();
+            if (data.length == 0) {
+                data = null;
             }
+
+            Log.i(TAG, "Drm event (" + args.arg1 + "," + args.arg2 + ")");
+            listener.onEvent(this, sessionId, args.arg1, args.arg2, data);
+        };
+    }
+
+    private Consumer<ListenerArgs> createOnKeyStatusChangeListener(
+            OnKeyStatusChangeListener listener) {
+        return args -> {
+            byte[] sessionId = args.parcel.createByteArray();
+            if (sessionId.length > 0) {
+                List<KeyStatus> keyStatusList = keyStatusListFromParcel(args.parcel);
+                boolean hasNewUsableKey = (args.parcel.readInt() != 0);
+
+                Log.i(TAG, "Drm key status changed");
+                listener.onKeyStatusChange(this, sessionId, keyStatusList, hasNewUsableKey);
+            }
+        };
+    }
+
+    private Consumer<ListenerArgs> createOnExpirationUpdateListener(
+            OnExpirationUpdateListener listener) {
+        return args -> {
+            byte[] sessionId = args.parcel.createByteArray();
+            if (sessionId.length > 0) {
+                long expirationTime = args.parcel.readLong();
+
+                Log.i(TAG, "Drm key expiration update: " + expirationTime);
+                listener.onExpirationUpdate(this, sessionId, expirationTime);
+            }
+        };
+    }
+
+    private Consumer<ListenerArgs> createOnSessionLostStateListener(
+            OnSessionLostStateListener listener) {
+        return args -> {
+            byte[] sessionId = args.parcel.createByteArray();
+            Log.i(TAG, "Drm session lost state event: ");
+            listener.onSessionLostState(this, sessionId);
+        };
+    }
+
+    private static class ListenerArgs {
+        private final Parcel parcel;
+        private final int arg1;
+        private final int arg2;
+
+        public ListenerArgs(Parcel parcel, int arg1, int arg2) {
+            this.parcel = parcel;
+            this.arg1 = arg1;
+            this.arg2 = arg2;
+        }
+    }
+
+    private static class ListenerWithExecutor {
+        private final Consumer<ListenerArgs> mConsumer;
+        private final Executor mExecutor;
+
+        public ListenerWithExecutor(Executor executor, Consumer<ListenerArgs> consumer) {
+            this.mExecutor = executor;
+            this.mConsumer = consumer;
         }
     }
 
@@ -764,35 +838,22 @@
         }
         switch (what) {
             case DRM_EVENT:
-                synchronized(md.mEventLock) {
-                    if (md.mEventHandler != null) {
-                        Message m = md.mEventHandler.obtainMessage(what, eventType, extra, obj);
-                        md.mEventHandler.sendMessage(m);
-                    }
-                }
-                break;
             case EXPIRATION_UPDATE:
-                synchronized(md.mExpirationUpdateLock) {
-                    if (md.mExpirationUpdateHandler != null) {
-                        Message m = md.mExpirationUpdateHandler.obtainMessage(what, obj);
-                        md.mExpirationUpdateHandler.sendMessage(m);
-                    }
-                }
-                break;
             case KEY_STATUS_CHANGE:
-                synchronized(md.mKeyStatusChangeLock) {
-                    if (md.mKeyStatusChangeHandler != null) {
-                        Message m = md.mKeyStatusChangeHandler.obtainMessage(what, obj);
-                        md.mKeyStatusChangeHandler.sendMessage(m);
-                    }
-                }
-                break;
             case SESSION_LOST_STATE:
-                synchronized(md.mSessionLostStateLock) {
-                    if (md.mSessionLostStateHandler != null) {
-                        Message m = md.mSessionLostStateHandler.obtainMessage(what, obj);
-                        md.mSessionLostStateHandler.sendMessage(m);
-                    }
+                ListenerWithExecutor listener  = md.mListenerMap.get(what);
+                if (listener != null) {
+                    final Runnable command = () -> {
+                        if (md.mNativeContext == 0) {
+                            Log.w(TAG, "MediaDrm went away with unhandled events");
+                            return;
+                        }
+                        if (obj != null && obj instanceof Parcel) {
+                            Parcel p = (Parcel)obj;
+                            listener.mConsumer.accept(new ListenerArgs(p, eventType, extra));
+                        }
+                    };
+                    listener.mExecutor.execute(command);
                 }
                 break;
             default:
@@ -1302,6 +1363,18 @@
         removeAllSecureStops();;
     }
 
+    /**
+     * @deprecated Not of any use for application development;
+     * please note that the related integer constants remain supported:
+     * {@link #HDCP_LEVEL_UNKNOWN},
+     * {@link #HDCP_NONE},
+     * {@link #HDCP_V1},
+     * {@link #HDCP_V2},
+     * {@link #HDCP_V2_1},
+     * {@link #HDCP_V2_2},
+     * {@link #HDCP_V2_3}
+     */
+    @Deprecated
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({HDCP_LEVEL_UNKNOWN, HDCP_NONE, HDCP_V1, HDCP_V2,
                         HDCP_V2_1, HDCP_V2_2, HDCP_V2_3, HDCP_NO_DIGITAL_OUTPUT})
@@ -1394,7 +1467,17 @@
     /**
      * Security level indicates the robustness of the device's DRM
      * implementation.
+     *
+     * @deprecated Not of any use for application development;
+     * please note that the related integer constants remain supported:
+     * {@link #SECURITY_LEVEL_UNKNOWN},
+     * {@link #SECURITY_LEVEL_SW_SECURE_CRYPTO},
+     * {@link #SECURITY_LEVEL_SW_SECURE_DECODE},
+     * {@link #SECURITY_LEVEL_HW_SECURE_CRYPTO},
+     * {@link #SECURITY_LEVEL_HW_SECURE_DECODE},
+     * {@link #SECURITY_LEVEL_HW_SECURE_ALL}
      */
+    @Deprecated
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({SECURITY_LEVEL_UNKNOWN, SECURITY_LEVEL_SW_SECURE_CRYPTO,
             SECURITY_LEVEL_SW_SECURE_DECODE, SECURITY_LEVEL_HW_SECURE_CRYPTO,
@@ -1505,13 +1588,13 @@
      * {@link #PROPERTY_DESCRIPTION}, {@link #PROPERTY_ALGORITHMS}
      */
     @NonNull
-    public native String getPropertyString(@NonNull @StringProperty String propertyName);
+    public native String getPropertyString(@NonNull String propertyName);
 
     /**
      * Set a MediaDrm String property value, given the property name string
      * and new value for the property.
      */
-    public native void setPropertyString(@NonNull @StringProperty String propertyName,
+    public native void setPropertyString(@NonNull String propertyName,
             @NonNull String value);
 
     /**
@@ -1533,14 +1616,14 @@
      * Standard fields names are {@link #PROPERTY_DEVICE_UNIQUE_ID}
      */
     @NonNull
-    public native byte[] getPropertyByteArray(@ArrayProperty String propertyName);
+    public native byte[] getPropertyByteArray(String propertyName);
 
     /**
     * Set a MediaDrm byte array property value, given the property name string
     * and new value for the property.
     */
-    public native void setPropertyByteArray(@NonNull @ArrayProperty
-            String propertyName, @NonNull byte[] value);
+    public native void setPropertyByteArray(
+            @NonNull String propertyName, @NonNull byte[] value);
 
     private static final native void setCipherAlgorithmNative(
             @NonNull MediaDrm drm, @NonNull byte[] sessionId, @NonNull String algorithm);
diff --git a/media/java/android/media/MediaHTTPConnection.java b/media/java/android/media/MediaHTTPConnection.java
index d724762..3838a999 100644
--- a/media/java/android/media/MediaHTTPConnection.java
+++ b/media/java/android/media/MediaHTTPConnection.java
@@ -37,6 +37,7 @@
 import java.net.UnknownServiceException;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
 
 /** @hide */
 public class MediaHTTPConnection extends IMediaHTTPConnection.Stub {
@@ -46,27 +47,23 @@
     // connection timeout - 30 sec
     private static final int CONNECT_TIMEOUT_MS = 30 * 1000;
 
-    @UnsupportedAppUsage
-    private long mCurrentOffset = -1;
-    @UnsupportedAppUsage
-    private URL mURL = null;
-    @UnsupportedAppUsage
-    private Map<String, String> mHeaders = null;
-    @UnsupportedAppUsage
-    private HttpURLConnection mConnection = null;
-    @UnsupportedAppUsage
-    private long mTotalSize = -1;
-    private InputStream mInputStream = null;
-
-    @UnsupportedAppUsage
-    private boolean mAllowCrossDomainRedirect = true;
-    @UnsupportedAppUsage
-    private boolean mAllowCrossProtocolRedirect = true;
-
     // from com.squareup.okhttp.internal.http
     private final static int HTTP_TEMP_REDIRECT = 307;
     private final static int MAX_REDIRECTS = 20;
 
+    class ConnectionState {
+        public HttpURLConnection mConnection = null;
+        public InputStream mInputStream = null;
+        public long mCurrentOffset = -1;
+        public Map<String, String> mHeaders = null;
+        public URL mURL = null;
+        public long mTotalSize = -1;
+        public boolean mAllowCrossDomainRedirect = true;
+        public boolean mAllowCrossProtocolRedirect = true;
+    }
+    private final AtomicReference<ConnectionState> mConnectionStateHolder =
+            new AtomicReference<ConnectionState>();
+
     @UnsupportedAppUsage
     public MediaHTTPConnection() {
         CookieHandler cookieHandler = CookieHandler.getDefault();
@@ -84,13 +81,23 @@
             Log.d(TAG, "connect: uri=" + uri + ", headers=" + headers);
         }
 
+        ConnectionState connectionState = mConnectionStateHolder.get();
+        synchronized (this) {
+            if (connectionState == null) {
+                connectionState = new ConnectionState();
+                mConnectionStateHolder.set(connectionState);
+            }
+        }
+
         try {
             disconnect();
-            mAllowCrossDomainRedirect = true;
-            mURL = new URL(uri);
-            mHeaders = convertHeaderStringToMap(headers);
+            connectionState.mAllowCrossDomainRedirect = true;
+            connectionState.mURL = new URL(uri);
+            connectionState.mHeaders = convertHeaderStringToMap(headers, connectionState);
         } catch (MalformedURLException e) {
             return null;
+        } finally {
+            mConnectionStateHolder.set(connectionState);
         }
 
         return native_getIMemory();
@@ -106,18 +113,21 @@
     }
 
     /* returns true iff header is internal */
-    private boolean filterOutInternalHeaders(String key, String val) {
+    private boolean filterOutInternalHeaders(
+            String key, String val, ConnectionState connectionState) {
         if ("android-allow-cross-domain-redirect".equalsIgnoreCase(key)) {
-            mAllowCrossDomainRedirect = parseBoolean(val);
+            connectionState.mAllowCrossDomainRedirect = parseBoolean(val);
             // cross-protocol redirects are also controlled by this flag
-            mAllowCrossProtocolRedirect = mAllowCrossDomainRedirect;
+            connectionState.mAllowCrossProtocolRedirect =
+                    connectionState.mAllowCrossDomainRedirect;
         } else {
             return false;
         }
         return true;
     }
 
-    private Map<String, String> convertHeaderStringToMap(String headers) {
+    private Map<String, String> convertHeaderStringToMap(String headers,
+            ConnectionState connectionState) {
         HashMap<String, String> map = new HashMap<String, String>();
 
         String[] pairs = headers.split("\r\n");
@@ -127,7 +137,7 @@
                 String key = pair.substring(0, colonPos);
                 String val = pair.substring(colonPos + 1);
 
-                if (!filterOutInternalHeaders(key, val)) {
+                if (!filterOutInternalHeaders(key, val, connectionState)) {
                     map.put(key, val);
                 }
             }
@@ -139,25 +149,28 @@
     @Override
     @UnsupportedAppUsage
     public void disconnect() {
-        teardownConnection();
-        mHeaders = null;
-        mURL = null;
+        ConnectionState connectionState = mConnectionStateHolder.getAndSet(null);
+        if (connectionState != null) {
+            teardownConnection(connectionState);
+            connectionState.mHeaders = null;
+            connectionState.mURL = null;
+        }
     }
 
-    private void teardownConnection() {
-        if (mConnection != null) {
-            if (mInputStream != null) {
+    private void teardownConnection(ConnectionState connectionState) {
+        if (connectionState.mConnection != null) {
+            if (connectionState.mInputStream != null) {
                 try {
-                    mInputStream.close();
+                    connectionState.mInputStream.close();
                 } catch (IOException e) {
                 }
-                mInputStream = null;
+                connectionState.mInputStream = null;
             }
 
-            mConnection.disconnect();
-            mConnection = null;
+            connectionState.mConnection.disconnect();
+            connectionState.mConnection = null;
 
-            mCurrentOffset = -1;
+            connectionState.mCurrentOffset = -1;
         }
     }
 
@@ -184,42 +197,44 @@
         return false;
     }
 
-    private void seekTo(long offset) throws IOException {
-        teardownConnection();
+    private void seekTo(long offset, ConnectionState connectionState) throws IOException {
+        teardownConnection(connectionState);
 
         try {
             int response;
             int redirectCount = 0;
 
-            URL url = mURL;
+            URL url = connectionState.mURL;
 
             // do not use any proxy for localhost (127.0.0.1)
             boolean noProxy = isLocalHost(url);
 
             while (true) {
                 if (noProxy) {
-                    mConnection = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY);
+                    connectionState.mConnection =
+                            (HttpURLConnection) url.openConnection(Proxy.NO_PROXY);
                 } else {
-                    mConnection = (HttpURLConnection)url.openConnection();
+                    connectionState.mConnection = (HttpURLConnection) url.openConnection();
                 }
-                mConnection.setConnectTimeout(CONNECT_TIMEOUT_MS);
+                connectionState.mConnection.setConnectTimeout(CONNECT_TIMEOUT_MS);
 
                 // handle redirects ourselves if we do not allow cross-domain redirect
-                mConnection.setInstanceFollowRedirects(mAllowCrossDomainRedirect);
+                connectionState.mConnection.setInstanceFollowRedirects(
+                        connectionState.mAllowCrossDomainRedirect);
 
-                if (mHeaders != null) {
-                    for (Map.Entry<String, String> entry : mHeaders.entrySet()) {
-                        mConnection.setRequestProperty(
+                if (connectionState.mHeaders != null) {
+                    for (Map.Entry<String, String> entry : connectionState.mHeaders.entrySet()) {
+                        connectionState.mConnection.setRequestProperty(
                                 entry.getKey(), entry.getValue());
                     }
                 }
 
                 if (offset > 0) {
-                    mConnection.setRequestProperty(
+                    connectionState.mConnection.setRequestProperty(
                             "Range", "bytes=" + offset + "-");
                 }
 
-                response = mConnection.getResponseCode();
+                response = connectionState.mConnection.getResponseCode();
                 if (response != HttpURLConnection.HTTP_MULT_CHOICE &&
                         response != HttpURLConnection.HTTP_MOVED_PERM &&
                         response != HttpURLConnection.HTTP_MOVED_TEMP &&
@@ -233,7 +248,7 @@
                     throw new NoRouteToHostException("Too many redirects: " + redirectCount);
                 }
 
-                String method = mConnection.getRequestMethod();
+                String method = connectionState.mConnection.getRequestMethod();
                 if (response == HTTP_TEMP_REDIRECT &&
                         !method.equals("GET") && !method.equals("HEAD")) {
                     // "If the 307 status code is received in response to a
@@ -241,34 +256,35 @@
                     // automatically redirect the request"
                     throw new NoRouteToHostException("Invalid redirect");
                 }
-                String location = mConnection.getHeaderField("Location");
+                String location = connectionState.mConnection.getHeaderField("Location");
                 if (location == null) {
                     throw new NoRouteToHostException("Invalid redirect");
                 }
-                url = new URL(mURL /* TRICKY: don't use url! */, location);
+                url = new URL(connectionState.mURL /* TRICKY: don't use url! */, location);
                 if (!url.getProtocol().equals("https") &&
                         !url.getProtocol().equals("http")) {
                     throw new NoRouteToHostException("Unsupported protocol redirect");
                 }
-                boolean sameProtocol = mURL.getProtocol().equals(url.getProtocol());
-                if (!mAllowCrossProtocolRedirect && !sameProtocol) {
+                boolean sameProtocol =
+                        connectionState.mURL.getProtocol().equals(url.getProtocol());
+                if (!connectionState.mAllowCrossProtocolRedirect && !sameProtocol) {
                     throw new NoRouteToHostException("Cross-protocol redirects are disallowed");
                 }
-                boolean sameHost = mURL.getHost().equals(url.getHost());
-                if (!mAllowCrossDomainRedirect && !sameHost) {
+                boolean sameHost = connectionState.mURL.getHost().equals(url.getHost());
+                if (!connectionState.mAllowCrossDomainRedirect && !sameHost) {
                     throw new NoRouteToHostException("Cross-domain redirects are disallowed");
                 }
 
                 if (response != HTTP_TEMP_REDIRECT) {
                     // update effective URL, unless it is a Temporary Redirect
-                    mURL = url;
+                    connectionState.mURL = url;
                 }
             }
 
-            if (mAllowCrossDomainRedirect) {
+            if (connectionState.mAllowCrossDomainRedirect) {
                 // remember the current, potentially redirected URL if redirects
                 // were handled by HttpURLConnection
-                mURL = mConnection.getURL();
+                connectionState.mURL = connectionState.mConnection.getURL();
             }
 
             if (response == HttpURLConnection.HTTP_PARTIAL) {
@@ -276,10 +292,9 @@
                 // because what we want is not just the length of the range
                 // returned but the size of the full content if available.
 
-                String contentRange =
-                    mConnection.getHeaderField("Content-Range");
+                String contentRange = connectionState.mConnection.getHeaderField("Content-Range");
 
-                mTotalSize = -1;
+                connectionState.mTotalSize = -1;
                 if (contentRange != null) {
                     // format is "bytes xxx-yyy/zzz
                     // where "zzz" is the total number of bytes of the
@@ -291,7 +306,7 @@
                             contentRange.substring(lastSlashPos + 1);
 
                         try {
-                            mTotalSize = Long.parseLong(total);
+                            connectionState.mTotalSize = Long.parseLong(total);
                         } catch (NumberFormatException e) {
                         }
                     }
@@ -299,7 +314,7 @@
             } else if (response != HttpURLConnection.HTTP_OK) {
                 throw new IOException();
             } else {
-                mTotalSize = mConnection.getContentLength();
+                connectionState.mTotalSize = connectionState.mConnection.getContentLength();
             }
 
             if (offset > 0 && response != HttpURLConnection.HTTP_PARTIAL) {
@@ -308,14 +323,14 @@
                 throw new ProtocolException();
             }
 
-            mInputStream =
-                new BufferedInputStream(mConnection.getInputStream());
+            connectionState.mInputStream =
+                new BufferedInputStream(connectionState.mConnection.getInputStream());
 
-            mCurrentOffset = offset;
+            connectionState.mCurrentOffset = offset;
         } catch (IOException e) {
-            mTotalSize = -1;
-            teardownConnection();
-            mCurrentOffset = -1;
+            connectionState.mTotalSize = -1;
+            teardownConnection(connectionState);
+            connectionState.mCurrentOffset = -1;
 
             throw e;
         }
@@ -324,10 +339,14 @@
     @Override
     @UnsupportedAppUsage
     public int readAt(long offset, int size) {
-        return native_readAt(offset, size);
+        ConnectionState connectionState = mConnectionStateHolder.get();
+        if (connectionState != null) {
+            return native_readAt(offset, size, connectionState);
+        }
+        return -1;
     }
 
-    private int readAt(long offset, byte[] data, int size) {
+    private int readAt(long offset, byte[] data, int size, ConnectionState connectionState) {
         StrictMode.ThreadPolicy policy =
             new StrictMode.ThreadPolicy.Builder().permitAll().build();
 
@@ -335,12 +354,12 @@
 
         try {
             synchronized(this) {
-                if (offset != mCurrentOffset) {
-                    seekTo(offset);
+                if (offset != connectionState.mCurrentOffset) {
+                    seekTo(offset, connectionState);
                 }
             }
 
-            int n = mInputStream.read(data, 0, size);
+            int n = connectionState.mInputStream.read(data, 0, size);
 
             if (n == -1) {
                 // InputStream signals EOS using a -1 result, our semantics
@@ -348,7 +367,7 @@
                 n = 0;
             }
 
-            mCurrentOffset += n;
+            connectionState.mCurrentOffset += n;
 
             if (VERBOSE) {
                 Log.d(TAG, "readAt " + offset + " / " + size + " => " + n);
@@ -380,35 +399,47 @@
 
     @Override
     public synchronized long getSize() {
-        if (mConnection == null) {
-            try {
-                seekTo(0);
-            } catch (IOException e) {
-                return -1;
+        ConnectionState connectionState = mConnectionStateHolder.get();
+        if (connectionState != null) {
+            if (connectionState.mConnection == null) {
+                try {
+                    seekTo(0, connectionState);
+                } catch (IOException e) {
+                    return -1;
+                }
             }
+            return connectionState.mTotalSize;
         }
 
-        return mTotalSize;
+        return -1;
     }
 
     @Override
     @UnsupportedAppUsage
     public synchronized String getMIMEType() {
-        if (mConnection == null) {
-            try {
-                seekTo(0);
-            } catch (IOException e) {
-                return "application/octet-stream";
+        ConnectionState connectionState = mConnectionStateHolder.get();
+        if (connectionState != null) {
+            if (connectionState.mConnection == null) {
+                try {
+                    seekTo(0, connectionState);
+                } catch (IOException e) {
+                    return "application/octet-stream";
+                }
             }
+            return connectionState.mConnection.getContentType();
         }
 
-        return mConnection.getContentType();
+        return null;
     }
 
     @Override
     @UnsupportedAppUsage
     public String getUri() {
-        return mURL.toString();
+        ConnectionState connectionState = mConnectionStateHolder.get();
+        if (connectionState != null) {
+            return connectionState.mURL.toString();
+        }
+        return null;
     }
 
     @Override
@@ -421,7 +452,7 @@
     private native final void native_finalize();
 
     private native final IBinder native_getIMemory();
-    private native final int native_readAt(long offset, int size);
+    private native int native_readAt(long offset, int size, ConnectionState connectionState);
 
     static {
         System.loadLibrary("media_jni");
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index abbfa88..040152a 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -2645,7 +2645,7 @@
      */
     private synchronized void setSubtitleAnchor() {
         if ((mSubtitleController == null) && (ActivityThread.currentApplication() != null)) {
-            getMediaTimeProvider();
+            final TimeProvider timeProvider = (TimeProvider) getMediaTimeProvider();
             final HandlerThread thread = new HandlerThread("SetSubtitleAnchorThread");
             thread.start();
             Handler handler = new Handler(thread.getLooper());
@@ -2653,7 +2653,8 @@
                 @Override
                 public void run() {
                     Context context = ActivityThread.currentApplication();
-                    mSubtitleController = new SubtitleController(context, mTimeProvider, MediaPlayer.this);
+                    mSubtitleController =
+                            new SubtitleController(context, timeProvider, MediaPlayer.this);
                     mSubtitleController.setAnchor(new Anchor() {
                         @Override
                         public void setSubtitleWidget(RenderingWidget subtitleWidget) {
@@ -2661,7 +2662,7 @@
 
                         @Override
                         public Looper getSubtitleLooper() {
-                            return mTimeProvider.mEventHandler.getLooper();
+                            return timeProvider.mEventHandler.getLooper();
                         }
                     });
                     thread.getLooper().quitSafely();
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index 0679e8e9..9a60923 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -215,17 +215,19 @@
     // Make sure the column ordering and then ..._COLUMN_INDEX are in sync
     
     private static final String[] INTERNAL_COLUMNS = new String[] {
-        MediaStore.Audio.Media._ID, MediaStore.Audio.Media.TITLE,
-        "\"" + MediaStore.Audio.Media.INTERNAL_CONTENT_URI + "\"",
-        MediaStore.Audio.Media.TITLE_KEY
+        MediaStore.Audio.Media._ID,
+        MediaStore.Audio.Media.TITLE,
+        MediaStore.Audio.Media.TITLE,
+        MediaStore.Audio.Media.TITLE_KEY,
     };
 
     private static final String[] MEDIA_COLUMNS = new String[] {
-        MediaStore.Audio.Media._ID, MediaStore.Audio.Media.TITLE,
-        "\"" + MediaStore.Audio.Media.EXTERNAL_CONTENT_URI + "\"",
-        MediaStore.Audio.Media.TITLE_KEY
+        MediaStore.Audio.Media._ID,
+        MediaStore.Audio.Media.TITLE,
+        MediaStore.Audio.Media.TITLE,
+        MediaStore.Audio.Media.TITLE_KEY,
     };
-    
+
     /**
      * The column index (in the cursor returned by {@link #getCursor()} for the
      * row ID.
@@ -459,8 +461,9 @@
                 // We don't need to re-add the internal ringtones for the work profile since
                 // they are the same as the personal profile. We just need the external
                 // ringtones.
-                return new ExternalRingtonesCursorWrapper(getMediaRingtones(parentContext),
-                        parentInfo.id);
+                final Cursor res = getMediaRingtones(parentContext);
+                return new ExternalRingtonesCursorWrapper(res, ContentProvider.maybeAddUserId(
+                        MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, parentInfo.id));
             }
         }
         return null;
@@ -580,14 +583,16 @@
 
     @UnsupportedAppUsage
     private Cursor getInternalRingtones() {
-        return query(
+        final Cursor res = query(
                 MediaStore.Audio.Media.INTERNAL_CONTENT_URI, INTERNAL_COLUMNS,
                 constructBooleanTrueWhereClause(mFilterColumns),
                 null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
+        return new ExternalRingtonesCursorWrapper(res, MediaStore.Audio.Media.INTERNAL_CONTENT_URI);
     }
 
     private Cursor getMediaRingtones() {
-        return getMediaRingtones(mContext);
+        final Cursor res = getMediaRingtones(mContext);
+        return new ExternalRingtonesCursorWrapper(res, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI);
     }
 
     @UnsupportedAppUsage
diff --git a/media/java/android/media/SRTRenderer.java b/media/java/android/media/SRTRenderer.java
index a3e2abd..505f996 100644
--- a/media/java/android/media/SRTRenderer.java
+++ b/media/java/android/media/SRTRenderer.java
@@ -125,6 +125,7 @@
                 String[] startEnd = header.split("-->");
                 cue.mStartTimeMs = parseMs(startEnd[0]);
                 cue.mEndTimeMs = parseMs(startEnd[1]);
+                cue.mRunID = runID;
 
                 String s;
                 List<String> paragraph = new ArrayList<String>();
diff --git a/media/java/android/media/SubtitleData.java b/media/java/android/media/SubtitleData.java
index 31622a9..2c6c61f 100644
--- a/media/java/android/media/SubtitleData.java
+++ b/media/java/android/media/SubtitleData.java
@@ -91,7 +91,7 @@
     }
 
     /**
-     * Returns the index of the MediaPlayer track which contains this subtitle data.
+     * Returns the index of the media player track which contains this subtitle data.
      * @return an index in the array returned by {@link MediaPlayer#getTrackInfo()}.
      */
     public int getTrackIndex() {
@@ -198,7 +198,7 @@
         /**
          * Sets the info of subtitle data.
          *
-         * @param trackIndex the ParcelFileDescriptor for the file to play
+         * @param trackIndex the index of the media player track which contains this subtitle data.
          * @param startTimeUs the start time in microsecond for the subtile data
          * @param durationUs the duration in microsecond for the subtile data
          * @param data the data array for the subtile data. It should not be null.
diff --git a/media/java/android/media/SubtitleTrack.java b/media/java/android/media/SubtitleTrack.java
index 5596c32..0705d97 100644
--- a/media/java/android/media/SubtitleTrack.java
+++ b/media/java/android/media/SubtitleTrack.java
@@ -263,7 +263,9 @@
         }
         updateView(mActiveCues);
         mNextScheduledTimeMs = -1;
-        mTimeProvider.notifyAt(MediaTimeProvider.NO_TIME, this);
+        if (mTimeProvider != null) {
+            mTimeProvider.notifyAt(MediaTimeProvider.NO_TIME, this);
+        }
     }
 
     /** @hide */
diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java
index 5f65d58..978583e 100644
--- a/media/java/android/media/audiopolicy/AudioPolicy.java
+++ b/media/java/android/media/audiopolicy/AudioPolicy.java
@@ -43,8 +43,11 @@
 import android.util.Log;
 import android.util.Slog;
 
+import com.android.internal.annotations.GuardedBy;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -74,6 +77,19 @@
     private boolean mIsFocusPolicy;
 
     /**
+     * The list of AudioTrack instances created to inject audio into the associated mixes
+     * Lazy initialization in {@link #createAudioTrackSource(AudioMix)}
+     */
+    @GuardedBy("mLock")
+    @Nullable private ArrayList<WeakReference<AudioTrack>> mInjectors;
+    /**
+     * The list AudioRecord instances created to capture audio from the associated mixes
+     * Lazy initialization in {@link #createAudioRecordSink(AudioMix)}
+     */
+    @GuardedBy("mLock")
+    @Nullable private ArrayList<WeakReference<AudioRecord>> mCaptors;
+
+    /**
      * The behavior of a policy with regards to audio focus where it relies on the application
      * to do the ducking, the is the legacy and default behavior.
      */
@@ -606,6 +622,12 @@
                         AudioFormat.CHANNEL_IN_STEREO, mix.getFormat().getEncoding()),
                 AudioManager.AUDIO_SESSION_ID_GENERATE
                 );
+        synchronized (mLock) {
+            if (mCaptors == null) {
+                mCaptors = new ArrayList<>(1);
+            }
+            mCaptors.add(new WeakReference<AudioRecord>(ar));
+        }
         return ar;
     }
 
@@ -638,9 +660,47 @@
                 AudioTrack.MODE_STREAM,
                 AudioManager.AUDIO_SESSION_ID_GENERATE
                 );
+        synchronized (mLock) {
+            if (mInjectors == null) {
+                mInjectors = new ArrayList<>(1);
+            }
+            mInjectors.add(new WeakReference<AudioTrack>(at));
+        }
         return at;
     }
 
+    /**
+     * @hide
+     */
+    public void invalidateCaptorsAndInjectors() {
+        if (!policyReadyToUse()) {
+            return;
+        }
+        synchronized (mLock) {
+            if (mInjectors != null) {
+                for (final WeakReference<AudioTrack> weakTrack : mInjectors) {
+                    final AudioTrack track = weakTrack.get();
+                    if (track == null) {
+                        break;
+                    }
+                    // TODO: add synchronous versions
+                    track.stop();
+                    track.flush();
+                }
+            }
+            if (mCaptors != null) {
+                for (final WeakReference<AudioRecord> weakRecord : mCaptors) {
+                    final AudioRecord record = weakRecord.get();
+                    if (record == null) {
+                        break;
+                    }
+                    // TODO: if needed: implement an invalidate method
+                    record.stop();
+                }
+            }
+        }
+    }
+
     public int getStatus() {
         return mStatus;
     }
diff --git a/media/java/android/media/session/ControllerLink.aidl b/media/java/android/media/session/ControllerLink.aidl
deleted file mode 100644
index 532df59..0000000
--- a/media/java/android/media/session/ControllerLink.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright 2019 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.session;
-
-parcelable ControllerLink;
diff --git a/media/java/android/media/session/ControllerLink.java b/media/java/android/media/session/ControllerLink.java
deleted file mode 100644
index d4ea2a3..0000000
--- a/media/java/android/media/session/ControllerLink.java
+++ /dev/null
@@ -1,1042 +0,0 @@
-/*
- * Copyright 2019 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.session;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.PendingIntent;
-import android.media.MediaMetadata;
-import android.media.MediaParceledListSlice;
-import android.media.Rating;
-import android.media.session.MediaController.PlaybackInfo;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.RemoteException;
-import android.os.ResultReceiver;
-import android.view.KeyEvent;
-
-import java.util.List;
-import java.util.Objects;
-
-/**
- * Handles incoming commands from {@link MediaController}.
- * @hide
- */
-public final class ControllerLink implements Parcelable {
-    public static final @android.annotation.NonNull Parcelable.Creator<ControllerLink> CREATOR =
-            new Parcelable.Creator<ControllerLink>() {
-                @Override
-                public ControllerLink createFromParcel(Parcel in) {
-                    return new ControllerLink(in.readStrongBinder());
-                }
-
-                @Override
-                public ControllerLink[] newArray(int size) {
-                    return new ControllerLink[size];
-                }
-            };
-
-    final ControllerStub mControllerStub;
-    final ISessionController mISessionController;
-
-    /**
-     * Constructor for stub (Callee)
-     */
-    public ControllerLink(@NonNull ControllerStub controllerStub) {
-        mControllerStub = controllerStub;
-        mISessionController = new StubProxy();
-    }
-
-    /**
-     * Constructor for interface (Caller)
-     */
-    public ControllerLink(IBinder binder) {
-        mControllerStub = null;
-        mISessionController = ISessionController.Stub.asInterface(binder);
-    }
-
-    /**
-     * Tell system that a controller sends a command.
-     *
-     * @param packageName the package name of the controller
-     * @param caller the {@link ControllerCallbackLink} of the controller
-     * @param command the name of the command
-     * @param args the arguments included with the command
-     * @param cb the result receiver for getting the result of the command
-     */
-    void sendCommand(@NonNull String packageName, @NonNull ControllerCallbackLink caller,
-            @NonNull String command, @Nullable Bundle args, @Nullable ResultReceiver cb) {
-        try {
-            mISessionController.sendCommand(packageName, caller, command, args, cb);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that a controller sends a media button event.
-     *
-     * @param packageName the package name of the controller
-     * @param caller the {@link ControllerCallbackLink} of the controller
-     * @param mediaButton the media button key event
-     */
-    boolean sendMediaButton(@NonNull String packageName,
-            @NonNull ControllerCallbackLink caller, @NonNull KeyEvent mediaButton) {
-        try {
-            return mISessionController.sendMediaButton(packageName, caller, mediaButton);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Registers a controller callback link to the system.
-     *
-     * @param packageName the package name of the controller
-     * @param cb the controller callback link to register
-     */
-    void registerCallback(@NonNull String packageName, @NonNull ControllerCallbackLink cb) {
-        try {
-            mISessionController.registerCallback(packageName, cb);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Unregisters a controller callback link from the system.
-     *
-     * @param cb the controller callback link to register
-     */
-    void unregisterCallback(@NonNull ControllerCallbackLink cb) {
-        try {
-            mISessionController.unregisterCallback(cb);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Gets the package name of the connected session.
-     */
-    @NonNull
-    String getPackageName() {
-        try {
-            return mISessionController.getPackageName();
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Gets the tag of the connected session.
-     */
-    @NonNull
-    String getTag() {
-        try {
-            return mISessionController.getTag();
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Gets the session info of the connected session.
-     */
-    @Nullable
-    Bundle getSessionInfo() {
-        try {
-            return mISessionController.getSessionInfo();
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Gets the {@link PendingIntent} for launching UI of the connected session.
-     */
-    @Nullable
-    PendingIntent getLaunchPendingIntent() {
-        try {
-            return mISessionController.getLaunchPendingIntent();
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Gets the flags of the connected session.
-     */
-    long getFlags() {
-        try {
-            return mISessionController.getFlags();
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Gets the volume attributes of the connected session.
-     */
-    @NonNull
-    PlaybackInfo getVolumeAttributes() {
-        try {
-            return mISessionController.getVolumeAttributes();
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that a controller requests adjusting the volume.
-     *
-     * @param packageName the package name of the controller
-     * @param opPackageName the op package name of this request
-     * @param caller the {@link ControllerCallbackLink} of the controller
-     * @param direction the direction to adjust the volume in
-     * @param flags the flags with this volume change request
-     */
-    void adjustVolume(@NonNull String packageName, @NonNull String opPackageName,
-            @NonNull ControllerCallbackLink caller, int direction,
-            int flags) {
-        try {
-            mISessionController.adjustVolume(packageName, opPackageName, caller, direction, flags);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that a controller requests setting the volume.
-     *
-     * @param packageName the package name of the controller
-     * @param opPackageName the op package name of this request
-     * @param caller the {@link ControllerCallbackLink} of the controller
-     * @param flags the flags with this volume change request
-     */
-    void setVolumeTo(@NonNull String packageName, @NonNull String opPackageName,
-            @NonNull ControllerCallbackLink caller, int value, int flags) {
-        try {
-            mISessionController.setVolumeTo(packageName, opPackageName, caller, value, flags);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that a controller requests preparing media.
-     *
-     * @param packageName the package name of the controller
-     * @param caller the {@link ControllerCallbackLink} of the controller
-     */
-    void prepare(@NonNull String packageName, @NonNull ControllerCallbackLink caller) {
-        try {
-            mISessionController.prepare(packageName, caller);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that a controller requests preparing media from given media ID.
-     *
-     * @param packageName the package name of the controller
-     * @param caller the {@link ControllerCallbackLink} of the controller
-     * @param mediaId the ID of the media
-     * @param extras the extras included with this request.
-     */
-    void prepareFromMediaId(@NonNull String packageName,
-            @NonNull ControllerCallbackLink caller, @NonNull String mediaId,
-            @Nullable Bundle extras) {
-        try {
-            mISessionController.prepareFromMediaId(packageName, caller, mediaId, extras);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that a controller requests preparing media from given search query.
-     *
-     * @param packageName the package name of the controller
-     * @param caller the {@link ControllerCallbackLink} of the controller
-     * @param query the search query
-     * @param extras the extras included with this request.
-     */
-    void prepareFromSearch(@NonNull String packageName,
-            @NonNull ControllerCallbackLink caller, @NonNull String query,
-            @Nullable Bundle extras) {
-        try {
-            mISessionController.prepareFromSearch(packageName, caller, query, extras);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that a controller requests preparing media from given uri.
-     *
-     * @param packageName the package name of the controller
-     * @param caller the {@link ControllerCallbackLink} of the controller
-     * @param uri the uri of the media
-     * @param extras the extras included with this request.
-     */
-    void prepareFromUri(@NonNull String packageName, @NonNull ControllerCallbackLink caller,
-            @NonNull Uri uri, @Nullable Bundle extras) {
-        try {
-            mISessionController.prepareFromUri(packageName, caller, uri, extras);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that a controller requests playing media.
-     *
-     * @param packageName the package name of the controller
-     * @param caller the {@link ControllerCallbackLink} of the controller
-     */
-    void play(@NonNull String packageName, @NonNull ControllerCallbackLink caller) {
-        try {
-            mISessionController.play(packageName, caller);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that a controller requests playing media from given media ID.
-     *
-     * @param packageName the package name of the controller
-     * @param caller the {@link ControllerCallbackLink} of the controller
-     * @param mediaId the ID of the media
-     * @param extras the extras included with this request.
-     */
-    void playFromMediaId(@NonNull String packageName, @NonNull ControllerCallbackLink caller,
-            @NonNull String mediaId, @Nullable Bundle extras) {
-        try {
-            mISessionController.playFromMediaId(packageName, caller, mediaId, extras);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that a controller requests playing media from given search query.
-     *
-     * @param packageName the package name of the controller
-     * @param caller the {@link ControllerCallbackLink} of the controller
-     * @param query the search query
-     * @param extras the extras included with this request.
-     */
-    void playFromSearch(@NonNull String packageName, @NonNull ControllerCallbackLink caller,
-            @NonNull String query, @Nullable Bundle extras) {
-        try {
-            mISessionController.playFromSearch(packageName, caller, query, extras);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that a controller requests playing media from given uri.
-     *
-     * @param packageName the package name of the controller
-     * @param caller the {@link ControllerCallbackLink} of the controller
-     * @param uri the uri of the media
-     * @param extras the extras included with this request.
-     */
-    void playFromUri(@NonNull String packageName, @NonNull ControllerCallbackLink caller,
-            @NonNull Uri uri, @Nullable Bundle extras) {
-        try {
-            mISessionController.playFromUri(packageName, caller, uri, extras);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that a controller requests skipping to the queue item with given ID.
-     *
-     * @param packageName the package name of the controller
-     * @param caller the {@link ControllerCallbackLink} of the controller
-     * @param id the queue id of the item
-     */
-    void skipToQueueItem(@NonNull String packageName, @NonNull ControllerCallbackLink caller,
-            long id) {
-        try {
-            mISessionController.skipToQueueItem(packageName, caller, id);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that a controller requests pausing media.
-     *
-     * @param packageName the package name of the controller
-     * @param caller the {@link ControllerCallbackLink} of the controller
-     */
-    void pause(@NonNull String packageName, @NonNull ControllerCallbackLink caller) {
-        try {
-            mISessionController.pause(packageName, caller);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that a controller requests stopping media.
-     *
-     * @param packageName the package name of the controller
-     * @param caller the {@link ControllerCallbackLink} of the controller
-     */
-    void stop(@NonNull String packageName, @NonNull ControllerCallbackLink caller) {
-        try {
-            mISessionController.stop(packageName, caller);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that a controller requests skipping to the next queue item.
-     *
-     * @param packageName the package name of the controller
-     * @param caller the {@link ControllerCallbackLink} of the controller
-     */
-    void next(@NonNull String packageName, @NonNull ControllerCallbackLink caller) {
-        try {
-            mISessionController.next(packageName, caller);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that a controller requests skipping to the previous queue item.
-     *
-     * @param packageName the package name of the controller
-     * @param caller the {@link ControllerCallbackLink} of the controller
-     */
-    void previous(@NonNull String packageName, @NonNull ControllerCallbackLink caller) {
-        try {
-            mISessionController.previous(packageName, caller);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that a controller requests fast-forwarding.
-     *
-     * @param packageName the package name of the controller
-     * @param caller the {@link ControllerCallbackLink} of the controller
-     */
-    void fastForward(@NonNull String packageName, @NonNull ControllerCallbackLink caller) {
-        try {
-            mISessionController.fastForward(packageName, caller);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that a controller requests rewinding.
-     *
-     * @param packageName the package name of the controller
-     * @param caller the {@link ControllerCallbackLink} of the controller
-     */
-    void rewind(@NonNull String packageName, @NonNull ControllerCallbackLink caller) {
-        try {
-            mISessionController.rewind(packageName, caller);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that a controller requests seeking to the specific position.
-     *
-     * @param packageName the package name of the controller
-     * @param caller the {@link ControllerCallbackLink} of the controller
-     * @param pos the position to move to, in milliseconds
-     */
-    void seekTo(@NonNull String packageName, @NonNull ControllerCallbackLink caller,
-            long pos) {
-        try {
-            mISessionController.seekTo(packageName, caller, pos);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that a controller requests rating of the current media.
-     *
-     * @param packageName the package name of the controller
-     * @param caller the {@link ControllerCallbackLink} of the controller
-     * @param rating the rating of the current media
-     */
-    void rate(@NonNull String packageName, @NonNull ControllerCallbackLink caller,
-            @NonNull Rating rating) {
-        try {
-            mISessionController.rate(packageName, caller, rating);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that a controller requests changing the playback speed.
-     *
-     * @param packageName the package name of the controller
-     * @param caller the {@link ControllerCallbackLink} of the controller
-     * @param speed the playback speed
-     */
-    void setPlaybackSpeed(@NonNull String packageName, @NonNull ControllerCallbackLink caller,
-            float speed) {
-        try {
-            mISessionController.setPlaybackSpeed(packageName, caller, speed);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that a controller sends a custom action.
-     *
-     * @param packageName the package name of the controller
-     * @param caller the {@link ControllerCallbackLink} of the controller
-     * @param action the name of the action
-     * @param args the arguments included with this action
-     */
-    void sendCustomAction(@NonNull String packageName,
-            @NonNull ControllerCallbackLink caller, @NonNull String action, @Nullable Bundle args) {
-        try {
-            mISessionController.sendCustomAction(packageName, caller, action, args);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Gets the current metadata of the connected session.
-     */
-    @Nullable
-    public MediaMetadata getMetadata() {
-        try {
-            return mISessionController.getMetadata();
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Gets the current playback state of the connected session.
-     */
-    @Nullable
-    public PlaybackState getPlaybackState() {
-        try {
-            return mISessionController.getPlaybackState();
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Gets the current queue of the connected session.
-     */
-    @Nullable
-    public List<MediaSession.QueueItem> getQueue() {
-        try {
-            MediaParceledListSlice queue = mISessionController.getQueue();
-            return queue == null ? null : queue.getList();
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Gets the current queue title of the connected session.
-     */
-    @Nullable
-    public CharSequence getQueueTitle() {
-        try {
-            return mISessionController.getQueueTitle();
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Gets the current extras of the connected session.
-     */
-    @Nullable
-    public Bundle getExtras() {
-        try {
-            return mISessionController.getExtras();
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Gets the current rating type of the connected session.
-     */
-    public int getRatingType() {
-        try {
-            return mISessionController.getRatingType();
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /** Gets the binder */
-    @NonNull
-    public IBinder getBinder() {
-        return mISessionController.asBinder();
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeStrongBinder(mISessionController.asBinder());
-    }
-
-    @Override
-    public int hashCode() {
-        return mISessionController.asBinder().hashCode();
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!(obj instanceof ControllerLink)) {
-            return false;
-        }
-        ControllerLink other = (ControllerLink) obj;
-        return Objects.equals(getBinder(), other.getBinder());
-    }
-
-    /**
-     * Class for Stub implementation
-     */
-    public abstract static class ControllerStub {
-        /** Stub method for ISessionController.sendCommand */
-        public void sendCommand(@NonNull String packageName, @NonNull ControllerCallbackLink caller,
-                @NonNull String command, @Nullable Bundle args, @Nullable ResultReceiver cb) {
-        }
-
-        /** Stub method for ISessionController.sendMediaButton */
-        public boolean sendMediaButton(@NonNull String packageName,
-                @NonNull ControllerCallbackLink caller, @NonNull KeyEvent mediaButton) {
-            return false;
-        }
-
-        /** Stub method for ISessionController.registerCallback */
-        public void registerCallback(@NonNull String packageName,
-                @NonNull ControllerCallbackLink cb) {
-        }
-
-        /** Stub method for ISessionController.unregisterCallback */
-        public void unregisterCallback(@NonNull ControllerCallbackLink cb) {
-        }
-
-        /** Stub method for ISessionController.getPackageName */
-        @NonNull
-        public String getPackageName() {
-            return null;
-        }
-
-        /** Stub method for ISessionController.getTag */
-        @NonNull
-        public String getTag() {
-            return null;
-        }
-
-        /** Stub method for ISessionController.getSessionInfo */
-        @Nullable
-        public Bundle getSessionInfo() {
-            return null;
-        }
-
-        /** Stub method for ISessionController.getLaunchPendingIntent */
-        @Nullable
-        public PendingIntent getLaunchPendingIntent() {
-            return null;
-        }
-
-        /** Stub method for ISessionController.getFlags */
-        public long getFlags() {
-            return 0;
-        }
-
-        /** Stub method for ISessionController.getVolumeAttributes */
-        @NonNull
-        public PlaybackInfo getVolumeAttributes() {
-            return null;
-        }
-
-        /** Stub method for ISessionController.adjustVolume */
-        public void adjustVolume(@NonNull String packageName, @NonNull String opPackageName,
-                @NonNull ControllerCallbackLink caller, int direction, int flags) {
-        }
-
-        /** Stub method for ISessionController.setVolumeTo */
-        public void setVolumeTo(@NonNull String packageName, @NonNull String opPackageName,
-                @NonNull ControllerCallbackLink caller, int value, int flags) {
-        }
-
-        /** Stub method for ISessionController.prepare */
-        public void prepare(@NonNull String packageName, @NonNull ControllerCallbackLink caller) {
-        }
-
-        /** Stub method for ISessionController.prepareFromMediaId */
-        public void prepareFromMediaId(@NonNull String packageName,
-                @NonNull ControllerCallbackLink caller, @NonNull String mediaId,
-                @Nullable Bundle extras) {
-        }
-
-        /** Stub method for ISessionController.prepareFromSearch */
-        public void prepareFromSearch(@NonNull String packageName,
-                @NonNull ControllerCallbackLink caller, @NonNull String query,
-                @Nullable Bundle extras) {
-        }
-
-        /** Stub method for ISessionController.prepareFromUri */
-        public void prepareFromUri(@NonNull String packageName,
-                @NonNull ControllerCallbackLink caller, @NonNull Uri uri, @Nullable Bundle extras) {
-        }
-
-        /** Stub method for ISessionController.play */
-        public void play(@NonNull String packageName, @NonNull ControllerCallbackLink caller) {
-        }
-
-        /** Stub method for ISessionController.playFromMediaId */
-        public void playFromMediaId(@NonNull String packageName,
-                @NonNull ControllerCallbackLink caller, @NonNull String mediaId,
-                @Nullable Bundle extras) {
-        }
-
-        /** Stub method for ISessionController.playFromSearch */
-        public void playFromSearch(@NonNull String packageName,
-                @NonNull ControllerCallbackLink caller, @NonNull String query,
-                @Nullable Bundle extras) {
-        }
-
-        /** Stub method for ISessionController.playFromUri */
-        public void playFromUri(@NonNull String packageName, @NonNull ControllerCallbackLink caller,
-                @NonNull Uri uri, @Nullable Bundle extras) {
-        }
-
-        /** Stub method for ISessionController.skipToQueueItem */
-        public void skipToQueueItem(@NonNull String packageName,
-                @NonNull ControllerCallbackLink caller, long id) {
-        }
-
-        /** Stub method for ISessionController.pause */
-        public void pause(@NonNull String packageName, @NonNull ControllerCallbackLink caller) {
-        }
-
-        /** Stub method for ISessionController.stop */
-        public void stop(@NonNull String packageName, @NonNull ControllerCallbackLink caller) {
-        }
-
-        /** Stub method for ISessionController.next */
-        public void next(@NonNull String packageName, @NonNull ControllerCallbackLink caller) {
-        }
-
-        /** Stub method for ISessionController.previous */
-        public void previous(@NonNull String packageName, @NonNull ControllerCallbackLink caller) {
-        }
-
-        /** Stub method for ISessionController.fastForward */
-        public void fastForward(@NonNull String packageName,
-                @NonNull ControllerCallbackLink caller) {
-        }
-
-        /** Stub method for ISessionController.rewind */
-        public void rewind(@NonNull String packageName, @NonNull ControllerCallbackLink caller) {
-        }
-
-        /** Stub method for ISessionController.seekTo */
-        public void seekTo(@NonNull String packageName, @NonNull ControllerCallbackLink caller,
-                long pos) {
-        }
-
-        /** Stub method for ISessionController.rate */
-        public void rate(@NonNull String packageName, @NonNull ControllerCallbackLink caller,
-                @NonNull Rating rating) {
-        }
-
-        /** Stub method for ISessionController.setPlaybackSpeed */
-        public void setPlaybackSpeed(@NonNull String packageName,
-                @NonNull ControllerCallbackLink caller, float speed) {
-        }
-
-        /** Stub method for ISessionController.sendCustomAction */
-        public void sendCustomAction(@NonNull String packageName,
-                @NonNull ControllerCallbackLink caller, @NonNull String action,
-                @Nullable Bundle args) {
-        }
-
-        /** Stub method for ISessionController.getMetadata */
-        @Nullable
-        public MediaMetadata getMetadata() {
-            return null;
-        }
-
-        /** Stub method for ISessionController.getPlaybackState */
-        @Nullable
-        public PlaybackState getPlaybackState() {
-            return null;
-        }
-
-        /** Stub method for ISessionController.getQueue */
-        @Nullable
-        public List<MediaSession.QueueItem> getQueue() {
-            return null;
-        }
-
-        /** Stub method for ISessionController.getQueueTitle */
-        @Nullable
-        public CharSequence getQueueTitle() {
-            return null;
-        }
-
-        /** Stub method for ISessionController.getExtras */
-        @Nullable
-        public Bundle getExtras() {
-            return null;
-        }
-
-        /** Stub method for ISessionController.getRatingType */
-        public int getRatingType() {
-            return Rating.RATING_NONE;
-        }
-    }
-
-    private class StubProxy extends ISessionController.Stub {
-        @Override
-        public void sendCommand(String packageName, ControllerCallbackLink caller,
-                String command, Bundle args, ResultReceiver cb) {
-            mControllerStub.sendCommand(packageName, caller, command, args, cb);
-        }
-
-        @Override
-        public boolean sendMediaButton(String packageName, ControllerCallbackLink caller,
-                KeyEvent mediaButton) {
-            return mControllerStub.sendMediaButton(packageName, caller, mediaButton);
-        }
-
-        @Override
-        public void registerCallback(String packageName, ControllerCallbackLink cb) {
-            mControllerStub.registerCallback(packageName, cb);
-        }
-
-        @Override
-        public void unregisterCallback(ControllerCallbackLink cb) {
-            mControllerStub.unregisterCallback(cb);
-        }
-
-        @Override
-        public String getPackageName() {
-            return mControllerStub.getPackageName();
-        }
-
-        @Override
-        public String getTag() {
-            return mControllerStub.getTag();
-        }
-
-        @Override
-        public Bundle getSessionInfo() {
-            return mControllerStub.getSessionInfo();
-        }
-
-        @Override
-        public PendingIntent getLaunchPendingIntent() {
-            return mControllerStub.getLaunchPendingIntent();
-        }
-
-        @Override
-        public long getFlags() {
-            return mControllerStub.getFlags();
-        }
-
-        @Override
-        public PlaybackInfo getVolumeAttributes() {
-            return mControllerStub.getVolumeAttributes();
-        }
-
-        @Override
-        public void adjustVolume(String packageName, String opPackageName,
-                ControllerCallbackLink caller, int direction, int flags) {
-            mControllerStub.adjustVolume(packageName, opPackageName, caller, direction, flags);
-        }
-
-        @Override
-        public void setVolumeTo(String packageName, String opPackageName,
-                ControllerCallbackLink caller, int value, int flags) {
-            mControllerStub.setVolumeTo(packageName, opPackageName, caller, value, flags);
-        }
-
-        @Override
-        public void prepare(String packageName, ControllerCallbackLink caller) {
-            mControllerStub.prepare(packageName, caller);
-        }
-
-        @Override
-        public void prepareFromMediaId(String packageName, ControllerCallbackLink caller,
-                String mediaId, Bundle extras) {
-            mControllerStub.prepareFromMediaId(packageName, caller, mediaId, extras);
-        }
-
-        @Override
-        public void prepareFromSearch(String packageName, ControllerCallbackLink caller,
-                String query, Bundle extras) {
-            mControllerStub.prepareFromSearch(packageName, caller, query, extras);
-        }
-
-        @Override
-        public void prepareFromUri(String packageName, ControllerCallbackLink caller,
-                Uri uri, Bundle extras) {
-            mControllerStub.prepareFromUri(packageName, caller, uri, extras);
-        }
-
-        @Override
-        public void play(String packageName, ControllerCallbackLink caller) {
-            mControllerStub.play(packageName, caller);
-        }
-
-        @Override
-        public void playFromMediaId(String packageName, ControllerCallbackLink caller,
-                String mediaId, Bundle extras) {
-            mControllerStub.playFromMediaId(packageName, caller, mediaId, extras);
-        }
-
-        @Override
-        public void playFromSearch(String packageName, ControllerCallbackLink caller,
-                String query, Bundle extras) {
-            mControllerStub.playFromSearch(packageName, caller, query, extras);
-        }
-
-        @Override
-        public void playFromUri(String packageName, ControllerCallbackLink caller,
-                Uri uri, Bundle extras) {
-            mControllerStub.playFromUri(packageName, caller, uri, extras);
-        }
-
-        @Override
-        public void skipToQueueItem(String packageName, ControllerCallbackLink caller, long id) {
-            mControllerStub.skipToQueueItem(packageName, caller, id);
-        }
-
-        @Override
-        public void pause(String packageName, ControllerCallbackLink caller) {
-            mControllerStub.pause(packageName, caller);
-        }
-
-        @Override
-        public void stop(String packageName, ControllerCallbackLink caller) {
-            mControllerStub.stop(packageName, caller);
-        }
-
-        @Override
-        public void next(String packageName, ControllerCallbackLink caller) {
-            mControllerStub.next(packageName, caller);
-        }
-
-        @Override
-        public void previous(String packageName, ControllerCallbackLink caller) {
-            mControllerStub.previous(packageName, caller);
-        }
-
-        @Override
-        public void fastForward(String packageName, ControllerCallbackLink caller) {
-            mControllerStub.fastForward(packageName, caller);
-        }
-
-        @Override
-        public void rewind(String packageName, ControllerCallbackLink caller) {
-            mControllerStub.rewind(packageName, caller);
-        }
-
-        @Override
-        public void seekTo(String packageName, ControllerCallbackLink caller, long pos) {
-            mControllerStub.seekTo(packageName, caller, pos);
-        }
-
-        @Override
-        public void rate(String packageName, ControllerCallbackLink caller, Rating rating) {
-            mControllerStub.rate(packageName, caller, rating);
-        }
-
-        @Override
-        public void setPlaybackSpeed(String packageName, ControllerCallbackLink caller,
-                float speed) {
-            mControllerStub.setPlaybackSpeed(packageName, caller, speed);
-        }
-
-        @Override
-        public void sendCustomAction(String packageName, ControllerCallbackLink caller,
-                String action, Bundle args) {
-            mControllerStub.sendCustomAction(packageName, caller, action, args);
-        }
-
-        @Override
-        public MediaMetadata getMetadata() {
-            return mControllerStub.getMetadata();
-        }
-
-        @Override
-        public PlaybackState getPlaybackState() {
-            return mControllerStub.getPlaybackState();
-        }
-
-        @Override
-        public MediaParceledListSlice getQueue() {
-            List<MediaSession.QueueItem> queue = mControllerStub.getQueue();
-            return queue == null ? null : new MediaParceledListSlice(queue);
-        }
-
-        @Override
-        public CharSequence getQueueTitle() {
-            return mControllerStub.getQueueTitle();
-        }
-
-        @Override
-        public Bundle getExtras() {
-            return mControllerStub.getExtras();
-        }
-
-        @Override
-        public int getRatingType() {
-            return mControllerStub.getRatingType();
-        }
-    }
-}
diff --git a/media/java/android/media/session/ISession.aidl b/media/java/android/media/session/ISession.aidl
index 9b1ad7b..fcde95a 100644
--- a/media/java/android/media/session/ISession.aidl
+++ b/media/java/android/media/session/ISession.aidl
@@ -19,7 +19,7 @@
 import android.media.AudioAttributes;
 import android.media.MediaMetadata;
 import android.media.MediaParceledListSlice;
-import android.media.session.ControllerLink;
+import android.media.session.ISessionController;
 import android.media.session.PlaybackState;
 import android.media.session.MediaSession;
 import android.os.Bundle;
@@ -31,7 +31,7 @@
  */
 interface ISession {
     void sendEvent(String event, in Bundle data);
-    ControllerLink getController();
+    ISessionController getController();
     void setFlags(int flags);
     void setActive(boolean active);
     void setMediaButtonReceiver(in PendingIntent mbr);
diff --git a/media/java/android/media/session/ISessionManager.aidl b/media/java/android/media/session/ISessionManager.aidl
index e85461f..02348476 100644
--- a/media/java/android/media/session/ISessionManager.aidl
+++ b/media/java/android/media/session/ISessionManager.aidl
@@ -22,10 +22,10 @@
 import android.media.session.ICallback;
 import android.media.session.IOnMediaKeyListener;
 import android.media.session.IOnVolumeKeyLongPressListener;
+import android.media.session.ISession;
 import android.media.session.ISession2TokensListener;
 import android.media.session.MediaSession;
 import android.media.session.SessionCallbackLink;
-import android.media.session.SessionLink;
 import android.os.Bundle;
 import android.view.KeyEvent;
 
@@ -34,7 +34,7 @@
  * @hide
  */
 interface ISessionManager {
-    SessionLink createSession(String packageName, in SessionCallbackLink sessionCb, String tag,
+    ISession createSession(String packageName, in SessionCallbackLink sessionCb, String tag,
             in Bundle sessionInfo, int userId);
     void notifySession2Created(in Session2Token sessionToken);
     List<MediaSession.Token> getSessions(in ComponentName compName, int userId);
@@ -55,8 +55,8 @@
     void addSession2TokensListener(in ISession2TokensListener listener, int userId);
     void removeSession2TokensListener(in ISession2TokensListener listener);
 
-    // This is for the system volume UI only
-    void setRemoteVolumeController(in IRemoteVolumeController rvc);
+    void registerRemoteVolumeController(in IRemoteVolumeController rvc);
+    void unregisterRemoteVolumeController(in IRemoteVolumeController rvc);
 
     // For PhoneWindowManager to precheck media keys
     boolean isGlobalPriorityActive();
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index 5ee52ce..036cd78 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -18,13 +18,13 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.media.AudioAttributes;
 import android.media.AudioManager;
 import android.media.MediaMetadata;
+import android.media.MediaParceledListSlice;
 import android.media.Rating;
 import android.media.VolumeProvider;
 import android.media.session.MediaSession.QueueItem;
@@ -35,6 +35,7 @@
 import android.os.Message;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.text.TextUtils;
 import android.util.Log;
@@ -68,7 +69,7 @@
     private static final int MSG_UPDATE_EXTRAS = 7;
     private static final int MSG_DESTROYED = 8;
 
-    private final ControllerLink mSessionBinder;
+    private final ISessionController mSessionBinder;
 
     private final MediaSession.Token mToken;
     private final Context mContext;
@@ -96,10 +97,10 @@
         if (token == null) {
             throw new IllegalArgumentException("token shouldn't be null");
         }
-        if (token.getControllerLink() == null) {
-            throw new IllegalArgumentException("token.getControllerLink() shouldn't be null");
+        if (token.getBinder() == null) {
+            throw new IllegalArgumentException("token.getBinder() shouldn't be null");
         }
-        mSessionBinder = token.getControllerLink();
+        mSessionBinder = token.getBinder();
         mTransportControls = new TransportControls();
         mToken = token;
         mContext = context;
@@ -132,7 +133,7 @@
         }
         try {
             return mSessionBinder.sendMediaButton(mContext.getPackageName(), mCbStub, keyEvent);
-        } catch (RuntimeException e) {
+        } catch (RemoteException e) {
             // System is dead. =(
         }
         return false;
@@ -146,7 +147,7 @@
     public @Nullable PlaybackState getPlaybackState() {
         try {
             return mSessionBinder.getPlaybackState();
-        } catch (RuntimeException e) {
+        } catch (RemoteException e) {
             Log.wtf(TAG, "Error calling getPlaybackState.", e);
             return null;
         }
@@ -160,7 +161,7 @@
     public @Nullable MediaMetadata getMetadata() {
         try {
             return mSessionBinder.getMetadata();
-        } catch (RuntimeException e) {
+        } catch (RemoteException e) {
             Log.wtf(TAG, "Error calling getMetadata.", e);
             return null;
         }
@@ -174,8 +175,9 @@
      */
     public @Nullable List<MediaSession.QueueItem> getQueue() {
         try {
-            return mSessionBinder.getQueue();
-        } catch (RuntimeException e) {
+            MediaParceledListSlice list = mSessionBinder.getQueue();
+            return list == null ? null : list.getList();
+        } catch (RemoteException e) {
             Log.wtf(TAG, "Error calling getQueue.", e);
         }
         return null;
@@ -187,7 +189,7 @@
     public @Nullable CharSequence getQueueTitle() {
         try {
             return mSessionBinder.getQueueTitle();
-        } catch (RuntimeException e) {
+        } catch (RemoteException e) {
             Log.wtf(TAG, "Error calling getQueueTitle", e);
         }
         return null;
@@ -199,7 +201,7 @@
     public @Nullable Bundle getExtras() {
         try {
             return mSessionBinder.getExtras();
-        } catch (RuntimeException e) {
+        } catch (RemoteException e) {
             Log.wtf(TAG, "Error calling getExtras", e);
         }
         return null;
@@ -222,7 +224,7 @@
     public int getRatingType() {
         try {
             return mSessionBinder.getRatingType();
-        } catch (RuntimeException e) {
+        } catch (RemoteException e) {
             Log.wtf(TAG, "Error calling getRatingType.", e);
             return Rating.RATING_NONE;
         }
@@ -236,7 +238,7 @@
     public long getFlags() {
         try {
             return mSessionBinder.getFlags();
-        } catch (RuntimeException e) {
+        } catch (RemoteException e) {
             Log.wtf(TAG, "Error calling getFlags.", e);
         }
         return 0;
@@ -250,7 +252,7 @@
     public @Nullable PlaybackInfo getPlaybackInfo() {
         try {
             return mSessionBinder.getVolumeAttributes();
-        } catch (RuntimeException e) {
+        } catch (RemoteException e) {
             Log.wtf(TAG, "Error calling getAudioInfo.", e);
         }
         return null;
@@ -265,7 +267,7 @@
     public @Nullable PendingIntent getSessionActivity() {
         try {
             return mSessionBinder.getLaunchPendingIntent();
-        } catch (RuntimeException e) {
+        } catch (RemoteException e) {
             Log.wtf(TAG, "Error calling getPendingIntent.", e);
         }
         return null;
@@ -298,7 +300,7 @@
             //       AppOpsManager usages.
             mSessionBinder.setVolumeTo(mContext.getPackageName(), mContext.getOpPackageName(),
                     mCbStub, value, flags);
-        } catch (RuntimeException e) {
+        } catch (RemoteException e) {
             Log.wtf(TAG, "Error calling setVolumeTo.", e);
         }
     }
@@ -323,7 +325,7 @@
             //       AppOpsManager usages.
             mSessionBinder.adjustVolume(mContext.getPackageName(), mContext.getOpPackageName(),
                     mCbStub, direction, flags);
-        } catch (RuntimeException e) {
+        } catch (RemoteException e) {
             Log.wtf(TAG, "Error calling adjustVolumeBy.", e);
         }
     }
@@ -389,7 +391,7 @@
         }
         try {
             mSessionBinder.sendCommand(mContext.getPackageName(), mCbStub, command, args, cb);
-        } catch (RuntimeException e) {
+        } catch (RemoteException e) {
             Log.d(TAG, "Dead object in sendCommand.", e);
         }
     }
@@ -403,7 +405,7 @@
         if (mPackageName == null) {
             try {
                 mPackageName = mSessionBinder.getPackageName();
-            } catch (RuntimeException e) {
+            } catch (RemoteException e) {
                 Log.d(TAG, "Dead object in getPackageName.", e);
             }
         }
@@ -420,7 +422,7 @@
         if (mSessionInfo == null) {
             try {
                 mSessionInfo = mSessionBinder.getSessionInfo();
-            } catch (RuntimeException e) {
+            } catch (RemoteException e) {
                 Log.d(TAG, "Dead object in getSessionInfo.", e);
             }
         }
@@ -437,7 +439,7 @@
         if (mTag == null) {
             try {
                 mTag = mSessionBinder.getTag();
-            } catch (RuntimeException e) {
+            } catch (RemoteException e) {
                 Log.d(TAG, "Dead object in getTag.", e);
             }
         }
@@ -447,7 +449,7 @@
     /*
      * @hide
      */
-    ControllerLink getSessionBinder() {
+    ISessionController getSessionBinder() {
         return mSessionBinder;
     }
 
@@ -457,7 +459,7 @@
     @UnsupportedAppUsage
     public boolean controlsSameSession(MediaController other) {
         if (other == null) return false;
-        return mSessionBinder.getBinder() == other.getSessionBinder().getBinder();
+        return mSessionBinder.asBinder() == other.getSessionBinder().asBinder();
     }
 
     private void addCallbackLocked(Callback cb, Handler handler) {
@@ -473,7 +475,7 @@
             try {
                 mSessionBinder.registerCallback(mContext.getPackageName(), mCbStub);
                 mCbRegistered = true;
-            } catch (RuntimeException e) {
+            } catch (RemoteException e) {
                 Log.e(TAG, "Dead object in registerCallback", e);
             }
         }
@@ -492,7 +494,7 @@
         if (mCbRegistered && mCallbacks.size() == 0) {
             try {
                 mSessionBinder.unregisterCallback(mCbStub);
-            } catch (RuntimeException e) {
+            } catch (RemoteException e) {
                 Log.e(TAG, "Dead object in removeCallbackLocked");
             }
             mCbRegistered = false;
@@ -619,7 +621,7 @@
         public void prepare() {
             try {
                 mSessionBinder.prepare(mContext.getPackageName(), mCbStub);
-            } catch (RuntimeException e) {
+            } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling prepare.", e);
             }
         }
@@ -644,7 +646,7 @@
             try {
                 mSessionBinder.prepareFromMediaId(mContext.getPackageName(), mCbStub, mediaId,
                         extras);
-            } catch (RuntimeException e) {
+            } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling prepare(" + mediaId + ").", e);
             }
         }
@@ -671,7 +673,7 @@
             try {
                 mSessionBinder.prepareFromSearch(mContext.getPackageName(), mCbStub, query,
                         extras);
-            } catch (RuntimeException e) {
+            } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling prepare(" + query + ").", e);
             }
         }
@@ -695,7 +697,7 @@
             }
             try {
                 mSessionBinder.prepareFromUri(mContext.getPackageName(), mCbStub, uri, extras);
-            } catch (RuntimeException e) {
+            } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling prepare(" + uri + ").", e);
             }
         }
@@ -706,7 +708,7 @@
         public void play() {
             try {
                 mSessionBinder.play(mContext.getPackageName(), mCbStub);
-            } catch (RuntimeException e) {
+            } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling play.", e);
             }
         }
@@ -726,7 +728,7 @@
             try {
                 mSessionBinder.playFromMediaId(mContext.getPackageName(), mCbStub, mediaId,
                         extras);
-            } catch (RuntimeException e) {
+            } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling play(" + mediaId + ").", e);
             }
         }
@@ -748,7 +750,7 @@
             }
             try {
                 mSessionBinder.playFromSearch(mContext.getPackageName(), mCbStub, query, extras);
-            } catch (RuntimeException e) {
+            } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling play(" + query + ").", e);
             }
         }
@@ -767,7 +769,7 @@
             }
             try {
                 mSessionBinder.playFromUri(mContext.getPackageName(), mCbStub, uri, extras);
-            } catch (RuntimeException e) {
+            } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling play(" + uri + ").", e);
             }
         }
@@ -779,7 +781,7 @@
         public void skipToQueueItem(long id) {
             try {
                 mSessionBinder.skipToQueueItem(mContext.getPackageName(), mCbStub, id);
-            } catch (RuntimeException e) {
+            } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling skipToItem(" + id + ").", e);
             }
         }
@@ -791,7 +793,7 @@
         public void pause() {
             try {
                 mSessionBinder.pause(mContext.getPackageName(), mCbStub);
-            } catch (RuntimeException e) {
+            } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling pause.", e);
             }
         }
@@ -803,7 +805,7 @@
         public void stop() {
             try {
                 mSessionBinder.stop(mContext.getPackageName(), mCbStub);
-            } catch (RuntimeException e) {
+            } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling stop.", e);
             }
         }
@@ -816,7 +818,7 @@
         public void seekTo(long pos) {
             try {
                 mSessionBinder.seekTo(mContext.getPackageName(), mCbStub, pos);
-            } catch (RuntimeException e) {
+            } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling seekTo.", e);
             }
         }
@@ -828,7 +830,7 @@
         public void fastForward() {
             try {
                 mSessionBinder.fastForward(mContext.getPackageName(), mCbStub);
-            } catch (RuntimeException e) {
+            } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling fastForward.", e);
             }
         }
@@ -839,7 +841,7 @@
         public void skipToNext() {
             try {
                 mSessionBinder.next(mContext.getPackageName(), mCbStub);
-            } catch (RuntimeException e) {
+            } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling next.", e);
             }
         }
@@ -851,7 +853,7 @@
         public void rewind() {
             try {
                 mSessionBinder.rewind(mContext.getPackageName(), mCbStub);
-            } catch (RuntimeException e) {
+            } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling rewind.", e);
             }
         }
@@ -862,7 +864,7 @@
         public void skipToPrevious() {
             try {
                 mSessionBinder.previous(mContext.getPackageName(), mCbStub);
-            } catch (RuntimeException e) {
+            } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling previous.", e);
             }
         }
@@ -877,7 +879,7 @@
         public void setRating(Rating rating) {
             try {
                 mSessionBinder.rate(mContext.getPackageName(), mCbStub, rating);
-            } catch (RuntimeException e) {
+            } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling rate.", e);
             }
         }
@@ -890,7 +892,7 @@
         public void setPlaybackSpeed(float speed) {
             try {
                 mSessionBinder.setPlaybackSpeed(mContext.getPackageName(), mCbStub, speed);
-            } catch (RuntimeException e) {
+            } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling setPlaybackSpeed.", e);
             }
         }
@@ -925,7 +927,7 @@
             }
             try {
                 mSessionBinder.sendCustomAction(mContext.getPackageName(), mCbStub, action, args);
-            } catch (RuntimeException e) {
+            } catch (RemoteException e) {
                 Log.d(TAG, "Dead object in sendCustomAction.", e);
             }
         }
@@ -954,7 +956,6 @@
         /**
          * @hide
          */
-        @SystemApi
         public PlaybackInfo(int type, int control, int max, int current, AudioAttributes attrs) {
             mVolumeType = type;
             mVolumeControl = control;
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index c4f8b79..cbc6c9d 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -36,6 +36,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.Process;
+import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.service.media.MediaBrowserService;
 import android.text.TextUtils;
@@ -163,11 +164,11 @@
                 .getSystemService(Context.MEDIA_SESSION_SERVICE);
         try {
             SessionCallbackLink cbLink = new SessionCallbackLink(context);
-            SessionLink sessionLink = manager.createSession(cbLink, tag, sessionInfo);
-            mImpl = new MediaSessionEngine(context, sessionLink, cbLink);
+            ISession binder = manager.createSession(cbLink, tag, sessionInfo);
+            mImpl = new MediaSessionEngine(context, binder, cbLink);
             mMaxBitmapSize = context.getResources().getDimensionPixelSize(
                     com.android.internal.R.dimen.config_mediaMetadataBitmapMaxSize);
-        } catch (RuntimeException e) {
+        } catch (RemoteException e) {
             throw new RuntimeException("Remote error creating session.", e);
         }
     }
@@ -445,19 +446,19 @@
     public static final class Token implements Parcelable {
 
         private final int mUid;
-        private final ControllerLink mControllerLink;
+        private final ISessionController mBinder;
 
         /**
          * @hide
          */
-        public Token(ControllerLink controllerLink) {
+        public Token(ISessionController binder) {
             mUid = Process.myUid();
-            mControllerLink = controllerLink;
+            mBinder = binder;
         }
 
         Token(Parcel in) {
             mUid = in.readInt();
-            mControllerLink = in.readParcelable(null);
+            mBinder = ISessionController.Stub.asInterface(in.readStrongBinder());
         }
 
         @Override
@@ -468,15 +469,14 @@
         @Override
         public void writeToParcel(Parcel dest, int flags) {
             dest.writeInt(mUid);
-            dest.writeParcelable(mControllerLink, flags);
+            dest.writeStrongBinder(mBinder.asBinder());
         }
 
         @Override
         public int hashCode() {
             final int prime = 31;
             int result = mUid;
-            result = prime * result + ((mControllerLink == null)
-                    ? 0 : mControllerLink.getBinder().hashCode());
+            result = prime * result + (mBinder == null ? 0 : mBinder.asBinder().hashCode());
             return result;
         }
 
@@ -492,7 +492,10 @@
             if (mUid != other.mUid) {
                 return false;
             }
-            return Objects.equals(mControllerLink, other.mControllerLink);
+            if (mBinder == null || other.mBinder == null) {
+                return mBinder == other.mBinder;
+            }
+            return Objects.equals(mBinder.asBinder(), other.mBinder.asBinder());
         }
 
         /**
@@ -504,11 +507,11 @@
         }
 
         /**
-         * Gets the controller link in this token.
+         * Gets the controller binder in this token.
          * @hide
          */
-        public ControllerLink getControllerLink() {
-            return mControllerLink;
+        public ISessionController getBinder() {
+            return mBinder;
         }
 
         public static final @android.annotation.NonNull Parcelable.Creator<Token> CREATOR =
diff --git a/media/java/android/media/session/MediaSessionEngine.java b/media/java/android/media/session/MediaSessionEngine.java
index 266bf32..7c5243a 100644
--- a/media/java/android/media/session/MediaSessionEngine.java
+++ b/media/java/android/media/session/MediaSessionEngine.java
@@ -25,6 +25,7 @@
 import android.media.AudioAttributes;
 import android.media.MediaDescription;
 import android.media.MediaMetadata;
+import android.media.MediaParceledListSlice;
 import android.media.Rating;
 import android.media.VolumeProvider;
 import android.media.session.MediaSessionManager.RemoteUserInfo;
@@ -34,6 +35,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.Parcel;
+import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.service.media.MediaBrowserService;
 import android.text.TextUtils;
@@ -55,7 +57,7 @@
 
     private final MediaSession.Token mSessionToken;
     private final MediaController mController;
-    private final SessionLink mSessionLink;
+    private final ISession mBinder;
 
     private CallbackMessageHandler mCallbackHandler;
     private VolumeProvider mVolumeProvider;
@@ -70,14 +72,14 @@
      * finished with the session.
      *
      * @param context The context to use to create the session.
-     * @param sessionLink A session link for the binder of MediaSessionRecord
+     * @param binder A session binder
      */
-    public MediaSessionEngine(@NonNull Context context, @NonNull SessionLink sessionLink,
-            @NonNull SessionCallbackLink cbLink) {
-        mSessionLink = sessionLink;
+    public MediaSessionEngine(@NonNull Context context, @NonNull ISession binder,
+            @NonNull SessionCallbackLink cbLink) throws RemoteException {
+        mBinder = binder;
 
         cbLink.setSessionEngine(this);
-        mSessionToken = new MediaSession.Token(mSessionLink.getController());
+        mSessionToken = new MediaSession.Token(mBinder.getController());
         mController = new MediaController(context, mSessionToken);
     }
 
@@ -134,8 +136,8 @@
      */
     public void setSessionActivity(@Nullable PendingIntent pi) {
         try {
-            mSessionLink.setLaunchPendingIntent(pi);
-        } catch (RuntimeException e) {
+            mBinder.setLaunchPendingIntent(pi);
+        } catch (RemoteException e) {
             Log.wtf(TAG, "Failure in setLaunchPendingIntent.", e);
         }
     }
@@ -150,8 +152,8 @@
      */
     public void setMediaButtonReceiver(@Nullable PendingIntent mbr) {
         try {
-            mSessionLink.setMediaButtonReceiver(mbr);
-        } catch (RuntimeException e) {
+            mBinder.setMediaButtonReceiver(mbr);
+        } catch (RemoteException e) {
             Log.wtf(TAG, "Failure in setMediaButtonReceiver.", e);
         }
     }
@@ -163,8 +165,8 @@
      */
     public void setFlags(int flags) {
         try {
-            mSessionLink.setFlags(flags);
-        } catch (RuntimeException e) {
+            mBinder.setFlags(flags);
+        } catch (RemoteException e) {
             Log.wtf(TAG, "Failure in setFlags.", e);
         }
     }
@@ -185,8 +187,8 @@
             throw new IllegalArgumentException("Attributes cannot be null for local playback.");
         }
         try {
-            mSessionLink.setPlaybackToLocal(attributes);
-        } catch (RuntimeException e) {
+            mBinder.setPlaybackToLocal(attributes);
+        } catch (RemoteException e) {
             Log.wtf(TAG, "Failure in setPlaybackToLocal.", e);
         }
     }
@@ -217,10 +219,10 @@
         });
 
         try {
-            mSessionLink.setPlaybackToRemote(volumeProvider.getVolumeControl(),
+            mBinder.setPlaybackToRemote(volumeProvider.getVolumeControl(),
                     volumeProvider.getMaxVolume());
-            mSessionLink.setCurrentVolume(volumeProvider.getCurrentVolume());
-        } catch (RuntimeException e) {
+            mBinder.setCurrentVolume(volumeProvider.getCurrentVolume());
+        } catch (RemoteException e) {
             Log.wtf(TAG, "Failure in setPlaybackToRemote.", e);
         }
     }
@@ -238,9 +240,9 @@
             return;
         }
         try {
-            mSessionLink.setActive(active);
+            mBinder.setActive(active);
             mActive = active;
-        } catch (RuntimeException e) {
+        } catch (RemoteException e) {
             Log.wtf(TAG, "Failure in setActive.", e);
         }
     }
@@ -267,8 +269,8 @@
             throw new IllegalArgumentException("event cannot be null or empty");
         }
         try {
-            mSessionLink.sendEvent(event, extras);
-        } catch (RuntimeException e) {
+            mBinder.sendEvent(event, extras);
+        } catch (RemoteException e) {
             Log.wtf(TAG, "Error sending event", e);
         }
     }
@@ -280,8 +282,8 @@
      */
     public void close() {
         try {
-            mSessionLink.destroySession();
-        } catch (RuntimeException e) {
+            mBinder.destroySession();
+        } catch (RemoteException e) {
             Log.wtf(TAG, "Error releasing session: ", e);
         }
     }
@@ -316,8 +318,8 @@
     public void setPlaybackState(@Nullable PlaybackState state) {
         mPlaybackState = state;
         try {
-            mSessionLink.setPlaybackState(state);
-        } catch (RuntimeException e) {
+            mBinder.setPlaybackState(state);
+        } catch (RemoteException e) {
             Log.wtf(TAG, "Dead object in setPlaybackState.", e);
         }
     }
@@ -344,8 +346,8 @@
         String metadataDescription = "size=" + fields + ", description=" + description;
 
         try {
-            mSessionLink.setMetadata(metadata, duration, metadataDescription);
-        } catch (RuntimeException e) {
+            mBinder.setMetadata(metadata, duration, metadataDescription);
+        } catch (RemoteException e) {
             Log.wtf(TAG, "Dead object in setPlaybackState.", e);
         }
     }
@@ -363,8 +365,8 @@
      */
     public void setQueue(@Nullable List<MediaSession.QueueItem> queue) {
         try {
-            mSessionLink.setQueue(queue);
-        } catch (RuntimeException e) {
+            mBinder.setQueue(queue == null ? null : new MediaParceledListSlice(queue));
+        } catch (RemoteException e) {
             Log.wtf("Dead object in setQueue.", e);
         }
     }
@@ -378,8 +380,8 @@
      */
     public void setQueueTitle(@Nullable CharSequence title) {
         try {
-            mSessionLink.setQueueTitle(title);
-        } catch (RuntimeException e) {
+            mBinder.setQueueTitle(title);
+        } catch (RemoteException e) {
             Log.wtf("Dead object in setQueueTitle.", e);
         }
     }
@@ -399,8 +401,8 @@
      */
     public void setRatingType(int type) {
         try {
-            mSessionLink.setRatingType(type);
-        } catch (RuntimeException e) {
+            mBinder.setRatingType(type);
+        } catch (RemoteException e) {
             Log.e(TAG, "Error in setRatingType.", e);
         }
     }
@@ -414,8 +416,8 @@
      */
     public void setExtras(@Nullable Bundle extras) {
         try {
-            mSessionLink.setExtras(extras);
-        } catch (RuntimeException e) {
+            mBinder.setExtras(extras);
+        } catch (RemoteException e) {
             Log.wtf("Dead object in setExtras.", e);
         }
     }
@@ -464,8 +466,8 @@
             }
         }
         try {
-            mSessionLink.setCurrentVolume(provider.getCurrentVolume());
-        } catch (RuntimeException e) {
+            mBinder.setCurrentVolume(provider.getCurrentVolume());
+        } catch (RemoteException e) {
             Log.e(TAG, "Error in notifyVolumeChanged", e);
         }
     }
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index fde4f88..7ca5c93 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -107,7 +107,7 @@
      * @hide
      */
     @NonNull
-    public SessionLink createSession(@NonNull SessionCallbackLink cbStub, @NonNull String tag,
+    public ISession createSession(@NonNull SessionCallbackLink cbStub, @NonNull String tag,
             @Nullable Bundle sessionInfo) {
         try {
             return mService.createSession(mContext.getPackageName(), cbStub, tag, sessionInfo,
@@ -424,17 +424,33 @@
     }
 
     /**
-     * Set the remote volume controller to receive volume updates on. Only for
-     * use by system UI.
+     * Set the remote volume controller to receive volume updates on.
+     * Only for use by System UI and Settings application.
      *
      * @param rvc The volume controller to receive updates on.
      * @hide
      */
-    public void setRemoteVolumeController(IRemoteVolumeController rvc) {
+    public void registerRemoteVolumeController(IRemoteVolumeController rvc) {
         try {
-            mService.setRemoteVolumeController(rvc);
+            mService.registerRemoteVolumeController(rvc);
         } catch (RemoteException e) {
-            Log.e(TAG, "Error in setRemoteVolumeController.", e);
+            Log.e(TAG, "Error in registerRemoteVolumeController.", e);
+        }
+    }
+
+    /**
+     * Unregisters the remote volume controller which was previously registered with
+     * {@link #registerRemoteVolumeController(IRemoteVolumeController)}.
+     * Only for use by System UI and Settings application.
+     *
+     * @param rvc The volume controller which was registered.
+     * @hide
+     */
+    public void unregisterRemoteVolumeController(IRemoteVolumeController rvc) {
+        try {
+            mService.unregisterRemoteVolumeController(rvc);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error in unregisterRemoteVolumeController.", e);
         }
     }
 
diff --git a/media/java/android/media/session/SessionLink.aidl b/media/java/android/media/session/SessionLink.aidl
deleted file mode 100644
index c3be23e..0000000
--- a/media/java/android/media/session/SessionLink.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright 2019 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.session;
-
-parcelable SessionLink;
diff --git a/media/java/android/media/session/SessionLink.java b/media/java/android/media/session/SessionLink.java
deleted file mode 100644
index 2b42a2d..0000000
--- a/media/java/android/media/session/SessionLink.java
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
- * Copyright 2019 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.session;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.PendingIntent;
-import android.media.AudioAttributes;
-import android.media.MediaMetadata;
-import android.media.MediaParceledListSlice;
-import android.media.session.MediaSession.QueueItem;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.RemoteException;
-
-import java.util.List;
-
-/**
- * Handles incoming commands from {@link MediaSession}.
- * @hide
- */
-public final class SessionLink implements Parcelable {
-    public static final @android.annotation.NonNull Parcelable.Creator<SessionLink> CREATOR =
-            new Parcelable.Creator<SessionLink>() {
-                @Override
-                public SessionLink createFromParcel(Parcel in) {
-                    return new SessionLink(in.readStrongBinder());
-                }
-
-                @Override
-                public SessionLink[] newArray(int size) {
-                    return new SessionLink[size];
-                }
-            };
-
-    final SessionStub mSessionStub;
-    final ISession mISession;
-
-    /**
-     * Constructor for stub (Callee)
-     */
-    public SessionLink(@NonNull SessionStub sessionStub) {
-        mSessionStub = sessionStub;
-        mISession = new StubProxy();
-    }
-
-    /**
-     * Constructor for interface (Caller)
-     */
-    public SessionLink(IBinder binder) {
-        mSessionStub = null;
-        mISession = ISession.Stub.asInterface(binder);
-    }
-
-    /**
-     * Tell system that the session sends an event to all the connected controllers.
-     *
-     * @param event the name of the event
-     * @param extras the extras included with the event
-     */
-    void sendEvent(@NonNull String event, @Nullable Bundle extras) {
-        try {
-            mISession.sendEvent(event, extras);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Gets the controller link from the system.
-     */
-    @NonNull
-    ControllerLink getController() {
-        try {
-            return mISession.getController();
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that the session sets the flags.
-     *
-     * @param flags the new session flags
-     */
-    void setFlags(int flags) {
-        try {
-            mISession.setFlags(flags);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that the session is (in)active.
-     *
-     * @param active the new activeness state
-     */
-    void setActive(boolean active) {
-        try {
-            mISession.setActive(active);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that the session sets the media button receiver.
-     *
-     * @param mbr the pending intent for media button receiver
-     */
-    void setMediaButtonReceiver(@Nullable PendingIntent mbr) {
-        try {
-            mISession.setMediaButtonReceiver(mbr);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that the session sets the pending intent for launching UI.
-     *
-     * @param pi the pending intent for launching UI
-     */
-    void setLaunchPendingIntent(@Nullable PendingIntent pi) {
-        try {
-            mISession.setLaunchPendingIntent(pi);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that the session is destroyed.
-     */
-    void destroySession() {
-        try {
-            mISession.destroySession();
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that the session sets the new metadata.
-     *
-     * @param metadata the new metadata
-     * @param duration the duration of the media in milliseconds
-     * @param metadataDescription the description of the metadata
-     */
-    void setMetadata(@Nullable MediaMetadata metadata, long duration,
-            @Nullable String metadataDescription) {
-        try {
-            mISession.setMetadata(metadata, duration, metadataDescription);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that the session sets the new playback state.
-     *
-     * @param state the new playback state
-     */
-    void setPlaybackState(@Nullable PlaybackState state) {
-        try {
-            mISession.setPlaybackState(state);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that the session sets the new queue.
-     *
-     * @param queue the new queue
-     */
-    void setQueue(@Nullable List<QueueItem> queue) {
-        try {
-            mISession.setQueue(queue == null ? null : new MediaParceledListSlice(queue));
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that the session sets the new queue title.
-     *
-     * @param title the new queue title
-     */
-    void setQueueTitle(@Nullable CharSequence title) {
-        try {
-            mISession.setQueueTitle(title);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that the session sets the new extras.
-     *
-     * @param extras the new extras
-     */
-    void setExtras(@Nullable Bundle extras) {
-        try {
-            mISession.setExtras(extras);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that the session sets the new rating type of the current media.
-     *
-     * @param type the rating type.
-     */
-    void setRatingType(int type) {
-        try {
-            mISession.setRatingType(type);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that the session represents a local playback.
-     *
-     * @param attributes the audio attributes of the local playback.
-     */
-    void setPlaybackToLocal(@NonNull AudioAttributes attributes) {
-        try {
-            mISession.setPlaybackToLocal(attributes);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that the session represents a remote playback.
-     *
-     * @param control the volume control type
-     * @param max the max volume
-     */
-    void setPlaybackToRemote(int control, int max) {
-        try {
-            mISession.setPlaybackToRemote(control, max);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Tell system that the session sets the new current volume.
-     *
-     * @param currentVolume the new current volume
-     */
-    void setCurrentVolume(int currentVolume) {
-        try {
-            mISession.setCurrentVolume(currentVolume);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /** Gets the binder */
-    @NonNull
-    public IBinder getBinder() {
-        return mISession.asBinder();
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeStrongBinder(mISession.asBinder());
-    }
-
-    /**
-     * Class for Stub implementation
-     */
-    public abstract static class SessionStub {
-        /** Stub method for ISession.sendEvent */
-        public void sendEvent(@NonNull String event, @Nullable Bundle data) {
-        }
-
-        /** Stub method for ISession.getController */
-        @NonNull
-        public ControllerLink getController() {
-            return null;
-        }
-
-        /** Stub method for ISession.setFlags */
-        public void setFlags(int flags) {
-        }
-
-        /** Stub method for ISession.setActive */
-        public void setActive(boolean active) {
-        }
-
-        /** Stub method for ISession.setMediaButtonReceiver */
-        public void setMediaButtonReceiver(@Nullable PendingIntent mbr) {
-        }
-
-        /** Stub method for ISession.setLaunchPendingIntent */
-        public void setLaunchPendingIntent(@Nullable PendingIntent pi) {
-        }
-
-        /** Stub method for ISession.destroySession */
-        public void destroySession() {
-        }
-
-        /** Stub method for ISession.setMetadata */
-        public void setMetadata(@Nullable MediaMetadata metadata, long duration,
-                @Nullable String metadataDescription) {
-        }
-
-        /** Stub method for ISession.setPlaybackState */
-        public void setPlaybackState(@Nullable PlaybackState state) {
-        }
-
-        /** Stub method for ISession.setQueue */
-        public void setQueue(@Nullable List<QueueItem> queue) {
-        }
-
-        /** Stub method for ISession.setQueueTitle */
-        public void setQueueTitle(@Nullable CharSequence title) {
-        }
-
-        /** Stub method for ISession.setExtras */
-        public void setExtras(@Nullable Bundle extras) {
-        }
-
-        /** Stub method for ISession.setRatingType */
-        public void setRatingType(int type) {
-        }
-
-        /** Stub method for ISession.setPlaybackToLocal */
-        public void setPlaybackToLocal(@NonNull AudioAttributes attributes) {
-        }
-
-        /** Stub method for ISession.setPlaybackToRemote */
-        public void setPlaybackToRemote(int control, int max) {
-        }
-
-        /** Stub method for ISession.setCurrentVolume */
-        public void setCurrentVolume(int currentVolume) {
-        }
-    }
-
-    private class StubProxy extends ISession.Stub {
-        @Override
-        public void sendEvent(String event, Bundle data) {
-            mSessionStub.sendEvent(event, data);
-        }
-
-        @Override
-        public ControllerLink getController() {
-            return mSessionStub.getController();
-        }
-
-        @Override
-        public void setFlags(int flags) {
-            mSessionStub.setFlags(flags);
-        }
-
-        @Override
-        public void setActive(boolean active) {
-            mSessionStub.setActive(active);
-        }
-
-        @Override
-        public void setMediaButtonReceiver(PendingIntent mbr) {
-            mSessionStub.setMediaButtonReceiver(mbr);
-        }
-
-        @Override
-        public void setLaunchPendingIntent(PendingIntent pi) {
-            mSessionStub.setLaunchPendingIntent(pi);
-        }
-
-        @Override
-        public void destroySession() {
-            mSessionStub.destroySession();
-        }
-
-        @Override
-        public void setMetadata(MediaMetadata metadata, long duration, String metadataDescription) {
-            mSessionStub.setMetadata(metadata, duration, metadataDescription);
-        }
-
-        @Override
-        public void setPlaybackState(PlaybackState state) {
-            mSessionStub.setPlaybackState(state);
-        }
-
-        @Override
-        public void setQueue(MediaParceledListSlice queue) {
-            mSessionStub.setQueue(queue == null ? null : queue.getList());
-        }
-
-        @Override
-        public void setQueueTitle(CharSequence title) {
-            mSessionStub.setQueueTitle(title);
-        }
-
-        @Override
-        public void setExtras(Bundle extras) {
-            mSessionStub.setExtras(extras);
-        }
-
-        @Override
-        public void setRatingType(int type) {
-            mSessionStub.setRatingType(type);
-        }
-
-        @Override
-        public void setPlaybackToLocal(AudioAttributes attributes) {
-            mSessionStub.setPlaybackToLocal(attributes);
-        }
-
-        @Override
-        public void setPlaybackToRemote(int control, int max) {
-            mSessionStub.setPlaybackToRemote(control, max);
-        }
-
-        @Override
-        public void setCurrentVolume(int currentVolume) {
-            mSessionStub.setCurrentVolume(currentVolume);
-        }
-    }
-}
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index 474b671..dc2d177 100755
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -54,6 +54,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
+import java.util.Objects;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.stream.IntStream;
 
@@ -248,7 +249,7 @@
     public MtpDatabase(Context context, String volumeName,
             String[] subDirectories) {
         native_setup();
-        mContext = context;
+        mContext = Objects.requireNonNull(context);
         mMediaProvider = context.getContentResolver()
                 .acquireContentProviderClient(MediaStore.AUTHORITY);
         mVolumeName = volumeName;
@@ -294,6 +295,10 @@
         }
     }
 
+    public Context getContext() {
+        return mContext;
+    }
+
     @Override
     public void close() {
         mManager.close();
diff --git a/media/java/android/mtp/MtpServer.java b/media/java/android/mtp/MtpServer.java
index a555d37..f0ab9a3 100644
--- a/media/java/android/mtp/MtpServer.java
+++ b/media/java/android/mtp/MtpServer.java
@@ -18,7 +18,12 @@
 
 import com.android.internal.util.Preconditions;
 
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.util.ByteStringUtils;
+
 import java.io.FileDescriptor;
+import java.util.Random;
 
 /**
  * Java wrapper for MTP/PTP support as USB responder.
@@ -29,6 +34,12 @@
     private long mNativeContext; // accessed by native methods
     private final MtpDatabase mDatabase;
     private final Runnable mOnTerminate;
+    private final Context mContext;
+
+// It requires "exactly 32 characters, including any leading 0s" in MTP spec
+// (5.1.1.14 Serial Number)
+    private static final int sID_LEN_BYTES = 16;
+    private static final int sID_LEN_STR = (sID_LEN_BYTES * 2);
 
     static {
         System.loadLibrary("media_jni");
@@ -41,10 +52,41 @@
             Runnable onTerminate,
             String deviceInfoManufacturer,
             String deviceInfoModel,
-            String deviceInfoDeviceVersion,
-            String deviceInfoSerialNumber) {
+            String deviceInfoDeviceVersion) {
         mDatabase = Preconditions.checkNotNull(database);
         mOnTerminate = Preconditions.checkNotNull(onTerminate);
+        mContext = mDatabase.getContext();
+
+        final String strID_PREFS_NAME = "mtp-cfg";
+        final String strID_PREFS_KEY = "mtp-id";
+        String strRandomId = null;
+        String deviceInfoSerialNumber;
+
+        SharedPreferences sharedPref =
+                mContext.getSharedPreferences(strID_PREFS_NAME, Context.MODE_PRIVATE);
+        if (sharedPref.contains(strID_PREFS_KEY)) {
+            strRandomId = sharedPref.getString(strID_PREFS_KEY, null);
+
+            // Check for format consistence (regenerate upon corruption)
+            if (strRandomId.length() != sID_LEN_STR) {
+                strRandomId = null;
+            } else {
+                // Only accept hex digit
+                for (int ii = 0; ii < strRandomId.length(); ii++)
+                    if (Character.digit(strRandomId.charAt(ii), 16) == -1) {
+                        strRandomId = null;
+                        break;
+                    }
+            }
+        }
+
+        if (strRandomId == null) {
+            strRandomId = getRandId();
+            sharedPref.edit().putString(strID_PREFS_KEY, strRandomId).apply();
+        }
+
+        deviceInfoSerialNumber = strRandomId;
+
         native_setup(
                 database,
                 controlFd,
@@ -56,6 +98,14 @@
         database.setServer(this);
     }
 
+    private String getRandId() {
+        Random randomVal = new Random();
+        byte[] randomBytes = new byte[sID_LEN_BYTES];
+
+        randomVal.nextBytes(randomBytes);
+        return ByteStringUtils.toHexString(randomBytes);
+    }
+
     public void start() {
         Thread thread = new Thread(this, "MtpServer");
         thread.start();
diff --git a/media/jni/android_media_MediaHTTPConnection.cpp b/media/jni/android_media_MediaHTTPConnection.cpp
index 365e045..d28c15c 100644
--- a/media/jni/android_media_MediaHTTPConnection.cpp
+++ b/media/jni/android_media_MediaHTTPConnection.cpp
@@ -109,7 +109,8 @@
     gFields.context = env->GetFieldID(clazz.get(), "mNativeContext", "J");
     CHECK(gFields.context != NULL);
 
-    gFields.readAtMethodID = env->GetMethodID(clazz.get(), "readAt", "(J[BI)I");
+    gFields.readAtMethodID = env->GetMethodID(
+            clazz.get(), "readAt", "(J[BILandroid/media/MediaHTTPConnection$ConnectionState;)I");
 }
 
 static void android_media_MediaHTTPConnection_native_setup(
@@ -132,7 +133,7 @@
 }
 
 static jint android_media_MediaHTTPConnection_native_readAt(
-        JNIEnv *env, jobject thiz, jlong offset, jint size) {
+        JNIEnv *env, jobject thiz, jlong offset, jint size, jobject connectionState) {
     sp<JMediaHTTPConnection> conn = getObject(env, thiz);
     if (size > JMediaHTTPConnection::kBufferSize) {
         size = JMediaHTTPConnection::kBufferSize;
@@ -141,7 +142,7 @@
     jbyteArray byteArrayObj = conn->getByteArrayObj();
 
     jint n = env->CallIntMethod(
-            thiz, gFields.readAtMethodID, offset, byteArrayObj, size);
+            thiz, gFields.readAtMethodID, offset, byteArrayObj, size, connectionState);
 
     if (n > 0) {
         env->GetByteArrayRegion(
@@ -158,7 +159,7 @@
     { "native_getIMemory", "()Landroid/os/IBinder;",
       (void *)android_media_MediaHTTPConnection_native_getIMemory },
 
-    { "native_readAt", "(JI)I",
+    { "native_readAt", "(JILandroid/media/MediaHTTPConnection$ConnectionState;)I",
       (void *)android_media_MediaHTTPConnection_native_readAt },
 
     { "native_init", "()V",
diff --git a/media/mca/Android.mk b/media/mca/Android.mk
deleted file mode 100644
index b1ce91e..0000000
--- a/media/mca/Android.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (C) 2011 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.
-#
-
-#
-# Build all native libraries
-#
-include $(call all-subdir-makefiles)
-
-
diff --git a/media/mca/samples/Android.mk b/media/mca/samples/Android.mk
deleted file mode 100644
index b1ce91e..0000000
--- a/media/mca/samples/Android.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (C) 2011 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.
-#
-
-#
-# Build all native libraries
-#
-include $(call all-subdir-makefiles)
-
-
diff --git a/media/mca/samples/CameraEffectsRecordingSample/Android.bp b/media/mca/samples/CameraEffectsRecordingSample/Android.bp
new file mode 100644
index 0000000..96e81ab
--- /dev/null
+++ b/media/mca/samples/CameraEffectsRecordingSample/Android.bp
@@ -0,0 +1,26 @@
+// Copyright (C) 2011 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.
+//
+
+// Build activity
+
+android_test {
+    name: "CameraEffectsRecordingSample",
+    srcs: ["**/*.java"],
+    platform_apis: true,
+    optimize: {
+        enabled: false,
+    },
+}
+
diff --git a/media/mca/samples/CameraEffectsRecordingSample/Android.mk b/media/mca/samples/CameraEffectsRecordingSample/Android.mk
deleted file mode 100644
index c81f2fc..0000000
--- a/media/mca/samples/CameraEffectsRecordingSample/Android.mk
+++ /dev/null
@@ -1,35 +0,0 @@
-# Copyright (C) 2011 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.
-#
-
-# Build activity
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := CameraEffectsRecordingSample
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
-
-# ============================================================
-
-# Also build all of the sub-targets under this one: the shared library.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/media/mca/tests/Android.bp b/media/mca/tests/Android.bp
new file mode 100644
index 0000000..6b11dd9
--- /dev/null
+++ b/media/mca/tests/Android.bp
@@ -0,0 +1,12 @@
+android_test {
+    name: "CameraEffectsTests",
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+    static_libs: ["junit"],
+    // Include all test java files.
+    srcs: ["src/**/*.java"],
+    platform_apis: true,
+    instrumentation_for: "CameraEffectsRecordingSample",
+}
diff --git a/media/mca/tests/Android.mk b/media/mca/tests/Android.mk
deleted file mode 100644
index 648af4e..0000000
--- a/media/mca/tests/Android.mk
+++ /dev/null
@@ -1,20 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CameraEffectsTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_INSTRUMENTATION_FOR := CameraEffectsRecordingSample
-
-include $(BUILD_PACKAGE)
-
-
diff --git a/media/native/midi/include/Doxyfile b/media/native/midi/include/Doxyfile
index 2828f48..e40bbdc 100644
--- a/media/native/midi/include/Doxyfile
+++ b/media/native/midi/include/Doxyfile
@@ -790,7 +790,7 @@
 # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
 # Note: If this tag is empty the current directory is searched.
 
-INPUT                  = "midi.h"
+INPUT                  = "amidi/AMidi.h"
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
diff --git a/media/native/midi/include/amidi/AMidi.h b/media/native/midi/include/amidi/AMidi.h
index 0d60b0d..cbe410f 100644
--- a/media/native/midi/include/amidi/AMidi.h
+++ b/media/native/midi/include/amidi/AMidi.h
@@ -13,6 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+/**
+ * @addtogroup Midi
+ * @{
+ */
+
+/**
+ * @file AMidi.h
+ */
 
 #ifndef ANDROID_MEDIA_AMIDI_H_
 #define ANDROID_MEDIA_AMIDI_H_
@@ -244,3 +252,6 @@
 #endif
 
 #endif /* ANDROID_MEDIA_AMIDI_H_ */
+/**
+@}
+*/
diff --git a/media/packages/BluetoothMidiService/Android.bp b/media/packages/BluetoothMidiService/Android.bp
new file mode 100644
index 0000000..f45114a
--- /dev/null
+++ b/media/packages/BluetoothMidiService/Android.bp
@@ -0,0 +1,6 @@
+android_app {
+    name: "BluetoothMidiService",
+    srcs: ["src/**/*.java"],
+    platform_apis: true,
+    certificate: "platform",
+}
diff --git a/media/packages/BluetoothMidiService/Android.mk b/media/packages/BluetoothMidiService/Android.mk
deleted file mode 100644
index 6f262bf..0000000
--- a/media/packages/BluetoothMidiService/Android.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES += \
-      $(call all-java-files-under,src)
-
-LOCAL_PACKAGE_NAME := BluetoothMidiService
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/media/tests/CameraBrowser/Android.bp b/media/tests/CameraBrowser/Android.bp
new file mode 100644
index 0000000..8e3ca19
--- /dev/null
+++ b/media/tests/CameraBrowser/Android.bp
@@ -0,0 +1,5 @@
+android_test {
+    name: "CameraBrowser",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+}
diff --git a/media/tests/CameraBrowser/Android.mk b/media/tests/CameraBrowser/Android.mk
deleted file mode 100644
index 46596a7..0000000
--- a/media/tests/CameraBrowser/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := CameraBrowser
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
diff --git a/media/tests/EffectsTest/Android.bp b/media/tests/EffectsTest/Android.bp
new file mode 100644
index 0000000..214e8c0
--- /dev/null
+++ b/media/tests/EffectsTest/Android.bp
@@ -0,0 +1,5 @@
+android_test {
+    name: "EffectsTest",
+    srcs: ["**/*.java"],
+    platform_apis: true,
+}
diff --git a/media/tests/EffectsTest/Android.mk b/media/tests/EffectsTest/Android.mk
deleted file mode 100644
index a066950..0000000
--- a/media/tests/EffectsTest/Android.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := EffectsTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
diff --git a/media/tests/MediaDump/Android.bp b/media/tests/MediaDump/Android.bp
new file mode 100644
index 0000000..0eba8b2
--- /dev/null
+++ b/media/tests/MediaDump/Android.bp
@@ -0,0 +1,6 @@
+android_app {
+    name: "MediaDump",
+    // Only compile source java files in this apk.
+    srcs: ["src/**/*.java"],
+    sdk_version: "current",
+}
diff --git a/media/tests/MediaDump/Android.mk b/media/tests/MediaDump/Android.mk
deleted file mode 100644
index 74afdd0..0000000
--- a/media/tests/MediaDump/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := MediaDump
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
-
-# Use the following include to make our test apk.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/media/tests/ScoAudioTest/Android.bp b/media/tests/ScoAudioTest/Android.bp
new file mode 100644
index 0000000..ad2b9171
--- /dev/null
+++ b/media/tests/ScoAudioTest/Android.bp
@@ -0,0 +1,5 @@
+android_test {
+    name: "scoaudiotest",
+    platform_apis: true,
+    srcs: ["**/*.java"],
+}
diff --git a/media/tests/ScoAudioTest/Android.mk b/media/tests/ScoAudioTest/Android.mk
deleted file mode 100644
index 2ad91a4..0000000
--- a/media/tests/ScoAudioTest/Android.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-#LOCAL_SDK_VERSION := current
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := scoaudiotest
-
-include $(BUILD_PACKAGE)
diff --git a/media/tests/SoundPoolTest/Android.bp b/media/tests/SoundPoolTest/Android.bp
new file mode 100644
index 0000000..473f531
--- /dev/null
+++ b/media/tests/SoundPoolTest/Android.bp
@@ -0,0 +1,5 @@
+android_test {
+    name: "SoundPoolTest",
+    srcs: ["**/*.java"],
+    platform_apis: true,
+}
diff --git a/media/tests/SoundPoolTest/Android.mk b/media/tests/SoundPoolTest/Android.mk
deleted file mode 100644
index 9ca33c8..0000000
--- a/media/tests/SoundPoolTest/Android.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := SoundPoolTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
diff --git a/media/tests/players/Android.bp b/media/tests/players/Android.bp
new file mode 100644
index 0000000..23c5f04
--- /dev/null
+++ b/media/tests/players/Android.bp
@@ -0,0 +1,31 @@
+// Copyright (C) 2009 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.
+
+cc_test_library {
+    name: "invoke_mock_media_player",
+    srcs: ["invoke_mock_media_player.cpp"],
+    shared_libs: [
+        "libbinder",
+        "libmedia",
+        "libutils",
+        "liblog",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wunused",
+        "-Wunreachable-code",
+    ],
+    gtest: false,
+}
diff --git a/media/tests/players/Android.mk b/media/tests/players/Android.mk
deleted file mode 100644
index ee9d850..0000000
--- a/media/tests/players/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (C) 2009 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= invoke_mock_media_player.cpp
-
-LOCAL_SHARED_LIBRARIES:= \
-    libbinder \
-    libmedia \
-    libutils \
-    liblog
-
-LOCAL_MODULE:= invoke_mock_media_player
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java
index 0c35204..3b278b4 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java
@@ -20,9 +20,11 @@
 
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.ViewMediatorCallback;
+import com.android.systemui.car.CarNotificationEntryManager;
 import com.android.systemui.car.CarNotificationInterruptionStateProvider;
 import com.android.systemui.statusbar.car.CarFacetButtonController;
 import com.android.systemui.statusbar.car.CarStatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.volume.CarVolumeDialogComponent;
@@ -54,7 +56,7 @@
     }
 
     public StatusBarKeyguardViewManager createStatusBarKeyguardViewManager(Context context,
-        ViewMediatorCallback viewMediatorCallback, LockPatternUtils lockPatternUtils) {
+            ViewMediatorCallback viewMediatorCallback, LockPatternUtils lockPatternUtils) {
         return new CarStatusBarKeyguardViewManager(context, viewMediatorCallback, lockPatternUtils);
     }
 
@@ -92,4 +94,12 @@
     public interface CarDependencyComponent {
         CarFacetButtonController getCarFacetButtonController();
     }
+
+    /**
+     * Use {@link CarNotificationEntryManager}, which does nothing when adding a notification.
+     */
+    @Singleton
+    public NotificationEntryManager provideNotificationEntryManager(Context context) {
+        return new CarNotificationEntryManager(context);
+    }
 }
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java b/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
new file mode 100644
index 0000000..6d9c7ba
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2019 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.car;
+
+import android.content.Context;
+import android.service.notification.NotificationListenerService;
+import android.service.notification.StatusBarNotification;
+
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+
+/**
+ * Car specific notification entry manager that does nothing when adding a notification.
+ *
+ * <p> This is because system UI notifications are disabled and we have a different implementation.
+ * Please see {@link com.android.car.notification}.
+ */
+public class CarNotificationEntryManager extends NotificationEntryManager {
+    public CarNotificationEntryManager(Context context) {
+        super(context);
+    }
+
+    @Override
+    public void addNotification(
+            StatusBarNotification notification, NotificationListenerService.RankingMap ranking) {
+    }
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index bd0e0b8..45459fc 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -161,6 +161,11 @@
         }
 
         buildNavBarContent();
+        // If the UI was rebuilt (day/night change) while the keyguard was up we need to
+        // correctly respect that state.
+        if (mIsKeyguard) {
+            updateNavBarForKeyguardContent();
+        }
     }
 
     private void addTemperatureViewToController(View v) {
@@ -211,6 +216,13 @@
     @Override
     public void showKeyguard() {
         super.showKeyguard();
+        updateNavBarForKeyguardContent();
+    }
+
+    /**
+     * Switch to the keyguard applicable content contained in the nav bars
+     */
+    private void updateNavBarForKeyguardContent() {
         getComponent(NotificationsUI.class).closeCarNotifications(0);
         if (mNavigationBarView != null) {
             mNavigationBarView.showKeyguardButtons();
@@ -606,4 +618,8 @@
         getComponent(NotificationsUI.class).toggleShowingCarNotifications();
     }
 
+    @Override
+    public void maybeEscalateHeadsUp() {
+        // Never send full screen intent in car.
+    }
 }
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarKeyguardViewManager.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarKeyguardViewManager.java
index 8c6b9b0..5921868 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarKeyguardViewManager.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarKeyguardViewManager.java
@@ -64,4 +64,12 @@
         CarStatusBar statusBar = (CarStatusBar) mStatusBar;
         statusBar.showUserSwitcher();
     }
+
+    /**
+     * Do nothing on this change.
+     * The base class hides the keyguard which for automotive we want to avoid b/c this would happen
+     * on a configuration change due to day/night (headlight state).
+     */
+    @Override
+    public void onDensityOrFontScaleChanged() {  }
 }
diff --git a/packages/CtsShim/build/shim/AndroidManifest.xml b/packages/CtsShim/build/shim/AndroidManifest.xml
index 9b813ac..3e546f1e 100644
--- a/packages/CtsShim/build/shim/AndroidManifest.xml
+++ b/packages/CtsShim/build/shim/AndroidManifest.xml
@@ -20,7 +20,7 @@
     package="com.android.cts.ctsshim" >
 
     <uses-sdk android:minSdkVersion="24"
-        android:targetSdkVersion="24" />
+        android:targetSdkVersion="28" />
 
     <restrict-update
         android:hash="__CAN_NOT_BE_UPDATED__" />
diff --git a/packages/CtsShim/build/shim_priv/AndroidManifest.xml b/packages/CtsShim/build/shim_priv/AndroidManifest.xml
index 9bf454c..9ab12c9 100644
--- a/packages/CtsShim/build/shim_priv/AndroidManifest.xml
+++ b/packages/CtsShim/build/shim_priv/AndroidManifest.xml
@@ -20,7 +20,7 @@
     package="com.android.cts.priv.ctsshim" >
 
     <uses-sdk android:minSdkVersion="24"
-        android:targetSdkVersion="24" />
+        android:targetSdkVersion="28" />
 
     <restrict-update
         android:hash="__HASH__" />
diff --git a/packages/CtsShim/build/shim_priv_upgrade/AndroidManifest.xml b/packages/CtsShim/build/shim_priv_upgrade/AndroidManifest.xml
index 023e93e..2354061 100644
--- a/packages/CtsShim/build/shim_priv_upgrade/AndroidManifest.xml
+++ b/packages/CtsShim/build/shim_priv_upgrade/AndroidManifest.xml
@@ -20,7 +20,7 @@
     package="com.android.cts.priv.ctsshim" >
 
     <uses-sdk android:minSdkVersion="24"
-        android:targetSdkVersion="24" />
+        android:targetSdkVersion="28" />
 
     <application
         android:hasCode="false"
diff --git a/packages/DynamicAndroidInstallationService/res/values/strings.xml b/packages/DynamicAndroidInstallationService/res/values/strings.xml
index 221e1d7..03c7c28 100644
--- a/packages/DynamicAndroidInstallationService/res/values/strings.xml
+++ b/packages/DynamicAndroidInstallationService/res/values/strings.xml
@@ -13,7 +13,7 @@
     <string name="keyguard_description">Please enter your password and continue to AndroidOnTap installation</string>
 
     <!-- Displayed on notification: DynAndroid installation is completed [CHAR LIMIT=128] -->
-    <string name="notification_install_completed">Installation is completed, you can reboot into the new installed system now.</string>
+    <string name="notification_install_completed">New system is ready, you can reboot into it or discard it.</string>
     <!-- Displayed on notification: DynAndroid installation is in progress [CHAR LIMIT=128] -->
     <string name="notification_install_inprogress">Installation is in progress.</string>
     <!-- Displayed on notification: DynAndroid installation is in progress [CHAR LIMIT=128] -->
@@ -30,4 +30,9 @@
     <!-- Action on notification: Reboot to AndroidOnTap [CHAR LIMIT=16] -->
     <string name="notification_action_reboot_to_dynandroid">Reboot</string>
 
+    <!-- Toast when installed DynamicAndroid is discarded [CHAR LIMIT=64] -->
+    <string name="toast_dynandroid_discarded">Installed AndroidOnTap is discarded.</string>
+    <!-- Toast when we fail to launch into DynamicAndroid [CHAR LIMIT=64] -->
+    <string name="toast_failed_to_reboot_to_dynandroid">Failed to reboot into AndroidOnTap.</string>
+
 </resources>
diff --git a/packages/DynamicAndroidInstallationService/src/com/android/dynandroid/DynamicAndroidInstallationService.java b/packages/DynamicAndroidInstallationService/src/com/android/dynandroid/DynamicAndroidInstallationService.java
index 719417e..d942bab 100644
--- a/packages/DynamicAndroidInstallationService/src/com/android/dynandroid/DynamicAndroidInstallationService.java
+++ b/packages/DynamicAndroidInstallationService/src/com/android/dynandroid/DynamicAndroidInstallationService.java
@@ -54,6 +54,7 @@
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.util.Log;
+import android.widget.Toast;
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
@@ -73,6 +74,8 @@
      */
     private static final String ACTION_CANCEL_INSTALL =
             "com.android.dynandroid.ACTION_CANCEL_INSTALL";
+    private static final String ACTION_DISCARD_INSTALL =
+            "com.android.dynandroid.ACTION_DISCARD_INSTALL";
     private static final String ACTION_REBOOT_TO_DYN_ANDROID =
             "com.android.dynandroid.ACTION_REBOOT_TO_DYN_ANDROID";
     private static final String ACTION_REBOOT_TO_NORMAL =
@@ -118,10 +121,6 @@
     private long mInstalledSize;
     private boolean mJustCancelledByUser;
 
-    private PendingIntent mPiCancel;
-    private PendingIntent mPiRebootToDynamicAndroid;
-    private PendingIntent mPiUninstallAndReboot;
-
     private InstallationAsyncTask mInstallTask;
 
 
@@ -155,6 +154,8 @@
             executeInstallCommand(intent);
         } else if (ACTION_CANCEL_INSTALL.equals(action)) {
             executeCancelCommand();
+        } else if (ACTION_DISCARD_INSTALL.equals(action)) {
+            executeDiscardCommand();
         } else if (ACTION_REBOOT_TO_DYN_ANDROID.equals(action)) {
             executeRebootToDynAndroidCommand();
         } else if (ACTION_REBOOT_TO_NORMAL.equals(action)) {
@@ -210,7 +211,7 @@
         }
 
         if (mInstallTask != null) {
-            Log.e(TAG, "There is already an install task running");
+            Log.e(TAG, "There is already an installation task running");
             return;
         }
 
@@ -234,10 +235,8 @@
     }
 
     private void executeCancelCommand() {
-        if (mInstallTask == null || mInstallTask.getStatus() == PENDING) {
+        if (mInstallTask == null || mInstallTask.getStatus() != RUNNING) {
             Log.e(TAG, "Cancel command triggered, but there is no task running");
-            mNM.cancel(NOTIFICATION_ID);
-
             return;
         }
 
@@ -247,25 +246,47 @@
             // Will cleanup and post status in onCancelled()
             Log.d(TAG, "Cancel request filed successfully");
         } else {
-            Log.d(TAG, "Requested cancel, completed task will be discarded");
+            Log.e(TAG, "Trying to cancel installation while it's already completed.");
+        }
+    }
 
-            resetTaskAndStop();
-            postStatus(STATUS_NOT_STARTED, CAUSE_INSTALL_CANCELLED);
+    private void executeDiscardCommand() {
+        if (isInDynamicAndroid()) {
+            Log.e(TAG, "We are now running in AOT, please reboot to normal system first");
+            return;
         }
 
+        if (getStatus() != STATUS_READY) {
+            Log.e(TAG, "Trying to discard AOT while there is no complete installation");
+            return;
+        }
+
+        Toast.makeText(this,
+                getString(R.string.toast_dynandroid_discarded),
+                Toast.LENGTH_LONG).show();
+
+        resetTaskAndStop();
+        postStatus(STATUS_NOT_STARTED, CAUSE_INSTALL_CANCELLED);
+
+        mDynAndroid.remove();
     }
 
     private void executeRebootToDynAndroidCommand() {
         if (mInstallTask == null || mInstallTask.getStatus() != FINISHED) {
-            Log.e(TAG, "Trying to reboot to DynamicAndroid, but there is no complete installation");
+            Log.e(TAG, "Trying to reboot to AOT while there is no complete installation");
             return;
         }
 
         if (!mInstallTask.commit()) {
-            // TODO: b/123673280 better UI response
             Log.e(TAG, "Failed to commit installation because of native runtime error.");
             mNM.cancel(NOTIFICATION_ID);
 
+            Toast.makeText(this,
+                    getString(R.string.toast_failed_to_reboot_to_dynandroid),
+                    Toast.LENGTH_LONG).show();
+
+            mDynAndroid.remove();
+
             return;
         }
 
@@ -277,8 +298,13 @@
     }
 
     private void executeRebootToNormalCommand() {
-        mDynAndroid.remove();
+        if (!isInDynamicAndroid()) {
+            Log.e(TAG, "It's already running in normal system.");
+            return;
+        }
 
+        // Per current design, we don't have disable() API. AOT is disabled on next reboot.
+        // TODO: Use better status query when b/125079548 is done.
         PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
 
         if (powerManager != null) {
@@ -287,9 +313,14 @@
     }
 
     private void executeNotifyIfInUseCommand() {
-        if (isInDynamicAndroid()) {
+        int status = getStatus();
+
+        if (status == STATUS_IN_USE) {
             startForeground(NOTIFICATION_ID,
                     buildNotification(STATUS_IN_USE, CAUSE_NOT_SPECIFIED));
+        } else if (status == STATUS_READY) {
+            startForeground(NOTIFICATION_ID,
+                    buildNotification(STATUS_READY, CAUSE_NOT_SPECIFIED));
         }
     }
 
@@ -312,18 +343,12 @@
         if (mNM != null) {
             mNM.createNotificationChannel(chan);
         }
+    }
 
-        Intent intentCancel = new Intent(this, DynamicAndroidInstallationService.class);
-        intentCancel.setAction(ACTION_CANCEL_INSTALL);
-        mPiCancel = PendingIntent.getService(this, 0, intentCancel, 0);
-
-        Intent intentRebootToDyn = new Intent(this, DynamicAndroidInstallationService.class);
-        intentRebootToDyn.setAction(ACTION_REBOOT_TO_DYN_ANDROID);
-        mPiRebootToDynamicAndroid = PendingIntent.getService(this, 0, intentRebootToDyn, 0);
-
-        Intent intentUninstallAndReboot = new Intent(this, DynamicAndroidInstallationService.class);
-        intentUninstallAndReboot.setAction(ACTION_REBOOT_TO_NORMAL);
-        mPiUninstallAndReboot = PendingIntent.getService(this, 0, intentUninstallAndReboot, 0);
+    private PendingIntent createPendingIntent(String action) {
+        Intent intent = new Intent(this, DynamicAndroidInstallationService.class);
+        intent.setAction(action);
+        return PendingIntent.getService(this, 0, intent, 0);
     }
 
     private Notification buildNotification(int status, int cause) {
@@ -342,7 +367,7 @@
 
                 builder.addAction(new Notification.Action.Builder(
                         null, getString(R.string.notification_action_cancel),
-                        mPiCancel).build());
+                        createPendingIntent(ACTION_CANCEL_INSTALL)).build());
 
                 break;
 
@@ -351,11 +376,11 @@
 
                 builder.addAction(new Notification.Action.Builder(
                         null, getString(R.string.notification_action_reboot_to_dynandroid),
-                        mPiRebootToDynamicAndroid).build());
+                        createPendingIntent(ACTION_REBOOT_TO_DYN_ANDROID)).build());
 
                 builder.addAction(new Notification.Action.Builder(
-                        null, getString(R.string.notification_action_cancel),
-                        mPiCancel).build());
+                        null, getString(R.string.notification_action_discard),
+                        createPendingIntent(ACTION_DISCARD_INSTALL)).build());
 
                 break;
 
@@ -364,7 +389,7 @@
 
                 builder.addAction(new Notification.Action.Builder(
                         null, getString(R.string.notification_action_uninstall),
-                        mPiUninstallAndReboot).build());
+                        createPendingIntent(ACTION_REBOOT_TO_NORMAL)).build());
 
                 break;
 
@@ -427,10 +452,10 @@
     private int getStatus() {
         if (isInDynamicAndroid()) {
             return STATUS_IN_USE;
-
+        } else if (isDynamicAndroidInstalled()) {
+            return STATUS_READY;
         } else if (mInstallTask == null) {
             return STATUS_NOT_STARTED;
-
         }
 
         switch (mInstallTask.getStatus()) {
@@ -458,6 +483,10 @@
         return mDynAndroid.isInUse();
     }
 
+    private boolean isDynamicAndroidInstalled() {
+        return mDynAndroid.isInstalled();
+    }
+
     void handleMessage(Message msg) {
         switch (msg.what) {
             case DynamicAndroidClient.MSG_REGISTER_LISTENER:
diff --git a/packages/ExtServices/Android.mk b/packages/ExtServices/Android.mk
index 1133499..a06dd86 100644
--- a/packages/ExtServices/Android.mk
+++ b/packages/ExtServices/Android.mk
@@ -25,10 +25,6 @@
 
 LOCAL_CERTIFICATE := platform
 
-LOCAL_AAPT_FLAGS := --shared-lib
-
-LOCAL_EXPORT_PACKAGE_RESOURCES := true
-
 LOCAL_PROGUARD_FLAG_FILES := proguard.proguard
 
 LOCAL_PRIVILEGED_MODULE := true
diff --git a/packages/ExtServices/AndroidManifest.xml b/packages/ExtServices/AndroidManifest.xml
index e47d53c..76e2fe7 100644
--- a/packages/ExtServices/AndroidManifest.xml
+++ b/packages/ExtServices/AndroidManifest.xml
@@ -78,6 +78,10 @@
             </intent-filter>
         </service>
 
+        <activity android:name=".notification.CopyCodeActivity"
+                  android:exported="false"
+                  android:theme="@android:style/Theme.NoDisplay"/>
+
         <library android:name="android.ext.services"/>
     </application>
 
diff --git a/packages/ExtServices/res/values/strings.xml b/packages/ExtServices/res/values/strings.xml
index a9a5450..de35441 100644
--- a/packages/ExtServices/res/values/strings.xml
+++ b/packages/ExtServices/res/values/strings.xml
@@ -24,4 +24,10 @@
         <item>EDIT_DISTANCE</item>
         <item>EXACT_MATCH</item>
     </string-array>
+
+    <!-- Action chip to copy a one time code to the user's clipboard [CHAR LIMIT=NONE]-->
+    <string name="copy_code_desc">Copy \u201c<xliff:g id="code" example="12345">%1$s</xliff:g>\u201c</string>
+    <!-- Toast to display when text is copied to the device clipboard [CHAR LIMIT=64]-->
+    <string name="code_copied_to_clipboard">Code copied</string>
+
 </resources>
diff --git a/packages/ExtServices/src/android/ext/services/notification/CopyCodeActivity.java b/packages/ExtServices/src/android/ext/services/notification/CopyCodeActivity.java
new file mode 100644
index 0000000..6708d4d
--- /dev/null
+++ b/packages/ExtServices/src/android/ext/services/notification/CopyCodeActivity.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2019 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.ext.services.notification;
+
+import android.app.Activity;
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Intent;
+import android.ext.services.R;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.widget.Toast;
+
+/**
+ * An activity that copies text in the Bundle.
+ */
+public class CopyCodeActivity extends Activity {
+    private static final String TAG = "CopyCodeActivity";
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        handleIntent();
+        finish();
+    }
+
+    private void handleIntent() {
+        String code = getIntent().getStringExtra(Intent.EXTRA_TEXT);
+        if (TextUtils.isEmpty(code)) {
+            Log.w(TAG, "handleIntent: empty code");
+            return;
+        }
+        ClipboardManager clipboardManager = getSystemService(ClipboardManager.class);
+        ClipData clipData = ClipData.newPlainText(null, code);
+        clipboardManager.setPrimaryClip(clipData);
+        Toast.makeText(getApplicationContext(), R.string.code_copied_to_clipboard,
+                Toast.LENGTH_SHORT).show();
+    }
+}
diff --git a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
index 24fa87a..bf8a3fa 100644
--- a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
+++ b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
@@ -15,11 +15,15 @@
  */
 package android.ext.services.notification;
 
+import android.annotation.Nullable;
 import android.app.Notification;
+import android.app.PendingIntent;
 import android.app.Person;
 import android.app.RemoteAction;
 import android.app.RemoteInput;
 import android.content.Context;
+import android.content.Intent;
+import android.ext.services.R;
 import android.graphics.drawable.Icon;
 import android.os.Bundle;
 import android.os.Parcelable;
@@ -48,11 +52,12 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import java.util.stream.Collectors;
 
 public class SmartActionsHelper {
-    private static final String KEY_ACTION_TYPE = "action_type";
-    private static final String KEY_ACTION_SCORE = "action_score";
+    static final String ENTITIES_EXTRAS = "entities-extras";
+    static final String KEY_ACTION_TYPE = "action_type";
+    static final String KEY_ACTION_SCORE = "action_score";
+    static final String KEY_TEXT = "text";
     // If a notification has any of these flags set, it's inelgibile for actions being added.
     private static final int FLAG_MASK_INELGIBILE_FOR_ACTIONS =
             Notification.FLAG_ONGOING_EVENT
@@ -109,11 +114,25 @@
             repliesScore.put(textReply, conversationAction.getConfidenceScore());
         }
 
-        ArrayList<Notification.Action> actions = conversationActions.stream()
-                .filter(conversationAction -> conversationAction.getAction() != null)
-                .map(action -> createNotificationAction(
-                        action.getAction(), action.getType(), action.getConfidenceScore()))
-                .collect(Collectors.toCollection(ArrayList::new));
+        ArrayList<Notification.Action> actions = new ArrayList<>();
+        for (ConversationAction conversationAction : conversationActions) {
+            if (!TextUtils.isEmpty(conversationAction.getTextReply())) {
+                continue;
+            }
+            Notification.Action notificationAction;
+            if (conversationAction.getAction() == null) {
+                notificationAction =
+                        createNotificationActionWithoutRemoteAction(conversationAction);
+            } else {
+                notificationAction = createNotificationActionFromRemoteAction(
+                        conversationAction.getAction(),
+                        conversationAction.getType(),
+                        conversationAction.getConfidenceScore());
+            }
+            if (notificationAction != null) {
+                actions.add(notificationAction);
+            }
+        }
 
         // Start a new session for logging if necessary.
         if (!TextUtils.isEmpty(resultId)
@@ -127,6 +146,55 @@
     }
 
     /**
+     * Creates notification action from ConversationAction that does not come up a RemoteAction.
+     * It could happen because we don't have common intents for some actions, like copying text.
+     */
+    @Nullable
+    private Notification.Action createNotificationActionWithoutRemoteAction(
+            ConversationAction conversationAction) {
+        if (ConversationAction.TYPE_COPY.equals(conversationAction.getType())) {
+            return createCopyCodeAction(conversationAction);
+        }
+        return null;
+    }
+
+    @Nullable
+    private Notification.Action createCopyCodeAction(ConversationAction conversationAction) {
+        Bundle extras = conversationAction.getExtras();
+        if (extras == null) {
+            return null;
+        }
+        Bundle entitiesExtas = extras.getParcelable(ENTITIES_EXTRAS);
+        if (entitiesExtas == null) {
+            return null;
+        }
+        String code = entitiesExtas.getString(KEY_TEXT);
+        if (TextUtils.isEmpty(code)) {
+            return null;
+        }
+        String contentDescription = mContext.getString(R.string.copy_code_desc, code);
+        Intent intent = new Intent(mContext, CopyCodeActivity.class);
+        intent.putExtra(Intent.EXTRA_TEXT, code);
+
+        RemoteAction remoteAction = new RemoteAction(Icon.createWithResource(
+                mContext.getResources(),
+                com.android.internal.R.drawable.ic_menu_copy_material),
+                code,
+                contentDescription,
+                PendingIntent.getActivity(
+                        mContext,
+                        code.hashCode(),
+                        intent,
+                        PendingIntent.FLAG_UPDATE_CURRENT
+                ));
+
+        return createNotificationActionFromRemoteAction(
+                remoteAction,
+                ConversationAction.TYPE_COPY,
+                conversationAction.getConfidenceScore());
+    }
+
+    /**
      * Returns whether the suggestion might be used in the notifications in SysUI.
      * <p>
      * Currently, NAS has no idea if suggestions will actually be used in the notification, and thus
@@ -292,7 +360,7 @@
         mTextClassifier.onTextClassifierEvent(textClassifierEvent);
     }
 
-    private Notification.Action createNotificationAction(
+    private Notification.Action createNotificationActionFromRemoteAction(
             RemoteAction remoteAction, String actionType, float score) {
         Icon icon = remoteAction.shouldShowIcon()
                 ? remoteAction.getIcon()
diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionsHelperTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionsHelperTest.java
index a1fbc7b..3a7d799 100644
--- a/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionsHelperTest.java
+++ b/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionsHelperTest.java
@@ -36,6 +36,7 @@
 import android.content.Intent;
 import android.content.pm.IPackageManager;
 import android.graphics.drawable.Icon;
+import android.os.Bundle;
 import android.os.Process;
 import android.service.notification.NotificationAssistantService;
 import android.service.notification.StatusBarNotification;
@@ -419,6 +420,31 @@
         assertTextClassifierEvent(events.get(1), TextClassifierEvent.TYPE_ACTIONS_SHOWN);
     }
 
+    @Test
+    public void testCopyAction() {
+        Bundle extras = new Bundle();
+        Bundle entitiesExtras = new Bundle();
+        entitiesExtras.putString(SmartActionsHelper.KEY_TEXT, "12345");
+        extras.putParcelable(SmartActionsHelper.ENTITIES_EXTRAS, entitiesExtras);
+        ConversationAction conversationAction =
+                new ConversationAction.Builder(ConversationAction.TYPE_COPY)
+                        .setExtras(extras)
+                        .build();
+        when(mTextClassifier.suggestConversationActions(any(ConversationActions.Request.class)))
+                .thenReturn(
+                        new ConversationActions(
+                                Collections.singletonList(conversationAction), null));
+
+        Notification notification = createMessageNotification();
+        when(mStatusBarNotification.getNotification()).thenReturn(notification);
+        SmartActionsHelper.SmartSuggestions suggestions =
+                mSmartActionsHelper.suggest(createNotificationEntry());
+
+        assertThat(suggestions.actions).hasSize(1);
+        Notification.Action action = suggestions.actions.get(0);
+        assertThat(action.title).isEqualTo("12345");
+    }
+
     private ZonedDateTime createZonedDateTimeFromMsUtc(long msUtc) {
         return ZonedDateTime.ofInstant(Instant.ofEpochMilli(msUtc), ZoneOffset.systemDefault());
     }
diff --git a/packages/NetworkStack/src/android/net/ip/IpClient.java b/packages/NetworkStack/src/android/net/ip/IpClient.java
index b1f6d24..7c7cdbd 100644
--- a/packages/NetworkStack/src/android/net/ip/IpClient.java
+++ b/packages/NetworkStack/src/android/net/ip/IpClient.java
@@ -18,8 +18,6 @@
 
 import static android.net.RouteInfo.RTN_UNICAST;
 import static android.net.shared.IpConfigurationParcelableUtil.toStableParcelable;
-import static android.net.shared.LinkPropertiesParcelableUtil.fromStableParcelable;
-import static android.net.shared.LinkPropertiesParcelableUtil.toStableParcelable;
 
 import static com.android.server.util.PermissionUtil.checkNetworkStackCallingPermission;
 
@@ -33,7 +31,6 @@
 import android.net.LinkProperties;
 import android.net.ProvisioningConfigurationParcelable;
 import android.net.ProxyInfo;
-import android.net.ProxyInfoParcelable;
 import android.net.RouteInfo;
 import android.net.TcpKeepalivePacketDataParcelable;
 import android.net.apf.ApfCapabilities;
@@ -201,7 +198,7 @@
         public void onProvisioningSuccess(LinkProperties newLp) {
             log("onProvisioningSuccess({" + newLp + "})");
             try {
-                mCallback.onProvisioningSuccess(toStableParcelable(newLp));
+                mCallback.onProvisioningSuccess(newLp);
             } catch (RemoteException e) {
                 log("Failed to call onProvisioningSuccess", e);
             }
@@ -210,7 +207,7 @@
         public void onProvisioningFailure(LinkProperties newLp) {
             log("onProvisioningFailure({" + newLp + "})");
             try {
-                mCallback.onProvisioningFailure(toStableParcelable(newLp));
+                mCallback.onProvisioningFailure(newLp);
             } catch (RemoteException e) {
                 log("Failed to call onProvisioningFailure", e);
             }
@@ -219,7 +216,7 @@
         public void onLinkPropertiesChange(LinkProperties newLp) {
             log("onLinkPropertiesChange({" + newLp + "})");
             try {
-                mCallback.onLinkPropertiesChange(toStableParcelable(newLp));
+                mCallback.onLinkPropertiesChange(newLp);
             } catch (RemoteException e) {
                 log("Failed to call onLinkPropertiesChange", e);
             }
@@ -525,9 +522,9 @@
             IpClient.this.setTcpBufferSizes(tcpBufferSizes);
         }
         @Override
-        public void setHttpProxy(ProxyInfoParcelable proxyInfo) {
+        public void setHttpProxy(ProxyInfo proxyInfo) {
             checkNetworkStackCallingPermission();
-            IpClient.this.setHttpProxy(fromStableParcelable(proxyInfo));
+            IpClient.this.setHttpProxy(proxyInfo);
         }
         @Override
         public void setMulticastFilter(boolean enabled) {
diff --git a/packages/NetworkStack/src/android/net/metrics/DataStallStatsUtils.java b/packages/NetworkStack/src/android/net/metrics/DataStallStatsUtils.java
index d1ca109..e23f10f 100644
--- a/packages/NetworkStack/src/android/net/metrics/DataStallStatsUtils.java
+++ b/packages/NetworkStack/src/android/net/metrics/DataStallStatsUtils.java
@@ -48,6 +48,8 @@
             return DataStallEventProto.VALID;
         } else if (result.isPortal()) {
             return DataStallEventProto.PORTAL;
+        } else if (result.isPartialConnectivity()) {
+            return DataStallEventProto.PARTIAL;
         } else {
             return DataStallEventProto.INVALID;
         }
diff --git a/packages/NetworkStack/src/com/android/server/NetworkStackService.java b/packages/NetworkStack/src/com/android/server/NetworkStackService.java
index 72955bb..e7c8e85 100644
--- a/packages/NetworkStack/src/com/android/server/NetworkStackService.java
+++ b/packages/NetworkStack/src/com/android/server/NetworkStackService.java
@@ -19,7 +19,6 @@
 import static android.net.dhcp.IDhcpServer.STATUS_INVALID_ARGUMENT;
 import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
 import static android.net.dhcp.IDhcpServer.STATUS_UNKNOWN_ERROR;
-import static android.net.shared.NetworkParcelableUtil.fromStableParcelable;
 
 import static com.android.server.util.PermissionUtil.checkDumpPermission;
 import static com.android.server.util.PermissionUtil.checkNetworkStackCallingPermission;
@@ -35,7 +34,6 @@
 import android.net.INetworkMonitorCallbacks;
 import android.net.INetworkStackConnector;
 import android.net.Network;
-import android.net.NetworkParcelable;
 import android.net.PrivateDnsConfigParcel;
 import android.net.dhcp.DhcpServer;
 import android.net.dhcp.DhcpServingParams;
@@ -152,12 +150,10 @@
         }
 
         @Override
-        public void makeNetworkMonitor(
-                NetworkParcelable network, String name, INetworkMonitorCallbacks cb)
+        public void makeNetworkMonitor(Network network, String name, INetworkMonitorCallbacks cb)
                 throws RemoteException {
-            final Network parsedNetwork = fromStableParcelable(network);
-            final SharedLog log = addValidationLogs(parsedNetwork, name);
-            final NetworkMonitor nm = new NetworkMonitor(mContext, cb, parsedNetwork, log);
+            final SharedLog log = addValidationLogs(network, name);
+            final NetworkMonitor nm = new NetworkMonitor(mContext, cb, network, log);
             cb.onNetworkMonitorCreated(new NetworkMonitorImpl(nm));
         }
 
diff --git a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
index fc56da7..9d91487 100644
--- a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
@@ -72,7 +72,7 @@
 import android.provider.Settings;
 import android.telephony.AccessNetworkConstants;
 import android.telephony.CellSignalStrength;
-import android.telephony.NetworkRegistrationState;
+import android.telephony.NetworkRegistrationInfo;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.TelephonyManager;
@@ -1615,12 +1615,12 @@
                 return;
             }
             // See if the data sub is registered for PS services on cell.
-            final NetworkRegistrationState nrs = dataSs.getNetworkRegistrationState(
-                    NetworkRegistrationState.DOMAIN_PS,
-                    AccessNetworkConstants.TransportType.WWAN);
+            final NetworkRegistrationInfo nri = dataSs.getNetworkRegistrationInfo(
+                    NetworkRegistrationInfo.DOMAIN_PS,
+                    AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
             latencyBroadcast.putExtra(
                     NetworkMonitorUtils.EXTRA_CELL_ID,
-                    nrs == null ? null : nrs.getCellIdentity());
+                    nri == null ? null : nri.getCellIdentity());
             latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_CONNECTIVITY_TYPE, TYPE_MOBILE);
         } else {
             return;
diff --git a/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java b/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java
index bd488ea..4536c47 100644
--- a/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java
+++ b/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java
@@ -16,13 +16,10 @@
 
 package android.net.ip;
 
-import static android.net.shared.LinkPropertiesParcelableUtil.fromStableParcelable;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
-import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyString;
 import static org.mockito.Mockito.eq;
@@ -207,8 +204,7 @@
         verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceSetEnableIPv6(iface, false);
         verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceClearAddrs(iface);
         verify(mCb, timeout(TEST_TIMEOUT_MS).times(1))
-                .onLinkPropertiesChange(argThat(
-                        lp -> fromStableParcelable(lp).equals(makeEmptyLinkProperties(iface))));
+                .onLinkPropertiesChange(makeEmptyLinkProperties(iface));
     }
 
     @Test
@@ -253,15 +249,13 @@
         mObserver.onInterfaceAddressUpdated(new LinkAddress(addresses[lastAddr]), iface);
         LinkProperties want = linkproperties(links(addresses), routes(prefixes));
         want.setInterfaceName(iface);
-        verify(mCb, timeout(TEST_TIMEOUT_MS).times(1)).onProvisioningSuccess(argThat(
-                lp -> fromStableParcelable(lp).equals(want)));
+        verify(mCb, timeout(TEST_TIMEOUT_MS).times(1)).onProvisioningSuccess(want);
 
         ipc.shutdown();
         verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceSetEnableIPv6(iface, false);
         verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceClearAddrs(iface);
         verify(mCb, timeout(TEST_TIMEOUT_MS).times(1))
-                .onLinkPropertiesChange(argThat(
-                        lp -> fromStableParcelable(lp).equals(makeEmptyLinkProperties(iface))));
+                .onLinkPropertiesChange(makeEmptyLinkProperties(iface));
     }
 
     @Test
diff --git a/packages/SettingsLib/ActionBarShadow/AndroidManifest.xml b/packages/SettingsLib/ActionBarShadow/AndroidManifest.xml
index 4b9f1ab..98c4cb4 100644
--- a/packages/SettingsLib/ActionBarShadow/AndroidManifest.xml
+++ b/packages/SettingsLib/ActionBarShadow/AndroidManifest.xml
@@ -18,6 +18,4 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.settingslib.widget">
 
-    <uses-sdk android:minSdkVersion="21" />
-
 </manifest>
diff --git a/packages/SettingsLib/AndroidManifest.xml b/packages/SettingsLib/AndroidManifest.xml
index 3873593..a347345 100644
--- a/packages/SettingsLib/AndroidManifest.xml
+++ b/packages/SettingsLib/AndroidManifest.xml
@@ -18,7 +18,4 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.settingslib">
 
-    <uses-sdk
-        android:minSdkVersion="21" />
-
 </manifest>
diff --git a/packages/SettingsLib/AppPreference/AndroidManifest.xml b/packages/SettingsLib/AppPreference/AndroidManifest.xml
index 7e71308..4b9f1ab 100644
--- a/packages/SettingsLib/AppPreference/AndroidManifest.xml
+++ b/packages/SettingsLib/AppPreference/AndroidManifest.xml
@@ -16,7 +16,7 @@
   -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.settingslib.widget.apppreference">
+          package="com.android.settingslib.widget">
 
     <uses-sdk android:minSdkVersion="21" />
 
diff --git a/packages/SettingsLib/AppPreference/src/com/android/settingslib/widget/apppreference/AppPreference.java b/packages/SettingsLib/AppPreference/src/com/android/settingslib/widget/apppreference/AppPreference.java
index 593b6f5..ab51a34 100644
--- a/packages/SettingsLib/AppPreference/src/com/android/settingslib/widget/apppreference/AppPreference.java
+++ b/packages/SettingsLib/AppPreference/src/com/android/settingslib/widget/apppreference/AppPreference.java
@@ -25,6 +25,8 @@
 import androidx.preference.Preference;
 import androidx.preference.PreferenceViewHolder;
 
+import com.android.settingslib.widget.R;
+
 public class AppPreference extends Preference {
 
     private int mProgress;
diff --git a/packages/SettingsLib/HelpUtils/AndroidManifest.xml b/packages/SettingsLib/HelpUtils/AndroidManifest.xml
index 35b3933..5240ce4 100644
--- a/packages/SettingsLib/HelpUtils/AndroidManifest.xml
+++ b/packages/SettingsLib/HelpUtils/AndroidManifest.xml
@@ -18,6 +18,4 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.settingslib.helputils">
 
-    <uses-sdk android:minSdkVersion="21" />
-
 </manifest>
diff --git a/packages/SettingsLib/RestrictedLockUtils/AndroidManifest.xml b/packages/SettingsLib/RestrictedLockUtils/AndroidManifest.xml
index d7b323a..d19a022 100644
--- a/packages/SettingsLib/RestrictedLockUtils/AndroidManifest.xml
+++ b/packages/SettingsLib/RestrictedLockUtils/AndroidManifest.xml
@@ -18,6 +18,4 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.settingslib.restrictedlockutils">
 
-    <uses-sdk android:minSdkVersion="21" />
-
 </manifest>
\ No newline at end of file
diff --git a/packages/SettingsLib/SearchWidget/AndroidManifest.xml b/packages/SettingsLib/SearchWidget/AndroidManifest.xml
index b86544e..5798801 100644
--- a/packages/SettingsLib/SearchWidget/AndroidManifest.xml
+++ b/packages/SettingsLib/SearchWidget/AndroidManifest.xml
@@ -18,6 +18,4 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.settingslib.search">
 
-    <uses-sdk android:minSdkVersion="21" />
-
 </manifest>
diff --git a/packages/SettingsLib/SettingsSpinner/AndroidManifest.xml b/packages/SettingsLib/SettingsSpinner/AndroidManifest.xml
index 5db9335..4b9f1ab 100644
--- a/packages/SettingsLib/SettingsSpinner/AndroidManifest.xml
+++ b/packages/SettingsLib/SettingsSpinner/AndroidManifest.xml
@@ -16,7 +16,7 @@
   -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.settingslib.widget.settingsspinner">
+          package="com.android.settingslib.widget">
 
     <uses-sdk android:minSdkVersion="21" />
 
diff --git a/packages/SettingsLib/SettingsSpinner/src/com/android/settingslib/widget/settingsspinner/SettingsSpinner.java b/packages/SettingsLib/SettingsSpinner/src/com/android/settingslib/widget/settingsspinner/SettingsSpinner.java
index 130cef2..5ef8f7a 100644
--- a/packages/SettingsLib/SettingsSpinner/src/com/android/settingslib/widget/settingsspinner/SettingsSpinner.java
+++ b/packages/SettingsLib/SettingsSpinner/src/com/android/settingslib/widget/settingsspinner/SettingsSpinner.java
@@ -20,6 +20,8 @@
 import android.util.AttributeSet;
 import android.widget.Spinner;
 
+import com.android.settingslib.widget.R;
+
 /**
  * A {@link Spinner} with settings style.
  *
diff --git a/packages/SettingsLib/SettingsSpinner/src/com/android/settingslib/widget/settingsspinner/SettingsSpinnerAdapter.java b/packages/SettingsLib/SettingsSpinner/src/com/android/settingslib/widget/settingsspinner/SettingsSpinnerAdapter.java
index 8bf8fce..f9aedd9 100644
--- a/packages/SettingsLib/SettingsSpinner/src/com/android/settingslib/widget/settingsspinner/SettingsSpinnerAdapter.java
+++ b/packages/SettingsLib/SettingsSpinner/src/com/android/settingslib/widget/settingsspinner/SettingsSpinnerAdapter.java
@@ -17,10 +17,10 @@
 package com.android.settingslib.widget.settingsspinner;
 
 import android.content.Context;
-import android.view.View;
-import android.view.ViewGroup;
 import android.widget.ArrayAdapter;
 
+import com.android.settingslib.widget.R;
+
 /**
  * An ArrayAdapter which was used by {@link SettingsSpinner} with settings style.
  */
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
index c8c05a0..b34f445 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
@@ -103,7 +103,7 @@
             setBatterySaverConfirmationAcknowledged(context);
         }
 
-        if (context.getSystemService(PowerManager.class).setPowerSaveMode(enable)) {
+        if (context.getSystemService(PowerManager.class).setPowerSaveModeEnabled(enable)) {
             if (enable) {
                 final int count =
                         Secure.getInt(cr, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, 0) + 1;
diff --git a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java
index 09107ce..ea39317 100644
--- a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java
+++ b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java
@@ -18,11 +18,11 @@
 
 import android.app.AppOpsManager;
 import android.content.Context;
+import android.content.PermissionChecker;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.graphics.drawable.Drawable;
-import android.os.Process;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.text.format.DateUtils;
@@ -82,6 +82,7 @@
      */
     public List<Access> getAppList() {
         // Retrieve a location usage list from AppOps
+        PackageManager pm = mContext.getPackageManager();
         AppOpsManager aoManager =
                 (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
         List<AppOpsManager.PackageOps> appOps = aoManager.getPackagesForOps(LOCATION_OPS);
@@ -96,19 +97,40 @@
 
         for (int i = 0; i < appOpsCount; ++i) {
             AppOpsManager.PackageOps ops = appOps.get(i);
-            // Don't show the Android System in the list - it's not actionable for the user.
-            // Also don't show apps belonging to background users except managed users.
             String packageName = ops.getPackageName();
             int uid = ops.getUid();
-            int userId = UserHandle.getUserId(uid);
-            boolean isAndroidOs =
-                    (uid == Process.SYSTEM_UID) && ANDROID_SYSTEM_PACKAGE_NAME.equals(packageName);
-            if (isAndroidOs || !profiles.contains(new UserHandle(userId))) {
+            UserHandle user = UserHandle.getUserHandleForUid(uid);
+
+            // Don't show apps belonging to background users except managed users.
+            if (!profiles.contains(user)) {
                 continue;
             }
-            Access access = getAccessFromOps(now, ops);
-            if (access != null) {
-                accesses.add(access);
+
+            // Don't show apps that do not have user sensitive location permissions
+            boolean showApp = true;
+            for (int op : LOCATION_OPS) {
+                final String permission = AppOpsManager.opToPermission(op);
+                final int permissionFlags = pm.getPermissionFlags(permission, packageName, user);
+                if (PermissionChecker.checkPermission(mContext, permission, -1, uid, packageName)
+                        == PermissionChecker.PERMISSION_GRANTED) {
+                    if ((permissionFlags
+                            & PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED) == 0) {
+                        showApp = false;
+                        break;
+                    }
+                } else {
+                    if ((permissionFlags
+                            & PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED) == 0) {
+                        showApp = false;
+                        break;
+                    }
+                }
+            }
+            if (showApp) {
+                Access access = getAccessFromOps(now, ops);
+                if (access != null) {
+                    accesses.add(access);
+                }
             }
         }
         return accesses;
diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/StringUtil.java b/packages/SettingsLib/src/com/android/settingslib/utils/StringUtil.java
index 3e3c039..83ef4f9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/utils/StringUtil.java
+++ b/packages/SettingsLib/src/com/android/settingslib/utils/StringUtil.java
@@ -107,20 +107,22 @@
     }
 
     /**
-     * Returns relative time for the given millis in the past, in a short format such as "2 days
-     * ago", "5 hr. ago", "40 min. ago", or "29 sec. ago".
+     * Returns relative time for the given millis in the past with different format style.
+     * In a short format such as "2 days ago", "5 hr. ago", "40 min. ago", or "29 sec. ago".
+     * In a long format such as "2 days ago", "5 hours ago",  "40 minutes ago" or "29 seconds ago".
      *
      * <p>The unit is chosen to have good information value while only using one unit. So 27 hours
      * and 50 minutes would be formatted as "28 hr. ago", while 50 hours would be formatted as
      * "2 days ago".
      *
-     * @param context the application context
-     * @param millis the elapsed time in milli seconds
+     * @param context     the application context
+     * @param millis      the elapsed time in milli seconds
      * @param withSeconds include seconds?
+     * @param formatStyle format style
      * @return the formatted elapsed time
      */
     public static CharSequence formatRelativeTime(Context context, double millis,
-            boolean withSeconds) {
+            boolean withSeconds, RelativeDateTimeFormatter.Style formatStyle) {
         final int seconds = (int) Math.floor(millis / 1000);
         final RelativeUnit unit;
         final int value;
@@ -144,9 +146,31 @@
         final RelativeDateTimeFormatter formatter = RelativeDateTimeFormatter.getInstance(
                 ULocale.forLocale(locale),
                 null /* default NumberFormat */,
-                RelativeDateTimeFormatter.Style.LONG,
+                formatStyle,
                 android.icu.text.DisplayContext.CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE);
 
         return formatter.format(value, RelativeDateTimeFormatter.Direction.LAST, unit);
     }
+
+    /**
+     * Returns relative time for the given millis in the past, in a long format such as "2 days
+     * ago", "5 hours ago",  "40 minutes ago" or "29 seconds ago".
+     *
+     * <p>The unit is chosen to have good information value while only using one unit. So 27 hours
+     * and 50 minutes would be formatted as "28 hr. ago", while 50 hours would be formatted as
+     * "2 days ago".
+     *
+     * @param context     the application context
+     * @param millis      the elapsed time in milli seconds
+     * @param withSeconds include seconds?
+     * @return the formatted elapsed time
+     * @deprecated use {@link #formatRelativeTime(Context, double, boolean,
+     * RelativeDateTimeFormatter.Style)} instead.
+     */
+    @Deprecated
+    public static CharSequence formatRelativeTime(Context context, double millis,
+            boolean withSeconds) {
+        return formatRelativeTime(context, millis, withSeconds,
+                RelativeDateTimeFormatter.Style.LONG);
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/volume/MediaSessions.java b/packages/SettingsLib/src/com/android/settingslib/volume/MediaSessions.java
index 4ed1154..f6cd971 100644
--- a/packages/SettingsLib/src/com/android/settingslib/volume/MediaSessions.java
+++ b/packages/SettingsLib/src/com/android/settingslib/volume/MediaSessions.java
@@ -95,7 +95,7 @@
         mMgr.addOnActiveSessionsChangedListener(mSessionsListener, null, mHandler);
         mInit = true;
         postUpdateSessions();
-        mMgr.setRemoteVolumeController(mRvc);
+        mMgr.registerRemoteVolumeController(mRvc);
     }
 
     protected void postUpdateSessions() {
@@ -110,6 +110,7 @@
         if (D.BUG) Log.d(TAG, "destroy");
         mInit = false;
         mMgr.removeOnActiveSessionsChangedListener(mSessionsListener);
+        mMgr.unregisterRemoteVolumeController(mRvc);
     }
 
     /**
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 59fbb72..800c401 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -307,6 +307,7 @@
     public AccessPoint(Context context, WifiConfiguration config) {
         mContext = context;
         loadConfig(config);
+        updateKey();
     }
 
     /**
@@ -317,6 +318,7 @@
         mContext = context;
         mFqdn = config.getHomeSp().getFqdn();
         mProviderFriendlyName = config.getHomeSp().getFriendlyName();
+        updateKey();
     }
 
     /**
@@ -355,7 +357,6 @@
         security = getSecurity(config);
         networkId = config.networkId;
         mConfig = config;
-        updateKey();
     }
 
     /** Updates {@link #mKey} and should only called upon object creation/initialization. */
@@ -363,6 +364,8 @@
         // TODO(sghuman): Consolidate Key logic on ScanResultMatchInfo
         if (isPasspoint()) {
             mKey = getKey(mConfig);
+        } else if (isPasspointConfig()) {
+            mKey = getKey(mFqdn);
         } else if (isOsuProvider()) {
             mKey = getKey(mOsuProvider);
         } else { // Non-Passpoint AP
@@ -618,15 +621,22 @@
      */
     public static String getKey(WifiConfiguration config) {
         if (config.isPasspoint()) {
-            return new StringBuilder()
-                    .append(KEY_PREFIX_FQDN)
-                    .append(config.FQDN).toString();
+            return getKey(config.FQDN);
         } else {
             return getKey(removeDoubleQuotes(config.SSID), config.BSSID, getSecurity(config));
         }
     }
 
     /**
+     * Returns the AccessPoint key corresponding to a Passpoint network by its FQDN.
+     */
+    public static String getKey(String fqdn) {
+        return new StringBuilder()
+                .append(KEY_PREFIX_FQDN)
+                .append(fqdn).toString();
+    }
+
+    /**
      * Returns the AccessPoint key corresponding to the OsuProvider.
      */
     public static String getKey(OsuProvider provider) {
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
index 7c367c7..9c8e3f4 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -1250,6 +1250,14 @@
         AccessPoint passpointAp = new AccessPoint(mContext, spyConfig, mScanResults, null);
         assertThat(passpointAp.getKey()).isEqualTo(AccessPoint.getKey(spyConfig));
 
+        PasspointConfiguration passpointConfig = new PasspointConfiguration();
+        HomeSp homeSp = new HomeSp();
+        homeSp.setFqdn("fqdn");
+        homeSp.setFriendlyName("Test Provider");
+        passpointConfig.setHomeSp(homeSp);
+        AccessPoint passpointConfigAp = new AccessPoint(mContext, passpointConfig);
+        assertThat(passpointConfigAp.getKey()).isEqualTo(AccessPoint.getKey("fqdn"));
+
         OsuProvider provider = createOsuProvider();
         AccessPoint osuAp = new AccessPoint(mContext, provider, mScanResults);
         assertThat(osuAp.getKey()).isEqualTo(AccessPoint.getKey(provider));
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java
index 2988905..2bb3c2a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java
@@ -60,7 +60,7 @@
 
         when(mMockContext.getContentResolver()).thenReturn(mMockResolver);
         when(mMockContext.getSystemService(eq(PowerManager.class))).thenReturn(mMockPowerManager);
-        when(mMockPowerManager.setPowerSaveMode(anyBoolean())).thenReturn(true);
+        when(mMockPowerManager.setPowerSaveModeEnabled(anyBoolean())).thenReturn(true);
     }
 
     @Test
@@ -71,7 +71,7 @@
         assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, true, true)).isFalse();
 
         verify(mMockContext, times(1)).sendBroadcast(any(Intent.class));
-        verify(mMockPowerManager, times(0)).setPowerSaveMode(anyBoolean());
+        verify(mMockPowerManager, times(0)).setPowerSaveModeEnabled(anyBoolean());
 
         // They shouldn't have changed.
         assertEquals(-1,
@@ -88,7 +88,7 @@
         assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, true, true)).isTrue();
 
         verify(mMockContext, times(0)).sendBroadcast(any(Intent.class));
-        verify(mMockPowerManager, times(1)).setPowerSaveMode(eq(true));
+        verify(mMockPowerManager, times(1)).setPowerSaveModeEnabled(eq(true));
 
         assertEquals(1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
         assertEquals(1, Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
@@ -102,7 +102,7 @@
         assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, true, true)).isTrue();
 
         verify(mMockContext, times(0)).sendBroadcast(any(Intent.class));
-        verify(mMockPowerManager, times(1)).setPowerSaveMode(eq(true));
+        verify(mMockPowerManager, times(1)).setPowerSaveModeEnabled(eq(true));
 
         assertEquals(1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
         assertEquals(2, Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
@@ -116,7 +116,7 @@
         assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, true, false)).isTrue();
 
         verify(mMockContext, times(0)).sendBroadcast(any(Intent.class));
-        verify(mMockPowerManager, times(1)).setPowerSaveMode(eq(true));
+        verify(mMockPowerManager, times(1)).setPowerSaveModeEnabled(eq(true));
 
         assertEquals(1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
         assertEquals(1, Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
@@ -131,7 +131,7 @@
         assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, false, false)).isTrue();
 
         verify(mMockContext, times(0)).sendBroadcast(any(Intent.class));
-        verify(mMockPowerManager, times(1)).setPowerSaveMode(eq(false));
+        verify(mMockPowerManager, times(1)).setPowerSaveModeEnabled(eq(false));
 
         assertEquals(-1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
         assertEquals(-2,
@@ -147,7 +147,7 @@
         assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, false, true)).isTrue();
 
         verify(mMockContext, times(0)).sendBroadcast(any(Intent.class));
-        verify(mMockPowerManager, times(1)).setPowerSaveMode(eq(false));
+        verify(mMockPowerManager, times(1)).setPowerSaveModeEnabled(eq(false));
 
         assertEquals(-1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
         assertEquals(-2,
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/StringUtilTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/StringUtilTest.java
index 8fbbfbb..b503972 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/StringUtilTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/StringUtilTest.java
@@ -21,6 +21,7 @@
 import static org.mockito.Mockito.spy;
 
 import android.content.Context;
+import android.icu.text.RelativeDateTimeFormatter;
 import android.text.SpannableStringBuilder;
 import android.text.format.DateUtils;
 import android.text.style.TtsSpan;
@@ -116,8 +117,8 @@
         final double testMillis = 40 * DateUtils.SECOND_IN_MILLIS;
         final String expectedTime = "Just now";
 
-        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
-                expectedTime);
+        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true,
+                RelativeDateTimeFormatter.Style.LONG).toString()).isEqualTo(expectedTime);
     }
 
     @Test
@@ -125,8 +126,8 @@
         final double testMillis = 40 * DateUtils.SECOND_IN_MILLIS;
         final String expectedTime = "1 minute ago";
 
-        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, false).toString()).isEqualTo(
-                expectedTime);
+        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, false,
+                RelativeDateTimeFormatter.Style.LONG).toString()).isEqualTo(expectedTime);
     }
 
     @Test
@@ -134,8 +135,8 @@
         final double testMillis = 119 * DateUtils.SECOND_IN_MILLIS;
         final String expectedTime = "Just now";
 
-        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
-                expectedTime);
+        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true,
+                RelativeDateTimeFormatter.Style.LONG).toString()).isEqualTo(expectedTime);
     }
 
     @Test
@@ -143,8 +144,8 @@
         final double testMillis = 119 * DateUtils.SECOND_IN_MILLIS;
         final String expectedTime = "2 minutes ago";
 
-        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, false).toString()).isEqualTo(
-                expectedTime);
+        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, false,
+                RelativeDateTimeFormatter.Style.LONG).toString()).isEqualTo(expectedTime);
     }
 
     @Test
@@ -152,8 +153,8 @@
         final double testMillis = 2 * DateUtils.MINUTE_IN_MILLIS;
         final String expectedTime = "2 minutes ago";
 
-        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
-                expectedTime);
+        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true,
+                RelativeDateTimeFormatter.Style.LONG).toString()).isEqualTo(expectedTime);
     }
 
     @Test
@@ -161,8 +162,8 @@
         final double testMillis = 119 * DateUtils.MINUTE_IN_MILLIS;
         final String expectedTime = "119 minutes ago";
 
-        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
-                expectedTime);
+        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true,
+                RelativeDateTimeFormatter.Style.LONG).toString()).isEqualTo(expectedTime);
     }
 
     @Test
@@ -170,8 +171,8 @@
         final double testMillis = 2 * DateUtils.HOUR_IN_MILLIS;
         final String expectedTime = "2 hours ago";
 
-        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
-                expectedTime);
+        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true,
+                RelativeDateTimeFormatter.Style.LONG).toString()).isEqualTo(expectedTime);
     }
 
     @Test
@@ -179,8 +180,8 @@
         final double testMillis = 47 * DateUtils.HOUR_IN_MILLIS;
         final String expectedTime = "47 hours ago";
 
-        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
-                expectedTime);
+        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true,
+                RelativeDateTimeFormatter.Style.LONG).toString()).isEqualTo(expectedTime);
     }
 
     @Test
@@ -188,8 +189,8 @@
         final double testMillis = 2 * DateUtils.DAY_IN_MILLIS;
         final String expectedTime = "2 days ago";
 
-        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
-                expectedTime);
+        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true,
+                RelativeDateTimeFormatter.Style.LONG).toString()).isEqualTo(expectedTime);
     }
 
     @Test
@@ -197,8 +198,8 @@
         final double testMillis = 0;
         final String expectedTime = "Just now";
 
-        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
-                expectedTime);
+        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true,
+                RelativeDateTimeFormatter.Style.LONG).toString()).isEqualTo(expectedTime);
     }
 
     @Test
@@ -206,7 +207,7 @@
         final double testMillis = 0;
         final String expectedTime = "0 minutes ago";
 
-        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, false).toString()).isEqualTo(
-                expectedTime);
+        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, false,
+                RelativeDateTimeFormatter.Style.LONG).toString()).isEqualTo(expectedTime);
     }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/apppreference/AppPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/apppreference/AppPreferenceTest.java
index da97cc8..042616a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/apppreference/AppPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/apppreference/AppPreferenceTest.java
@@ -23,6 +23,8 @@
 
 import androidx.preference.PreferenceViewHolder;
 
+import com.android.settingslib.widget.R;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index 274acad..36bb8ef 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -16,10 +16,6 @@
 
 package com.android.providers.settings;
 
-import android.os.Process;
-import com.android.internal.app.LocalePicker;
-import com.android.internal.annotations.VisibleForTesting;
-
 import android.annotation.NonNull;
 import android.app.ActivityManager;
 import android.app.IActivityManager;
@@ -30,7 +26,6 @@
 import android.content.Intent;
 import android.content.res.Configuration;
 import android.icu.util.ULocale;
-import android.location.LocationManager;
 import android.media.AudioManager;
 import android.media.RingtoneManager;
 import android.net.Uri;
@@ -38,13 +33,14 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
-import android.os.UserManager;
 import android.provider.Settings;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.ArraySet;
 
-import java.lang.IllegalArgumentException;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.app.LocalePicker;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Locale;
@@ -145,9 +141,6 @@
             if (Settings.System.SOUND_EFFECTS_ENABLED.equals(name)) {
                 setSoundEffects(Integer.parseInt(value) == 1);
                 // fall through to the ordinary write to settings
-            } else if (Settings.Secure.LOCATION_PROVIDERS_ALLOWED.equals(name)) {
-                setGpsLocation(value);
-                return;
             } else if (Settings.Secure.BACKUP_AUTO_RESTORE.equals(name)) {
                 setAutoRestore(Integer.parseInt(value) == 1);
             } else if (isAlreadyConfiguredCriticalAccessibilitySetting(name)) {
@@ -297,21 +290,6 @@
         } catch (RemoteException e) {}
     }
 
-    private void setGpsLocation(String value) {
-        UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
-        if (um.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION)) {
-            return;
-        }
-        final String GPS = LocationManager.GPS_PROVIDER;
-        boolean enabled =
-            GPS.equals(value) ||
-                value.startsWith(GPS + ",") ||
-                value.endsWith("," + GPS) ||
-                value.contains("," + GPS + ",");
-        LocationManager lm = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
-        lm.setProviderEnabledForUser(GPS, enabled, Process.myUserHandle());
-    }
-
     private void setSoundEffects(boolean enable) {
         if (enable) {
             mAudioManager.loadSoundEffects();
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 2c2987c..ff25ad9 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -1103,9 +1103,7 @@
 
     private boolean mutateConfigSetting(String name, String value, String prefix,
             boolean makeDefault, int operation, int mode) {
-
-        // TODO(b/117663715): Ensure the caller can access the setting.
-        // enforceReadPermission(WRITE_DEVICE_CONFIG);
+        enforceWritePermission(Manifest.permission.WRITE_DEVICE_CONFIG);
 
         // Perform the mutation.
         synchronized (mLock) {
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index fc6ef2b..d639e5e 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -175,6 +175,9 @@
 
     <uses-permission android:name="android.permission.MANAGE_APPOPS" />
 
+    <!-- Permission needed to run network tests in CTS -->
+    <uses-permission android:name="android.permission.MANAGE_TEST_NETWORKS" />
+
     <application android:label="@string/app_label"
                  android:defaultToDeviceProtectedStorage="true"
                  android:directBootAware="true">
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 9425941..c2495b5 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -58,7 +58,6 @@
         "androidx.arch.core_core-runtime",
         "androidx.lifecycle_lifecycle-extensions",
         "androidx.dynamicanimation_dynamicanimation",
-        "iconloader_base",
         "SystemUI-tags",
         "SystemUI-proto",
         "dagger2-2.19",
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActionsPanelPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActionsPanelPlugin.java
index 7c72688..6be7707 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActionsPanelPlugin.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActionsPanelPlugin.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.plugins;
 
+import android.app.PendingIntent;
 import android.view.View;
 
 import com.android.systemui.plugins.annotations.DependsOn;
@@ -62,6 +63,15 @@
 
         /** Dismisses the Global Actions menu. */
         void dismissGlobalActionsMenu();
+
+        /** Starts a PendingIntent, dismissing the keyguard if necessary. */
+        default void startPendingIntentDismissingKeyguard(PendingIntent pendingIntent) {
+            try {
+                pendingIntent.send();
+            } catch (PendingIntent.CanceledException e) {
+                // no-op
+            }
+        }
     }
 
     /**
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/VolumeDialogController.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/VolumeDialogController.java
index 5f4cf03..2b10ccb 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/VolumeDialogController.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/VolumeDialogController.java
@@ -58,6 +58,10 @@
     void userActivity();
     void getState();
 
+    boolean areCaptionsEnabled();
+    void setCaptionsEnabled(boolean isEnabled);
+    void getCaptionsComponentState();
+
     @ProvidesInterface(version = StreamState.VERSION)
     public static final class StreamState {
         public static final int VERSION = 1;
@@ -186,5 +190,6 @@
         void onScreenOff();
         void onShowSafetyWarning(int flags);
         void onAccessibilityModeChanged(Boolean showA11yStream);
+        void onCaptionComponentStateChanged(Boolean isComponentEnabled);
     }
 }
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
index bca3530..42600c1 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
@@ -247,27 +247,6 @@
         }
     }
 
-
-    @ProvidesInterface(version = AirplaneBooleanState.VERSION)
-    public static class AirplaneBooleanState extends BooleanState {
-        public static final int VERSION = 1;
-        public boolean isAirplaneMode;
-
-        @Override
-        public boolean copyTo(State other) {
-            final AirplaneBooleanState o = (AirplaneBooleanState) other;
-            final boolean changed = super.copyTo(other) || o.isAirplaneMode != isAirplaneMode;
-            o.isAirplaneMode = isAirplaneMode;
-            return changed;
-        }
-
-        public State copy() {
-            AirplaneBooleanState state = new AirplaneBooleanState();
-            copyTo(state);
-            return state;
-        }
-    }
-
     @ProvidesInterface(version = SlashState.VERSION)
     public static class SlashState {
         public static final int VERSION = 2;
diff --git a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml b/packages/SystemUI/res/drawable/global_action_panel_scrim.xml
index 177b8d2..8b8258f 100644
--- a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml
+++ b/packages/SystemUI/res/drawable/global_action_panel_scrim.xml
@@ -19,8 +19,8 @@
        android:shape="rectangle">
     <gradient
         android:centerY="0.45"
-        android:startColor="#be3c4043"
-        android:centerColor="#be3c4043"
+        android:startColor="#dc3c4043"
+        android:centerColor="#dc3c4043"
         android:endColor="#4d3c4043"
         android:angle="270" />
 </shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_odi_captions.xml b/packages/SystemUI/res/drawable/ic_volume_odi_captions.xml
new file mode 100644
index 0000000..9b90729
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_volume_odi_captions.xml
@@ -0,0 +1,24 @@
+<!--
+     Copyright (C) 2019 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="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M20,4C21.1,4 22,4.9 22,6L22,18C22,19.1 21.1,20 20,20L4,20C2.9,20 2,19.1 2,18L2,6C2,4.9 2.9,4 4,4L20,4ZM20,18L20,6L4,6L4,18L20,18ZM6,10L8,10L8,12L6,12L6,10ZM6,14L14,14L14,16L6,16L6,14ZM16,14L18,14L18,16L16,16L16,14ZM10,10L18,10L18,12L10,12L10,10Z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_volume_odi_captions_disabled.xml b/packages/SystemUI/res/drawable/ic_volume_odi_captions_disabled.xml
new file mode 100644
index 0000000..f3d8d3b9
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_volume_odi_captions_disabled.xml
@@ -0,0 +1,24 @@
+<!--
+     Copyright (C) 2019 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="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M16.9675,14L18,14L18,15.0275L16.9675,14ZM20,17.0176L20,6L8.9281,6L6.9182,4L20,4C21.1,4 22,4.9 22,6L22,18C22,18.2949 21.9353,18.5755 21.8194,18.8281L20,17.0176ZM12.9478,10L18,10L18,12L14.9576,12L12.9478,10ZM1.2823,0.8824L22.8489,22.4489L21.6337,23.6641L17.9696,20L4,20C2.9,20 2,19.1 2,18L2,6C2,5.4577 2.2188,4.964 2.5724,4.6028L0.0672,2.0975L1.2823,0.8824ZM13.9696,16L6,16L6,14L11.9696,14L8,10.0304L8,12L6,12L6,10L7.9696,10L4,6.0304L4,18L15.9696,18L13.9696,16Z"/>
+</vector>
diff --git a/packages/SystemUI/res/layout-land/global_actions_grid.xml b/packages/SystemUI/res/layout-land/global_actions_grid.xml
index 235d0fc..c51e71b 100644
--- a/packages/SystemUI/res/layout-land/global_actions_grid.xml
+++ b/packages/SystemUI/res/layout-land/global_actions_grid.xml
@@ -7,7 +7,8 @@
     android:orientation="horizontal"
     android:clipToPadding="false"
     android:theme="@style/qs_theme"
-    android:gravity="top|right"
+    android:paddingLeft="@dimen/global_actions_top_padding"
+    android:gravity="top|left"
     android:clipChildren="false"
 >
     <LinearLayout
diff --git a/packages/SystemUI/res/layout-land/global_actions_grid_seascape.xml b/packages/SystemUI/res/layout-land/global_actions_grid_seascape.xml
index e028214..de853c7 100644
--- a/packages/SystemUI/res/layout-land/global_actions_grid_seascape.xml
+++ b/packages/SystemUI/res/layout-land/global_actions_grid_seascape.xml
@@ -7,7 +7,8 @@
     android:orientation="horizontal"
     android:clipToPadding="false"
     android:theme="@style/qs_theme"
-    android:gravity="top|left"
+    android:gravity="top|right"
+    android:paddingRight="@dimen/global_actions_top_padding"
     android:clipChildren="false"
 >
     <LinearLayout
diff --git a/packages/SystemUI/res/layout/biometric_dialog.xml b/packages/SystemUI/res/layout/biometric_dialog.xml
index 1e8cd5a..83557f2 100644
--- a/packages/SystemUI/res/layout/biometric_dialog.xml
+++ b/packages/SystemUI/res/layout/biometric_dialog.xml
@@ -39,152 +39,158 @@
             android:layout_height="0dp"
             android:layout_weight="1" />
 
-        <LinearLayout
+        <ScrollView
             android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="horizontal">
-
-            <!-- This is not a Space since Spaces cannot be clicked. The width of this changes depending
-             on horizontal/portrait orientation -->
-            <View
-                android:id="@+id/left_space"
-                android:layout_weight="1"
-                android:layout_width="0dp"
-                android:layout_height="match_parent"/>
+            android:layout_height="wrap_content">
 
             <LinearLayout
-                android:id="@+id/dialog"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:orientation="vertical"
-                android:background="@drawable/biometric_dialog_bg"
-                android:layout_marginBottom="@dimen/biometric_dialog_border_padding"
-                android:layout_marginLeft="@dimen/biometric_dialog_border_padding"
-                android:layout_marginRight="@dimen/biometric_dialog_border_padding">
+                android:orientation="horizontal">
 
-                <TextView
-                    android:id="@+id/title"
-                    android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:layout_marginEnd="24dp"
-                    android:layout_marginStart="24dp"
-                    android:layout_marginTop="24dp"
-                    android:gravity="@integer/biometric_dialog_text_gravity"
-                    android:textSize="20sp"
-                    android:maxLines="1"
-                    android:singleLine="true"
-                    android:ellipsize="marquee"
-                    android:marqueeRepeatLimit="marquee_forever"
-                    android:textColor="?android:attr/textColorPrimary"/>
+                <!-- This is not a Space since Spaces cannot be clicked. The width of this changes
+                depending on horizontal/portrait orientation -->
+                <View
+                    android:id="@+id/left_space"
+                    android:layout_weight="1"
+                    android:layout_width="0dp"
+                    android:layout_height="match_parent"/>
 
-                <TextView
-                    android:id="@+id/subtitle"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:layout_marginTop="8dp"
-                    android:layout_marginStart="24dp"
-                    android:layout_marginEnd="24dp"
-                    android:gravity="@integer/biometric_dialog_text_gravity"
-                    android:textSize="16sp"
-                    android:maxLines="1"
-                    android:singleLine="true"
-                    android:ellipsize="marquee"
-                    android:marqueeRepeatLimit="marquee_forever"
-                    android:textColor="?android:attr/textColorPrimary"/>
+                    <LinearLayout
+                        android:id="@+id/dialog"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:orientation="vertical"
+                        android:background="@drawable/biometric_dialog_bg"
+                        android:layout_marginBottom="@dimen/biometric_dialog_border_padding"
+                        android:layout_marginLeft="@dimen/biometric_dialog_border_padding"
+                        android:layout_marginRight="@dimen/biometric_dialog_border_padding">
 
-                <TextView
-                    android:id="@+id/description"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:layout_marginEnd="24dp"
-                    android:layout_marginStart="24dp"
-                    android:gravity="@integer/biometric_dialog_text_gravity"
-                    android:paddingTop="8dp"
-                    android:textSize="16sp"
-                    android:maxLines="4"
-                    android:textColor="?android:attr/textColorPrimary"/>
+                        <TextView
+                            android:id="@+id/title"
+                            android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            android:layout_marginEnd="24dp"
+                            android:layout_marginStart="24dp"
+                            android:layout_marginTop="24dp"
+                            android:gravity="@integer/biometric_dialog_text_gravity"
+                            android:textSize="20sp"
+                            android:maxLines="1"
+                            android:singleLine="true"
+                            android:ellipsize="marquee"
+                            android:marqueeRepeatLimit="marquee_forever"
+                            android:textColor="?android:attr/textColorPrimary"/>
 
-                <ImageView
-                    android:id="@+id/biometric_icon"
-                    android:layout_width="@dimen/biometric_dialog_biometric_icon_size"
-                    android:layout_height="@dimen/biometric_dialog_biometric_icon_size"
-                    android:layout_gravity="center_horizontal"
-                    android:layout_marginTop="48dp"
-                    android:scaleType="fitXY" />
+                        <TextView
+                            android:id="@+id/subtitle"
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            android:layout_marginTop="8dp"
+                            android:layout_marginStart="24dp"
+                            android:layout_marginEnd="24dp"
+                            android:gravity="@integer/biometric_dialog_text_gravity"
+                            android:textSize="16sp"
+                            android:maxLines="1"
+                            android:singleLine="true"
+                            android:ellipsize="marquee"
+                            android:marqueeRepeatLimit="marquee_forever"
+                            android:textColor="?android:attr/textColorPrimary"/>
 
-                <TextView
-                    android:id="@+id/error"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:layout_marginEnd="24dp"
-                    android:layout_marginStart="24dp"
-                    android:paddingTop="16dp"
-                    android:paddingBottom="24dp"
-                    android:textSize="12sp"
-                    android:gravity="center_horizontal"
-                    android:accessibilityLiveRegion="polite"
-                    android:contentDescription="@string/accessibility_biometric_dialog_help_area"
-                    android:textColor="?android:attr/textColorSecondary"/>
+                        <TextView
+                            android:id="@+id/description"
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            android:layout_marginEnd="24dp"
+                            android:layout_marginStart="24dp"
+                            android:gravity="@integer/biometric_dialog_text_gravity"
+                            android:paddingTop="8dp"
+                            android:textSize="16sp"
+                            android:maxLines="4"
+                            android:textColor="?android:attr/textColorPrimary"/>
 
-                <LinearLayout
-                    android:layout_width="match_parent"
-                    android:layout_height="72dip"
-                    android:paddingTop="24dp"
-                    android:layout_gravity="center_vertical"
-                    style="?android:attr/buttonBarStyle"
-                    android:orientation="horizontal"
-                    android:measureWithLargestChild="true">
-                    <Space android:id="@+id/leftSpacer"
-                        android:layout_width="12dp"
-                        android:layout_height="match_parent"
-                        android:visibility="visible" />
-                    <!-- Negative Button -->
-                    <Button android:id="@+id/button2"
-                        android:layout_width="wrap_content"
-                        android:layout_height="match_parent"
-                        style="@*android:style/Widget.DeviceDefault.Button.Borderless.Colored"
-                        android:gravity="center"
-                        android:maxLines="2" />
-                    <Space android:id="@+id/middleSpacer"
-                        android:layout_width="0dp"
-                        android:layout_height="match_parent"
-                        android:layout_weight="1"
-                        android:visibility="visible" />
-                    <!-- Positive Button -->
-                    <Button android:id="@+id/button1"
-                        android:layout_width="wrap_content"
-                        android:layout_height="match_parent"
-                        style="@*android:style/Widget.DeviceDefault.Button.Colored"
-                        android:gravity="center"
-                        android:maxLines="2"
-                        android:text="@string/biometric_dialog_confirm"
-                        android:visibility="gone"/>
-                    <!-- Try Again Button -->
-                    <Button android:id="@+id/button_try_again"
-                        android:layout_width="wrap_content"
-                        android:layout_height="match_parent"
-                        style="@*android:style/Widget.DeviceDefault.Button.Colored"
-                        android:gravity="center"
-                        android:maxLines="2"
-                        android:text="@string/biometric_dialog_try_again"
-                        android:visibility="gone"/>
-                    <Space android:id="@+id/rightSpacer"
-                        android:layout_width="12dip"
-                        android:layout_height="match_parent"
-                        android:visibility="visible" />
-                </LinearLayout>
+                        <ImageView
+                            android:id="@+id/biometric_icon"
+                            android:layout_width="@dimen/biometric_dialog_biometric_icon_size"
+                            android:layout_height="@dimen/biometric_dialog_biometric_icon_size"
+                            android:layout_gravity="center_horizontal"
+                            android:layout_marginTop="48dp"
+                            android:scaleType="fitXY" />
+
+                        <TextView
+                            android:id="@+id/error"
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            android:layout_marginEnd="24dp"
+                            android:layout_marginStart="24dp"
+                            android:paddingTop="16dp"
+                            android:paddingBottom="24dp"
+                            android:textSize="12sp"
+                            android:gravity="center_horizontal"
+                            android:accessibilityLiveRegion="polite"
+                            android:contentDescription="@string/accessibility_biometric_dialog_help_area"
+                            android:textColor="?android:attr/textColorSecondary"/>
+
+                        <LinearLayout
+                            android:layout_width="match_parent"
+                            android:layout_height="72dip"
+                            android:paddingTop="24dp"
+                            android:layout_gravity="center_vertical"
+                            style="?android:attr/buttonBarStyle"
+                            android:orientation="horizontal"
+                            android:measureWithLargestChild="true">
+                            <Space android:id="@+id/leftSpacer"
+                                android:layout_width="12dp"
+                                android:layout_height="match_parent"
+                                android:visibility="visible" />
+                            <!-- Negative Button -->
+                            <Button android:id="@+id/button2"
+                                android:layout_width="wrap_content"
+                                android:layout_height="match_parent"
+                                style="@*android:style/Widget.DeviceDefault.Button.Borderless.Colored"
+                                android:gravity="center"
+                                android:maxLines="2" />
+                            <Space android:id="@+id/middleSpacer"
+                                android:layout_width="0dp"
+                                android:layout_height="match_parent"
+                                android:layout_weight="1"
+                                android:visibility="visible" />
+                            <!-- Positive Button -->
+                            <Button android:id="@+id/button1"
+                                android:layout_width="wrap_content"
+                                android:layout_height="match_parent"
+                                style="@*android:style/Widget.DeviceDefault.Button.Colored"
+                                android:gravity="center"
+                                android:maxLines="2"
+                                android:text="@string/biometric_dialog_confirm"
+                                android:visibility="gone"/>
+                            <!-- Try Again Button -->
+                            <Button android:id="@+id/button_try_again"
+                                android:layout_width="wrap_content"
+                                android:layout_height="match_parent"
+                                style="@*android:style/Widget.DeviceDefault.Button.Colored"
+                                android:gravity="center"
+                                android:maxLines="2"
+                                android:text="@string/biometric_dialog_try_again"
+                                android:visibility="gone"/>
+                            <Space android:id="@+id/rightSpacer"
+                                android:layout_width="12dip"
+                                android:layout_height="match_parent"
+                                android:visibility="visible" />
+                        </LinearLayout>
+                    </LinearLayout>
+
+                <!-- This is not a Space since Spaces cannot be clicked. The width of this changes
+                depending on horizontal/portrait orientation -->
+                <View
+                    android:id="@+id/right_space"
+                    android:layout_weight="1"
+                    android:layout_width="0dp"
+                    android:layout_height="match_parent" />
+
             </LinearLayout>
 
-            <!-- This is not a Space since Spaces cannot be clicked. The width of this changes depending
-             on horizontal/portrait orientation -->
-            <View
-                android:id="@+id/right_space"
-                android:layout_weight="1"
-                android:layout_width="0dp"
-                android:layout_height="match_parent" />
-
-        </LinearLayout>
+        </ScrollView>
 
     </LinearLayout>
 
diff --git a/packages/SystemUI/res/layout/global_actions_grid.xml b/packages/SystemUI/res/layout/global_actions_grid.xml
index a620a8e..8651e5a 100644
--- a/packages/SystemUI/res/layout/global_actions_grid.xml
+++ b/packages/SystemUI/res/layout/global_actions_grid.xml
@@ -6,8 +6,9 @@
     android:layout_height="match_parent"
     android:orientation="horizontal"
     android:clipToPadding="false"
+    android:paddingTop="@dimen/global_actions_top_padding"
     android:theme="@style/qs_theme"
-    android:gravity="bottom|center"
+    android:gravity="top|center"
     android:clipChildren="false"
 >
     <LinearLayout
@@ -30,7 +31,6 @@
             android:paddingTop="@dimen/global_actions_grid_vertical_padding"
             android:paddingBottom="@dimen/global_actions_grid_vertical_padding"
             android:orientation="vertical"
-            android:background="?android:attr/colorBackgroundFloating"
             android:gravity="center"
             android:translationZ="@dimen/global_actions_translate"
         />
@@ -47,7 +47,6 @@
             android:paddingRight="@dimen/global_actions_grid_horizontal_padding"
             android:paddingTop="@dimen/global_actions_grid_vertical_padding"
             android:paddingBottom="@dimen/global_actions_grid_vertical_padding"
-            android:background="?android:attr/colorBackgroundFloating"
         >
             <LinearLayout
                 android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index 725ace4..0d44931 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -255,6 +255,7 @@
                             android:layout_width="40dp"
                             android:layout_height="40dp"
                             android:clickable="false"
+                            android:contentDescription="@string/inline_block_button"
                             android:tint="@color/GM2_grey_400"
                             style="@style/TextAppearance.NotificationInfo.Button"/>
                     </FrameLayout>
@@ -289,6 +290,7 @@
                             android:layout_width="40dp"
                             android:layout_height="40dp"
                             android:clickable="false"
+                            android:contentDescription="@string/inline_silent_button_silent"
                             android:tint="@color/GM2_grey_400"
                             style="@style/TextAppearance.NotificationInfo.Button"/>
                     </FrameLayout>
@@ -322,6 +324,7 @@
                             android:layout_gravity="center"
                             android:layout_width="40dp"
                             android:layout_height="40dp"
+                            android:contentDescription="@string/inline_silent_button_alert"
                             android:clickable="false"
                             android:tint="@color/GM2_grey_400"
                             style="@style/TextAppearance.NotificationInfo.Button"/>
diff --git a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
index f64a64e6..b16e062 100644
--- a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
+++ b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
@@ -28,7 +28,7 @@
     android:orientation="horizontal"
     android:focusable="true">
 
-        <LinearLayout
+        <FrameLayout
             android:id="@+id/background"
             android:layout_height="@dimen/ongoing_appops_chip_height"
             android:layout_width="wrap_content"
@@ -37,25 +37,8 @@
                     android:id="@+id/icons_container"
                     android:layout_height="match_parent"
                     android:layout_width="wrap_content"
-                    android:layout_marginStart="@dimen/ongoing_appops_chip_items_margin"
-                    android:layout_gravity="center_vertical"
+                    android:layout_gravity="center"
                     android:gravity="center_vertical"
                     />
-
-                <TextView
-                    android:id="@+id/text_container"
-                    android:layout_height="match_parent"
-                    android:layout_width="wrap_content"
-                    android:layout_gravity="center_vertical|end"
-                    android:paddingStart="@dimen/ongoing_appops_chip_text_padding"
-                    android:paddingEnd="@dimen/ongoing_appops_chip_text_padding"
-                    android:gravity="center_vertical"
-                    android:singleLine="true"
-                    android:ellipsize="end"
-                    android:lines="1"
-                    android:textAppearance="@style/TextAppearance.StatusBar.Clock"
-                    android:textSize="@dimen/ongoing_appops_chip_text_size"
-                    android:textColor="@color/status_bar_clock_color"
-                />
-          </LinearLayout>
+          </FrameLayout>
 </com.android.systemui.privacy.OngoingPrivacyChip>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/status_bar_notification_footer.xml b/packages/SystemUI/res/layout/status_bar_notification_footer.xml
index 056f16a..174a3b8 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_footer.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_footer.xml
@@ -33,6 +33,7 @@
             android:layout_height="wrap_content"
             android:layout_gravity="start"
             android:focusable="true"
+            android:contentDescription="@string/accessibility_manage_notification"
             android:text="@string/manage_notifications_text"
             android:textColor="?attr/wallpaperTextColor"
             android:textAllCaps="false"/>
diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml
index ca34c23..130be89 100644
--- a/packages/SystemUI/res/layout/volume_dialog.xml
+++ b/packages/SystemUI/res/layout/volume_dialog.xml
@@ -98,5 +98,27 @@
             </FrameLayout>
         </LinearLayout>
 
+        <FrameLayout
+            android:id="@+id/odi_captions"
+            android:layout_width="@dimen/volume_dialog_caption_size"
+            android:layout_height="@dimen/volume_dialog_caption_size"
+            android:layout_marginTop="@dimen/volume_dialog_spacer"
+            android:translationZ="@dimen/volume_dialog_elevation"
+            android:layout_gravity="right"
+            android:clipToPadding="false"
+            android:visibility="gone"
+            android:background="@drawable/rounded_bg_full">
+            <com.android.keyguard.AlphaOptimizedImageButton
+                android:id="@+id/odi_captions_icon"
+                android:src="@drawable/ic_volume_odi_captions_disabled"
+                style="@style/VolumeButtons"
+                android:background="@drawable/rounded_ripple"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:tint="@color/accent_tint_color_selector"
+                android:layout_gravity="center"
+                android:soundEffectsEnabled="false" />
+        </FrameLayout>
+
     </LinearLayout>
 </FrameLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml
index 5803bf1..d74d258 100644
--- a/packages/SystemUI/res/values-night/colors.xml
+++ b/packages/SystemUI/res/values-night/colors.xml
@@ -47,4 +47,16 @@
 
     <!-- The color of the background in the bottom part of QSCustomizer -->
     <color name="qs_customize_decoration">@color/GM2_grey_800</color>
+
+    <!-- The color of the background in the separated list of the Global Actions menu -->
+    <color name="global_actions_separated_background">@color/GM2_grey_900</color>
+
+    <!-- The color of the background in the grid of the Global Actions menu -->
+    <color name="global_actions_grid_background">@color/GM2_grey_800</color>
+
+    <!-- The color of the text in the Global Actions menu -->
+    <color name="global_actions_text">@color/GM2_grey_200</color>
+
+    <!-- The color of the text in the Global Actions menu -->
+    <color name="global_actions_alert_text">@color/GM2_red_300</color>
 </resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 0e4ffee..b82c250 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -38,6 +38,18 @@
     <color name="qs_customize_background">@color/GM2_grey_50</color>
     <color name="qs_customize_decoration">@color/GM2_grey_100</color>
 
+    <!-- The color of the background in the separated list of the Global Actions menu -->
+    <color name="global_actions_separated_background">@color/GM2_grey_300</color>
+
+    <!-- The color of the background in the grid of the Global Actions menu -->
+    <color name="global_actions_grid_background">@color/GM2_grey_200</color>
+
+    <!-- The color of the text in the Global Actions menu -->
+    <color name="global_actions_text">@color/GM2_grey_900</color>
+
+    <!-- The color of the text in the Global Actions menu -->
+    <color name="global_actions_alert_text">@color/GM2_red_500</color>
+
     <!-- Tint color for the content on the notification overflow card. -->
     <color name="keyguard_overflow_content_color">#ff686868</color>
 
@@ -149,4 +161,7 @@
     <color name="GM2_grey_700">#5F6368</color>
     <color name="GM2_grey_800">#3C4043</color>
     <color name="GM2_grey_900">#202124</color>
+
+    <color name="GM2_red_300">#F28B82</color>
+    <color name="GM2_red_500">#B71C1C</color>
 </resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 8b4f66d..f8295eb 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -330,7 +330,7 @@
     <!-- Nav bar button default ordering/layout -->
     <string name="config_navBarLayout" translatable="false">left[.5W],back[1WC];home;recent[1WC],right[.5W]</string>
     <string name="config_navBarLayoutQuickstep" translatable="false">back[1.7WC];home;contextual[1.7WC]</string>
-    <string name="config_navBarLayoutHandle" translatable="false">";home_handle;assistant_handle[.18WC]"</string>
+    <string name="config_navBarLayoutHandle" translatable="false">";home_handle;"</string>
 
     <bool name="quick_settings_show_full_alarm">false</bool>
 
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index c83cb59..30cbaaa 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -34,11 +34,10 @@
     <dimen name="navigation_bar_deadzone_size_max">32dp</dimen>
 
     <!-- dimensions for the navigation bar handle -->
-    <dimen name="navigation_handle_radius">2dp</dimen>
-    <dimen name="navigation_handle_bottom">8dp</dimen>
+    <dimen name="navigation_handle_radius">1dp</dimen>
+    <dimen name="navigation_handle_bottom">6dp</dimen>
     <dimen name="navigation_handle_horizontal_margin">30dp</dimen>
-    <dimen name="navigation_home_handle_width">180dp</dimen>
-    <dimen name="navigation_assistant_handle_width">36dp</dimen>
+    <dimen name="navigation_home_handle_width">280dp</dimen>
 
     <!-- Height of notification icons in the status bar -->
     <dimen name="status_bar_icon_size">@*android:dimen/status_bar_icon_size</dimen>
@@ -336,6 +335,8 @@
 
     <dimen name="volume_dialog_ringer_size">64dp</dimen>
 
+    <dimen name="volume_dialog_caption_size">64dp</dimen>
+
     <dimen name="volume_dialog_tap_target_size">48dp</dimen>
 
     <dimen name="volume_dialog_spacer">4dp</dimen>
@@ -865,10 +866,12 @@
 
     <!-- Global actions power menu -->
     <dimen name="global_actions_panel_width">120dp</dimen>
-    <dimen name="global_actions_top_padding">120dp</dimen>
     <dimen name="global_actions_padding">12dp</dimen>
     <dimen name="global_actions_translate">9dp</dimen>
 
+    <!-- Distance from the top of screen in pixels, to position the power menu near the button. -->
+    <dimen name="global_actions_top_padding">330px</dimen>
+
     <!-- Global actions grid layout -->
     <dimen name="global_actions_grid_side_margin">4dp</dimen>
 
@@ -999,10 +1002,8 @@
     <dimen name="ongoing_appops_chip_margin">0dp</dimen>
     <!-- Height of the Ongoing App Ops chip -->
     <dimen name="ongoing_appops_chip_height">32dp</dimen>
-    <!-- Start and End padding for Ongoing App Ops chip -->
-    <dimen name="ongoing_appops_chip_text_padding">8dp</dimen>
     <!-- Padding between background of Ongoing App Ops chip and content -->
-    <dimen name="ongoing_appops_chip_bg_padding">0dp</dimen>
+    <dimen name="ongoing_appops_chip_bg_padding">8dp</dimen>
     <!-- Side padding between background of Ongoing App Ops chip and content -->
     <dimen name="ongoing_appops_chip_side_padding">8dp</dimen>
     <!-- Margin between icons of Ongoing App Ops chip when QQS-->
@@ -1013,10 +1014,7 @@
     <dimen name="ongoing_appops_chip_icon_size">@*android:dimen/status_bar_icon_size</dimen>
     <!-- Radius of Ongoing App Ops chip corners -->
     <dimen name="ongoing_appops_chip_bg_corner_radius">16dp</dimen>
-    <!-- Size of text of Ongoing App Ops chip -->
-    <dimen name="ongoing_appops_chip_text_size">12sp</dimen>
-    <!-- Margin between items in Ongoing App Ops chip -->
-    <dimen name="ongoing_appops_chip_items_margin">8dp</dimen>
+
 
     <!-- How much a bubble is elevated -->
     <dimen name="bubble_elevation">8dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 16222f7..da43391 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -266,6 +266,8 @@
     <string name="accessibility_scanning_face">Scanning face</string>
     <!-- Click action label for accessibility for the smart reply buttons (not shown on-screen).". [CHAR LIMIT=NONE] -->
     <string name="accessibility_send_smart_reply">Send</string>
+    <!-- Content description of the manage notification button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_manage_notification">Manage notifications</string>
     <!-- Click action label for accessibility for the unlock button. [CHAR LIMIT=NONE] -->
     <string name="unlock_label">unlock</string>
     <!-- Click action label for accessibility for the phone button. [CHAR LIMIT=NONE] -->
@@ -2318,26 +2320,12 @@
          app for debugging. Will not be seen by users. [CHAR LIMIT=20] -->
     <string name="heap_dump_tile_name">Dump SysUI Heap</string>
 
-    <!-- Text on chip for multiple apps using a single app op [CHAR LIMIT=12] -->
-    <plurals name="ongoing_privacy_chip_multiple_apps">
-        <item quantity="one"><xliff:g id="num_apps" example="1">%d</xliff:g> app</item>
-        <item quantity="few"><xliff:g id="num_apps" example="3">%d</xliff:g> apps</item>
-        <item quantity="other"><xliff:g id="num_apps" example="3">%d</xliff:g> apps</item>
-    </plurals>
-
     <!-- Content description for ongoing privacy chip. Use with a single app [CHAR LIMIT=NONE]-->
     <string name="ongoing_privacy_chip_content_single_app"><xliff:g id="app" example="Example App">%1$s</xliff:g> is using your <xliff:g id="types_list" example="camera, location">%2$s</xliff:g>.</string>
 
     <!-- Content description for ongoing privacy chip. Use with multiple apps [CHAR LIMIT=NONE]-->
     <string name="ongoing_privacy_chip_content_multiple_apps">Applications are using your <xliff:g id="types_list" example="camera, location">%s</xliff:g>.</string>
 
-    <!-- Content description for ongoing privacy chip. Use with multiple apps using same app op[CHAR LIMIT=NONE]-->
-    <plurals name="ongoing_privacy_chip_content_multiple_apps_single_op">
-        <item quantity="one"><xliff:g id="num_apps" example="1">%1$d</xliff:g> application is using your <xliff:g id="type" example="camera">%2$s</xliff:g>.</item>
-        <item quantity="few"><xliff:g id="num_apps" example="3">%1$d</xliff:g> applications are using your <xliff:g id="type" example="camera">%2$s</xliff:g>.</item>
-        <item quantity="other"><xliff:g id="num_apps" example="3">%1$d</xliff:g> applications are using your <xliff:g id="type" example="camera">%2$s</xliff:g>.</item>
-    </plurals>
-
     <!-- Action for accepting the Ongoing privacy dialog [CHAR LIMIT=10]-->
     <string name="ongoing_privacy_dialog_ok">Got it</string>
 
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityOptionsCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityOptionsCompat.java
index ea6fb48..7b39ba3 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityOptionsCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityOptionsCompat.java
@@ -78,4 +78,12 @@
                     }
                 });
     }
+
+    /**
+     * Sets the flag to freeze the recents task list reordering as a part of launching the activity.
+     */
+    public static ActivityOptions setFreezeRecentTasksList(ActivityOptions opts) {
+        opts.setFreezeRecentTasksReordering();
+        return opts;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index d40fa66..ce65b5a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -60,8 +60,8 @@
      */
     private ViewGroup mBigClockContainer;
     /**
-     * Status area (date and other stuff) shown below the clock. Plugin can decide whether
-     * or not to show it below the alternate clock.
+     * Status area (date and other stuff) shown below the clock. Plugin can decide whether or not to
+     * show it below the alternate clock.
      */
     private View mKeyguardStatusArea;
     /**
@@ -75,24 +75,19 @@
     private boolean mSupportsDarkText;
     private int[] mColorPalette;
 
+    /**
+     * Track the state of the status bar to know when to hide the big_clock_container.
+     */
+    private int mStatusBarState;
+
     private final StatusBarStateController.StateListener mStateListener =
             new StatusBarStateController.StateListener() {
                 @Override
                 public void onStateChanged(int newState) {
-                    if (mBigClockContainer == null) {
-                        return;
-                    }
-                    if (newState == StatusBarState.SHADE) {
-                        if (mBigClockContainer.getVisibility() == View.VISIBLE) {
-                            mBigClockContainer.setVisibility(View.INVISIBLE);
-                        }
-                    } else {
-                        if (mBigClockContainer.getVisibility() == View.INVISIBLE) {
-                            mBigClockContainer.setVisibility(View.VISIBLE);
-                        }
-                    }
+                    mStatusBarState = newState;
+                    updateBigClockVisibility();
                 }
-    };
+            };
 
     private ClockManager.ClockChangedListener mClockChangedListener = this::setClockPlugin;
 
@@ -139,7 +134,9 @@
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
         Dependency.get(ClockManager.class).addOnClockChangedListener(mClockChangedListener);
-        Dependency.get(StatusBarStateController.class).addCallback(mStateListener);
+        StatusBarStateController stateController = Dependency.get(StatusBarStateController.class);
+        stateController.addCallback(mStateListener);
+        mStateListener.onStateChanged(stateController.getState());
         SysuiColorExtractor colorExtractor = Dependency.get(SysuiColorExtractor.class);
         colorExtractor.addOnColorsChangedListener(mColorsListener);
         updateColors(colorExtractor);
@@ -151,7 +148,7 @@
         Dependency.get(ClockManager.class).removeOnClockChangedListener(mClockChangedListener);
         Dependency.get(StatusBarStateController.class).removeCallback(mStateListener);
         Dependency.get(SysuiColorExtractor.class)
-            .removeOnColorsChangedListener(mColorsListener);
+                .removeOnColorsChangedListener(mColorsListener);
         setClockPlugin(null);
     }
 
@@ -164,7 +161,7 @@
             }
             if (mBigClockContainer != null) {
                 mBigClockContainer.removeAllViews();
-                mBigClockContainer.setVisibility(View.GONE);
+                updateBigClockVisibility();
             }
             mClockPlugin = null;
         }
@@ -184,7 +181,7 @@
         View bigClockView = plugin.getBigClockView();
         if (bigClockView != null && mBigClockContainer != null) {
             mBigClockContainer.addView(bigClockView);
-            mBigClockContainer.setVisibility(View.VISIBLE);
+            updateBigClockVisibility();
         }
         // Hide default clock.
         if (!plugin.shouldShowStatusArea()) {
@@ -208,12 +205,10 @@
             View bigClockView = mClockPlugin.getBigClockView();
             if (bigClockView != null) {
                 container.addView(bigClockView);
-                if (container.getVisibility() == View.GONE) {
-                    container.setVisibility(View.VISIBLE);
-                }
             }
         }
         mBigClockContainer = container;
+        updateBigClockVisibility();
     }
 
     /**
@@ -254,6 +249,7 @@
 
     /**
      * Set the amount (ratio) that the device has transitioned to doze.
+     *
      * @param darkAmount Amount of transition to doze: 1f for doze and 0f for awake.
      */
     public void setDarkAmount(float darkAmount) {
@@ -307,9 +303,24 @@
         }
     }
 
+    private void updateBigClockVisibility() {
+        if (mBigClockContainer == null) {
+            return;
+        }
+        final boolean inDisplayState = mStatusBarState == StatusBarState.KEYGUARD
+                || mStatusBarState == StatusBarState.SHADE_LOCKED;
+        final int visibility =
+                inDisplayState && mBigClockContainer.getChildCount() != 0 ? View.VISIBLE
+                        : View.GONE;
+        if (mBigClockContainer.getVisibility() != visibility) {
+            mBigClockContainer.setVisibility(visibility);
+        }
+    }
+
     /**
-     * Sets if the keyguard slice is showing a center-aligned header. We need a smaller clock
-     * in these cases.
+     * Sets if the keyguard slice is showing a center-aligned header. We need a smaller clock in
+     * these
+     * cases.
      */
     public void setKeyguardShowingHeader(boolean hasHeader) {
         if (mShowingHeader == hasHeader || hasCustomClock()) {
@@ -327,12 +338,12 @@
                 mClockView.getPaddingRight(), paddingBottom);
     }
 
-    @VisibleForTesting (otherwise = VisibleForTesting.NONE)
+    @VisibleForTesting(otherwise = VisibleForTesting.NONE)
     ClockManager.ClockChangedListener getClockChangedListener() {
         return mClockChangedListener;
     }
 
-    @VisibleForTesting (otherwise = VisibleForTesting.NONE)
+    @VisibleForTesting(otherwise = VisibleForTesting.NONE)
     StatusBarStateController.StateListener getStateListener() {
         return mStateListener;
     }
@@ -352,7 +363,8 @@
 
     /**
      * Special layout transition that scales the clock view as its bounds change, to make it look
-     * like the text is shrinking.
+     * like
+     * the text is shrinking.
      */
     private class ClockBoundsTransition extends ChangeBounds {
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 97160b6..63f8cd6 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -105,11 +105,6 @@
  * Watches for updates that may be interesting to the keyguard, and provides
  * the up to date information as well as a registration for callbacks that care
  * to be updated.
- *
- * Note: under time crunch, this has been extended to include some stuff that
- * doesn't really belong here.  see {@link #handleBatteryUpdate} where it shutdowns
- * the device, and {@link #getFailedUnlockAttempts()}, {@link #reportFailedAttempt()}
- * and {@link #clearFailedUnlockAttempts()}.  Maybe we should rename this 'KeyguardContext'...
  */
 public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
 
@@ -1568,6 +1563,15 @@
         updateFaceListeningState();
     }
 
+    /**
+     * Requests face authentication if we're on a state where it's allowed.
+     * This will re-trigger auth in case it fails.
+     */
+    public void requestFaceAuth() {
+        if (DEBUG) Log.d(TAG, "requestFaceAuth()");
+        updateFaceListeningState();
+    }
+
     private void updateFaceListeningState() {
         // If this message exists, we should not authenticate again until this message is
         // consumed by the handler
@@ -1629,7 +1633,7 @@
             return;
         }
         if (DEBUG) Log.v(TAG, "startListeningForFingerprint()");
-        int userId = ActivityManager.getCurrentUser();
+        int userId = getCurrentUser();
         if (isUnlockWithFingerprintPossible(userId)) {
             if (mFingerprintCancelSignal != null) {
                 mFingerprintCancelSignal.cancel();
@@ -1647,7 +1651,7 @@
             return;
         }
         if (DEBUG) Log.v(TAG, "startListeningForFace()");
-        int userId = ActivityManager.getCurrentUser();
+        int userId = getCurrentUser();
         if (isUnlockWithFacePossible(userId)) {
             if (mFaceCancelSignal != null) {
                 mFaceCancelSignal.cancel();
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ImageClock.java b/packages/SystemUI/src/com/android/keyguard/clock/ImageClock.java
index 2275380..95f1004 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ImageClock.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ImageClock.java
@@ -59,7 +59,7 @@
      */
     public void onTimeChanged() {
         mTime.setTimeInMillis(System.currentTimeMillis());
-        final float hourAngle = mTime.get(Calendar.HOUR) * 30f;
+        final float hourAngle = mTime.get(Calendar.HOUR) * 30f + mTime.get(Calendar.MINUTE) * 0.5f;
         mHourHand.setRotation(hourAngle);
         final float minuteAngle = mTime.get(Calendar.MINUTE) * 6f;
         mMinuteHand.setRotation(minuteAngle);
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java b/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java
index 34c855b..8cdd632 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java
@@ -103,7 +103,8 @@
         final float centerY = getHeight() / 2f;
 
         final float minutesRotation = mTime.get(Calendar.MINUTE) * 6f;
-        final float hoursRotation = (mTime.get(Calendar.HOUR) * 30);
+        final float hoursRotation = mTime.get(Calendar.HOUR) * 30
+                + mTime.get(Calendar.MINUTE) * 0.5f;
 
         // Compute length of clock hands. Hour hand is 60% the length from center to edge
         // and minute hand is twice the length to make sure it extends past screen edge.
diff --git a/packages/SystemUI/src/com/android/systemui/HardwareBgDrawable.java b/packages/SystemUI/src/com/android/systemui/HardwareBgDrawable.java
index 97d7999..d631cf3 100644
--- a/packages/SystemUI/src/com/android/systemui/HardwareBgDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/HardwareBgDrawable.java
@@ -115,4 +115,4 @@
     public void setRotatedBackground(boolean rotatedBackground) {
         mRotatedBackground = rotatedBackground;
     }
-}
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
index 5086c99..72ab02c 100644
--- a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
@@ -215,7 +215,7 @@
         } else {
             rotateLeft();
         }
-        if (mSeparated) {
+        if (mAdapter.hasSeparatedItems()) {
             if (from == ROTATION_SEASCAPE || to == ROTATION_SEASCAPE) {
                 // Separated view has top margin, so seascape separated view need special rotation,
                 // not a full left or right rotation.
@@ -257,10 +257,10 @@
 
     @Override
     public void onUpdateList() {
-        removeAllItems();
+        super.onUpdateList();
         ArrayList<GlobalActionsDialog.Action> separatedActions =
-                mAdapter.getSeparatedItems(mSeparated);
-        ArrayList<GlobalActionsDialog.Action> listActions = mAdapter.getListItems(mSeparated);
+                mAdapter.getSeparatedItems();
+        ArrayList<GlobalActionsDialog.Action> listActions = mAdapter.getListItems();
 
         for (int i = 0; i < mAdapter.getCount(); i++) {
             Object action = mAdapter.getItem(i);
@@ -461,8 +461,9 @@
         if (mList == null) return;
         // If got separated button, setRotatedBackground to false,
         // all items won't get white background.
-        mListBackground.setRotatedBackground(mSeparated);
-        mSeparatedViewBackground.setRotatedBackground(mSeparated);
+        boolean separated = mAdapter.hasSeparatedItems();
+        mListBackground.setRotatedBackground(separated);
+        mSeparatedViewBackground.setRotatedBackground(separated);
         if (mDivision != null && mDivision.getVisibility() == VISIBLE) {
             int index = mRotatedBackground ? 0 : 1;
             mDivision.getLocationOnScreen(mTmp2);
@@ -508,26 +509,27 @@
         int screenHeight;
         int totalHeight;
         int targetGravity;
+        boolean separated = mAdapter.hasSeparatedItems();
         MarginLayoutParams params = (MarginLayoutParams) mSeparatedView.getLayoutParams();
         switch (RotationUtils.getRotation(getContext())) {
             case RotationUtils.ROTATION_LANDSCAPE:
                 defaultTopPadding = getPaddingLeft();
                 viewsTotalHeight = mList.getMeasuredWidth() + mSeparatedView.getMeasuredWidth();
-                separatedViewTopMargin = mSeparated ? params.leftMargin : 0;
+                separatedViewTopMargin = separated ? params.leftMargin : 0;
                 screenHeight = getMeasuredWidth();
                 targetGravity = Gravity.CENTER_HORIZONTAL|Gravity.TOP;
                 break;
             case RotationUtils.ROTATION_SEASCAPE:
                 defaultTopPadding = getPaddingRight();
                 viewsTotalHeight = mList.getMeasuredWidth() + mSeparatedView.getMeasuredWidth();
-                separatedViewTopMargin = mSeparated ? params.leftMargin : 0;
+                separatedViewTopMargin = separated ? params.leftMargin : 0;
                 screenHeight = getMeasuredWidth();
                 targetGravity = Gravity.CENTER_HORIZONTAL|Gravity.BOTTOM;
                 break;
             default: // Portrait
                 defaultTopPadding = getPaddingTop();
                 viewsTotalHeight = mList.getMeasuredHeight() + mSeparatedView.getMeasuredHeight();
-                separatedViewTopMargin = mSeparated ? params.topMargin : 0;
+                separatedViewTopMargin = separated ? params.topMargin : 0;
                 screenHeight = getMeasuredHeight();
                 targetGravity = Gravity.CENTER_VERTICAL|Gravity.RIGHT;
                 break;
diff --git a/packages/SystemUI/src/com/android/systemui/MultiListLayout.java b/packages/SystemUI/src/com/android/systemui/MultiListLayout.java
index 2bc4720..d063a0f 100644
--- a/packages/SystemUI/src/com/android/systemui/MultiListLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/MultiListLayout.java
@@ -33,8 +33,8 @@
  */
 public abstract class MultiListLayout extends LinearLayout {
     protected boolean mHasOutsideTouch;
-    protected boolean mSeparated;
     protected MultiListAdapter mAdapter;
+    protected boolean mSnapToEdge;
 
     protected int mRotation;
     protected RotationListener mRotationListener;
@@ -70,12 +70,10 @@
     }
 
     /**
-     * Sets whether the separated view should be shown, and handles updating visibility on
-     * that view.
+     * Sets whether the GlobalActions view should snap to the edge of the screen.
      */
-    public void setSeparated(boolean separated) {
-        mSeparated = separated;
-        setSeparatedViewVisibility(separated);
+    public void setSnapToEdge(boolean snap) {
+        mSnapToEdge = snap;
     }
 
     /**
@@ -123,7 +121,9 @@
         onUpdateList();
     }
 
-    protected abstract void onUpdateList();
+    protected void onUpdateList() {
+        setSeparatedViewVisibility(mAdapter.hasSeparatedItems());
+    }
 
     public void setRotationListener(RotationListener listener) {
         mRotationListener = listener;
@@ -156,13 +156,13 @@
          * Creates an ArrayList of items which should be rendered in the separated view.
          * @param useSeparatedView is true if the separated view will be used, false otherwise.
          */
-        public abstract ArrayList getSeparatedItems(boolean useSeparatedView);
+        public abstract ArrayList getSeparatedItems();
 
         /**
          * Creates an ArrayList of items which should be rendered in the list view.
          * @param useSeparatedView True if the separated view will be used, false otherwise.
          */
-        public abstract ArrayList getListItems(boolean useSeparatedView);
+        public abstract ArrayList getListItems();
 
         /**
          * Callback to run when an individual item is clicked or pressed.
@@ -176,5 +176,13 @@
          * @return True if the long-click was handled, false otherwise.
          */
         public abstract boolean onLongClickItem(int position);
+
+        /**
+         * Determines whether the mAdapter contains any separated items, used to determine whether
+         * or not to hide the separated list from view.
+         */
+        public boolean hasSeparatedItems() {
+            return getSeparatedItems().size() > 0;
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index ff68d2b..97a277b 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -14,6 +14,7 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.PixelFormat;
+import android.graphics.Rect;
 import android.os.AsyncTask;
 import android.os.Binder;
 import android.os.Bundle;
@@ -173,6 +174,26 @@
         startAssistInternal(args, assistComponent, isService);
     }
 
+    /**
+     * Returns a {@code Rect} containing system UI presented on behalf of the assistant that
+     * consumes touches.
+     */
+    @Nullable
+    public Rect getTouchableRegion() {
+        // intentional no-op, vendor's AssistManager implementation should override if needed.
+        return null;
+    }
+
+    /** Registers a listener for changes to system UI presented on behalf of the assistant. */
+    public void setAssistSysUiChangeListener(AssistSysUiChangeListener listener) {
+        // intentional no-op, vendor's AssistManager implementation should override if needed.
+    }
+
+    /** Returns {@code true} if the system UI is showing UI for the assistant. */
+    public boolean hasAssistUi() {
+        return false;
+    }
+
     public void hideAssist() {
         mAssistUtils.hideCurrentSession();
     }
diff --git a/core/java/android/net/ProxyInfoParcelable.aidl b/packages/SystemUI/src/com/android/systemui/assist/AssistSysUiChangeListener.java
similarity index 62%
copy from core/java/android/net/ProxyInfoParcelable.aidl
copy to packages/SystemUI/src/com/android/systemui/assist/AssistSysUiChangeListener.java
index 59fd846..d03afb6 100644
--- a/core/java/android/net/ProxyInfoParcelable.aidl
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistSysUiChangeListener.java
@@ -5,20 +5,23 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *     http://www.apache.org/licenses/LICENSE-2.0
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
-*/
+ */
 
-package android.net;
+package com.android.systemui.assist;
 
-parcelable ProxyInfoParcelable {
-    String host;
-    int port;
-    String[] exclusionList;
-    String pacFileUrl;
+/**
+ * Used to notify when system UI is showing UI for the assistant.
+ */
+public interface AssistSysUiChangeListener {
+
+    /** Called when the visibility of system UI for the assistant has changed. */
+    void onChange(boolean isVisible);
+
 }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
index 016b8fe..4028109 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
@@ -191,32 +191,41 @@
         mCurrentDialogArgs = args;
         final int type = args.argi1;
 
+        // Create a new dialog but do not replace the current one yet.
+        BiometricDialogView newDialog;
         if (type == BiometricAuthenticator.TYPE_FINGERPRINT) {
-            mCurrentDialog = new FingerprintDialogView(mContext, mCallback);
+            newDialog = new FingerprintDialogView(mContext, mCallback);
         } else if (type == BiometricAuthenticator.TYPE_FACE) {
-            mCurrentDialog = new FaceDialogView(mContext, mCallback);
+            newDialog = new FaceDialogView(mContext, mCallback);
         } else {
             Log.e(TAG, "Unsupported type: " + type);
-        }
-
-        if (savedState != null) {
-            mCurrentDialog.restoreState(savedState);
-        }
-
-        if (DEBUG) Log.d(TAG, "handleShowDialog, isAnimatingAway: "
-                + mCurrentDialog.isAnimatingAway() + " type: " + type);
-
-        if (mCurrentDialog.isAnimatingAway()) {
-            mCurrentDialog.forceRemove();
-        } else if (mDialogShowing) {
-            Log.w(TAG, "Dialog already showing");
             return;
         }
+
+        if (DEBUG) Log.d(TAG, "handleShowDialog, "
+                + " savedState: " + savedState
+                + " mCurrentDialog: " + mCurrentDialog
+                + " newDialog: " + newDialog
+                + " type: " + type);
+
+        if (savedState != null) {
+            // SavedState is only non-null if it's from onConfigurationChanged. Restore the state
+            // even though it may be removed / re-created again
+            newDialog.restoreState(savedState);
+        } else if (mCurrentDialog != null && mDialogShowing) {
+            // If somehow we're asked to show a dialog, the old one doesn't need to be animated
+            // away. This can happen if the app cancels and re-starts auth during configuration
+            // change. This is ugly because we also have to do things on onConfigurationChanged
+            // here.
+            mCurrentDialog.forceRemove();
+        }
+
         mReceiver = (IBiometricServiceReceiverInternal) args.arg2;
-        mCurrentDialog.setBundle((Bundle)args.arg1);
-        mCurrentDialog.setRequireConfirmation((boolean) args.arg3);
-        mCurrentDialog.setUserId(args.argi2);
-        mCurrentDialog.setSkipIntro(skipAnimation);
+        newDialog.setBundle((Bundle) args.arg1);
+        newDialog.setRequireConfirmation((boolean) args.arg3);
+        newDialog.setUserId(args.argi2);
+        newDialog.setSkipIntro(skipAnimation);
+        mCurrentDialog = newDialog;
         mWindowManager.addView(mCurrentDialog, mCurrentDialog.getLayoutParams());
         mDialogShowing = true;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index eb85589..e0ed111 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -118,6 +118,7 @@
     private final BubbleTaskStackListener mTaskStackListener;
     private BubbleStateChangeListener mStateChangeListener;
     private BubbleExpandListener mExpandListener;
+    @Nullable private BubbleStackView.SurfaceSynchronizer mSurfaceSynchronizer;
 
     private BubbleData mBubbleData;
     private BubbleStackView mStackView;
@@ -178,7 +179,12 @@
 
     @Inject
     public BubbleController(Context context, StatusBarWindowController statusBarWindowController,
-            BubbleData data) {
+                            BubbleData data) {
+        this(context, statusBarWindowController, data, null /* synchronizer */);
+    }
+
+    public BubbleController(Context context, StatusBarWindowController statusBarWindowController,
+            BubbleData data, @Nullable BubbleStackView.SurfaceSynchronizer synchronizer) {
         mContext = context;
 
         mNotificationEntryManager = Dependency.get(NotificationEntryManager.class);
@@ -206,6 +212,7 @@
         }
 
         mBubbleData = data;
+        mSurfaceSynchronizer = synchronizer;
     }
 
     /**
@@ -297,7 +304,7 @@
             mStackView.updateBubble(notif, updatePosition);
         } else {
             if (mStackView == null) {
-                mStackView = new BubbleStackView(mContext, mBubbleData);
+                mStackView = new BubbleStackView(mContext, mBubbleData, mSurfaceSynchronizer);
                 ViewGroup sbv = mStatusBarWindowController.getStatusBarView();
                 // XXX: Bug when you expand the shade on top of expanded bubble, there is no scrim
                 // between bubble and the shade
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 888e3fe..1cc6b87 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -19,6 +19,7 @@
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
 
+import android.annotation.NonNull;
 import android.app.Notification;
 import android.app.PendingIntent;
 import android.content.Context;
@@ -32,6 +33,7 @@
 import android.service.notification.StatusBarNotification;
 import android.util.Log;
 import android.util.StatsLog;
+import android.view.Choreographer;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
@@ -67,6 +69,43 @@
     private static final String TAG = "BubbleStackView";
     private static final boolean DEBUG = false;
 
+    /**
+     * Interface to synchronize {@link View} state and the screen.
+     *
+     * {@hide}
+     */
+    interface SurfaceSynchronizer {
+        /**
+         * Wait until requested change on a {@link View} is reflected on the screen.
+         *
+         * @param callback callback to run after the change is reflected on the screen.
+         */
+        void syncSurfaceAndRun(Runnable callback);
+    }
+
+    private static final SurfaceSynchronizer DEFAULT_SURFACE_SYNCHRONIZER =
+            new SurfaceSynchronizer() {
+        @Override
+        public void syncSurfaceAndRun(Runnable callback) {
+            Choreographer.getInstance().postFrameCallback(new Choreographer.FrameCallback() {
+                // Just wait 2 frames. There is no guarantee, but this is usually enough time that
+                // the requested change is reflected on the screen.
+                // TODO: Once SurfaceFlinger provide APIs to sync the state of {@code View} and
+                // surfaces, rewrite this logic with them.
+                private int mFrameWait = 2;
+
+                @Override
+                public void doFrame(long frameTimeNanos) {
+                    if (--mFrameWait > 0) {
+                        Choreographer.getInstance().postFrameCallback(this);
+                    } else {
+                        callback.run();
+                    }
+                }
+            });
+        }
+    };
+
     private Point mDisplaySize;
 
     private final SpringAnimation mExpandedViewXAnim;
@@ -79,7 +118,6 @@
 
     private FrameLayout mExpandedViewContainer;
 
-
     private int mBubbleSize;
     private int mBubblePadding;
     private int mExpandedAnimateXDistance;
@@ -129,7 +167,11 @@
         }
     };
 
-    public BubbleStackView(Context context, BubbleData data) {
+    @NonNull private final SurfaceSynchronizer mSurfaceSynchronizer;
+
+
+    public BubbleStackView(Context context, BubbleData data,
+                           @Nullable SurfaceSynchronizer synchronizer) {
         super(context);
 
         mBubbleData = data;
@@ -160,6 +202,7 @@
 
         mStackAnimationController = new StackAnimationController();
         mExpandedAnimationController = new ExpandedAnimationController(mDisplaySize);
+        mSurfaceSynchronizer = synchronizer != null ? synchronizer : DEFAULT_SURFACE_SYNCHRONIZER;
 
         mBubbleContainer = new PhysicsAnimationLayout(context);
         mBubbleContainer.setMaxRenderedChildren(
@@ -314,17 +357,28 @@
             // If we weren't previously expanded we should animate open.
             animateExpansion(true /* expand */);
             logBubbleEvent(mExpandedBubble, StatsLog.BUBBLE_UICHANGED__ACTION__EXPANDED);
+            mExpandedBubble.entry.setShowInShadeWhenBubble(false);
+            notifyExpansionChanged(mExpandedBubble.entry, true /* expanded */);
         } else {
-            // Otherwise just update the views
-            // TODO: probably animate / page to expanded one
-            updateExpandedBubble();
-            updatePointerPosition();
-            requestUpdate();
-            logBubbleEvent(prevBubble, StatsLog.BUBBLE_UICHANGED__ACTION__COLLAPSED);
-            logBubbleEvent(mExpandedBubble, StatsLog.BUBBLE_UICHANGED__ACTION__EXPANDED);
+            // Make the container of the expanded view transparent before removing the expanded view
+            // from it. Otherwise a punch hole created by {@link android.view.SurfaceView} in the
+            // expanded view becomes visible on the screen. See b/126856255
+            mExpandedViewContainer.setAlpha(0.0f);
+
+            mSurfaceSynchronizer.syncSurfaceAndRun(new Runnable() {
+                @Override
+                public void run() {
+                    updateExpandedBubble();
+                    updatePointerPosition();
+                    requestUpdate();
+                    logBubbleEvent(prevBubble, StatsLog.BUBBLE_UICHANGED__ACTION__COLLAPSED);
+                    logBubbleEvent(mExpandedBubble,
+                            StatsLog.BUBBLE_UICHANGED__ACTION__EXPANDED);
+                    mExpandedBubble.entry.setShowInShadeWhenBubble(false);
+                    notifyExpansionChanged(mExpandedBubble.entry, true /* expanded */);
+                }
+            });
         }
-        mExpandedBubble.entry.setShowInShadeWhenBubble(false);
-        notifyExpansionChanged(mExpandedBubble.entry, true /* expanded */);
     }
 
     /**
@@ -426,7 +480,9 @@
 
         if (reason == BubbleController.DISMISS_USER_GESTURE) {
             Notification.BubbleMetadata bubbleMetadata = bubble.entry.getBubbleMetadata();
-            PendingIntent deleteIntent = bubbleMetadata.getDeleteIntent();
+            PendingIntent deleteIntent = bubbleMetadata != null
+                    ? bubbleMetadata.getDeleteIntent()
+                    : null;
             if (deleteIntent != null) {
                 try {
                     deleteIntent.send();
@@ -767,6 +823,7 @@
             mExpandedViewContainer.addView(mExpandedBubble.expandedView);
             mExpandedBubble.expandedView.populateExpandedView();
             mExpandedViewContainer.setVisibility(mIsExpanded ? VISIBLE : GONE);
+            mExpandedViewContainer.setAlpha(1.0f);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java b/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java
index 06dbdbf..a4592d5 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java
@@ -121,11 +121,17 @@
                     if (dozeState == State.DOZE
                             && mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT)) {
                         mMachine.requestState(State.DOZE_AOD);
-                        break;
                     }
-                    // continue below
+                    else {
+                        requestPulseOutNow(dozeState);
+                    }
+                    break;
                 case DockManager.STATE_DOCKED_HIDE:
-                    requestPulseOutNow(dozeState);
+                    if (dozeState == State.DOZE_AOD) {
+                        mMachine.requestState(State.DOZE);
+                    } else {
+                        requestPulseOutNow(dozeState);
+                    }
                     break;
                 default:
                     // no-op
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index b2f707f..bc3f48d 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -28,6 +28,7 @@
 import android.hardware.SensorEventListener;
 import android.hardware.SensorManager;
 import android.hardware.display.AmbientDisplayConfiguration;
+import android.metrics.LogMaker;
 import android.os.Handler;
 import android.os.SystemClock;
 import android.os.UserHandle;
@@ -35,7 +36,10 @@
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.util.Preconditions;
+import com.android.systemui.Dependency;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.util.Assert;
@@ -79,6 +83,7 @@
     private long mNotificationPulseTime;
     private boolean mPulsePending;
 
+    private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
 
     public DozeTriggers(Context context, DozeMachine machine, DozeHost dozeHost,
             AlarmManager alarmManager, AmbientDisplayConfiguration config,
@@ -159,8 +164,15 @@
                     if (screenX != -1 && screenY != -1) {
                         mDozeHost.onSlpiTap(screenX, screenY);
                     }
+                    // Logs screen wake up reason of either single or double tap.
+                    mMetricsLogger.write(new LogMaker(MetricsEvent.DOZING)
+                            .setType(MetricsEvent.TYPE_UPDATE).setSubtype(pulseReason));
                     mMachine.wakeUp();
                 } else if (isPickup) {
+                    // Logs screen wake up reason of lift.
+                    mMetricsLogger.write(new LogMaker(MetricsEvent.DOZING)
+                            .setType(MetricsEvent.TYPE_UPDATE)
+                            .setSubtype(DozeLog.REASON_SENSOR_PICKUP));
                     mMachine.wakeUp();
                 } else {
                     mDozeHost.extendPulse();
@@ -298,6 +310,10 @@
                 continuePulseRequest(reason);
             }
         }, !mDozeParameters.getProxCheckBeforePulse() || performedProxCheck, reason);
+
+        // Logs request pulse reason on AOD screen.
+        mMetricsLogger.write(new LogMaker(MetricsEvent.DOZING)
+                .setType(MetricsEvent.TYPE_UPDATE).setSubtype(reason));
     }
 
     private boolean canPulse() {
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index b07f909..f07887e 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -24,6 +24,7 @@
 import android.app.ActivityManager;
 import android.app.Dialog;
 import android.app.KeyguardManager;
+import android.app.PendingIntent;
 import android.app.WallpaperManager;
 import android.app.admin.DevicePolicyManager;
 import android.app.trust.TrustManager;
@@ -38,7 +39,6 @@
 import android.graphics.drawable.Drawable;
 import android.media.AudioManager;
 import android.net.ConnectivityManager;
-import android.os.Build;
 import android.os.Handler;
 import android.os.Message;
 import android.os.RemoteException;
@@ -87,12 +87,11 @@
 import com.android.systemui.MultiListLayout;
 import com.android.systemui.MultiListLayout.MultiListAdapter;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
 import com.android.systemui.plugins.GlobalActionsPanelPlugin;
 import com.android.systemui.statusbar.phone.ScrimController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.ExtensionController;
-import com.android.systemui.statusbar.policy.ExtensionController.Extension;
 import com.android.systemui.util.EmergencyDialerConstants;
 import com.android.systemui.util.leak.RotationUtils;
 import com.android.systemui.volume.SystemUIInterpolators.LogAccelerateInterpolator;
@@ -156,13 +155,12 @@
     private boolean mHasVibrator;
     private boolean mHasLogoutButton;
     private boolean mHasLockdownButton;
-    private boolean mUseSeparatedList;
     private final boolean mShowSilentToggle;
     private final EmergencyAffordanceManager mEmergencyAffordanceManager;
     private final ScreenshotHelper mScreenshotHelper;
     private final ScreenRecordHelper mScreenRecordHelper;
-
-    private final Extension<GlobalActionsPanelPlugin> mPanelExtension;
+    private final ActivityStarter mActivityStarter;
+    private GlobalActionsPanelPlugin mPanelPlugin;
 
     /**
      * @param context everything needs a context :(
@@ -208,10 +206,7 @@
 
         Dependency.get(ConfigurationController.class).addCallback(this);
 
-        mPanelExtension = Dependency.get(ExtensionController.class)
-            .newExtension(GlobalActionsPanelPlugin.class)
-            .withPlugin(GlobalActionsPanelPlugin.class)
-            .build();
+        mActivityStarter = Dependency.get(ActivityStarter.class);
     }
 
     /**
@@ -219,9 +214,11 @@
      *
      * @param keyguardShowing True if keyguard is showing
      */
-    public void showDialog(boolean keyguardShowing, boolean isDeviceProvisioned) {
+    public void showDialog(boolean keyguardShowing, boolean isDeviceProvisioned,
+            GlobalActionsPanelPlugin panelPlugin) {
         mKeyguardShowing = keyguardShowing;
         mDeviceProvisioned = isDeviceProvisioned;
+        mPanelPlugin = panelPlugin;
         if (mDialog != null) {
             mDialog.dismiss();
             mDialog = null;
@@ -334,7 +331,6 @@
         ArraySet<String> addedKeys = new ArraySet<String>();
         mHasLogoutButton = false;
         mHasLockdownButton = false;
-        mUseSeparatedList = true;
         for (int i = 0; i < defaultActions.length; i++) {
             String actionKey = defaultActions[i];
             if (addedKeys.contains(actionKey)) {
@@ -382,8 +378,7 @@
                     mHasLogoutButton = true;
                 }
             } else if (GLOBAL_ACTION_KEY_EMERGENCY.equals(actionKey)) {
-                if (mUseSeparatedList
-                        && !mEmergencyAffordanceManager.needsEmergencyAffordance()) {
+                if (!mEmergencyAffordanceManager.needsEmergencyAffordance()) {
                     mItems.add(new EmergencyDialerAction());
                 }
             } else {
@@ -394,21 +389,31 @@
         }
 
         if (mEmergencyAffordanceManager.needsEmergencyAffordance()) {
-            mItems.add(getEmergencyAction());
+            mItems.add(new EmergencyAffordanceAction());
         }
 
         mAdapter = new MyAdapter();
 
         GlobalActionsPanelPlugin.PanelViewController panelViewController =
-                mPanelExtension.get() != null
-                        ? mPanelExtension.get().onPanelShown(() -> {
-                            if (mDialog != null) {
-                                mDialog.dismiss();
-                            }
-                        })
+                mPanelPlugin != null
+                        ? mPanelPlugin.onPanelShown(
+                                new GlobalActionsPanelPlugin.Callbacks() {
+                                    @Override
+                                    public void dismissGlobalActionsMenu() {
+                                        if (mDialog != null) {
+                                            mDialog.dismiss();
+                                        }
+                                    }
+
+                                    @Override
+                                    public void startPendingIntentDismissingKeyguard(
+                                            PendingIntent intent) {
+                                        mActivityStarter
+                                                .startPendingIntentDismissingKeyguard(intent);
+                                    }
+                                })
                         : null;
-        ActionsDialog dialog = new ActionsDialog(mContext, mAdapter, mUseSeparatedList,
-                panelViewController);
+        ActionsDialog dialog = new ActionsDialog(mContext, mAdapter, panelViewController);
         dialog.setCanceledOnTouchOutside(false); // Handled by the custom class.
         dialog.setKeyguardShowing(mKeyguardShowing);
 
@@ -473,7 +478,59 @@
         }
     }
 
-    private class EmergencyDialerAction extends SinglePressAction {
+    private abstract class EmergencyAction extends SinglePressAction {
+        EmergencyAction(int iconResId, int messageResId) {
+            super(iconResId, messageResId);
+        }
+
+        @Override
+        public boolean shouldBeSeparated() {
+            return shouldUseSeparatedView();
+        }
+
+        @Override
+        public View create(
+                Context context, View convertView, ViewGroup parent, LayoutInflater inflater) {
+            View v = super.create(context, convertView, parent, inflater);
+            int textColor;
+            if (shouldBeSeparated()) {
+                textColor = v.getResources().getColor(
+                        com.android.systemui.R.color.global_actions_alert_text);
+            } else {
+                textColor = v.getResources().getColor(
+                        com.android.systemui.R.color.global_actions_text);
+            }
+            TextView messageView = v.findViewById(R.id.message);
+            messageView.setTextColor(textColor);
+            ImageView icon = (ImageView) v.findViewById(R.id.icon);
+            icon.getDrawable().setTint(textColor);
+            return v;
+        }
+
+        @Override
+        public boolean showDuringKeyguard() {
+            return true;
+        }
+
+        @Override
+        public boolean showBeforeProvisioning() {
+            return true;
+        }
+    }
+
+    private class EmergencyAffordanceAction extends EmergencyAction {
+        EmergencyAffordanceAction() {
+            super(R.drawable.emergency_icon,
+                    R.string.global_action_emergency);
+        }
+
+        @Override
+        public void onPress() {
+            mEmergencyAffordanceManager.performEmergencyCall();
+        }
+    }
+
+    private class EmergencyDialerAction extends EmergencyAction {
         private EmergencyDialerAction() {
             super(R.drawable.ic_faster_emergency,
                     R.string.global_action_emergency);
@@ -490,21 +547,6 @@
                     EmergencyDialerConstants.ENTRY_TYPE_POWER_MENU);
             mContext.startActivityAsUser(intent, UserHandle.CURRENT);
         }
-
-        @Override
-        public boolean showDuringKeyguard() {
-            return true;
-        }
-
-        @Override
-        public boolean showBeforeProvisioning() {
-            return true;
-        }
-
-        @Override
-        public boolean shouldBeSeparated() {
-            return true;
-        }
     }
 
     private final class RestartAction extends SinglePressAction implements LongPressAction {
@@ -636,14 +678,6 @@
         public boolean showBeforeProvisioning() {
             return false;
         }
-
-        @Override
-        public String getStatus() {
-            return mContext.getString(
-                    R.string.bugreport_status,
-                    Build.VERSION.RELEASE,
-                    Build.ID);
-        }
     }
 
     private final class LogoutAction extends SinglePressAction {
@@ -700,32 +734,6 @@
         };
     }
 
-    private Action getEmergencyAction() {
-        Drawable emergencyIcon = mContext.getDrawable(R.drawable.emergency_icon);
-        if (!mUseSeparatedList) {
-            // use un-colored legacy treatment
-            emergencyIcon.setTintList(null);
-        }
-
-        return new SinglePressAction(R.drawable.emergency_icon,
-                R.string.global_action_emergency) {
-            @Override
-            public void onPress() {
-                mEmergencyAffordanceManager.performEmergencyCall();
-            }
-
-            @Override
-            public boolean showDuringKeyguard() {
-                return true;
-            }
-
-            @Override
-            public boolean showBeforeProvisioning() {
-                return true;
-            }
-        };
-    }
-
     private Action getAssistAction() {
         return new SinglePressAction(R.drawable.ic_action_assist_focused,
                 R.string.global_action_assist) {
@@ -931,9 +939,9 @@
         }
 
         @Override
-        public ArrayList<Action> getSeparatedItems(boolean shouldUseSeparatedView) {
+        public ArrayList<Action> getSeparatedItems() {
             ArrayList<Action> separatedActions = new ArrayList<Action>();
-            if (!shouldUseSeparatedView) {
+            if (!shouldUseSeparatedView()) {
                 return separatedActions;
             }
             for (int i = 0; i < mItems.size(); i++) {
@@ -946,8 +954,8 @@
         }
 
         @Override
-        public ArrayList<Action> getListItems(boolean shouldUseSeparatedView) {
-            if (!shouldUseSeparatedView) {
+        public ArrayList<Action> getListItems() {
+            if (!shouldUseSeparatedView()) {
                 return new ArrayList<Action>(mItems);
             }
             ArrayList<Action> listActions = new ArrayList<Action>();
@@ -1491,21 +1499,19 @@
         private final Context mContext;
         private final MyAdapter mAdapter;
         private MultiListLayout mGlobalActionsLayout;
-        private final Drawable mBackgroundDrawable;
+        private Drawable mBackgroundDrawable;
         private final ColorExtractor mColorExtractor;
         private final GlobalActionsPanelPlugin.PanelViewController mPanelController;
         private boolean mKeyguardShowing;
-        private boolean mUseSeparatedList;
         private boolean mShowing;
-        private final float mScrimAlpha;
+        private float mScrimAlpha;
 
-        ActionsDialog(Context context, MyAdapter adapter, boolean separated,
+        ActionsDialog(Context context, MyAdapter adapter,
                 GlobalActionsPanelPlugin.PanelViewController plugin) {
             super(context, com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActions);
             mContext = context;
             mAdapter = adapter;
             mColorExtractor = Dependency.get(SysuiColorExtractor.class);
-            mUseSeparatedList = separated;
 
             // Window initialization
             Window window = getWindow();
@@ -1525,51 +1531,38 @@
                     | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                     | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
             window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
-
-            initializeLayout();
-
             setTitle(R.string.global_actions);
 
             mPanelController = plugin;
-            View panelView = initializePanel();
-            if (panelView == null) {
-                mBackgroundDrawable = new GradientDrawable(context);
-                mScrimAlpha = ScrimController.GRADIENT_SCRIM_ALPHA;
-            } else {
-                mBackgroundDrawable = context.getDrawable(
-                        com.android.systemui.R.drawable.global_action_panel_scrim);
-                mScrimAlpha = 1f;
-                addContentView(
-                        panelView,
-                        new ViewGroup.LayoutParams(
-                                ViewGroup.LayoutParams.MATCH_PARENT,
-                                ViewGroup.LayoutParams.MATCH_PARENT));
-            }
-            window.setBackgroundDrawable(mBackgroundDrawable);
+            initializeLayout();
         }
 
-        private View initializePanel() {
-            if (isPanelEnabled(mContext) && mPanelController != null) {
-                View panelView = mPanelController.getPanelContent();
-                if (panelView != null) {
-                    FrameLayout panelContainer = new FrameLayout(mContext);
-                    FrameLayout.LayoutParams panelParams =
-                            new FrameLayout.LayoutParams(
-                                    FrameLayout.LayoutParams.MATCH_PARENT,
-                                    FrameLayout.LayoutParams.WRAP_CONTENT);
-                    panelContainer.addView(panelView, panelParams);
-                    return panelContainer;
-                }
+        private boolean initializePanel() {
+            if (!isPanelEnabled(mContext) || mPanelController == null) {
+                return false;
             }
-            return null;
+            View panelView = mPanelController.getPanelContent();
+            if (panelView == null) {
+                return false;
+            }
+            FrameLayout panelContainer = new FrameLayout(mContext);
+            FrameLayout.LayoutParams panelParams =
+                    new FrameLayout.LayoutParams(
+                            FrameLayout.LayoutParams.MATCH_PARENT,
+                            FrameLayout.LayoutParams.WRAP_CONTENT);
+            panelContainer.addView(panelView, panelParams);
+            addContentView(
+                    panelContainer,
+                    new ViewGroup.LayoutParams(
+                            ViewGroup.LayoutParams.MATCH_PARENT,
+                            ViewGroup.LayoutParams.MATCH_PARENT));
+            return true;
         }
 
         private void initializeLayout() {
             setContentView(getGlobalActionsLayoutId(mContext));
-            mGlobalActionsLayout = (MultiListLayout)
-                    findViewById(com.android.systemui.R.id.global_actions_view);
+            mGlobalActionsLayout = findViewById(com.android.systemui.R.id.global_actions_view);
             mGlobalActionsLayout.setOutsideTouchListener(view -> dismiss());
-            mGlobalActionsLayout.setSeparated(mUseSeparatedList);
             mGlobalActionsLayout.setListViewAccessibilityDelegate(new View.AccessibilityDelegate() {
                 @Override
                 public boolean dispatchPopulateAccessibilityEvent(
@@ -1581,11 +1574,18 @@
             });
             mGlobalActionsLayout.setRotationListener(this::onRotate);
             mGlobalActionsLayout.setAdapter(mAdapter);
-        }
 
-        private boolean isPanelEnabled(Context context) {
-            return FeatureFlagUtils.isEnabled(
-                    context, FeatureFlagUtils.GLOBAL_ACTIONS_PANEL_ENABLED);
+            boolean panelEnabled = initializePanel();
+            if (!panelEnabled) {
+                mBackgroundDrawable = new GradientDrawable(mContext);
+                mScrimAlpha = ScrimController.GRADIENT_SCRIM_ALPHA;
+            } else {
+                mBackgroundDrawable = mContext.getDrawable(
+                        com.android.systemui.R.drawable.global_action_panel_scrim);
+                mScrimAlpha = 1f;
+            }
+            mGlobalActionsLayout.setSnapToEdge(panelEnabled);
+            getWindow().setBackgroundDrawable(mBackgroundDrawable);
         }
 
         private int getGlobalActionsLayoutId(Context context) {
@@ -1691,6 +1691,9 @@
         void dismissImmediately() {
             super.dismiss();
             mShowing = false;
+            if (mPanelController != null) {
+                mPanelController.onDismissed();
+            }
         }
 
         private float getAnimTranslation() {
@@ -1726,9 +1729,25 @@
     }
 
     /**
-     * Determines whether or not the Global Actions Dialog should use the newer grid-style layout.
+     * Determines whether or not the Global Actions menu should use the newer grid-style layout.
      */
-    public static boolean isGridEnabled(Context context) {
+    private static boolean isGridEnabled(Context context) {
         return FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.GLOBAL_ACTIONS_GRID_ENABLED);
     }
+
+    /**
+     * Determines whether or not the Global Actions Panel should appear when the power button
+     * is held.
+     */
+    private static boolean isPanelEnabled(Context context) {
+        return FeatureFlagUtils.isEnabled(
+                context, FeatureFlagUtils.GLOBAL_ACTIONS_PANEL_ENABLED);
+    }
+
+    /**
+     * Determines whether the Global Actions menu should use a separated view for emergency actions.
+     */
+    private static boolean shouldUseSeparatedView() {
+        return true;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java
index cda7669..9a0759c 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.text.TextUtils;
 import android.util.AttributeSet;
+import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
 
@@ -41,11 +42,16 @@
     }
 
     private void setBackgrounds() {
+        int gridBackgroundColor = getResources().getColor(
+                com.android.systemui.R.color.global_actions_grid_background, null);
+        int separatedBackgroundColor = getResources().getColor(
+                com.android.systemui.R.color.global_actions_separated_background, null);
         HardwareBgDrawable listBackground  = new HardwareBgDrawable(true, true, getContext());
-        HardwareBgDrawable separatedViewBackground = new HardwareBgDrawable(true, true,
-                getContext());
+        HardwareBgDrawable separatedBackground = new HardwareBgDrawable(true, true, getContext());
+        listBackground.setTint(gridBackgroundColor);
+        separatedBackground.setTint(separatedBackgroundColor);
         getListView().setBackground(listBackground);
-        getSeparatedView().setBackground(separatedViewBackground);
+        getSeparatedView().setBackground(separatedBackground);
     }
 
     @Override
@@ -71,10 +77,10 @@
 
     @Override
     public void onUpdateList() {
-        removeAllItems();
+        super.onUpdateList();
         ArrayList<GlobalActionsDialog.Action> separatedActions =
-                mAdapter.getSeparatedItems(mSeparated);
-        ArrayList<GlobalActionsDialog.Action> listActions = mAdapter.getListItems(mSeparated);
+                mAdapter.getSeparatedItems();
+        ArrayList<GlobalActionsDialog.Action> listActions = mAdapter.getListItems();
         setExpectedListItemCount(listActions.size());
         int rotation = RotationUtils.getRotation(mContext);
 
@@ -108,6 +114,7 @@
                 parent.addView(v);
             }
         }
+        updateSnapPosition();
     }
 
     @Override
@@ -115,6 +122,19 @@
         return findViewById(com.android.systemui.R.id.separated_button);
     }
 
+    private void updateSnapPosition() {
+        if (mSnapToEdge) {
+            setPadding(0, 0, 0, 0);
+            if (mRotation == RotationUtils.ROTATION_LANDSCAPE) {
+                setGravity(Gravity.RIGHT);
+            } else if (mRotation == RotationUtils.ROTATION_SEASCAPE) {
+                setGravity(Gravity.LEFT);
+            } else {
+                setGravity(Gravity.BOTTOM);
+            }
+        }
+    }
+
     @Override
     protected ListGridLayout getListView() {
         return findViewById(android.R.id.list);
@@ -148,7 +168,7 @@
     }
 
     /**
-     * Not used in this implementation of the Global Actions Menu, but necessary for some others.
+     * Not ued in this implementation of the Global Actions Menu, but necessary for some others.
      */
     @Override
     public void setDivisionView(View v) {
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
index 19a7cea..4cf58b7 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
@@ -37,8 +37,10 @@
 import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.plugins.GlobalActions;
+import com.android.systemui.plugins.GlobalActionsPanelPlugin;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.ExtensionController;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
 
 public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks {
@@ -48,6 +50,7 @@
     private final Context mContext;
     private final KeyguardMonitor mKeyguardMonitor;
     private final DeviceProvisionedController mDeviceProvisionedController;
+    private final ExtensionController.Extension<GlobalActionsPanelPlugin> mPanelExtension;
     private GlobalActionsDialog mGlobalActions;
     private boolean mDisabled;
 
@@ -56,6 +59,10 @@
         mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
         mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
         SysUiServiceProvider.getComponent(context, CommandQueue.class).addCallback(this);
+        mPanelExtension = Dependency.get(ExtensionController.class)
+                .newExtension(GlobalActionsPanelPlugin.class)
+                .withPlugin(GlobalActionsPanelPlugin.class)
+                .build();
     }
 
     @Override
@@ -74,7 +81,8 @@
             mGlobalActions = new GlobalActionsDialog(mContext, manager);
         }
         mGlobalActions.showDialog(mKeyguardMonitor.isShowing(),
-                mDeviceProvisionedController.isDeviceProvisioned());
+                mDeviceProvisionedController.isDeviceProvisioned(),
+                mPanelExtension.get());
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/ListGridLayout.java b/packages/SystemUI/src/com/android/systemui/globalactions/ListGridLayout.java
index 6c106df..048f801 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/ListGridLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/ListGridLayout.java
@@ -114,7 +114,7 @@
         if (mExpectedCount == 3) {
             return 1;
         }
-        return (int) Math.ceil(Math.sqrt(mExpectedCount));
+        return (int) Math.round(Math.sqrt(mExpectedCount));
     }
 
     private int getColumnCount() {
@@ -122,6 +122,6 @@
         if (mExpectedCount == 3) {
             return 3;
         }
-        return (int) Math.round(Math.sqrt(mExpectedCount));
+        return (int) Math.ceil(Math.sqrt(mExpectedCount));
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
index 15dc43f..23742c0 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
@@ -17,9 +17,9 @@
 import android.content.Context
 import android.util.AttributeSet
 import android.view.ViewGroup
+import android.widget.FrameLayout
 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.statusbar.policy.KeyguardMonitor
@@ -42,9 +42,8 @@
     private val sidePadding =
             context.resources.getDimensionPixelSize(R.dimen.ongoing_appops_chip_side_padding)
     private val backgroundDrawable = context.getDrawable(R.drawable.privacy_chip_bg)
-    private lateinit var text: TextView
     private lateinit var iconsContainer: LinearLayout
-    private lateinit var back: LinearLayout
+    private lateinit var back: FrameLayout
     var expanded = false
         set(value) {
             if (value != field) {
@@ -66,14 +65,14 @@
         super.onFinishInflate()
 
         back = findViewById(R.id.background)
-        text = findViewById(R.id.text_container)
         iconsContainer = findViewById(R.id.icons_container)
     }
 
     // Should only be called if the builder icons or app changed
     private fun updateView() {
         back.background = if (expanded) backgroundDrawable else null
-        back.setPaddingRelative(0, 0, if (expanded) sidePadding else 0, 0)
+        val padding = if (expanded) sidePadding else 0
+        back.setPaddingRelative(padding, 0, padding, 0)
         fun setIcons(dialogBuilder: PrivacyDialogBuilder, iconsContainer: ViewGroup) {
             iconsContainer.removeAllViews()
             dialogBuilder.generateIcons().forEachIndexed { i, it ->
@@ -95,44 +94,17 @@
         if (!privacyList.isEmpty()) {
             generateContentDescription()
             setIcons(builder, iconsContainer)
-            setApplicationText()
         } else {
-            text.visibility = GONE
             iconsContainer.removeAllViews()
         }
         requestLayout()
     }
 
-    private fun setApplicationText() {
-        text.visibility = if (builder.types.size == 1 && expanded) VISIBLE else GONE
-        if (builder.types.size == 1 && expanded) {
-            if (builder.app != null && !amISecure()) {
-                text.setText(builder.app?.applicationName)
-            } else {
-                text.text = context.resources.getQuantityString(
-                        R.plurals.ongoing_privacy_chip_multiple_apps,
-                        builder.appsAndTypes.size, builder.appsAndTypes.size)
-            }
-        }
-    }
-
     private fun amISecure() = keyguardMonitor.isShowing && keyguardMonitor.isSecure
 
     private fun generateContentDescription() {
         val typesText = builder.joinTypes()
-        if (builder.types.size > 1) {
-            contentDescription = context.getString(
-                    R.string.ongoing_privacy_chip_content_multiple_apps, typesText)
-        } else {
-            if (builder.app != null && !amISecure()) {
-                contentDescription =
-                        context.getString(R.string.ongoing_privacy_chip_content_single_app,
-                                builder.app?.applicationName, typesText)
-            } else {
-                contentDescription = context.resources.getQuantityString(
-                        R.plurals.ongoing_privacy_chip_content_multiple_apps_single_op,
-                        builder.appsAndTypes.size, builder.appsAndTypes.size, typesText)
-            }
-        }
+        contentDescription = context.getString(
+                R.string.ongoing_privacy_chip_content_multiple_apps, typesText)
     }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt
index bbea6b2..59b3c34 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt
@@ -22,7 +22,6 @@
 
     val appsAndTypes: List<Pair<PrivacyApplication, List<PrivacyType>>>
     val types: List<PrivacyType>
-    val app: PrivacyApplication?
     private val separator = context.getString(R.string.ongoing_privacy_dialog_separator)
     private val lastSeparator = context.getString(R.string.ongoing_privacy_dialog_last_separator)
 
@@ -32,8 +31,6 @@
                 .sortedWith(compareBy({ -it.second.size }, // Sort by number of AppOps
                         { it.second.min() })) // Sort by "smallest" AppOpp (Location is largest)
         types = itemsList.map { it.privacyType }.distinct().sorted()
-        val singleApp = appsAndTypes.size == 1
-        app = if (singleApp) appsAndTypes[0].first else null
     }
 
     fun generateIconsForApp(types: List<PrivacyType>): List<Drawable> {
@@ -58,11 +55,7 @@
     }
 
     fun getDialogTitle(): String {
-        if (app != null) {
-            return context.getString(R.string.ongoing_privacy_dialog_single_app_title, joinTypes())
-        } else {
-            return context.getString(R.string.ongoing_privacy_dialog_multiple_apps_title,
+        return context.getString(R.string.ongoing_privacy_dialog_multiple_apps_title,
                     joinTypes())
-        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index aa972e3..8e77851 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -127,12 +127,12 @@
     @Override
     public void onTuningChanged(String key, String newValue) {
         if (ALLOW_FANCY_ANIMATION.equals(key)) {
-            mAllowFancy = newValue == null || Integer.parseInt(newValue) != 0;
+            mAllowFancy = TunerService.parseIntegerSwitch(newValue, true);
             if (!mAllowFancy) {
                 clearAnimationState();
             }
         } else if (MOVE_FULL_ROWS.equals(key)) {
-            mFullRows = newValue == null || Integer.parseInt(newValue) != 0;
+            mFullRows = TunerService.parseIntegerSwitch(newValue, true);
         } else if (QuickQSPanel.NUM_QUICK_TILES.equals(key)) {
             mNumQuickTiles = mQuickQsPanel.getNumQuickTiles(mQs.getContext());
             clearAnimationState();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 3c3dfb1..b93f8d04 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -183,7 +183,7 @@
     }
 
     private void updateViewVisibilityForTuningValue(View view, @Nullable String newValue) {
-        view.setVisibility(newValue == null || Integer.parseInt(newValue) != 0 ? VISIBLE : GONE);
+        view.setVisibility(TunerService.parseIntegerSwitch(newValue, true) ? VISIBLE : GONE);
     }
 
     public void openDetails(String subPanel) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index 305fbf2..b135f7b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -159,8 +159,8 @@
             mBindTryCount++;
             try {
                 mIsBound = mContext.bindServiceAsUser(mIntent, this,
-                        Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
-                        mUser);
+                        Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE
+                        | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS, mUser);
             } catch (SecurityException e) {
                 Log.e(TAG, "Failed to bind to service", e);
                 mIsBound = false;
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 b7e07f8..5e6f18e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -20,14 +20,12 @@
 import android.content.ComponentName;
 import android.content.Intent;
 import android.os.UserManager;
-import android.provider.Settings.Global;
 import android.service.quicksettings.Tile;
 import android.widget.Switch;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
-import com.android.systemui.plugins.qs.QSTile.AirplaneBooleanState;
-import com.android.systemui.qs.GlobalSetting;
+import com.android.systemui.plugins.qs.QSTile.BooleanState;
 import com.android.systemui.qs.QSHost;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.statusbar.policy.DataSaverController;
@@ -36,7 +34,7 @@
 import javax.inject.Inject;
 
 /** Quick settings tile: Hotspot **/
-public class HotspotTile extends QSTileImpl<AirplaneBooleanState> {
+public class HotspotTile extends QSTileImpl<BooleanState> {
     private static final Intent TETHER_SETTINGS = new Intent().setComponent(new ComponentName(
             "com.android.settings", "com.android.settings.TetherSettings"));
 
@@ -46,7 +44,6 @@
     private final DataSaverController mDataSaverController;
 
     private final HotspotAndDataSaverCallbacks mCallbacks = new HotspotAndDataSaverCallbacks();
-    private final GlobalSetting mAirplaneMode;
     private boolean mListening;
 
     @Inject
@@ -55,12 +52,6 @@
         super(host);
         mHotspotController = hotspotController;
         mDataSaverController = dataSaverController;
-        mAirplaneMode = new GlobalSetting(mContext, mHandler, Global.AIRPLANE_MODE_ON) {
-            @Override
-            protected void handleValueChanged(int value) {
-                refreshState();
-            }
-        };
         mHotspotController.observe(this, mCallbacks);
         mDataSaverController.observe(this, mCallbacks);
     }
@@ -76,18 +67,12 @@
     }
 
     @Override
-    public AirplaneBooleanState newTileState() {
-        return new AirplaneBooleanState();
-    }
-
-    @Override
     public void handleSetListening(boolean listening) {
         if (mListening == listening) return;
         mListening = listening;
         if (listening) {
             refreshState();
         }
-        mAirplaneMode.setListening(listening);
     }
 
     @Override
@@ -96,10 +81,14 @@
     }
 
     @Override
+    public BooleanState newTileState() {
+        return new BooleanState();
+    }
+
+    @Override
     protected void handleClick() {
         final boolean isEnabled = mState.value;
-        if (!isEnabled &&
-                (mAirplaneMode.getValue() != 0 || mDataSaverController.isDataSaverEnabled())) {
+        if (!isEnabled && mDataSaverController.isDataSaverEnabled()) {
             return;
         }
         // Immediately enter transient enabling state when turning hotspot on.
@@ -113,7 +102,7 @@
     }
 
     @Override
-    protected void handleUpdateState(AirplaneBooleanState state, Object arg) {
+    protected void handleUpdateState(BooleanState state, Object arg) {
         final boolean transientEnabling = arg == ARG_SHOW_TRANSIENT_ENABLING;
         if (state.slash == null) {
             state.slash = new SlashState();
@@ -138,7 +127,6 @@
 
         state.icon = mEnabledStatic;
         state.label = mContext.getString(R.string.quick_settings_hotspot_label);
-        state.isAirplaneMode = mAirplaneMode.getValue() != 0;
         state.isTransient = isTransient;
         state.slash.isSlashed = !state.value && !state.isTransient;
         if (state.isTransient) {
@@ -147,7 +135,7 @@
         state.expandedAccessibilityClassName = Switch.class.getName();
         state.contentDescription = state.label;
 
-        final boolean isTileUnavailable = (state.isAirplaneMode || isDataSaverEnabled);
+        final boolean isTileUnavailable = isDataSaverEnabled;
         final boolean isTileActive = (state.value || state.isTransient);
 
         if (isTileUnavailable) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 4da8ca2..9219594 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -107,6 +107,7 @@
     private IOverviewProxy mOverviewProxy;
     private int mConnectionBackoffAttempts;
     private @InteractionType int mInteractionFlags;
+    private boolean mBound;
     private boolean mIsEnabled;
     private int mCurrentBoundedUserId = -1;
     private float mBackButtonAlpha;
@@ -510,16 +511,15 @@
         mHandler.removeCallbacks(mConnectionRunnable);
         Intent launcherServiceIntent = new Intent(ACTION_QUICKSTEP)
                 .setPackage(mRecentsComponentName.getPackageName());
-        boolean bound = false;
         try {
-            bound = mContext.bindServiceAsUser(launcherServiceIntent,
+            mBound = mContext.bindServiceAsUser(launcherServiceIntent,
                     mOverviewServiceConnection,
                     Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
                     UserHandle.of(mDeviceProvisionedController.getCurrentUser()));
         } catch (SecurityException e) {
             Log.e(TAG_OPS, "Unable to bind because of security error", e);
         }
-        if (bound) {
+        if (mBound) {
             // Ensure that connection has been established even if it thinks it is bound
             mHandler.postDelayed(mDeferredConnectionCallback, DEFERRED_CALLBACK_MILLIS);
         } else {
@@ -573,9 +573,14 @@
     }
 
     private void disconnectFromLauncherService() {
+        if (mBound) {
+            // Always unbind the service (ie. if called through onNullBinding or onBindingDied)
+            mContext.unbindService(mOverviewServiceConnection);
+            mBound = false;
+        }
+
         if (mOverviewProxy != null) {
             mOverviewProxy.asBinder().unlinkToDeath(mOverviewServiceDeathRcpt, 0);
-            mContext.unbindService(mOverviewServiceConnection);
             mOverviewProxy = null;
             notifyBackButtonAlphaChanged(1f, false /* animate */);
             notifyConnectionChanged();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index dfbb32e..8faeb15 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -664,6 +664,9 @@
         public void onBiometricRunningStateChanged(boolean running,
                 BiometricSourceType biometricSourceType) {
             if (running) {
+                // Let's hide any previous messages when authentication starts, otherwise
+                // multiple auth attempts would overlap.
+                hideTransientIndication();
                 mMessageToShowOnScreenOn = null;
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
index 311bf7a..c2da517 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
@@ -79,6 +79,8 @@
         mDismissButton.setContentDescription(
                 mContext.getString(R.string.accessibility_clear_all));
         mManageButton.setText(R.string.manage_notifications_text);
+        mManageButton.setContentDescription(
+                mContext.getString(R.string.accessibility_manage_notification));
     }
 
     public boolean isButtonVisible() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index fea01ef..54bdaa2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -122,11 +122,22 @@
     }
 
     /**
-     * Sends an intent to open the app settings for a particular package and optional
+     * Sends an intent to open the notification settings for a particular package and optional
      * channel.
      */
     private void startAppNotificationSettingsActivity(String packageName, final int appUid,
             final NotificationChannel channel, ExpandableNotificationRow row) {
+        final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
+        intent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName);
+        intent.putExtra(Settings.EXTRA_APP_UID, appUid);
+        if (channel != null) {
+            intent.putExtra(EXTRA_FRAGMENT_ARG_KEY, channel.getId());
+        }
+        mNotificationActivityStarter.startNotificationGutsIntent(intent, appUid, row);
+    }
+
+    private void startAppDetailsSettingsActivity(String packageName, final int appUid,
+            final NotificationChannel channel, ExpandableNotificationRow row) {
         final Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
         intent.setData(Uri.fromParts("package", packageName, null));
         intent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName);
@@ -141,7 +152,7 @@
             ExpandableNotificationRow row) {
         if (ops.contains(OP_SYSTEM_ALERT_WINDOW)) {
             if (ops.contains(OP_CAMERA) || ops.contains(OP_RECORD_AUDIO)) {
-                startAppNotificationSettingsActivity(pkg, uid, null, row);
+                startAppDetailsSettingsActivity(pkg, uid, null, row);
             } else {
                 Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
                 intent.setData(Uri.fromParts("package", pkg, null));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index de0e194..9844d8e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -37,7 +37,6 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.ScreenDecorations;
-import com.android.systemui.bubbles.BubbleController;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.StatusBarState;
@@ -57,14 +56,14 @@
  * A implementation of HeadsUpManager for phone and car.
  */
 public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
-        ViewTreeObserver.OnComputeInternalInsetsListener, VisualStabilityManager.Callback,
-        OnHeadsUpChangedListener, ConfigurationController.ConfigurationListener, StateListener {
+        VisualStabilityManager.Callback, OnHeadsUpChangedListener,
+        ConfigurationController.ConfigurationListener, StateListener {
     private static final String TAG = "HeadsUpManagerPhone";
 
     private final View mStatusBarWindowView;
     private final NotificationGroupManager mGroupManager;
-    private final StatusBar mBar;
     private final VisualStabilityManager mVisualStabilityManager;
+    private final StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
     private boolean mReleaseOnExpandFinish;
 
     private int mStatusBarHeight;
@@ -78,13 +77,9 @@
     private boolean mIsExpanded;
     private int[] mTmpTwoArray = new int[2];
     private boolean mHeadsUpGoingAway;
-    private boolean mWaitingOnCollapseWhenGoingAway;
-    private boolean mBubbleGoingAway;
-    private boolean mIsObserving;
     private int mStatusBarState;
 
     private AnimationStateHandler mAnimationStateHandler;
-    private BubbleController mBubbleController = Dependency.get(BubbleController.class);
 
     private final Pools.Pool<HeadsUpEntryPhone> mEntryPool = new Pools.Pool<HeadsUpEntryPhone>() {
         private Stack<HeadsUpEntryPhone> mPoolObjects = new Stack<>();
@@ -107,14 +102,17 @@
     ///////////////////////////////////////////////////////////////////////////////////////////////
     //  Constructor:
 
-    public HeadsUpManagerPhone(@NonNull final Context context, @NonNull View statusBarWindowView,
-            @NonNull NotificationGroupManager groupManager, @NonNull StatusBar bar,
-            @NonNull VisualStabilityManager visualStabilityManager) {
+    public HeadsUpManagerPhone(@NonNull final Context context,
+                               @NonNull View statusBarWindowView,
+                               @NonNull NotificationGroupManager groupManager,
+                               @NonNull StatusBar bar,
+                               @NonNull VisualStabilityManager visualStabilityManager) {
         super(context);
 
         mStatusBarWindowView = statusBarWindowView;
+        mStatusBarTouchableRegionManager = new StatusBarTouchableRegionManager(context, this, bar,
+                statusBarWindowView);
         mGroupManager = groupManager;
-        mBar = bar;
         mVisualStabilityManager = visualStabilityManager;
 
         initResources();
@@ -125,16 +123,10 @@
                 if (Log.isLoggable(TAG, Log.WARN)) {
                     Log.w(TAG, "onHeadsUpPinnedModeChanged");
                 }
-                updateTouchableRegionListener();
+                mStatusBarTouchableRegionManager.updateTouchableRegion();
             }
         });
         Dependency.get(StatusBarStateController.class).addCallback(this);
-        mBubbleController.setBubbleStateChangeListener((hasBubbles) -> {
-            if (!hasBubbles) {
-                mBubbleGoingAway = true;
-            }
-            updateTouchableRegionListener();
-        });
     }
 
     public void setAnimationStateHandler(AnimationStateHandler handler) {
@@ -209,14 +201,10 @@
         if (isExpanded != mIsExpanded) {
             mIsExpanded = isExpanded;
             if (isExpanded) {
-                // make sure our state is sane
-                mWaitingOnCollapseWhenGoingAway = false;
                 mHeadsUpGoingAway = false;
-                updateTouchableRegionListener();
             }
-            if (mBubbleController.hasBubbles() || !mIsExpanded) {
-                updateTouchableRegionListener();
-            }
+            mStatusBarTouchableRegionManager.setIsStatusBarExpanded(isExpanded);
+            mStatusBarTouchableRegionManager.updateTouchableRegion();
         }
     }
 
@@ -233,15 +221,21 @@
         if (headsUpGoingAway != mHeadsUpGoingAway) {
             mHeadsUpGoingAway = headsUpGoingAway;
             if (!headsUpGoingAway) {
-                waitForStatusBarLayout();
+                mStatusBarTouchableRegionManager.updateTouchableRegionAfterLayout();
+            } else {
+                mStatusBarTouchableRegionManager.updateTouchableRegion();
             }
-            updateTouchableRegionListener();
         }
     }
 
+    public boolean isHeadsUpGoingAway() {
+        return mHeadsUpGoingAway;
+    }
+
     /**
      * Notifies that a remote input textbox in notification gets active or inactive.
-     * @param entry The entry of the target notification.
+     *
+     * @param entry             The entry of the target notification.
      * @param remoteInputActive True to notify active, False to notify inactive.
      */
     public void setRemoteInputActive(
@@ -295,23 +289,23 @@
         dumpInternal(fd, pw, args);
     }
 
-    ///////////////////////////////////////////////////////////////////////////////////////////////
-    //  ViewTreeObserver.OnComputeInternalInsetsListener overrides:
-
     /**
-     * Overridden from TreeObserver.
+     * Update touch insets to include any area needed for touching a heads up notification.
+     *
+     * @param info Insets that will include heads up notification touch area after execution.
      */
-    @Override
-    public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) {
-        if (mIsExpanded || mBar.isBouncerShowing()) {
-            // The touchable region is always the full area when expanded
-            return;
-        }
-        if (hasPinnedHeadsUp()) {
+    @Nullable
+    public void updateTouchableRegion(ViewTreeObserver.InternalInsetsInfo info) {
+        info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
+
+        if (!hasPinnedHeadsUp()) {
+            info.touchableRegion.set(0, 0, mStatusBarWindowView.getWidth(), mStatusBarHeight);
+            updateRegionForNotch(info.touchableRegion);
+        } else {
             NotificationEntry topEntry = getTopEntry();
             if (topEntry.isChildInGroup()) {
-                final NotificationEntry groupSummary
-                        = mGroupManager.getGroupSummary(topEntry.notification);
+                final NotificationEntry groupSummary =
+                        mGroupManager.getGroupSummary(topEntry.notification);
                 if (groupSummary != null) {
                     topEntry = groupSummary;
                 }
@@ -321,23 +315,8 @@
             int minX = mTmpTwoArray[0];
             int maxX = mTmpTwoArray[0] + topRow.getWidth();
             int height = topRow.getIntrinsicHeight();
-
-            info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
             info.touchableRegion.set(minX, 0, maxX, mHeadsUpInset + height);
-        } else {
-            setCollapsedTouchableInsets(info);
         }
-        Rect r = mBubbleController.getTouchableRegion();
-        if (r != null) {
-            info.touchableRegion.union(r);
-        }
-        mBubbleGoingAway = false;
-    }
-
-    private void setCollapsedTouchableInsets(ViewTreeObserver.InternalInsetsInfo info) {
-        info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
-        info.touchableRegion.set(0, 0, mStatusBarWindowView.getWidth(), mStatusBarHeight);
-        updateRegionForNotch(info.touchableRegion);
     }
 
     private void updateRegionForNotch(Region region) {
@@ -364,9 +343,7 @@
 
     @Override
     public void onConfigChanged(Configuration newConfig) {
-        Resources resources = mContext.getResources();
-        mStatusBarHeight = resources.getDimensionPixelSize(
-                com.android.internal.R.dimen.status_bar_height);
+        initResources();
     }
 
     ///////////////////////////////////////////////////////////////////////////////////////////////
@@ -401,14 +378,15 @@
 
     @Override
     protected boolean shouldHeadsUpBecomePinned(NotificationEntry entry) {
-          return mStatusBarState != StatusBarState.KEYGUARD && !mIsExpanded
-                  || super.shouldHeadsUpBecomePinned(entry);
+        return mStatusBarState != StatusBarState.KEYGUARD && !mIsExpanded
+                || super.shouldHeadsUpBecomePinned(entry);
     }
 
     @Override
     protected void dumpInternal(FileDescriptor fd, PrintWriter pw, String[] args) {
         super.dumpInternal(fd, pw, args);
-        pw.print("  mBarState="); pw.println(mStatusBarState);
+        pw.print("  mBarState=");
+        pw.println(mStatusBarState);
     }
 
     ///////////////////////////////////////////////////////////////////////////////////////////////
@@ -438,45 +416,6 @@
         return headsUpEntry == null || headsUpEntry != topEntry || super.canRemoveImmediately(key);
     }
 
-    /**
-     * We need to wait on the whole panel to collapse, before we can remove the touchable region
-     * listener.
-     */
-    private void waitForStatusBarLayout() {
-        mWaitingOnCollapseWhenGoingAway = true;
-        mStatusBarWindowView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
-            @Override
-            public void onLayoutChange(View v, int left, int top, int right, int bottom,
-                    int oldLeft,
-                    int oldTop, int oldRight, int oldBottom) {
-                if (mStatusBarWindowView.getHeight() <= mStatusBarHeight) {
-                    mStatusBarWindowView.removeOnLayoutChangeListener(this);
-                    mWaitingOnCollapseWhenGoingAway = false;
-                    updateTouchableRegionListener();
-                }
-            }
-        });
-    }
-
-    // TODO: some kind of TouchableRegionManager to deal with this, HeadsUpManager is not really
-    // the right place
-    private void updateTouchableRegionListener() {
-        boolean shouldObserve = hasPinnedHeadsUp() || mHeadsUpGoingAway
-                || mBubbleController.hasBubbles() || mBubbleGoingAway
-                || mWaitingOnCollapseWhenGoingAway
-                || mStatusBarWindowView.getRootWindowInsets().getDisplayCutout() != null;
-        if (shouldObserve == mIsObserving) {
-            return;
-        }
-        if (shouldObserve) {
-            mStatusBarWindowView.getViewTreeObserver().addOnComputeInternalInsetsListener(this);
-            mStatusBarWindowView.requestLayout();
-        } else {
-            mStatusBarWindowView.getViewTreeObserver().removeOnComputeInternalInsetsListener(this);
-        }
-        mIsObserving = shouldObserve;
-    }
-
     ///////////////////////////////////////////////////////////////////////////////////////////////
     //  HeadsUpEntryPhone:
 
@@ -490,7 +429,7 @@
         }
 
         public void setEntry(@NonNull final NotificationEntry entry) {
-           Runnable removeHeadsUpRunnable = () -> {
+            Runnable removeHeadsUpRunnable = () -> {
                 if (!mVisualStabilityManager.isReorderingAllowed()) {
                     mEntriesToRemoveWhenReorderingAllowed.add(entry);
                     mVisualStabilityManager.addReorderingAllowedCallback(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index e953ad5..c8ce392 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -483,7 +483,9 @@
                 R.color.light_mode_icon_color_single_tone);
         float intensity = textColor == Color.WHITE ? 0 : 1;
         mCarrierLabel.setTextColor(iconColor);
-        mIconManager.setTint(iconColor);
+        if (mIconManager != null) {
+            mIconManager.setTint(iconColor);
+        }
 
         applyDarkness(R.id.battery, mEmptyRect, intensity * (1f - mDarkAmount), iconColor);
         applyDarkness(R.id.clock, mEmptyRect, intensity, iconColor);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
index b7d1fc6..27394d9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -21,6 +21,7 @@
 import android.content.res.TypedArray;
 import android.graphics.Color;
 import android.graphics.PorterDuff;
+import android.graphics.drawable.Animatable2;
 import android.graphics.drawable.AnimatedVectorDrawable;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
@@ -134,6 +135,16 @@
 
             if (animation != null && isAnim) {
                 animation.forceAnimationOnUI();
+                animation.clearAnimationCallbacks();
+                animation.registerAnimationCallback(new Animatable2.AnimationCallback() {
+                    @Override
+                    public void onAnimationEnd(Drawable drawable) {
+                        if (getDrawable() == animation && state == getState()
+                                && doesAnimationLoop(iconAnimRes)) {
+                            animation.start();
+                        }
+                    }
+                });
                 animation.start();
             }
 
@@ -215,6 +226,10 @@
         return mContext.getDrawable(iconRes);
     }
 
+    private boolean doesAnimationLoop(int resourceId) {
+        return resourceId == com.android.internal.R.anim.lock_scanning;
+    }
+
     private static int getAnimationResForTransition(int oldState, int newState,
             boolean wasPulsing, boolean pulsing,
             boolean wasDozing, boolean dozing) {
@@ -236,7 +251,7 @@
             return com.android.internal.R.anim.lock_lock;
         } else if (newState == STATE_SCANNING_FACE) {
             return com.android.internal.R.anim.lock_scanning;
-        } else if (!wasPulsing && pulsing) {
+        } else if (!wasPulsing && pulsing && newState != STATE_LOCK_OPEN) {
             return com.android.internal.R.anim.lock_in;
         }
         return -1;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java
index 409d60f..2d54970 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java
@@ -16,203 +16,159 @@
 
 package com.android.systemui.statusbar.phone;
 
+import static android.view.Display.DEFAULT_DISPLAY;
+
 import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.graphics.Color;
 import android.graphics.Rect;
 import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
 import android.provider.Settings;
-import android.util.DisplayMetrics;
-import android.view.SurfaceControl;
+import android.view.CompositionSamplingListener;
 import android.view.View;
 
-import com.android.systemui.R;
+import java.io.PrintWriter;
 
-public class NavBarTintController {
+/**
+ * Updates the nav bar tint based on the color of the content behind the nav bar.
+ */
+public class NavBarTintController implements View.OnAttachStateChangeListener,
+        View.OnLayoutChangeListener {
+
     public static final int MIN_COLOR_ADAPT_TRANSITION_TIME = 400;
     public static final int DEFAULT_COLOR_ADAPT_TRANSITION_TIME = 1700;
 
-    private final HandlerThread mColorAdaptHandlerThread = new HandlerThread("ColorExtractThread");
-    private Handler mColorAdaptionHandler;
-
-    // Poll time for each iteration to color sample
-    private static final int COLOR_ADAPTION_TIMEOUT = 300;
-
     // Passing the threshold of this luminance value will make the button black otherwise white
     private static final float LUMINANCE_THRESHOLD = 0.3f;
 
-    // The margin from the bounds of the view to color sample around
-    private static final int COLOR_SAMPLE_MARGIN = 10;
-
-    private boolean mRunning;
-
+    private final Handler mHandler = new Handler();
     private final NavigationBarView mNavigationBarView;
     private final LightBarTransitionsController mLightBarController;
-    private final Handler mMainHandler = new Handler(Looper.getMainLooper());
-    private final int mBarRadius;
-    private final int mBarBottom;
+
+    private final CompositionSamplingListener mSamplingListener;
+    private final Runnable mUpdateSamplingListener = this::updateSamplingListener;
+    private final Rect mSamplingBounds = new Rect();
+    private boolean mSamplingEnabled = false;
+    private boolean mSamplingListenerRegistered = false;
+
+    private float mLastMediaLuma;
+    private boolean mUpdateOnNextDraw;
 
     public NavBarTintController(NavigationBarView navigationBarView,
             LightBarTransitionsController lightBarController) {
+        mSamplingListener = new CompositionSamplingListener(
+                navigationBarView.getContext().getMainExecutor()) {
+            @Override
+            public void onSampleCollected(float medianLuma) {
+                updateTint(medianLuma);
+            }
+        };
         mNavigationBarView = navigationBarView;
+        mNavigationBarView.addOnAttachStateChangeListener(this);
+        mNavigationBarView.addOnLayoutChangeListener(this);
         mLightBarController = lightBarController;
-
-        final Resources res = navigationBarView.getResources();
-        mBarRadius = res.getDimensionPixelSize(R.dimen.navigation_handle_radius);
-        mBarBottom = res.getDimensionPixelSize(R.dimen.navigation_handle_bottom);
     }
 
-    public void start() {
+    void onDraw() {
+        if (mUpdateOnNextDraw) {
+            mUpdateOnNextDraw = false;
+            requestUpdateSamplingListener();
+        }
+    }
+
+    void start() {
         if (!isEnabled(mNavigationBarView.getContext())) {
             return;
         }
-        if (mColorAdaptionHandler == null) {
-            mColorAdaptHandlerThread.start();
-            mColorAdaptionHandler = new Handler(mColorAdaptHandlerThread.getLooper());
-        }
-        mColorAdaptionHandler.removeCallbacksAndMessages(null);
-        mColorAdaptionHandler.post(this::updateTint);
-        mRunning = true;
+        mSamplingEnabled = true;
+        // Defer calling updateSamplingListener since we may have just reinflated prior to this
+        requestUpdateSamplingListener();
     }
 
-    public void end() {
-        if (mColorAdaptionHandler != null) {
-            mColorAdaptionHandler.removeCallbacksAndMessages(null);
-        }
-        mRunning = false;
+    void stop() {
+        mSamplingEnabled = false;
+        requestUpdateSamplingListener();
     }
 
-    public void stop() {
-        end();
-        if (mColorAdaptionHandler != null) {
-            mColorAdaptHandlerThread.quitSafely();
-        }
+    @Override
+    public void onViewAttachedToWindow(View view) {
+        requestUpdateSamplingListener();
     }
 
-    private void updateTint() {
-        int[] navPos = new int[2];
-        int[] butPos = new int[2];
+    @Override
+    public void onViewDetachedFromWindow(View view) {
+        // Defer calling updateSamplingListener the attach info has not yet been reset
+        requestUpdateSamplingListener();
+    }
+
+    @Override
+    public void onLayoutChange(View v, int left, int top, int right, int bottom,
+            int oldLeft, int oldTop, int oldRight, int oldBottom) {
+        mSamplingBounds.setEmpty();
+        // TODO: Extend this to 2/3 button layout as well
         View view = mNavigationBarView.getHomeHandle().getCurrentView();
-        if (view == null) {
-            return;
+        if (view != null) {
+            int[] pos = new int[2];
+            view.getLocationOnScreen(pos);
+            final Rect samplingBounds = new Rect(pos[0], pos[1],
+                    pos[0] + view.getWidth(), pos[1] + view.getHeight());
+            if (!samplingBounds.equals(mSamplingBounds)) {
+                mSamplingBounds.set(samplingBounds);
+                requestUpdateSamplingListener();
+            }
         }
-
-        // Determine the area of the icon within its view bounds
-        view.getLocationInSurface(butPos);
-        final int navWidth = view.getWidth();
-        final int navHeight = view.getHeight();
-        int viewBottom = butPos[1] + navHeight - mBarBottom;
-        final Rect viewIconRect = new Rect(butPos[0], viewBottom - mBarRadius * 2,
-                butPos[0] + navWidth, viewBottom);
-
-        if (mNavigationBarView.getCurrentView() == null || viewIconRect.isEmpty()) {
-            scheduleColorAdaption();
-            return;
-        }
-        mNavigationBarView.getCurrentView().getLocationOnScreen(navPos);
-        viewIconRect.offset(navPos[0], navPos[1]);
-
-        // Apply a margin area around the button region to sample the colors, crop from screenshot
-        final Rect cropRect = new Rect(viewIconRect);
-        cropRect.inset(-COLOR_SAMPLE_MARGIN, -COLOR_SAMPLE_MARGIN);
-        if (cropRect.isEmpty()) {
-            scheduleColorAdaption();
-            return;
-        }
-
-        // Determine the size of the home area
-        Rect homeArea = new Rect(COLOR_SAMPLE_MARGIN, COLOR_SAMPLE_MARGIN,
-                viewIconRect.width() + COLOR_SAMPLE_MARGIN,
-                viewIconRect.height() + COLOR_SAMPLE_MARGIN);
-
-        // Get the screenshot around the home button icon to determine the color
-        DisplayMetrics mDisplayMetrics = new DisplayMetrics();
-        mNavigationBarView.getContext().getDisplay().getRealMetrics(mDisplayMetrics);
-        final Bitmap hardBitmap = SurfaceControl
-                .screenshot(new Rect(), mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels,
-                        mNavigationBarView.getContext().getDisplay().getRotation());
-        if (hardBitmap != null && cropRect.bottom <= hardBitmap.getHeight()
-                && cropRect.left + cropRect.width() <= hardBitmap.getWidth()) {
-            final Bitmap cropBitmap = Bitmap.createBitmap(hardBitmap, cropRect.left, cropRect.top,
-                    cropRect.width(), cropRect.height());
-            final Bitmap softBitmap = cropBitmap.copy(Config.ARGB_8888, false);
-
-            // Get the luminance value to determine if the home button should be black or white
-            final int[] pixels = new int[softBitmap.getByteCount() / 4];
-            softBitmap.getPixels(pixels, 0, softBitmap.getWidth(), 0, 0, softBitmap.getWidth(),
-                    softBitmap.getHeight());
-            float r = 0, g = 0, blue = 0;
-
-            int width = cropRect.width();
-            int total = 0;
-            for (int i = 0; i < pixels.length; i += 4) {
-                int x = i % width;
-                int y = i / width;
-                if (!homeArea.contains(x, y)) {
-                    r += Color.red(pixels[i]);
-                    g += Color.green(pixels[i]);
-                    blue += Color.blue(pixels[i]);
-                    total++;
-                }
-            }
-
-            r /= total;
-            g /= total;
-            blue /= total;
-
-            r = Math.max(Math.min(r / 255f, 1), 0);
-            g = Math.max(Math.min(g / 255f, 1), 0);
-            blue = Math.max(Math.min(blue / 255f, 1), 0);
-
-            if (r <= 0.03928) {
-                r /= 12.92;
-            } else {
-                r = (float) Math.pow((r + 0.055) / 1.055, 2.4);
-            }
-            if (g <= 0.03928) {
-                g /= 12.92;
-            } else {
-                g = (float) Math.pow((g + 0.055) / 1.055, 2.4);
-            }
-            if (blue <= 0.03928) {
-                blue /= 12.92;
-            } else {
-                blue = (float) Math.pow((blue + 0.055) / 1.055, 2.4);
-            }
-
-            if (r * 0.2126 + g * 0.7152 + blue * 0.0722 > LUMINANCE_THRESHOLD) {
-                // Black
-                mMainHandler.post(
-                        () -> mLightBarController
-                                .setIconsDark(true /* dark */, true /* animate */));
-            } else {
-                // White
-                mMainHandler.post(
-                        () -> mLightBarController
-                                .setIconsDark(false /* dark */, true /* animate */));
-            }
-            cropBitmap.recycle();
-            hardBitmap.recycle();
-        }
-        scheduleColorAdaption();
     }
 
-    private void scheduleColorAdaption() {
-        mColorAdaptionHandler.removeCallbacksAndMessages(null);
-        if (!mRunning || !isEnabled(mNavigationBarView.getContext())) {
-            return;
+    private void requestUpdateSamplingListener() {
+        mHandler.removeCallbacks(mUpdateSamplingListener);
+        mHandler.post(mUpdateSamplingListener);
+    }
+
+    private void updateSamplingListener() {
+        if (mSamplingListenerRegistered) {
+            mSamplingListenerRegistered = false;
+            CompositionSamplingListener.unregister(mSamplingListener);
         }
-        mColorAdaptionHandler.postDelayed(this::updateTint, COLOR_ADAPTION_TIMEOUT);
+        if (mSamplingEnabled && !mSamplingBounds.isEmpty()
+                && mNavigationBarView.isAttachedToWindow()) {
+            if (!mNavigationBarView.getViewRootImpl().getSurfaceControl().isValid()) {
+                // The view may still be attached, but the surface backing the window can be
+                // destroyed, so wait until the next draw to update the listener again
+                mUpdateOnNextDraw = true;
+                return;
+            }
+            mSamplingListenerRegistered = true;
+            CompositionSamplingListener.register(mSamplingListener, DEFAULT_DISPLAY,
+                    mNavigationBarView.getViewRootImpl().getSurfaceControl().getHandle(),
+                    mSamplingBounds);
+        }
+    }
+
+    private void updateTint(float medianLuma) {
+        mLastMediaLuma = medianLuma;
+        if (medianLuma > LUMINANCE_THRESHOLD) {
+            // Black
+            mLightBarController.setIconsDark(true /* dark */, true /* animate */);
+        } else {
+            // White
+            mLightBarController.setIconsDark(false /* dark */, true /* animate */);
+        }
+    }
+
+    void dump(PrintWriter pw) {
+        pw.println("NavBarTintController:");
+        pw.println("  navBar isAttached: " + mNavigationBarView.isAttachedToWindow());
+        pw.println("  navBar isScValid: " + (mNavigationBarView.isAttachedToWindow()
+                ? mNavigationBarView.getViewRootImpl().getSurfaceControl().isValid()
+                : "false"));
+        pw.println("  mSamplingListenerRegistered: " + mSamplingListenerRegistered);
+        pw.println("  mSamplingBounds: " + mSamplingBounds);
+        pw.println("  mLastMediaLuma: " + mLastMediaLuma);
     }
 
     public static boolean isEnabled(Context context) {
-        return Settings.Global.getInt(context.getContentResolver(),
-                NavigationPrototypeController.NAV_COLOR_ADAPT_ENABLE_SETTING, 0) == 1
-            && Settings.Global.getInt(context.getContentResolver(),
-                NavigationPrototypeController.SHOW_HOME_HANDLE_SETTING, 0) == 1;
+        return context.getDisplayId() == DEFAULT_DISPLAY
+                && Settings.Global.getInt(context.getContentResolver(),
+                        NavigationPrototypeController.NAV_COLOR_ADAPT_ENABLE_SETTING, 0) == 1
+                && Settings.Global.getInt(context.getContentResolver(),
+                        NavigationPrototypeController.SHOW_HOME_HANDLE_SETTING, 0) == 1;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java
index 7a42b03..1478a07 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java
@@ -20,7 +20,6 @@
 import android.hardware.input.InputManager;
 import android.os.Handler;
 import android.os.SystemClock;
-import android.view.HapticFeedbackConstants;
 import android.view.InputDevice;
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
@@ -103,7 +102,6 @@
     private void performBack() {
         sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
         sendEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK);
-        mNavigationBarView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
     }
 
     private boolean shouldExecuteBackOnUp() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java
index fcf5893..4c7fdb0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java
@@ -22,6 +22,7 @@
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.PixelFormat;
+import android.os.SystemClock;
 import android.util.FloatProperty;
 import android.util.MathUtils;
 import android.view.Gravity;
@@ -31,6 +32,7 @@
 import android.view.WindowManager;
 
 import com.android.systemui.R;
+import com.android.systemui.shared.system.QuickStepContract;
 
 public class NavigationBarEdgePanel extends View {
     private static final String TAG = "NavigationBarEdgePanel";
@@ -48,6 +50,7 @@
     private static final float START_POINTING_RATIO = 0.3f;
     private static final float POINTEDNESS_BEFORE_SNAP_RATIO = 0.4f;
     private static final int ANIM_DURATION_MS = 150;
+    private static final long HAPTIC_TIMEOUT_MS = 200;
 
     private final Paint mPaint = new Paint();
     private final Paint mProtectionPaint = new Paint();
@@ -65,6 +68,8 @@
     private float mStartY;
     private float mStartX;
 
+    private boolean mDragSlopPassed;
+    private long mLastSlopHapticTime;
     private boolean mGestureDetected;
     private boolean mArrowsPointLeft;
     private float mGestureLength;
@@ -169,6 +174,7 @@
     public boolean onTouchEvent(MotionEvent event) {
         switch (event.getActionMasked()) {
             case MotionEvent.ACTION_DOWN : {
+                mDragSlopPassed = false;
                 show(event.getX(), event.getY());
                 break;
             }
@@ -263,6 +269,13 @@
     private void handleNewSwipePoint(float x) {
         float dist = MathUtils.abs(x - mStartX);
 
+        // Apply a haptic on drag slop passed
+        if (!mDragSlopPassed && dist > QuickStepContract.getQuickStepDragSlopPx()) {
+            mDragSlopPassed = true;
+            performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK);
+            mLastSlopHapticTime = SystemClock.uptimeMillis();
+        }
+
         setDragProgress(MathUtils.constrainedMap(
                 0, 1.0f,
                 0, mGestureLength * TRACK_LENGTH_MULTIPLIER,
@@ -286,7 +299,10 @@
             }
         } else {
             if (!mGestureDetected) {
-                performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK);
+                // Prevent another haptic if it was just used
+                if (SystemClock.uptimeMillis() - mLastSlopHapticTime > HAPTIC_TIMEOUT_MS) {
+                    performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK);
+                }
                 mGestureDetected = true;
 
                 mLegAnimator.setFloatValues(1f);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index b68c7c6..0978901 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -991,7 +991,7 @@
                     }
                 } else {
                     // Screen off disable it
-                    mNavigationBarView.getColorAdaptionController().end();
+                    mNavigationBarView.getColorAdaptionController().stop();
                 }
             }
             if (Intent.ACTION_USER_SWITCHED.equals(action)) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index 2a38f77..faa2ab1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -63,7 +63,6 @@
     public static final String NAVSPACE = "space";
     public static final String CLIPBOARD = "clipboard";
     public static final String HOME_HANDLE = "home_handle";
-    public static final String ASSISTANT_HANDLE = "assistant_handle";
     public static final String KEY = "key";
     public static final String LEFT = "left";
     public static final String RIGHT = "right";
@@ -399,8 +398,6 @@
             v = inflater.inflate(R.layout.contextual, parent, false);
         } else if (HOME_HANDLE.equals(button)) {
             v = inflater.inflate(R.layout.home_handle, parent, false);
-        } else if (ASSISTANT_HANDLE.equals(button)) {
-            v = inflater.inflate(R.layout.assistant_handle, parent, false);
         } else if (button.startsWith(KEY)) {
             String uri = extractImage(button);
             int code = extractKeycode(button);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index b540fb4..18612c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -333,7 +333,7 @@
             if (enabled) {
                 mColorAdaptionController.start();
             } else {
-                mColorAdaptionController.end();
+                mColorAdaptionController.stop();
             }
         }
 
@@ -434,7 +434,6 @@
         mButtonDispatchers.put(R.id.back, new ButtonDispatcher(R.id.back));
         mButtonDispatchers.put(R.id.home, new ButtonDispatcher(R.id.home));
         mButtonDispatchers.put(R.id.home_handle, new ButtonDispatcher(R.id.home_handle));
-        mButtonDispatchers.put(R.id.assistant_handle, new ButtonDispatcher(R.id.assistant_handle));
         mButtonDispatchers.put(R.id.recent_apps, new ButtonDispatcher(R.id.recent_apps));
         mButtonDispatchers.put(R.id.menu, menuButton);
         mButtonDispatchers.put(R.id.ime_switcher, imeSwitcherButton);
@@ -486,6 +485,12 @@
         }
     }
 
+    @Override
+    protected void dispatchDraw(Canvas canvas) {
+        super.dispatchDraw(canvas);
+        mColorAdaptionController.onDraw();
+    }
+
     private void updateNavigationGestures() {
         if (mGestureHelper instanceof QuickStepController) {
             final int[] assignedMap = mPrototypeController.getGestureActionMap();
@@ -632,10 +637,6 @@
         return mButtonDispatchers.get(R.id.home_handle);
     }
 
-    public ButtonDispatcher getAssistantHandle() {
-        return mButtonDispatchers.get(R.id.assistant_handle);
-    }
-
     public SparseArray<ButtonDispatcher> getButtonDispatchers() {
         return mButtonDispatchers;
     }
@@ -990,7 +991,7 @@
         if (visible) {
             mColorAdaptionController.start();
         } else {
-            mColorAdaptionController.end();
+            mColorAdaptionController.stop();
         }
     }
 
@@ -1002,7 +1003,6 @@
     // TODO(b/112934365): move this back to NavigationBarFragment when prototype is removed
     private void updateAssistantAvailability() {
         boolean available = mAssistantAvailable && mPrototypeController.isAssistantGestureEnabled();
-        getAssistantHandle().setVisibility(available ? View.VISIBLE : View.GONE);
         if (mOverviewProxyService.getProxy() != null) {
             try {
                 mOverviewProxyService.getProxy().onAssistantAvailable(available);
@@ -1244,7 +1244,7 @@
         if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
             mColorAdaptionController.start();
         } else {
-            mColorAdaptionController.end();
+            mColorAdaptionController.stop();
         }
     }
 
@@ -1330,7 +1330,6 @@
         Dependency.get(PluginManager.class).addPluginListener(this,
                 NavGesture.class, false /* Only one */);
         setUpSwipeUpOnboarding(isQuickStepSwipeUpEnabled());
-        mColorAdaptionController.start();
 
         if (mPrototypeController.isEnabled()) {
             WindowManager wm = (WindowManager) getContext()
@@ -1363,7 +1362,6 @@
             mGestureHelper.destroy();
         }
         mPrototypeController.unregister();
-        mColorAdaptionController.stop();
         setUpSwipeUpOnboarding(false);
         for (int i = 0; i < mButtonDispatchers.size(); ++i) {
             mButtonDispatchers.valueAt(i).onDestroy();
@@ -1454,6 +1452,7 @@
             mGestureHelper.dump(pw);
         }
         mRecentsOnboarding.dump(pw);
+        mColorAdaptionController.dump(pw);
     }
 
     @Override
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 1e8f67f..253bdfb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -326,6 +326,14 @@
     private int mDisplayId;
     private KeyguardBouncer mBouncer;
 
+    /**
+     * Cache the resource id of the theme to avoid unnecessary work in onThemeChanged.
+     *
+     * onThemeChanged is forced when the theme might not have changed. So, to avoid unncessary
+     * work, check the current id with the cached id.
+     */
+    private int mThemeResId;
+
     @Inject
     public NotificationPanelView(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
             NotificationWakeUpCoordinator coordinator,
@@ -342,6 +350,7 @@
         mCommandQueue = getComponent(context, CommandQueue.class);
         mDisplayId = context.getDisplayId();
         mPulseExpansionHandler = pulseExpansionHandler;
+        mThemeResId = context.getThemeResId();
     }
 
     /**
@@ -390,6 +399,9 @@
         Dependency.get(StatusBarStateController.class).addCallback(this);
         Dependency.get(ZenModeController.class).addCallback(this);
         Dependency.get(ConfigurationController.class).addCallback(this);
+        // Theme might have changed between inflating this view and attaching it to the window, so
+        // force a call to onThemeChanged
+        onThemeChanged();
     }
 
     @Override
@@ -452,6 +464,12 @@
 
     @Override
     public void onThemeChanged() {
+        final int themeResId = getContext().getThemeResId();
+        if (mThemeResId == themeResId) {
+            return;
+        }
+        mThemeResId = themeResId;
+
         updateShowEmptyShadeView();
 
         // Re-inflate the status view group.
@@ -1212,6 +1230,12 @@
         setQsExpansion(height);
         requestPanelHeightUpdate();
         mNotificationStackScroller.checkSnoozeLeavebehind();
+
+        // When expanding QS, let's authenticate the user if possible,
+        // this will speed up notification actions.
+        if (height == 0) {
+            mStatusBar.requestFaceAuth();
+        }
     }
 
     private void setQsExpanded(boolean expanded) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
index a7b8eff..e887f5b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
@@ -83,6 +83,10 @@
     private final Stub mRotationWatcher = new Stub() {
         @Override
         public void onRotationChanged(final int rotation) throws RemoteException {
+            if (getCurrentView() == null) {
+                return;
+            }
+
             // We need this to be scheduled as early as possible to beat the redrawing of
             // window in response to the orientation change.
             Handler h = getCurrentView().getHandler();
@@ -235,7 +239,9 @@
 
         // If window rotation matches suggested rotation, remove any current suggestions
         if (rotation == windowRotation) {
-            getCurrentView().removeCallbacks(mRemoveRotationProposal);
+            if (getCurrentView() != null) {
+                getCurrentView().removeCallbacks(mRemoveRotationProposal);
+            }
             setRotateSuggestionButtonState(false /* visible */);
             return;
         }
@@ -259,9 +265,11 @@
             // If the navbar isn't shown, flag the rotate icon to be shown should the navbar become
             // visible given some time limit.
             mPendingRotationSuggestion = true;
-            getCurrentView().removeCallbacks(mCancelPendingRotationProposal);
-            getCurrentView().postDelayed(mCancelPendingRotationProposal,
-                    NAVBAR_HIDDEN_PENDING_ICON_TIMEOUT_MS);
+            if (getCurrentView() != null) {
+                getCurrentView().removeCallbacks(mCancelPendingRotationProposal);
+                getCurrentView().postDelayed(mCancelPendingRotationProposal,
+                        NAVBAR_HIDDEN_PENDING_ICON_TIMEOUT_MS);
+            }
         }
     }
 
@@ -328,7 +336,9 @@
     private void onRotationSuggestionsDisabled() {
         // Immediately hide the rotate button and clear any planned removal
         setRotateSuggestionButtonState(false /* visible */, true /* force */);
-        getCurrentView().removeCallbacks(mRemoveRotationProposal);
+        if (getCurrentView() != null) {
+            getCurrentView().removeCallbacks(mRemoveRotationProposal);
+        }
     }
 
     private void showAndLogRotationSuggestion() {
@@ -361,6 +371,10 @@
     }
 
     private void rescheduleRotationTimeout(final boolean reasonHover) {
+        if (getCurrentView() == null) {
+            return;
+        }
+
         // May be called due to a new rotation proposal or a change in hover state
         if (reasonHover) {
             // Don't reschedule if a hide animator is running
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 9b801b6..7e330e9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -538,7 +538,7 @@
     private BatteryController mBatteryController;
     protected boolean mPanelExpanded;
     private UiModeManager mUiModeManager;
-    private boolean mIsKeyguard;
+    protected boolean mIsKeyguard;
     private LogMaker mStatusBarStateLog;
     protected NotificationIconAreaController mNotificationIconAreaController;
     @Nullable private View mAmbientIndicationContainer;
@@ -1315,6 +1315,15 @@
         mEntryManager.updateNotifications();
     }
 
+    /**
+     * Asks {@link KeyguardUpdateMonitor} to run face auth.
+     */
+    public void requestFaceAuth() {
+        if (!mUnlockMethodCache.canSkipBouncer()) {
+            mKeyguardUpdateMonitor.requestFaceAuth();
+        }
+    }
+
     public void updateAreThereNotifications() {
         if (SPEW) {
             final boolean clearable = hasActiveNotifications() &&
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index b0e006d..74c0018 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -248,7 +248,6 @@
             ActivityManager.getService().resumeAppSwitches();
         } catch (RemoteException e) {
         }
-        int launchResult;
         // If we are launching a work activity and require to launch
         // separate work challenge, we defer the activity action and cancel
         // notification until work challenge is unlocked.
@@ -277,24 +276,7 @@
             fillInIntent = new Intent().putExtra(Notification.EXTRA_REMOTE_INPUT_DRAFT,
                     remoteInputText.toString());
         }
-        RemoteAnimationAdapter adapter = mActivityLaunchAnimator.getLaunchAnimation(
-                row, wasOccluded);
-        try {
-            if (adapter != null) {
-                ActivityTaskManager.getService()
-                        .registerRemoteAnimationForNextActivityStart(
-                                intent.getCreatorPackage(), adapter);
-            }
-            launchResult = intent.sendAndReturnResult(mContext, 0, fillInIntent, null,
-                    null, null, getActivityOptions(adapter));
-            mActivityLaunchAnimator.setLaunchResult(launchResult, isActivityIntent);
-        } catch (RemoteException | PendingIntent.CanceledException e) {
-            // the stack trace isn't very helpful here.
-            // Just log the exception message.
-            Log.w(TAG, "Sending contentIntent failed: " + e);
-
-            // TODO: Dismiss Keyguard.
-        }
+        startNotificationIntent(intent, fillInIntent, row, wasOccluded, isActivityIntent);
         if (isActivityIntent) {
             mAssistManager.hideAssist();
         }
@@ -327,6 +309,27 @@
         mIsCollapsingToShowActivityOverLockscreen = false;
     }
 
+    private void startNotificationIntent(PendingIntent intent, Intent fillInIntent,
+            ExpandableNotificationRow row, boolean wasOccluded, boolean isActivityIntent) {
+        RemoteAnimationAdapter adapter = mActivityLaunchAnimator.getLaunchAnimation(row,
+                wasOccluded);
+        try {
+            if (adapter != null) {
+                ActivityTaskManager.getService()
+                        .registerRemoteAnimationForNextActivityStart(
+                                intent.getCreatorPackage(), adapter);
+            }
+            int launchResult = intent.sendAndReturnResult(mContext, 0, fillInIntent, null,
+                    null, null, getActivityOptions(adapter));
+            mActivityLaunchAnimator.setLaunchResult(launchResult, isActivityIntent);
+        } catch (RemoteException | PendingIntent.CanceledException e) {
+            // the stack trace isn't very helpful here.
+            // Just log the exception message.
+            Log.w(TAG, "Sending contentIntent failed: " + e);
+            // TODO: Dismiss Keyguard.
+        }
+    }
+
     @Override
     public void startNotificationGutsIntent(final Intent intent, final int appUid,
             ExpandableNotificationRow row) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
new file mode 100644
index 0000000..603c969
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Rect;
+import android.view.View;
+import android.view.ViewTreeObserver;
+import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.assist.AssistManager;
+import com.android.systemui.bubbles.BubbleController;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
+
+/**
+ * Manages what parts of the status bar are touchable. Clients are primarily UI that displays in the
+ * status bar even though the UI doesn't look like part of the status bar.
+ */
+public final class StatusBarTouchableRegionManager implements
+        OnComputeInternalInsetsListener, ConfigurationListener {
+
+    private final AssistManager mAssistManager = Dependency.get(AssistManager.class);
+    private final BubbleController mBubbleController = Dependency.get(BubbleController.class);
+    private final Context mContext;
+    private final HeadsUpManagerPhone mHeadsUpManager;
+    private boolean mIsStatusBarExpanded = false;
+    private boolean mShouldAdjustInsets = false;
+    private final StatusBar mStatusBar;
+    private int mStatusBarHeight;
+    private final View mStatusBarWindowView;
+    private boolean mForceCollapsedUntilLayout = false;
+
+    public StatusBarTouchableRegionManager(@NonNull Context context,
+                                           HeadsUpManagerPhone headsUpManager,
+                                           @NonNull StatusBar statusBar,
+                                           @NonNull View statusBarWindowView) {
+        mContext = context;
+        mHeadsUpManager = headsUpManager;
+        mStatusBar = statusBar;
+        mStatusBarWindowView = statusBarWindowView;
+
+        initResources();
+
+        mAssistManager.setAssistSysUiChangeListener((isVisible) -> {
+            updateTouchableRegion();
+        });
+        mBubbleController.setBubbleStateChangeListener((hasBubbles) -> {
+            updateTouchableRegion();
+        });
+        Dependency.get(ConfigurationController.class).addCallback(this);
+    }
+
+    /**
+     * Set the touchable portion of the status bar based on what elements are visible.
+     */
+    public void updateTouchableRegion() {
+        boolean hasCutoutInset = (mStatusBarWindowView != null)
+                && (mStatusBarWindowView.getRootWindowInsets() != null)
+                && (mStatusBarWindowView.getRootWindowInsets().getDisplayCutout() != null);
+        boolean shouldObserve =
+                mHeadsUpManager.hasPinnedHeadsUp() || mHeadsUpManager.isHeadsUpGoingAway()
+                        || mBubbleController.hasBubbles()
+                        || mAssistManager.hasAssistUi()
+                        || mForceCollapsedUntilLayout
+                        || hasCutoutInset;
+        if (shouldObserve == mShouldAdjustInsets) {
+            return;
+        }
+
+        if (shouldObserve) {
+            mStatusBarWindowView.getViewTreeObserver().addOnComputeInternalInsetsListener(this);
+            mStatusBarWindowView.requestLayout();
+        } else {
+            mStatusBarWindowView.getViewTreeObserver().removeOnComputeInternalInsetsListener(this);
+        }
+        mShouldAdjustInsets = shouldObserve;
+    }
+
+    /**
+     * Calls {@code updateTouchableRegion()} after a layout pass completes.
+     */
+    public void updateTouchableRegionAfterLayout() {
+        mForceCollapsedUntilLayout = true;
+        mStatusBarWindowView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
+            @Override
+            public void onLayoutChange(View v, int left, int top, int right, int bottom,
+                                       int oldLeft,
+                                       int oldTop, int oldRight, int oldBottom) {
+                if (mStatusBarWindowView.getHeight() <= mStatusBarHeight) {
+                    mStatusBarWindowView.removeOnLayoutChangeListener(this);
+                    mForceCollapsedUntilLayout = false;
+                    updateTouchableRegion();
+                }
+            }
+        });
+    }
+
+    /**
+     * Notify that the status bar panel gets expanded or collapsed.
+     *
+     * @param isExpanded True to notify expanded, false to notify collapsed.
+     */
+    public void setIsStatusBarExpanded(boolean isExpanded) {
+        if (isExpanded != mIsStatusBarExpanded) {
+            mIsStatusBarExpanded = isExpanded;
+            if (isExpanded) {
+                // make sure our state is sane
+                mForceCollapsedUntilLayout = false;
+            }
+            updateTouchableRegion();
+        }
+    }
+
+    @Override
+    public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) {
+        if (mIsStatusBarExpanded || mStatusBar.isBouncerShowing()) {
+            // The touchable region is always the full area when expanded
+            return;
+        }
+
+        mHeadsUpManager.updateTouchableRegion(info);
+
+        Rect bubbleRect = mBubbleController.getTouchableRegion();
+        if (bubbleRect != null) {
+            info.touchableRegion.union(bubbleRect);
+        }
+
+        Rect assistRect = mAssistManager.getTouchableRegion();
+        if (assistRect != null) {
+            info.touchableRegion.union(assistRect);
+        }
+    }
+
+    @Override
+    public void onConfigChanged(Configuration newConfig) {
+        initResources();
+    }
+
+    @Override
+    public void onDensityOrFontScaleChanged() {
+        initResources();
+    }
+
+    @Override
+    public void onOverlayChanged() {
+        initResources();
+    }
+
+    private void initResources() {
+        Resources resources = mContext.getResources();
+        mStatusBarHeight = resources.getDimensionPixelSize(
+                com.android.internal.R.dimen.status_bar_height);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
index 4299af7..c2c3f81 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
@@ -288,7 +288,7 @@
     @Override
     public void onTuningChanged(String key, String newValue) {
         if (CLOCK_SECONDS.equals(key)) {
-            mShowSeconds = newValue != null && Integer.parseInt(newValue) != 0;
+            mShowSeconds = TunerService.parseIntegerSwitch(newValue, false);
             updateShowSeconds();
         } else {
             setClockVisibleByUser(!StatusBarIconController.getIconBlacklist(newValue)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index 0461057..d1a2253 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -26,8 +26,10 @@
 import android.provider.Settings;
 import android.util.ArrayMap;
 import android.util.Log;
+import android.view.accessibility.AccessibilityManager;
 
 import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.AlertingNotificationManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -55,9 +57,11 @@
     protected int mUser;
 
     private final ArrayMap<String, Long> mSnoozedPackages;
+    private final AccessibilityManagerWrapper mAccessibilityMgr;
 
     public HeadsUpManager(@NonNull final Context context) {
         mContext = context;
+        mAccessibilityMgr = Dependency.get(AccessibilityManagerWrapper.class);
         Resources resources = context.getResources();
         mMinimumDisplayTime = resources.getInteger(R.integer.heads_up_notification_minimum_time);
         mAutoDismissNotificationDecay = resources.getInteger(R.integer.heads_up_notification_decay);
@@ -409,5 +413,22 @@
             // The actual post time will be just after the heads-up really slided in
             return super.calculatePostTime() + mTouchAcceptanceDelay;
         }
+
+        @Override
+        protected long calculateFinishTime() {
+            return mPostTime + getRecommendedTimeoutMillis();
+        }
+
+        /**
+         * Get user-preferred or default timeout duration. The larger one will be returned.
+         * @return milliseconds before auto-dismiss
+         */
+        private int getRecommendedTimeoutMillis() {
+            return mAccessibilityMgr.getRecommendedTimeoutMillis(
+                    mAutoDismissNotificationDecay,
+                    AccessibilityManager.FLAG_CONTENT_CONTROLS
+                            | AccessibilityManager.FLAG_CONTENT_ICONS
+                            | AccessibilityManager.FLAG_CONTENT_TEXT);
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index d404982..024404d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.policy;
 
 import static android.view.Display.INVALID_DISPLAY;
+import static android.view.KeyEvent.KEYCODE_UNKNOWN;
 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK;
 
@@ -101,7 +102,7 @@
         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.KeyButtonView,
                 defStyle, 0);
 
-        mCode = a.getInteger(R.styleable.KeyButtonView_keyCode, 0);
+        mCode = a.getInteger(R.styleable.KeyButtonView_keyCode, KEYCODE_UNKNOWN);
 
         mSupportsLongpress = a.getBoolean(R.styleable.KeyButtonView_keyRepeat, true);
         mPlaySounds = a.getBoolean(R.styleable.KeyButtonView_playSound, true);
@@ -124,7 +125,7 @@
 
     @Override
     public boolean isClickable() {
-        return mCode != 0 || super.isClickable();
+        return mCode != KEYCODE_UNKNOWN || super.isClickable();
     }
 
     public void setCode(int code) {
@@ -163,7 +164,7 @@
     @Override
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(info);
-        if (mCode != 0) {
+        if (mCode != KEYCODE_UNKNOWN) {
             info.addAction(new AccessibilityNodeInfo.AccessibilityAction(ACTION_CLICK, null));
             if (mSupportsLongpress || isLongClickable()) {
                 info.addAction(
@@ -182,13 +183,13 @@
 
     @Override
     public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
-        if (action == ACTION_CLICK && mCode != 0) {
+        if (action == ACTION_CLICK && mCode != KEYCODE_UNKNOWN) {
             sendEvent(KeyEvent.ACTION_DOWN, 0, SystemClock.uptimeMillis());
             sendEvent(KeyEvent.ACTION_UP, 0);
             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
             playSoundEffect(SoundEffectConstants.CLICK);
             return true;
-        } else if (action == ACTION_LONG_CLICK && mCode != 0) {
+        } else if (action == ACTION_LONG_CLICK && mCode != KEYCODE_UNKNOWN) {
             sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.FLAG_LONG_PRESS);
             sendEvent(KeyEvent.ACTION_UP, 0);
             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
@@ -197,6 +198,7 @@
         return super.performAccessibilityActionInternal(action, arguments);
     }
 
+    @Override
     public boolean onTouchEvent(MotionEvent ev) {
         final boolean showSwipeUI = mOverviewProxyService.shouldShowSwipeUpUI();
         final int action = ev.getAction();
@@ -218,7 +220,7 @@
                 // Use raw X and Y to detect gestures in case a parent changes the x and y values
                 mTouchDownX = (int) ev.getRawX();
                 mTouchDownY = (int) ev.getRawY();
-                if (mCode != 0) {
+                if (mCode != KEYCODE_UNKNOWN) {
                     sendEvent(KeyEvent.ACTION_DOWN, 0, mDownTime);
                 } else {
                     // Provide the same haptic feedback that the system offers for virtual keys.
@@ -249,7 +251,7 @@
                 break;
             case MotionEvent.ACTION_CANCEL:
                 setPressed(false);
-                if (mCode != 0) {
+                if (mCode != KEYCODE_UNKNOWN) {
                     sendEvent(KeyEvent.ACTION_UP, KeyEvent.FLAG_CANCELED);
                 }
                 removeCallbacks(mCheckLongPress);
@@ -269,7 +271,7 @@
                     // and it feels weird to sometimes get a release haptic and other times not.
                     performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY_RELEASE);
                 }
-                if (mCode != 0) {
+                if (mCode != KEYCODE_UNKNOWN) {
                     if (doIt) {
                         sendEvent(KeyEvent.ACTION_UP, 0);
                         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
@@ -299,7 +301,7 @@
         sendEvent(action, flags, SystemClock.uptimeMillis());
     }
 
-    void sendEvent(int action, int flags, long when) {
+    private void sendEvent(int action, int flags, long when) {
         mMetricsLogger.write(new LogMaker(MetricsEvent.ACTION_NAV_BUTTON_EVENT)
                 .setType(MetricsEvent.TYPE_ACTION)
                 .setSubtype(mCode)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 3deede0..d3164a0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -22,7 +22,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.provider.Settings.Global;
-import android.telephony.NetworkRegistrationState;
+import android.telephony.NetworkRegistrationInfo;
 import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
@@ -475,7 +475,7 @@
         if (mServiceState == null) return null;
 
         int nrStatus = mServiceState.getNrStatus();
-        if (nrStatus == NetworkRegistrationState.NR_STATUS_CONNECTED) {
+        if (nrStatus == NetworkRegistrationInfo.NR_STATUS_CONNECTED) {
             // Check if the NR 5G is using millimeter wave and the icon is config.
             if (mServiceState.getNrFrequencyRange() == ServiceState.FREQUENCY_RANGE_MMWAVE) {
                 if (mConfig.nr5GIconMap.containsKey(Config.NR_CONNECTED_MMWAVE)) {
@@ -488,11 +488,11 @@
             if (mConfig.nr5GIconMap.containsKey(Config.NR_CONNECTED)) {
                 return mConfig.nr5GIconMap.get(Config.NR_CONNECTED);
             }
-        } else if (nrStatus == NetworkRegistrationState.NR_STATUS_NOT_RESTRICTED) {
+        } else if (nrStatus == NetworkRegistrationInfo.NR_STATUS_NOT_RESTRICTED) {
             if (mConfig.nr5GIconMap.containsKey(Config.NR_NOT_RESTRICTED)) {
                 return mConfig.nr5GIconMap.get(Config.NR_NOT_RESTRICTED);
             }
-        } else if (nrStatus == NetworkRegistrationState.NR_STATUS_RESTRICTED) {
+        } else if (nrStatus == NetworkRegistrationInfo.NR_STATUS_RESTRICTED) {
             if (mConfig.nr5GIconMap.containsKey(Config.NR_RESTRICTED)) {
                 return mConfig.nr5GIconMap.get(Config.NR_RESTRICTED);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index f79ad71..f4d6237 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -21,7 +21,9 @@
 import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT;
 import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_NONE;
 import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_OUT;
+import static android.telephony.PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE;
 
+import static com.android.internal.telephony.PhoneConstants.MAX_PHONE_COUNT_DUAL_SIM;
 import static com.android.systemui.Dependency.BG_LOOPER_NAME;
 
 import android.content.BroadcastReceiver;
@@ -41,6 +43,7 @@
 import android.os.PersistableBundle;
 import android.provider.Settings;
 import android.telephony.CarrierConfigManager;
+import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.SubscriptionInfo;
@@ -107,6 +110,16 @@
     private final CurrentUserTracker mUserTracker;
     private Config mConfig;
 
+    private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
+        @Override
+        public void onActiveDataSubscriptionIdChanged(int subId) {
+            mActiveMobileDataSubscription = subId;
+            doUpdateMobileControllers();
+        }
+    };
+
+    private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
     // Subcontrollers.
     @VisibleForTesting
     final WifiSignalController mWifiSignalController;
@@ -281,6 +294,7 @@
             mSubscriptionListener = new SubListener();
         }
         mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener);
+        mPhone.listen(mPhoneStateListener, LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
 
         // broadcasts
         IntentFilter filter = new IntentFilter();
@@ -525,6 +539,7 @@
 
     @VisibleForTesting
     void handleConfigurationChanged() {
+        updateMobileControllers();
         for (int i = 0; i < mMobileSignalControllers.size(); i++) {
             MobileSignalController controller = mMobileSignalControllers.valueAt(i);
             controller.setConfiguration(mConfig);
@@ -539,13 +554,39 @@
         doUpdateMobileControllers();
     }
 
+    private void filterMobileSubscriptionInSameGroup(List<SubscriptionInfo> subscriptions) {
+        if (subscriptions.size() == MAX_PHONE_COUNT_DUAL_SIM) {
+            SubscriptionInfo info1 = subscriptions.get(0);
+            SubscriptionInfo info2 = subscriptions.get(1);
+            if (info1.getGroupUuid() != null && info1.getGroupUuid().equals(info2.getGroupUuid())) {
+                // If both subscriptions are primary, show both.
+                if (!info1.isOpportunistic() && !info2.isOpportunistic()) return;
+
+                // If carrier required, always show signal bar of primary subscription.
+                // Otherwise, show whichever subscription is currently active for Internet.
+                boolean alwaysShowPrimary = CarrierConfigManager.getDefaultConfig()
+                        .getBoolean(CarrierConfigManager
+                        .KEY_ALWAYS_SHOW_PRIMARY_SIGNAL_BAR_IN_OPPORTUNISTIC_NETWORK_BOOLEAN);
+                if (alwaysShowPrimary) {
+                    subscriptions.remove(info1.isOpportunistic() ? info1 : info2);
+                } else {
+                    subscriptions.remove(info1.getSubscriptionId() == mActiveMobileDataSubscription
+                            ? info2 : info1);
+                }
+            }
+        }
+    }
+
     @VisibleForTesting
     void doUpdateMobileControllers() {
         List<SubscriptionInfo> subscriptions = mSubscriptionManager
-                .getActiveSubscriptionInfoList(true);
+                .getActiveSubscriptionInfoList(false);
         if (subscriptions == null) {
             subscriptions = Collections.emptyList();
         }
+
+        filterMobileSubscriptionInSameGroup(subscriptions);
+
         // If there have been no relevant changes to any of the subscriptions, we can leave as is.
         if (hasCorrectMobileControllers(subscriptions)) {
             // Even if the controllers are correct, make sure we have the right no sims state.
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
index 3bccdab..338e178 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
@@ -107,4 +107,12 @@
         });
         dialog.show();
     }
+
+    public static boolean parseIntegerSwitch(String value, boolean defaultValue) {
+        try {
+            return value != null ? Integer.parseInt(value) != 0 : defaultValue;
+        } catch (NumberFormatException e) {
+            return defaultValue;
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java
index 2df9000..52b58d4 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java
@@ -39,7 +39,7 @@
 
     @Override
     public void onTuningChanged(String key, String newValue) {
-        setChecked(newValue != null ? Integer.parseInt(newValue) != 0 : mDefault);
+        setChecked(TunerService.parseIntegerSwitch(newValue, mDefault));
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/volume/Events.java b/packages/SystemUI/src/com/android/systemui/volume/Events.java
index 1596ddb..6e740b8 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/Events.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/Events.java
@@ -55,6 +55,7 @@
     public static final int EVENT_RINGER_TOGGLE = 18; // (ringer_mode)
     public static final int EVENT_SHOW_USB_OVERHEAT_ALARM = 19; // (reason|int) (keyguard|bool)
     public static final int EVENT_DISMISS_USB_OVERHEAT_ALARM = 20; // (reason|int) (keyguard|bool)
+    public static final int EVENT_ODI_CAPTIONS_CLICK = 21;
 
     private static final String[] EVENT_TAGS = {
             "show_dialog",
@@ -77,7 +78,8 @@
             "zen_mode_config_changed",
             "ringer_toggle",
             "show_usb_overheat_alarm",
-            "dismiss_usb_overheat_alarm"
+            "dismiss_usb_overheat_alarm",
+            "odi_captions_click"
     };
 
     public static final int DISMISS_REASON_UNKNOWN = 0;
@@ -90,6 +92,7 @@
     public static final int DISMISS_STREAM_GONE = 7;
     public static final int DISMISS_REASON_OUTPUT_CHOOSER = 8;
     public static final int DISMISS_REASON_USB_OVERHEAD_ALARM_CHANGED = 9;
+    public static final int DISMISS_REASON_ODI_CAPTIONS_CLICKED = 10;
     public static final String[] DISMISS_REASONS = {
             "unknown",
             "touch_outside",
@@ -100,7 +103,8 @@
             "done_clicked",
             "a11y_stream_changed",
             "output_chooser",
-            "usb_temperature_below_threshold"
+            "usb_temperature_below_threshold",
+            "odi_captions_clicked"
     };
 
     public static final int SHOW_REASON_UNKNOWN = 0;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
index 0805677..d2f185a 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
@@ -101,28 +101,23 @@
 
     @Override
     public void onTuningChanged(String key, String newValue) {
+        boolean volumeDownToEnterSilent = mVolumePolicy.volumeDownToEnterSilent;
+        boolean volumeUpToExitSilent = mVolumePolicy.volumeUpToExitSilent;
+        boolean doNotDisturbWhenSilent = mVolumePolicy.doNotDisturbWhenSilent;
+
         if (VOLUME_DOWN_SILENT.equals(key)) {
-            final boolean volumeDownToEnterSilent = newValue != null
-                    ? Integer.parseInt(newValue) != 0
-                    : DEFAULT_VOLUME_DOWN_TO_ENTER_SILENT;
-            setVolumePolicy(volumeDownToEnterSilent,
-                    mVolumePolicy.volumeUpToExitSilent, mVolumePolicy.doNotDisturbWhenSilent,
-                    mVolumePolicy.vibrateToSilentDebounce);
+            volumeDownToEnterSilent =
+                TunerService.parseIntegerSwitch(newValue, DEFAULT_VOLUME_DOWN_TO_ENTER_SILENT);
         } else if (VOLUME_UP_SILENT.equals(key)) {
-            final boolean volumeUpToExitSilent = newValue != null
-                    ? Integer.parseInt(newValue) != 0
-                    : DEFAULT_VOLUME_UP_TO_EXIT_SILENT;
-            setVolumePolicy(mVolumePolicy.volumeDownToEnterSilent,
-                    volumeUpToExitSilent, mVolumePolicy.doNotDisturbWhenSilent,
-                    mVolumePolicy.vibrateToSilentDebounce);
+            volumeUpToExitSilent =
+                TunerService.parseIntegerSwitch(newValue, DEFAULT_VOLUME_UP_TO_EXIT_SILENT);
         } else if (VOLUME_SILENT_DO_NOT_DISTURB.equals(key)) {
-            final boolean doNotDisturbWhenSilent = newValue != null
-                    ? Integer.parseInt(newValue) != 0
-                    : DEFAULT_DO_NOT_DISTURB_WHEN_SILENT;
-            setVolumePolicy(mVolumePolicy.volumeDownToEnterSilent,
-                    mVolumePolicy.volumeUpToExitSilent, doNotDisturbWhenSilent,
-                    mVolumePolicy.vibrateToSilentDebounce);
+            doNotDisturbWhenSilent =
+                TunerService.parseIntegerSwitch(newValue, DEFAULT_DO_NOT_DISTURB_WHEN_SILENT);
         }
+
+        setVolumePolicy(volumeDownToEnterSilent, volumeUpToExitSilent, doNotDisturbWhenSilent,
+                mVolumePolicy.vibrateToSilentDebounce);
     }
 
     private void setVolumePolicy(boolean volumeDownToEnterSilent, boolean volumeUpToExitSilent,
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
index 4c16297..9192a25 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
@@ -48,6 +48,7 @@
 import android.provider.Settings;
 import android.service.notification.Condition;
 import android.service.notification.ZenModeConfig;
+import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.view.accessibility.AccessibilityManager;
@@ -270,6 +271,22 @@
         mWorker.sendEmptyMessage(W.GET_STATE);
     }
 
+    public boolean areCaptionsEnabled() {
+        int currentValue = Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Secure.ODI_CAPTIONS_ENABLED, 0);
+        return currentValue == 1;
+    }
+
+    public void setCaptionsEnabled(boolean isEnabled) {
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                Settings.Secure.ODI_CAPTIONS_ENABLED, isEnabled ? 1 : 0);
+    }
+
+    public void getCaptionsComponentState() {
+        if (mDestroyed) return;
+        mWorker.sendEmptyMessage(W.GET_CAPTIONS_COMPONENT_STATE);
+    }
+
     public void notifyVisible(boolean visible) {
         if (mDestroyed) return;
         mWorker.obtainMessage(W.NOTIFY_VISIBLE, visible ? 1 : 0, 0).sendToTarget();
@@ -365,6 +382,38 @@
         }
     }
 
+    private void onGetCaptionsComponentStateW() {
+        try {
+            String componentNameString = mContext.getString(
+                    com.android.internal.R.string.config_defaultSystemCaptionsService);
+            if (TextUtils.isEmpty(componentNameString)) {
+                // component doesn't exist
+                mCallbacks.onCaptionComponentStateChanged(false);
+                return;
+            }
+
+            if (D.BUG) {
+                Log.i(TAG, String.format(
+                        "isCaptionsServiceEnabled componentNameString=%s", componentNameString));
+            }
+
+            ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
+            if (componentName == null) {
+                mCallbacks.onCaptionComponentStateChanged(false);
+                return;
+            }
+
+            PackageManager packageManager = mContext.getPackageManager();
+            mCallbacks.onCaptionComponentStateChanged(
+                    packageManager.getComponentEnabledSetting(componentName)
+                    == PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
+        } catch (Exception ex) {
+            Log.e(TAG,
+                    "isCaptionsServiceEnabled failed to check for captions component", ex);
+            mCallbacks.onCaptionComponentStateChanged(false);
+        }
+    }
+
     private void onAccessibilityModeChanged(Boolean showA11yStream) {
         mCallbacks.onAccessibilityModeChanged(showA11yStream);
     }
@@ -718,6 +767,7 @@
         private static final int USER_ACTIVITY = 13;
         private static final int SHOW_SAFETY_WARNING = 14;
         private static final int ACCESSIBILITY_MODE_CHANGED = 15;
+        private static final int GET_CAPTIONS_COMPONENT_STATE = 16;
 
         W(Looper looper) {
             super(looper);
@@ -740,8 +790,8 @@
                 case NOTIFY_VISIBLE: onNotifyVisibleW(msg.arg1 != 0); break;
                 case USER_ACTIVITY: onUserActivityW(); break;
                 case SHOW_SAFETY_WARNING: onShowSafetyWarningW(msg.arg1); break;
+                case GET_CAPTIONS_COMPONENT_STATE: onGetCaptionsComponentStateW(); break;
                 case ACCESSIBILITY_MODE_CHANGED: onAccessibilityModeChanged((Boolean) msg.obj);
-
             }
         }
     }
@@ -881,6 +931,15 @@
                 });
             }
         }
+
+        @Override
+        public void onCaptionComponentStateChanged(Boolean isComponentEnabled) {
+            boolean componentEnabled = isComponentEnabled == null ? false : isComponentEnabled;
+            for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
+                entry.getValue().post(
+                        () -> entry.getKey().onCaptionComponentStateChanged(componentEnabled));
+            }
+        }
     }
 
 
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index ffd8206..398b309 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -29,6 +29,7 @@
 import static android.view.View.GONE;
 import static android.view.View.VISIBLE;
 
+import static com.android.systemui.volume.Events.DISMISS_REASON_ODI_CAPTIONS_CLICKED;
 import static com.android.systemui.volume.Events.DISMISS_REASON_SETTINGS_CLICKED;
 
 import android.animation.ObjectAnimator;
@@ -125,6 +126,8 @@
     private ViewGroup mDialogRowsView;
     private ViewGroup mRinger;
     private ImageButton mRingerIcon;
+    private ViewGroup mODICaptionsView;
+    private ImageButton mODICaptionsIcon;
     private View mSettingsView;
     private ImageButton mSettingsIcon;
     private FrameLayout mZenIcon;
@@ -240,6 +243,10 @@
             mRingerIcon = mRinger.findViewById(R.id.ringer_icon);
             mZenIcon = mRinger.findViewById(R.id.dnd_icon);
         }
+        mODICaptionsView = mDialog.findViewById(R.id.odi_captions);
+        if (mODICaptionsView != null) {
+            mODICaptionsIcon = mODICaptionsView.findViewById(R.id.odi_captions_icon);
+        }
         mSettingsView = mDialog.findViewById(R.id.settings_container);
         mSettingsIcon = mDialog.findViewById(R.id.settings);
 
@@ -270,6 +277,7 @@
         updateRowsH(getActiveRow());
         initRingerH();
         initSettingsH();
+        initODICaptionsH();
     }
 
     protected ViewGroup getDialogView() {
@@ -478,6 +486,42 @@
         updateRingerH();
     }
 
+    private void initODICaptionsH() {
+        if (mODICaptionsIcon != null) {
+            mODICaptionsIcon.setOnClickListener(v -> {
+                onCaptionIconClicked();
+                Events.writeEvent(mContext, Events.EVENT_ODI_CAPTIONS_CLICK);
+                dismissH(DISMISS_REASON_ODI_CAPTIONS_CLICKED);
+            });
+        }
+
+        mController.getCaptionsComponentState();
+    }
+
+    private void updateODICaptionsH(boolean isServiceComponentEnabled) {
+        if (mODICaptionsView != null) {
+            mODICaptionsView.setVisibility(isServiceComponentEnabled ? VISIBLE : GONE);
+        }
+
+        if (!isServiceComponentEnabled) return;
+
+        updateCaptionsIcon();
+    }
+
+    private void updateCaptionsIcon() {
+        mHandler.post(
+                mODICaptionsIcon.setImageResourceAsync(
+                        mController.areCaptionsEnabled()
+                                ? R.drawable.ic_volume_odi_captions
+                                : R.drawable.ic_volume_odi_captions_disabled));
+    }
+
+    private void onCaptionIconClicked() {
+        boolean isEnabled = mController.areCaptionsEnabled();
+        mController.setCaptionsEnabled(!isEnabled);
+        updateCaptionsIcon();
+    }
+
     private void incrementManualToggleCount() {
         ContentResolver cr = mContext.getContentResolver();
         int ringerCount = Settings.Secure.getInt(cr, Settings.Secure.MANUAL_RINGER_TOGGLE_COUNT, 0);
@@ -558,6 +602,7 @@
         mDialog.show();
         Events.writeEvent(mContext, Events.EVENT_SHOW_DIALOG, reason, mKeyguard.isKeyguardLocked());
         mController.notifyVisible(true);
+        mController.getCaptionsComponentState();
     }
 
     protected void rescheduleTimeoutH() {
@@ -1151,6 +1196,11 @@
             }
 
         }
+
+        @Override
+        public void onCaptionComponentStateChanged(Boolean isComponentEnabled) {
+            updateODICaptionsH(isComponentEnabled);
+        }
     };
 
     private final class H extends Handler {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
index b0d1106..29505a2 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
@@ -101,6 +101,8 @@
         // AND the plugin returns a view for the big clock
         ClockPlugin plugin = mock(ClockPlugin.class);
         when(plugin.getBigClockView()).thenReturn(mBigClock);
+        // AND in the keyguard state
+        mStateListener.onStateChanged(StatusBarState.KEYGUARD);
         // WHEN the plugin is connected
         mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
         // THEN the big clock container is visible and it is the parent of the
@@ -166,6 +168,8 @@
         ClockPlugin plugin = mock(ClockPlugin.class);
         TextClock pluginView = new TextClock(getContext());
         when(plugin.getBigClockView()).thenReturn(pluginView);
+        // AND in the keyguard state
+        mStateListener.onStateChanged(StatusBarState.KEYGUARD);
         // WHEN the plugin is connected and then disconnected
         mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
         mKeyguardClockSwitch.getClockChangedListener().onClockChanged(null);
@@ -245,21 +249,25 @@
     }
 
     @Test
-    public void onStateChanged_InvisibleInShade() {
+    public void onStateChanged_GoneInShade() {
         // GIVEN that the big clock container is visible
         mBigClockContainer.setVisibility(View.VISIBLE);
         mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer);
         // WHEN transitioned to SHADE state
         mStateListener.onStateChanged(StatusBarState.SHADE);
-        // THEN the container is invisible.
-        assertThat(mBigClockContainer.getVisibility()).isEqualTo(View.INVISIBLE);
+        // THEN the container is gone.
+        assertThat(mBigClockContainer.getVisibility()).isEqualTo(View.GONE);
     }
 
     @Test
     public void onStateChanged_VisibleInKeyguard() {
-        // GIVEN that the big clock container is invisible
-        mBigClockContainer.setVisibility(View.INVISIBLE);
+        // GIVEN that the big clock container is gone
+        mBigClockContainer.setVisibility(View.GONE);
         mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer);
+        // AND GIVEN that a plugin is active.
+        ClockPlugin plugin = mock(ClockPlugin.class);
+        when(plugin.getBigClockView()).thenReturn(mBigClock);
+        mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
         // WHEN transitioned to KEYGUARD state
         mStateListener.onStateChanged(StatusBarState.KEYGUARD);
         // THEN the container is visible.
@@ -274,6 +282,8 @@
         ClockPlugin plugin = mock(ClockPlugin.class);
         when(plugin.getBigClockView()).thenReturn(mBigClock);
         mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
+        // AND in the keyguard state
+        mStateListener.onStateChanged(StatusBarState.KEYGUARD);
         // WHEN the container is associated with the clock switch
         mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer);
         // THEN the container remains visible.
@@ -281,20 +291,6 @@
     }
 
     @Test
-    public void setBigClockContainer_invisible() {
-        // GIVEN that the big clock container is invisible
-        mBigClockContainer.setVisibility(View.INVISIBLE);
-        // AND GIVEN that a plugin is active.
-        ClockPlugin plugin = mock(ClockPlugin.class);
-        when(plugin.getBigClockView()).thenReturn(mBigClock);
-        mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
-        // WHEN the container is associated with the clock switch
-        mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer);
-        // THEN the container remains invisible.
-        assertThat(mBigClockContainer.getVisibility()).isEqualTo(View.INVISIBLE);
-    }
-
-    @Test
     public void setBigClockContainer_gone() {
         // GIVEN that the big clock container is gone
         mBigClockContainer.setVisibility(View.GONE);
@@ -302,6 +298,8 @@
         ClockPlugin plugin = mock(ClockPlugin.class);
         when(plugin.getBigClockView()).thenReturn(mBigClock);
         mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
+        // AND in the keyguard state
+        mStateListener.onStateChanged(StatusBarState.KEYGUARD);
         // WHEN the container is associated with the clock switch
         mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer);
         // THEN the container is made visible.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index 42c221a..4e9d892 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -329,10 +329,10 @@
     }
 
     static class TestableBubbleController extends BubbleController {
-
+        // Let's assume surfaces can be synchronized immediately.
         TestableBubbleController(Context context,
                 StatusBarWindowController statusBarWindowController, BubbleData data) {
-            super(context, statusBarWindowController, data);
+            super(context, statusBarWindowController, data, Runnable::run);
         }
 
         @Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
index 4ba2858..df014a4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
@@ -202,4 +202,16 @@
 
         verify(mMachine).requestState(eq(State.DOZE));
     }
+
+    @Test
+    public void testTransitionToPulsing_whenDockedHide_requestPulseOut() {
+        mDockHandler.transitionTo(DozeMachine.State.UNINITIALIZED, DozeMachine.State.INITIALIZED);
+        when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE_PULSING);
+        when(mMachine.getPulseReason()).thenReturn(DozeLog.PULSE_REASON_DOCKING);
+        mDockManagerFake.setDockEvent(DockManager.STATE_DOCKED_HIDE);
+
+        mDockHandler.transitionTo(DozeMachine.State.INITIALIZED, State.DOZE_PULSING);
+
+        verify(mHost).stopPulsing();
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
index 7797cb3..7bd4158 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
@@ -19,8 +19,10 @@
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
 
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.when;
 
+import android.content.Context;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.view.View;
@@ -31,6 +33,7 @@
 import com.android.systemui.statusbar.AlertingNotificationManagerTest;
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -53,15 +56,29 @@
     @Mock private VisualStabilityManager mVSManager;
     @Mock private StatusBar mBar;
 
+    private final class TestableHeadsUpManagerPhone extends HeadsUpManagerPhone {
+        TestableHeadsUpManagerPhone(Context context, View statusBarWindowView,
+                NotificationGroupManager groupManager, StatusBar bar,
+                VisualStabilityManager vsManager) {
+            super(context, statusBarWindowView, groupManager, bar, vsManager);
+            mMinimumDisplayTime = TEST_MINIMUM_DISPLAY_TIME;
+            mAutoDismissNotificationDecay = TEST_AUTO_DISMISS_TIME;
+        }
+    }
+
     protected AlertingNotificationManager createAlertingNotificationManager() {
         return mHeadsUpManager;
     }
 
     @Before
     public void setUp() {
+        AccessibilityManagerWrapper mAccessibilityMgr =
+                mDependency.injectMockDependency(AccessibilityManagerWrapper.class);
+        when(mAccessibilityMgr.getRecommendedTimeoutMillis(anyInt(), anyInt()))
+                .thenReturn(TEST_AUTO_DISMISS_TIME);
         when(mVSManager.isReorderingAllowed()).thenReturn(true);
-        mHeadsUpManager = new HeadsUpManagerPhone(mContext, mStatusBarWindowView, mGroupManager,
-                mBar, mVSManager);
+        mHeadsUpManager = new TestableHeadsUpManagerPhone(mContext, mStatusBarWindowView,
+                mGroupManager, mBar, mVSManager);
         super.setUp();
         mHeadsUpManager.mHandler = mTestHandler;
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java
new file mode 100644
index 0000000..6b83fed
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+
+import android.content.Context;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.statusbar.AlertingNotificationManager;
+import com.android.systemui.statusbar.AlertingNotificationManagerTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class HeadsUpManagerTest extends AlertingNotificationManagerTest {
+    private static final int TEST_A11Y_AUTO_DISMISS_TIME = 600;
+    private static final int TEST_A11Y_TIMEOUT_TIME = 5_000;
+
+    private AccessibilityManagerWrapper mAccessibilityMgr;
+    private HeadsUpManager mHeadsUpManager;
+    private boolean mLivesPastNormalTime;
+
+    private final class TestableHeadsUpManager extends HeadsUpManager {
+        TestableHeadsUpManager(Context context) {
+            super(context);
+            mMinimumDisplayTime = TEST_MINIMUM_DISPLAY_TIME;
+            mAutoDismissNotificationDecay = TEST_AUTO_DISMISS_TIME;
+        }
+    }
+
+    protected AlertingNotificationManager createAlertingNotificationManager() {
+        return mHeadsUpManager;
+    }
+
+    @Before
+    public void setUp() {
+        mAccessibilityMgr = mDependency.injectMockDependency(AccessibilityManagerWrapper.class);
+
+        mHeadsUpManager = new TestableHeadsUpManager(mContext);
+        super.setUp();
+        mHeadsUpManager.mHandler = mTestHandler;
+    }
+
+    @Test
+    public void testShowNotification_autoDismissesWithAccessibilityTimeout() {
+        doReturn(TEST_A11Y_AUTO_DISMISS_TIME).when(mAccessibilityMgr)
+                .getRecommendedTimeoutMillis(anyInt(), anyInt());
+        mHeadsUpManager.showNotification(mEntry);
+        Runnable pastNormalTimeRunnable =
+                () -> mLivesPastNormalTime = mHeadsUpManager.isAlerting(mEntry.key);
+        mTestHandler.postDelayed(pastNormalTimeRunnable,
+                        (TEST_A11Y_AUTO_DISMISS_TIME + TEST_AUTO_DISMISS_TIME) / 2);
+        mTestHandler.postDelayed(TEST_TIMEOUT_RUNNABLE, TEST_A11Y_TIMEOUT_TIME);
+
+        TestableLooper.get(this).processMessages(2);
+
+        assertFalse("Test timed out", mTimedOut);
+        assertTrue("Heads up should live long enough", mLivesPastNormalTime);
+        assertFalse(mHeadsUpManager.isAlerting(mEntry.key));
+    }
+}
+
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
index 2baea1a..5786796 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
@@ -7,7 +7,7 @@
 
 import android.net.NetworkCapabilities;
 import android.os.Looper;
-import android.telephony.NetworkRegistrationState;
+import android.telephony.NetworkRegistrationInfo;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -151,7 +151,7 @@
         updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
                 TelephonyManager.NETWORK_TYPE_LTE);
         ServiceState ss = Mockito.mock(ServiceState.class);
-        doReturn(NetworkRegistrationState.NR_STATUS_CONNECTED).when(ss).getNrStatus();
+        doReturn(NetworkRegistrationInfo.NR_STATUS_CONNECTED).when(ss).getNrStatus();
         doReturn(ServiceState.FREQUENCY_RANGE_HIGH).when(ss).getNrFrequencyRange();
         mPhoneStateListener.onServiceStateChanged(ss);
 
@@ -165,7 +165,7 @@
         updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
                 TelephonyManager.NETWORK_TYPE_LTE);
         ServiceState ss = Mockito.mock(ServiceState.class);
-        doReturn(NetworkRegistrationState.NR_STATUS_CONNECTED).when(ss).getNrStatus();
+        doReturn(NetworkRegistrationInfo.NR_STATUS_CONNECTED).when(ss).getNrStatus();
         doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(ss).getNrFrequencyRange();
         mPhoneStateListener.onServiceStateChanged(ss);
 
@@ -179,7 +179,7 @@
         updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
                 TelephonyManager.NETWORK_TYPE_LTE);
         ServiceState ss = Mockito.mock(ServiceState.class);
-        doReturn(NetworkRegistrationState.NR_STATUS_RESTRICTED).when(ss).getNrStatus();
+        doReturn(NetworkRegistrationInfo.NR_STATUS_RESTRICTED).when(ss).getNrStatus();
         mPhoneStateListener.onServiceStateChanged(mServiceState);
 
         verifyDataIndicators(TelephonyIcons.ICON_LTE);
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index 9673a84..f106228 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -260,6 +260,18 @@
     PREVIOUSLY_VISIBLE = 2;
   }
 
+  // Explanations for notification importance, derived from
+  // NotificationRecord.mImportanceExplanation.
+  enum NotificationImportanceExplanation {
+    IMPORTANCE_EXPLANATION_UNKNOWN = 0;
+    IMPORTANCE_EXPLANATION_APP = 1;     // App-specified channel importance.
+    IMPORTANCE_EXPLANATION_USER = 2;    // User-specified channel importance.
+    IMPORTANCE_EXPLANATION_ASST = 3;    // Notification Assistant override.
+    IMPORTANCE_EXPLANATION_SYSTEM = 4;  // System override.
+    // Like _APP, but based on pre-channels priority signal.
+    IMPORTANCE_EXPLANATION_APP_PRE_CHANNELS = 5;
+  }
+
   // Known visual elements: views or controls.
   enum View {
     // Unknown view
@@ -7090,6 +7102,24 @@
     // Panel for Wifi
     PANEL_WIFI = 1687;
 
+    // Custom tag for NotificationItem. A NotificationImportanceExplanation.
+    FIELD_NOTIFICATION_IMPORTANCE_EXPLANATION = 1688;
+
+    // Custom tag for NotificationItem. The initial "natural" importance.
+    FIELD_NOTIFICATION_IMPORTANCE_INITIAL = 1689;
+
+    // Custom tag for NotificationItem.  A NotificationImportanceExplanation.
+    // The source of the "natural" importance, if it was overridden.
+    FIELD_NOTIFICATION_IMPORTANCE_INITIAL_EXPLANATION = 1690;
+
+    // Custom tag for NotificationItem. The Notification Assistant's
+    // override of importance. Logged separately only if it was
+    // overridden by the system.
+    FIELD_NOTIFICATION_IMPORTANCE_ASST = 1691;
+
+    // Open: Settings > Special App Access > Do not disturb control for app
+    ZEN_ACCESS_DETAIL = 1692;
+
     // ---- End Q Constants, all Q constants go above this line ----
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS
diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto
index 16d8e95..ffbf1ae 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -226,6 +226,10 @@
     // Inform that user that the USB port is free of contaminants.
     NOTE_USB_CONTAMINANT_NOT_DETECTED = 53;
 
+    // Inform the user that Test Harness Mode is active.
+    // Package: android
+    NOTE_TEST_HARNESS_MODE_ENABLED = 54;
+
     // ADD_NEW_IDS_ABOVE_THIS_LINE
     // Legacy IDs with arbitrary values appear below
     // Legacy IDs existed as stable non-conflicting constants prior to the O release
diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto
index 9f049cf..0d17f22 100644
--- a/proto/src/wifi.proto
+++ b/proto/src/wifi.proto
@@ -1957,7 +1957,7 @@
   optional LinkProbeStatus probe_status_since_last_update = 24;
 
   // The elapsed time of the most recent link probe since last stats update;
-  optional int32 probe_elapsed_time_ms_since_last_update = 25;
+  optional int32 probe_elapsed_time_since_last_update_ms = 25;
 
   // The MCS rate of the most recent link probe since last stats update
   optional int32 probe_mcs_rate_since_last_update = 26;
@@ -2291,13 +2291,13 @@
   optional int32 count = 3;
 }
 
-// Single entry in a map from int32 => int32
-message MapEntryInt32Int32 {
+// Counts occurrences of a int32 key
+message Int32Count {
   // the key
   optional int32 key = 1;
 
-  // the value
-  optional int32 value = 2;
+  // the count
+  optional int32 count = 2;
 }
 
 message LinkProbeStats {
@@ -2328,16 +2328,16 @@
   }
 
   // Counts the occurrences of RSSI values when a link probe succeeds.
-  repeated MapEntryInt32Int32 success_rssi_counts = 1;
+  repeated Int32Count success_rssi_counts = 1;
 
   // Counts the occurrences of RSSI values when a link probe fails.
-  repeated MapEntryInt32Int32 failure_rssi_counts = 2;
+  repeated Int32Count failure_rssi_counts = 2;
 
   // Counts the occurrences of Link Speed values when a link probe succeeds.
-  repeated MapEntryInt32Int32 success_link_speed_counts = 3;
+  repeated Int32Count success_link_speed_counts = 3;
 
   // Counts the occurrences of Link Speed values when a link probe fails.
-  repeated MapEntryInt32Int32 failure_link_speed_counts = 4;
+  repeated Int32Count failure_link_speed_counts = 4;
 
   // Histogram for the number of seconds since the last TX success when a link probe succeeds.
   repeated HistogramBucketInt32 success_seconds_since_last_tx_success_histogram = 5;
@@ -2364,7 +2364,7 @@
   // same network selection as experiment2.
   // The keys are the number of network choices, and the values are the number of occurrences of
   // this number of network choices when exp1 and exp2 make the same network selection.
-  repeated MapEntryInt32Int32 same_selection_num_choices_counter = 3;
+  repeated Int32Count same_selection_num_choices_counter = 3;
 
   // Counts occurrences of the number of network choices there were when experiment1 makes the
   // same network selection as experiment2.
@@ -2372,7 +2372,7 @@
   // this number of network choices when exp1 and exp2 make different network selections.
   // Note that it is possible for the network selection to be different even when there only exists
   // a single network choice, since choosing not to connect to that network is a valid choice.
-  repeated MapEntryInt32Int32 different_selection_num_choices_counter = 4;
+  repeated Int32Count different_selection_num_choices_counter = 4;
 }
 
 // NetworkRequest API metrics.
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index 4293157..85c82bc 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -16,12 +16,6 @@
 
 package android.renderscript;
 
-import java.io.File;
-import java.lang.reflect.Method;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.AssetManager;
@@ -32,6 +26,12 @@
 import android.util.Log;
 import android.view.Surface;
 
+import java.io.File;
+import java.lang.reflect.Method;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
 // TODO: Clean up the whitespace that separates methods in this class.
 
 /**
@@ -114,8 +114,9 @@
                 Class<?> vm_runtime = Class.forName("dalvik.system.VMRuntime");
                 Method get_runtime = vm_runtime.getDeclaredMethod("getRuntime");
                 sRuntime = get_runtime.invoke(null);
-                registerNativeAllocation = vm_runtime.getDeclaredMethod("registerNativeAllocation", Integer.TYPE);
-                registerNativeFree = vm_runtime.getDeclaredMethod("registerNativeFree", Integer.TYPE);
+                registerNativeAllocation =
+                        vm_runtime.getDeclaredMethod("registerNativeAllocation", Long.TYPE);
+                registerNativeFree = vm_runtime.getDeclaredMethod("registerNativeFree", Long.TYPE);
             } catch (Exception e) {
                 Log.e(LOG_TAG, "Error loading GC methods: " + e);
                 throw new RSRuntimeException("Error loading GC methods: " + e);
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
index a19a847..3bd6220 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
@@ -91,7 +91,8 @@
         if (userState == null) return;
         final long identity = Binder.clearCallingIdentity();
         try {
-            int flags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE;
+            int flags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE
+                    | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS;
             if (userState.getBindInstantServiceAllowed()) {
                 flags |= Context.BIND_ALLOW_INSTANT;
             }
diff --git a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
index 65e31f3..1e3f20e 100644
--- a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
@@ -809,13 +809,9 @@
 
         // Announce the end of the gesture recognition.
         sendAccessibilityEvent(AccessibilityEvent.TYPE_GESTURE_DETECTION_END);
+        // Don't announce the end of a the touch interaction if users didn't lift their fingers.
         if (interactionEnd) {
-            // Announce the end of a the touch interaction.
             sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
-        } else {
-            // If gesture detection is end, but user doesn't release the finger, announce the
-            // transition to exploration state.
-            sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START);
         }
 
         mExitGestureDetectionModeDelayed.cancel();
@@ -1151,10 +1147,7 @@
         public void run() {
             // Announce the end of gesture recognition.
             sendAccessibilityEvent(AccessibilityEvent.TYPE_GESTURE_DETECTION_END);
-            // Clearing puts is in touch exploration state with a finger already
-            // down, so announce the transition to exploration state.
             clear();
-            sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START);
         }
     }
 
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 0e852f8..6597312 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -38,6 +38,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
 import android.database.ContentObserver;
 import android.graphics.Rect;
 import android.os.Binder;
@@ -189,6 +190,16 @@
         final IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
         context.registerReceiver(mBroadcastReceiver, filter, null, FgThread.getHandler());
+
+        if (mSupportedSmartSuggestionModes != AutofillManager.FLAG_SMART_SUGGESTION_OFF) {
+            // Must eager load the services so they bind to the augmented autofill service
+            final UserManager um = getContext().getSystemService(UserManager.class);
+            final List<UserInfo> users = um.getUsers();
+            for (int i = 0; i < users.size(); i++) {
+                final int userId = users.get(i).id;
+                getServiceForUserLocked(userId);
+            }
+        }
     }
 
     @Override // from AbstractMasterSystemService
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index f5f26a3..9612346 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -194,7 +194,7 @@
         mAugmentedAutofillResolver = new FrameworkResourcesServiceNameResolver(master.getContext(),
                 com.android.internal.R.string.config_defaultAugmentedAutofillService);
         mAugmentedAutofillResolver.setOnTemporaryServiceNameChangedCallback(
-                (u, s) -> updateRemoteAugmentedAutofillService(s));
+                (u, s) -> updateRemoteAugmentedAutofillService());
 
         updateLocked(disabled);
     }
@@ -223,6 +223,7 @@
             }
             sendStateToClients(false);
         }
+        updateRemoteAugmentedAutofillService();
         return enabledChanged;
     }
 
@@ -298,7 +299,8 @@
             final IAutoFillManagerClient client = IAutoFillManagerClient.Stub
                     .asInterface(appCallbackToken);
             try {
-                client.setSessionFinished(AutofillManager.STATE_DISABLED_BY_SERVICE);
+                client.setSessionFinished(AutofillManager.STATE_DISABLED_BY_SERVICE,
+                        /* autofillableIds= */ null);
             } catch (RemoteException e) {
                 Slog.w(TAG, "Could not notify " + shortComponentName + " that it's disabled: " + e);
             }
@@ -1093,7 +1095,7 @@
     /**
      * Called when the {@link #mAugmentedAutofillResolver} changed (among other places).
      */
-    private void updateRemoteAugmentedAutofillService(@Nullable String serviceName) {
+    void updateRemoteAugmentedAutofillService() {
         synchronized (mLock) {
             if (mRemoteAugmentedAutofillService != null) {
                 if (sVerbose) {
@@ -1105,7 +1107,9 @@
                 mRemoteAugmentedAutofillServiceInfo = null;
             }
 
-            mRemoteAugmentedAutofillService = getRemoteAugmentedAutofillServiceLocked();
+            if (isEnabledLocked()) {
+                mRemoteAugmentedAutofillService = getRemoteAugmentedAutofillServiceLocked();
+            }
         }
     }
 
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
index 3c0da7d..3d392c7 100644
--- a/services/autofill/java/com/android/server/autofill/Helper.java
+++ b/services/autofill/java/com/android/server/autofill/Helper.java
@@ -20,12 +20,14 @@
 import android.annotation.Nullable;
 import android.app.assist.AssistStructure;
 import android.app.assist.AssistStructure.ViewNode;
+import android.app.assist.AssistStructure.WindowNode;
 import android.content.ComponentName;
 import android.metrics.LogMaker;
 import android.service.autofill.Dataset;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Slog;
+import android.view.View;
 import android.view.WindowManager;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillValue;
@@ -205,6 +207,32 @@
         }
     }
 
+    /**
+     * Gets the {@link AutofillId} of the autofillable nodes in the {@code structure}.
+     */
+    @NonNull
+    static ArraySet<AutofillId> getAutofillableIds(@NonNull AssistStructure structure) {
+        final ArraySet<AutofillId> ids = new ArraySet<>();
+        final int size = structure.getWindowNodeCount();
+        for (int i = 0; i < size; i++) {
+            final WindowNode node = structure.getWindowNodeAt(i);
+            addAutofillableIds(node.getRootViewNode(), ids);
+        }
+        return ids;
+    }
+
+    private static void addAutofillableIds(@NonNull ViewNode node,
+            @NonNull ArraySet<AutofillId> ids) {
+        if (node.getAutofillType() != View.AUTOFILL_TYPE_NONE) {
+            ids.add(node.getAutofillId());
+        }
+        final int size = node.getChildCount();
+        for (int i = 0; i < size; i++) {
+            final ViewNode child = node.getChildAt(i);
+            addAutofillableIds(child, ids);
+        }
+    }
+
     private interface ViewNodeFilter {
         boolean matches(ViewNode node);
     }
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 7fbfc42..ea47033 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -26,6 +26,7 @@
 import static android.view.autofill.AutofillManager.ACTION_VIEW_EXITED;
 import static android.view.autofill.AutofillManager.FLAG_SMART_SUGGESTION_SYSTEM;
 import static android.view.autofill.AutofillManager.getSmartSuggestionModeToString;
+import static android.view.autofill.Helper.toList;
 
 import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
 import static com.android.server.autofill.Helper.getNumericValue;
@@ -266,6 +267,15 @@
     @GuardedBy("mLock")
     private ArrayList<LogMaker> mAugmentedRequestsLogs;
 
+
+    /**
+     * List of autofill ids of autofillable fields present in the AssistStructure that can be used
+     * to trigger new augmented autofill requests (because the "standard" service was not interested
+     * on autofilling the app.
+     */
+    @GuardedBy("mLock")
+    private ArraySet<AutofillId> mAugmentedAutofillableIds;
+
     /**
      * Receiver of assist data from the app's {@link Activity}.
      */
@@ -699,14 +709,14 @@
                 if (requestLog != null) {
                     requestLog.addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS, -1);
                 }
-                processNullResponseLocked(requestFlags);
+                processNullResponseLocked(requestId, requestFlags);
                 return;
             }
 
             fieldClassificationIds = response.getFieldClassificationIds();
             if (fieldClassificationIds != null && !mService.isFieldClassificationEnabledLocked()) {
                 Slog.w(TAG, "Ignoring " + response + " because field detection is disabled");
-                processNullResponseLocked(requestFlags);
+                processNullResponseLocked(requestId, requestFlags);
                 return;
             }
         }
@@ -739,7 +749,7 @@
                         && response.getAuthentication() == null)
                 || disableDuration > 0) {
             // Response is "empty" from an UI point of view, need to notify client.
-            notifyUnavailableToClient(sessionFinishedState);
+            notifyUnavailableToClient(sessionFinishedState, /* autofillableIds= */ null);
         }
 
         if (requestLog != null) {
@@ -802,7 +812,8 @@
                 }
             }
         }
-        notifyUnavailableToClient(AutofillManager.STATE_UNKNOWN_FAILED);
+        notifyUnavailableToClient(AutofillManager.STATE_UNKNOWN_FAILED,
+                /* autofillableIds= */ null);
         if (showMessage) {
             getUiForShowing().showError(message, this);
         }
@@ -1131,7 +1142,7 @@
             }
             logAuthenticationStatusLocked(requestId,
                     MetricsEvent.AUTOFILL_INVALID_AUTHENTICATION);
-            processNullResponseLocked(0);
+            processNullResponseLocked(requestId, 0);
         }
     }
 
@@ -2326,12 +2337,28 @@
                     return;
                 }
 
+                if (mAugmentedAutofillableIds != null && mAugmentedAutofillableIds.contains(id)) {
+                    // View was already reported when server could not handle a response, but it
+                    // triggered augmented autofill
+
+                    if (sDebug) Slog.d(TAG, "updateLocked(" + id + "): augmented-autofillable");
+
+                    // Update the view states first...
+                    mCurrentViewId = viewState.id;
+                    viewState.setCurrentValue(value);
+
+                    // ...then trigger the augmented autofill UI
+                    triggerAugmentedAutofillLocked();
+                    return;
+                }
+
                 requestNewFillResponseOnViewEnteredIfNecessaryLocked(id, viewState, flags);
 
                 // Remove the UI if the ViewState has changed.
                 if (!Objects.equals(mCurrentViewId, viewState.id)) {
                     mUi.hideFillUi(this);
                     mCurrentViewId = viewState.id;
+                    hideAugmentedAutofillLocked(viewState);
                 }
 
                 // If the ViewState is ready to be displayed, onReady() will be called.
@@ -2339,8 +2366,9 @@
                 break;
             case ACTION_VIEW_EXITED:
                 if (Objects.equals(mCurrentViewId, viewState.id)) {
-                    if (sVerbose) Slog.d(TAG, "Exiting view " + id);
+                    if (sVerbose) Slog.v(TAG, "Exiting view " + id);
                     mUi.hideFillUi(this);
+                    hideAugmentedAutofillLocked(viewState);
                     mCurrentViewId = null;
                 }
                 break;
@@ -2349,6 +2377,15 @@
         }
     }
 
+    @GuardedBy("mLock")
+    private void hideAugmentedAutofillLocked(@NonNull ViewState viewState) {
+        if ((viewState.getState()
+                & ViewState.STATE_TRIGGERED_AUGMENTED_AUTOFILL) != 0) {
+            viewState.resetState(ViewState.STATE_TRIGGERED_AUGMENTED_AUTOFILL);
+            cancelAugmentedAutofillLocked();
+        }
+    }
+
     /**
      * Checks whether a view should be ignored.
      */
@@ -2428,14 +2465,15 @@
         }
     }
 
-    private void notifyUnavailableToClient(int sessionFinishedState) {
+    private void notifyUnavailableToClient(int sessionFinishedState,
+            @Nullable ArraySet<AutofillId> autofillableIds) {
         synchronized (mLock) {
             if (mCurrentViewId == null) return;
             try {
                 if (mHasCallback) {
                     mClient.notifyNoFillUi(id, mCurrentViewId, sessionFinishedState);
                 } else if (sessionFinishedState != 0) {
-                    mClient.setSessionFinished(sessionFinishedState);
+                    mClient.setSessionFinished(sessionFinishedState, toList(autofillableIds));
                 }
             } catch (RemoteException e) {
                 Slog.e(TAG, "Error notifying client no fill UI: id=" + mCurrentViewId, e);
@@ -2551,10 +2589,22 @@
     }
 
     @GuardedBy("mLock")
-    private void processNullResponseLocked(int flags) {
+    private void processNullResponseLocked(int requestId, int flags) {
         if ((flags & FLAG_MANUAL_REQUEST) != 0) {
             getUiForShowing().showError(R.string.autofill_error_cannot_autofill, this);
         }
+
+        final FillContext context = getFillContextByRequestIdLocked(requestId);
+
+        final ArraySet<AutofillId> autofillableIds;
+        if (context != null) {
+            final AssistStructure structure = context.getStructure();
+            autofillableIds = Helper.getAutofillableIds(structure);
+        } else {
+            Slog.w(TAG, "processNullResponseLocked(): no context for req " + requestId);
+            autofillableIds = null;
+        }
+
         mService.resetLastResponse();
 
         // The default autofill service cannot fullfill the request, let's check if the augmented
@@ -2563,19 +2613,18 @@
         if (mAugmentedAutofillDestroyer == null) {
             if (sVerbose) {
                 Slog.v(TAG, "canceling session " + id + " when server returned null and there is no"
-                        + " AugmentedAutofill for user");
+                        + " AugmentedAutofill for user. AutofillableIds: " + autofillableIds);
             }
             // Nothing to be done, but need to notify client.
-            notifyUnavailableToClient(AutofillManager.STATE_FINISHED);
+            notifyUnavailableToClient(AutofillManager.STATE_FINISHED, autofillableIds);
             removeSelf();
         } else {
-            // TODO(b/123099468, b/119638958): must set internal state so when user focus other
-            // fields it does not generate a new call to the standard autofill service (right now
-            // it does). Must also add CTS tests to exercise this scenario.
             if (sVerbose) {
                 Slog.v(TAG, "keeping session " + id + " when server returned null but "
-                        + "there is an AugmentedAutofill for user");
+                        + "there is an AugmentedAutofill for user. AutofillableIds: "
+                        + autofillableIds);
             }
+            mAugmentedAutofillableIds = autofillableIds;
         }
     }
 
@@ -2643,7 +2692,9 @@
             return null;
         }
 
-        final AutofillValue currentValue = mViewStates.get(mCurrentViewId).getCurrentValue();
+        final ViewState viewState = mViewStates.get(mCurrentViewId);
+        viewState.setState(ViewState.STATE_TRIGGERED_AUGMENTED_AUTOFILL);
+        final AutofillValue currentValue = viewState.getCurrentValue();
 
         // TODO(b/111330312): we might need to add a new state in the AutofillManager to optimize
         // further AFM -> AFMS calls.
@@ -2665,6 +2716,18 @@
     }
 
     @GuardedBy("mLock")
+    private void cancelAugmentedAutofillLocked() {
+        final RemoteAugmentedAutofillService remoteService = mService
+                .getRemoteAugmentedAutofillServiceLocked();
+        if (remoteService == null) {
+            Slog.w(TAG, "cancelAugmentedAutofillLocked(): no service for user");
+            return;
+        }
+        if (sVerbose) Slog.v(TAG, "cancelAugmentedAutofillLocked() on " + mCurrentViewId);
+        remoteService.onDestroyAutofillWindowsRequest();
+    }
+
+    @GuardedBy("mLock")
     private void processResponseLocked(@NonNull FillResponse newResponse,
             @Nullable Bundle newClientState, int flags) {
         // Make sure we are hiding the UI which will be shown
@@ -2950,6 +3013,10 @@
             pw.println(mAugmentedRequestsLogs.size());
         }
 
+        if (mAugmentedAutofillableIds != null) {
+            pw.print(prefix); pw.print("mAugmentedAutofillableIds: ");
+            pw.println(mAugmentedAutofillableIds);
+        }
         mRemoteFillService.dump(prefix, pw);
     }
 
@@ -3134,7 +3201,7 @@
         mUi.destroyAll(mPendingSaveUi, this, false);
         if (!isPendingSaveUi) {
             try {
-                mClient.setSessionFinished(clientState);
+                mClient.setSessionFinished(clientState, /* autofillableIds= */ null);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Error notifying client to finish session", e);
             }
diff --git a/services/autofill/java/com/android/server/autofill/ViewState.java b/services/autofill/java/com/android/server/autofill/ViewState.java
index 2cc6d20..33a2e50 100644
--- a/services/autofill/java/com/android/server/autofill/ViewState.java
+++ b/services/autofill/java/com/android/server/autofill/ViewState.java
@@ -17,6 +17,7 @@
 package com.android.server.autofill;
 
 import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
+
 import static com.android.server.autofill.Helper.sDebug;
 
 import android.annotation.NonNull;
@@ -47,8 +48,6 @@
 
     private static final String TAG = "ViewState";
 
-    // NOTE: state constants must be public because of flagstoString().
-    public static final int STATE_UNKNOWN = 0x000;
     /** Initial state. */
     public static final int STATE_INITIAL = 0x001;
     /** View id is present in a dataset returned by the service. */
@@ -73,6 +72,8 @@
     public static final int STATE_AUTOFILL_FAILED = 0x400;
     /** View has been autofilled at least once. */
     public static final int STATE_AUTOFILLED_ONCE = 0x800;
+    /** View triggered the latest augmented autofill request. */
+    public static final int STATE_TRIGGERED_AUGMENTED_AUTOFILL = 0x1000;
 
     public final AutofillId id;
 
diff --git a/services/backup/java/com/android/server/backup/params/RestoreParams.java b/services/backup/java/com/android/server/backup/params/RestoreParams.java
index 5125b0d..c9a6b60 100644
--- a/services/backup/java/com/android/server/backup/params/RestoreParams.java
+++ b/services/backup/java/com/android/server/backup/params/RestoreParams.java
@@ -105,7 +105,7 @@
     /**
      * Caller specifies whether is considered a system-level restore.
      */
-    public static RestoreParams createForRestoreSome(
+    public static RestoreParams createForRestorePackages(
             TransportClient transportClient,
             IRestoreObserver observer,
             IBackupManagerMonitor monitor,
diff --git a/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java b/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java
index 0fa0f89..10304c3 100644
--- a/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java
+++ b/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java
@@ -22,6 +22,7 @@
 import static com.android.server.backup.internal.BackupHandler.MSG_RUN_GET_RESTORE_SETS;
 import static com.android.server.backup.internal.BackupHandler.MSG_RUN_RESTORE;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.backup.IBackupManagerMonitor;
 import android.app.backup.IRestoreObserver;
@@ -192,18 +193,22 @@
     }
 
     // Restores of more than a single package are treated as 'system' restores
-    public synchronized int restoreSome(long token, IRestoreObserver observer,
-            IBackupManagerMonitor monitor, String[] packages) {
+    public synchronized int restorePackages(long token, @Nullable IRestoreObserver observer,
+            @NonNull String[] packages, @Nullable IBackupManagerMonitor monitor) {
         mBackupManagerService.getContext().enforceCallingOrSelfPermission(
                 android.Manifest.permission.BACKUP,
                 "performRestore");
 
         if (DEBUG) {
             StringBuilder b = new StringBuilder(128);
-            b.append("restoreSome token=");
+            b.append("restorePackages token=");
             b.append(Long.toHexString(token));
             b.append(" observer=");
-            b.append(observer.toString());
+            if (observer == null) {
+                b.append("null");
+            } else {
+                b.append(observer.toString());
+            }
             b.append(" monitor=");
             if (monitor == null) {
                 b.append("null");
@@ -260,7 +265,7 @@
                     try {
                         return sendRestoreToHandlerLocked(
                                 (transportClient, listener) ->
-                                        RestoreParams.createForRestoreSome(
+                                        RestoreParams.createForRestorePackages(
                                                 transportClient,
                                                 observer,
                                                 monitor,
@@ -268,7 +273,7 @@
                                                 packages,
                                                 /* isSystemRestore */ packages.length > 1,
                                                 listener),
-                                "RestoreSession.restoreSome(" + packages.length + " packages)");
+                                "RestoreSession.restorePackages(" + packages.length + " packages)");
                     } finally {
                         Binder.restoreCallingIdentity(oldId);
                     }
diff --git a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
index 836a5e8..56eacc0 100644
--- a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
+++ b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
@@ -41,6 +41,7 @@
 import android.text.TextUtils;
 import android.util.Slog;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
 import com.android.server.LocalServices;
 import com.android.server.backup.BackupAgentTimeoutParameters;
@@ -120,6 +121,7 @@
 
     // Pipes for moving data
     private ParcelFileDescriptor[] mPipes = null;
+    private final Object mPipesLock = new Object();
 
     // Widget blob to be restored out-of-band
     private byte[] mWidgetData = null;
@@ -129,6 +131,8 @@
 
     private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
     final boolean mIsAdbRestore;
+    @GuardedBy("mPipesLock")
+    private boolean mPipesClosed;
 
     public FullRestoreEngine(UserBackupManagerService backupManagerService,
             BackupRestoreTask monitorTask, IFullBackupRestoreObserver observer,
@@ -578,24 +582,26 @@
     }
 
     private void setUpPipes() throws IOException {
-        mPipes = ParcelFileDescriptor.createPipe();
+        synchronized (mPipesLock) {
+            mPipes = ParcelFileDescriptor.createPipe();
+            mPipesClosed = false;
+        }
     }
 
     private void tearDownPipes() {
         // Teardown might arise from the inline restore processing or from the asynchronous
         // timeout mechanism, and these might race.  Make sure we don't try to close and
         // null out the pipes twice.
-        synchronized (this) {
-            if (mPipes != null) {
+        synchronized (mPipesLock) {
+            if (!mPipesClosed && mPipes != null) {
                 try {
                     mPipes[0].close();
-                    mPipes[0] = null;
                     mPipes[1].close();
-                    mPipes[1] = null;
+
+                    mPipesClosed = true;
                 } catch (IOException e) {
                     Slog.w(TAG, "Couldn't close agent pipes", e);
                 }
-                mPipes = null;
             }
         }
     }
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index c75b4c6..9995d8e 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -115,7 +115,7 @@
     public ContentCaptureManagerService(@NonNull Context context) {
         super(context, new FrameworkResourcesServiceNameResolver(context,
                 com.android.internal.R.string.config_defaultContentCaptureService),
-                UserManager.DISALLOW_CONTENT_CAPTURE);
+                UserManager.DISALLOW_CONTENT_CAPTURE, /* refreshServiceOnPackageUpdate=*/ false);
         DeviceConfig.addOnPropertyChangedListener(DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
                 ActivityThread.currentApplication().getMainExecutor(),
                 (namespace, key, value) -> onDeviceConfigChange(key, value));
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index feb1ac1..c423f9c 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -100,6 +100,13 @@
     @GuardedBy("mLock")
     private final WhitelistHelper mWhitelistHelper = new WhitelistHelper();
 
+    /**
+     * When {@code true}, remote service died but service state is kept so it's restored after
+     * the system re-binds to it.
+     */
+    @GuardedBy("mLock")
+    private boolean mZombie;
+
     // TODO(b/111276913): add mechanism to prune stale sessions, similar to Autofill's
 
     ContentCapturePerUserService(@NonNull ContentCaptureManagerService master,
@@ -179,6 +186,37 @@
     public void onServiceDied(@NonNull RemoteContentCaptureService service) {
         // Don't do anything; eventually the system will bind to it again...
         Slog.w(TAG, "remote service died: " + service);
+        synchronized (mLock) {
+            mZombie = true;
+        }
+    }
+
+    /**
+     * Called after the remote service connected, it's used to restore state from a 'zombie'
+     * service (i.e., after it died).
+     */
+    void onConnected() {
+        synchronized (mLock) {
+            if (mZombie) {
+                // Sanity check - shouldn't happen
+                if (mRemoteService == null) {
+                    Slog.w(TAG, "Cannot ressurect sessions because remote service is null");
+                    return;
+                }
+
+                mZombie = false;
+                final int numSessions = mSessions.size();
+                if (mMaster.debug) {
+                    Slog.d(TAG, "Ressurrecting remote service (" + mRemoteService + ") on "
+                            + numSessions + " sessions");
+                }
+
+                for (int i = 0; i < numSessions; i++) {
+                    final ContentCaptureServerSession session = mSessions.valueAt(i);
+                    session.resurrectLocked();
+                }
+            }
+        }
     }
 
     // TODO(b/119613670): log metrics
@@ -260,7 +298,7 @@
         }
 
         final ContentCaptureServerSession newSession = new ContentCaptureServerSession(
-                activityToken, this, mRemoteService, componentName, taskId,
+                activityToken, this, mRemoteService, componentName, clientReceiver, taskId,
                 displayId, sessionId, uid, flags);
         if (mMaster.verbose) {
             Slog.v(TAG, "startSession(): new session for "
@@ -389,6 +427,9 @@
     @GuardedBy("mLock")
     public void destroyLocked() {
         if (mMaster.debug) Slog.d(TAG, "destroyLocked()");
+        if (mRemoteService != null) {
+            mRemoteService.destroy();
+        }
         destroySessionsLocked();
     }
 
@@ -449,6 +490,8 @@
     protected void dumpLocked(String prefix, PrintWriter pw) {
         super.dumpLocked(prefix, pw);
 
+        pw.print(prefix); pw.print("Zombie: "); pw.println(mZombie);
+
         final String prefix2 = prefix + "  ";
         if (mRemoteService != null) {
             pw.print(prefix); pw.println("remote service:");
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
index 4094843..da19836 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
@@ -23,6 +23,7 @@
 import android.util.LocalLog;
 import android.util.Slog;
 import android.view.contentcapture.ContentCaptureContext;
+import android.view.contentcapture.ContentCaptureSession;
 import android.view.contentcapture.ContentCaptureSessionId;
 
 import com.android.internal.annotations.GuardedBy;
@@ -44,6 +45,12 @@
     private final ContentCaptureContext mContentCaptureContext;
 
     /**
+     * Reference to the binder object help at the client-side process and used to set its state.
+     */
+    @NonNull
+    private final IResultReceiver mSessionStateReceiver;
+
+    /**
      * Canonical session id.
      */
     private final String mId;
@@ -56,7 +63,7 @@
     ContentCaptureServerSession(@NonNull IBinder activityToken,
             @NonNull ContentCapturePerUserService service,
             @NonNull RemoteContentCaptureService remoteService,
-            @NonNull ComponentName appComponentName,
+            @NonNull ComponentName appComponentName, @NonNull IResultReceiver sessionStateReceiver,
             int taskId, int displayId, @NonNull String sessionId, int uid, int flags) {
         mActivityToken = activityToken;
         mService = service;
@@ -65,6 +72,7 @@
         mRemoteService = remoteService;
         mContentCaptureContext = new ContentCaptureContext(/* clientContext= */ null,
                 appComponentName, taskId, displayId, flags);
+        mSessionStateReceiver = sessionStateReceiver;
     }
 
     /**
@@ -79,7 +87,8 @@
      */
     @GuardedBy("mLock")
     public void notifySessionStartedLocked(@NonNull IResultReceiver clientReceiver) {
-        mRemoteService.onSessionStarted(mContentCaptureContext, mId, mUid, clientReceiver);
+        mRemoteService.onSessionStarted(mContentCaptureContext, mId, mUid, clientReceiver,
+                ContentCaptureSession.STATE_ACTIVE);
     }
 
     /**
@@ -129,6 +138,17 @@
         }
     }
 
+    /**
+     * Called to restore the active state of a session that was paused while the service died.
+     */
+    @GuardedBy("mLock")
+    public void resurrectLocked() {
+        mRemoteService.onSessionStarted(new ContentCaptureContext(mContentCaptureContext,
+                ContentCaptureContext.FLAG_RECONNECTED), mId, mUid, mSessionStateReceiver,
+                ContentCaptureSession.STATE_ACTIVE
+                        | ContentCaptureSession.STATE_SERVICE_RESURRECTED);
+    }
+
     @GuardedBy("mLock")
     public void dumpLocked(@NonNull String prefix, @NonNull PrintWriter pw) {
         pw.print(prefix); pw.print("id: ");  pw.print(mId); pw.println();
diff --git a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
index 1d2d625..2ce5059 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
@@ -40,14 +40,16 @@
 
     private final IBinder mServerCallback;
     private final int mIdleUnbindTimeoutMs;
+    private final ContentCapturePerUserService mPerUserService;
 
     RemoteContentCaptureService(Context context, String serviceInterface,
             ComponentName serviceComponentName, IContentCaptureServiceCallback callback, int userId,
-            ContentCaptureServiceCallbacks callbacks, boolean bindInstantServiceAllowed,
+            ContentCapturePerUserService perUserService, boolean bindInstantServiceAllowed,
             boolean verbose, int idleUnbindTimeoutMs) {
-        super(context, serviceInterface, serviceComponentName, userId, callbacks,
+        super(context, serviceInterface, serviceComponentName, userId, perUserService,
                 context.getMainThreadHandler(), bindInstantServiceAllowed, verbose,
                 /* initialCapacity= */ 2);
+        mPerUserService = perUserService;
         mServerCallback = callback.asBinder();
         mIdleUnbindTimeoutMs = idleUnbindTimeoutMs;
 
@@ -65,19 +67,25 @@
         return mIdleUnbindTimeoutMs;
     }
 
-    @Override // from RemoteService
-    protected void handleOnConnectedStateChanged(boolean state) {
-        if (state && getTimeoutIdleBindMillis() != PERMANENT_BOUND_TIMEOUT_MS) {
+    @Override // from AbstractRemoteService
+    protected void handleOnConnectedStateChanged(boolean connected) {
+        if (connected && getTimeoutIdleBindMillis() != PERMANENT_BOUND_TIMEOUT_MS) {
             scheduleUnbind();
         }
         try {
-            if (state) {
-                mService.onConnected(mServerCallback, sVerbose, sDebug);
+            if (connected) {
+                try {
+                    mService.onConnected(mServerCallback, sVerbose, sDebug);
+                } finally {
+                    // Update the system-service state, in case the service reconnected after
+                    // dying
+                    mPerUserService.onConnected();
+                }
             } else {
                 mService.onDisconnected();
             }
         } catch (Exception e) {
-            Slog.w(mTag, "Exception calling onConnectedStateChanged(" + state + "): " + e);
+            Slog.w(mTag, "Exception calling onConnectedStateChanged(" + connected + "): " + e);
         }
     }
 
@@ -86,8 +94,10 @@
      * {@link RemoteContentCaptureService} to indicate the session was created.
      */
     public void onSessionStarted(@Nullable ContentCaptureContext context,
-            @NonNull String sessionId, int uid, @NonNull IResultReceiver clientReceiver) {
-        scheduleAsyncRequest((s) -> s.onSessionStarted(context, sessionId, uid, clientReceiver));
+            @NonNull String sessionId, int uid, @NonNull IResultReceiver clientReceiver,
+            int initialState) {
+        scheduleAsyncRequest(
+                (s) -> s.onSessionStarted(context, sessionId, uid, clientReceiver, initialState));
     }
 
     /**
diff --git a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java
index 69b4672..55a0621 100644
--- a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java
+++ b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java
@@ -35,6 +35,7 @@
 import android.os.UserManager;
 import android.util.Slog;
 
+import com.android.internal.os.IResultReceiver;
 import com.android.server.LocalServices;
 import com.android.server.infra.AbstractMasterSystemService;
 import com.android.server.infra.FrameworkResourcesServiceNameResolver;
@@ -114,13 +115,14 @@
 
     private class ContentSuggestionsManagerStub extends IContentSuggestionsManager.Stub {
         @Override
-        public void provideContextImage(int taskId, @NonNull Bundle imageContextRequestExtras) {
+        public void provideContextImage(
+                int userId,
+                int taskId,
+                @NonNull Bundle imageContextRequestExtras) {
             if (imageContextRequestExtras == null) {
                 throw new IllegalArgumentException("Expected non-null imageContextRequestExtras");
             }
-
-            final int userId = UserHandle.getCallingUserId();
-            enforceCallerIsRecents(userId, "provideContextImage");
+            enforceCallerIsRecents(UserHandle.getCallingUserId(), "provideContextImage");
 
             synchronized (mLock) {
                 final ContentSuggestionsPerUserService service = getServiceForUserLocked(userId);
@@ -136,10 +138,10 @@
 
         @Override
         public void suggestContentSelections(
+                int userId,
                 @NonNull SelectionsRequest selectionsRequest,
                 @NonNull ISelectionsCallback selectionsCallback) {
-            final int userId = UserHandle.getCallingUserId();
-            enforceCallerIsRecents(userId, "suggestContentSelections");
+            enforceCallerIsRecents(UserHandle.getCallingUserId(), "suggestContentSelections");
 
             synchronized (mLock) {
                 final ContentSuggestionsPerUserService service = getServiceForUserLocked(userId);
@@ -155,10 +157,10 @@
 
         @Override
         public void classifyContentSelections(
+                int userId,
                 @NonNull ClassificationsRequest classificationsRequest,
                 @NonNull IClassificationsCallback callback) {
-            final int userId = UserHandle.getCallingUserId();
-            enforceCallerIsRecents(userId, "classifyContentSelections");
+            enforceCallerIsRecents(UserHandle.getCallingUserId(), "classifyContentSelections");
 
             synchronized (mLock) {
                 final ContentSuggestionsPerUserService service = getServiceForUserLocked(userId);
@@ -173,9 +175,9 @@
         }
 
         @Override
-        public void notifyInteraction(@NonNull String requestId, @NonNull Bundle bundle) {
-            final int userId = UserHandle.getCallingUserId();
-            enforceCallerIsRecents(userId, "notifyInteraction");
+        public void notifyInteraction(
+                int userId, @NonNull String requestId, @NonNull Bundle bundle) {
+            enforceCallerIsRecents(UserHandle.getCallingUserId(), "notifyInteraction");
 
             synchronized (mLock) {
                 final ContentSuggestionsPerUserService service = getServiceForUserLocked(userId);
@@ -189,6 +191,18 @@
             }
         }
 
+        @Override
+        public void isEnabled(int userId, @NonNull IResultReceiver receiver)
+                throws RemoteException {
+            enforceCallerIsRecents(UserHandle.getCallingUserId(), "isEnabled");
+
+            boolean isDisabled;
+            synchronized (mLock) {
+                isDisabled = isDisabledLocked(userId);
+            }
+            receiver.send(isDisabled ? 0 : 1, null);
+        }
+
         public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
                 @Nullable FileDescriptor err,
                 @NonNull String[] args, @Nullable ShellCallback callback,
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 72f7a68..b2ee686 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -41,7 +41,6 @@
 import static android.net.NetworkPolicyManager.RULE_NONE;
 import static android.net.NetworkPolicyManager.uidRulesToString;
 import static android.net.shared.NetworkMonitorUtils.isValidationRequired;
-import static android.net.shared.NetworkParcelableUtil.toStableParcelable;
 import static android.os.Process.INVALID_UID;
 import static android.system.OsConstants.IPPROTO_TCP;
 import static android.system.OsConstants.IPPROTO_UDP;
@@ -73,6 +72,7 @@
 import android.net.INetworkPolicyListener;
 import android.net.INetworkPolicyManager;
 import android.net.INetworkStatsService;
+import android.net.ISocketKeepaliveCallback;
 import android.net.ITetheringEventCallback;
 import android.net.InetAddresses;
 import android.net.IpPrefix;
@@ -299,6 +299,15 @@
     private INetworkPolicyManager mPolicyManager;
     private NetworkPolicyManagerInternal mPolicyManagerInternal;
 
+    /**
+     * TestNetworkService (lazily) created upon first usage. Locked to prevent creation of multiple
+     * instances.
+     */
+    @GuardedBy("mTNSLock")
+    private TestNetworkService mTNS;
+
+    private final Object mTNSLock = new Object();
+
     private String mCurrentTcpBufferSizes;
 
     private static final SparseArray<String> sMagicDecoderRing = MessageUtils.findMessageNames(
@@ -5380,7 +5389,7 @@
         final long token = Binder.clearCallingIdentity();
         try {
             getNetworkStack().makeNetworkMonitor(
-                    toStableParcelable(nai.network), name, new NetworkMonitorCallbacks(nai));
+                    nai.network, name, new NetworkMonitorCallbacks(nai));
         } finally {
             Binder.restoreCallingIdentity(token);
         }
@@ -6690,32 +6699,32 @@
     }
 
     @Override
-    public void startNattKeepalive(Network network, int intervalSeconds, Messenger messenger,
-            IBinder binder, String srcAddr, int srcPort, String dstAddr) {
+    public void startNattKeepalive(Network network, int intervalSeconds,
+            ISocketKeepaliveCallback cb, String srcAddr, int srcPort, String dstAddr) {
         enforceKeepalivePermission();
         mKeepaliveTracker.startNattKeepalive(
                 getNetworkAgentInfoForNetwork(network),
-                intervalSeconds, messenger, binder,
+                intervalSeconds, cb,
                 srcAddr, srcPort, dstAddr, NattSocketKeepalive.NATT_PORT);
     }
 
     @Override
     public void startNattKeepaliveWithFd(Network network, FileDescriptor fd, int resourceId,
-            int intervalSeconds, Messenger messenger, IBinder binder, String srcAddr,
+            int intervalSeconds, ISocketKeepaliveCallback cb, String srcAddr,
             String dstAddr) {
         enforceKeepalivePermission();
         mKeepaliveTracker.startNattKeepalive(
                 getNetworkAgentInfoForNetwork(network), fd, resourceId,
-                intervalSeconds, messenger, binder,
+                intervalSeconds, cb,
                 srcAddr, dstAddr, NattSocketKeepalive.NATT_PORT);
     }
 
     @Override
     public void startTcpKeepalive(Network network, FileDescriptor fd, int intervalSeconds,
-            Messenger messenger, IBinder binder) {
+            ISocketKeepaliveCallback cb) {
         enforceKeepalivePermission();
         mKeepaliveTracker.startTcpKeepalive(
-                getNetworkAgentInfoForNetwork(network), fd, intervalSeconds, messenger, binder);
+                getNetworkAgentInfoForNetwork(network), fd, intervalSeconds, cb);
     }
 
     @Override
@@ -6958,4 +6967,22 @@
             return vpn != null && vpn.getLockdown();
         }
     }
+
+    /**
+     * Returns a IBinder to a TestNetworkService. Will be lazily created as needed.
+     *
+     * <p>The TestNetworkService must be run in the system server due to TUN creation.
+     */
+    @Override
+    public IBinder startOrGetTestNetworkService() {
+        synchronized (mTNSLock) {
+            TestNetworkService.enforceTestNetworkPermissions(mContext);
+
+            if (mTNS == null) {
+                mTNS = new TestNetworkService(mContext, mNMS);
+            }
+
+            return mTNS;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index c2a0611..7fab2b96 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -501,6 +501,8 @@
         }
 
         if (broadcast) {
+            // needs to be sent to everyone because we don't know which user may have changed
+            // LOCATION_MODE state.
             mContext.sendBroadcastAsUser(
                     new Intent(LocationManager.MODE_CHANGED_ACTION),
                     UserHandle.ALL);
@@ -1212,6 +1214,13 @@
                             "-" + mName,
                             mCurrentUserId);
                 }
+
+                // needs to be sent to all users because whether or not a provider is enabled for
+                // a given user is complicated... we broadcast to everyone and let them figure it
+                // out via isProviderEnabled()
+                Intent intent = new Intent(LocationManager.PROVIDERS_CHANGED_ACTION);
+                intent.putExtra(LocationManager.EXTRA_PROVIDER_NAME, mName);
+                mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
             }
 
             if (useable == mUseable) {
@@ -1232,10 +1241,6 @@
             }
 
             updateProviderUseableLocked(this);
-
-            mContext.sendBroadcastAsUser(
-                    new Intent(LocationManager.PROVIDERS_CHANGED_ACTION),
-                    UserHandle.ALL);
         }
 
         @GuardedBy("mLock")
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index e28d484..f416110 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -2717,6 +2717,38 @@
     }
 
     /**
+     * Check whether the device supports filesystem checkpointing.
+     *
+     * @return true if the device supports filesystem checkpointing, false otherwise.
+     */
+    @Override
+    public boolean supportsCheckpoint() throws RemoteException {
+        // Only the system process is permitted to start checkpoints
+        if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
+            throw new SecurityException("no permission to check filesystem checkpoint support");
+        }
+
+        return mVold.supportsCheckpoint();
+    }
+
+    /**
+     * Signal that checkpointing partitions should start a checkpoint on the next boot.
+     *
+     * @param numTries Number of times to try booting in checkpoint mode, before we will boot
+     *                 non-checkpoint mode and commit all changes immediately. Callers are
+     *                 responsible for ensuring that boot is safe (eg, by rolling back updates).
+     */
+    @Override
+    public void startCheckpoint(int numTries) throws RemoteException {
+        // Only the system process is permitted to start checkpoints
+        if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
+            throw new SecurityException("no permission to start filesystem checkpoint");
+        }
+
+        mVold.startCheckpoint(numTries);
+    }
+
+    /**
      * Signal that checkpointing partitions should commit changes
      */
     @Override
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 710a0ba3..3a50aa8 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -30,13 +30,11 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.os.BatteryManager;
 import android.os.Binder;
-import android.os.Build;
 import android.os.Handler;
 import android.os.PowerManager;
 import android.os.PowerManager.ServiceType;
@@ -356,8 +354,8 @@
             try {
                 synchronized (mLock) {
                     if (mNightMode != mode) {
-                        // Only persist setting if not transient night mode or not in car mode
-                        if (!shouldTransientNightWhenInCarMode() || !mCarModeEnabled) {
+                        // Only persist setting if not in car mode
+                        if (!mCarModeEnabled) {
                             Settings.Secure.putIntForUser(getContext().getContentResolver(),
                                     Settings.Secure.UI_NIGHT_MODE, mode, user);
                         }
@@ -444,34 +442,12 @@
         }
     }
 
-    // Night mode settings in car mode are only persisted below Q.
-    // When targeting Q, changes are not saved and night mode will be re-read
-    // from settings when exiting car mode.
-    private boolean shouldTransientNightWhenInCarMode() {
-        int uid = Binder.getCallingUid();
-        PackageManager packageManager = getContext().getPackageManager();
-        String[] packagesForUid = packageManager.getPackagesForUid(uid);
-        if (packagesForUid == null || packagesForUid.length == 0) {
-            return false;
-        }
-
-        try {
-            ApplicationInfo appInfo = packageManager.getApplicationInfoAsUser(
-                    packagesForUid[0], 0, uid);
-
-            return appInfo.targetSdkVersion >= Build.VERSION_CODES.Q;
-        } catch (PackageManager.NameNotFoundException ignored) {
-        }
-
-        return false;
-    }
-
     void setCarModeLocked(boolean enabled, int flags) {
         if (mCarModeEnabled != enabled) {
             mCarModeEnabled = enabled;
 
-            // When transient night mode and exiting car mode, restore night mode from settings
-            if (shouldTransientNightWhenInCarMode() && !mCarModeEnabled) {
+            // When exiting car mode, restore night mode from settings
+            if (!mCarModeEnabled) {
                 Context context = getContext();
                 updateNightModeFromSettings(context,
                         context.getResources(),
@@ -534,9 +510,8 @@
             uiMode |= mNightMode << 4;
         }
 
-        // Override night mode in power save mode if not transient night mode or not in car mode
-        boolean shouldOverrideNight = !mCarModeEnabled || !shouldTransientNightWhenInCarMode();
-        if (mPowerSave && shouldOverrideNight) {
+        // Override night mode in power save mode if not in car mode
+        if (mPowerSave && !mCarModeEnabled) {
             uiMode &= ~Configuration.UI_MODE_NIGHT_NO;
             uiMode |= Configuration.UI_MODE_NIGHT_YES;
         }
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 85ec2dd..e357ce8 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -131,9 +131,6 @@
     // calling startForeground() before we ANR + stop it.
     static final int SERVICE_START_FOREGROUND_TIMEOUT = 10*1000;
 
-    // For how long after a whitelisted service's start its process can start a background activity
-    private static final int SERVICE_BG_ACTIVITY_START_TIMEOUT_MS = 10*1000;
-
     final ActivityManagerService mAm;
 
     // Maximum number of services that we allow to start in the background
@@ -333,8 +330,8 @@
                             + " delayedStop=" + r.delayedStop);
                 } else {
                     try {
-                        startServiceInnerLocked(this, r.pendingStarts.get(0).intent, r, false, true,
-                                false);
+                        startServiceInnerLocked(this, r.pendingStarts.get(0).intent, r, false,
+                                true);
                     } catch (TransactionTooLargeException e) {
                         // Ignore, nobody upstack cares.
                     }
@@ -637,26 +634,26 @@
         }
 
         if (allowBackgroundActivityStarts) {
-            ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false);
-            if (proc != null) {
-                proc.addAllowBackgroundActivityStartsToken(r);
-                // schedule removal of the whitelisting token after the timeout
-                removeAllowBackgroundActivityStartsServiceToken(proc, r,
-                        SERVICE_BG_ACTIVITY_START_TIMEOUT_MS);
-            }
+            r.hasStartedWhitelistingBgActivityStarts = true;
+            scheduleCleanUpHasStartedWhitelistingBgActivityStartsLocked(r);
         }
-        ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting,
-                allowBackgroundActivityStarts);
+
+        ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
         return cmp;
     }
 
-    private void removeAllowBackgroundActivityStartsServiceToken(ProcessRecord proc,
-            ServiceRecord r, int delayMillis) {
-        mAm.mHandler.postDelayed(() -> {
-            if (proc != null) {
-                proc.removeAllowBackgroundActivityStartsToken(r);
-            }
-        }, delayMillis);
+    private void scheduleCleanUpHasStartedWhitelistingBgActivityStartsLocked(ServiceRecord r) {
+        // if there's a request pending from the past, drop it before scheduling a new one
+        if (r.startedWhitelistingBgActivityStartsCleanUp == null) {
+            r.startedWhitelistingBgActivityStartsCleanUp = () -> {
+                synchronized(mAm) {
+                    r.setHasStartedWhitelistingBgActivityStarts(false);
+                }
+            };
+        }
+        mAm.mHandler.removeCallbacks(r.startedWhitelistingBgActivityStartsCleanUp);
+        mAm.mHandler.postDelayed(r.startedWhitelistingBgActivityStartsCleanUp,
+                mAm.mConstants.SERVICE_BG_ACTIVITY_START_TIMEOUT);
     }
 
     private boolean requestStartTargetPermissionsReviewIfNeededLocked(ServiceRecord r,
@@ -705,8 +702,7 @@
     }
 
     ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
-            boolean callerFg, boolean addToStarting, boolean allowBackgroundActivityStarts)
-            throws TransactionTooLargeException {
+            boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
         ServiceState stracker = r.getTracker();
         if (stracker != null) {
             stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
@@ -717,8 +713,7 @@
         synchronized (r.stats.getBatteryStats()) {
             r.stats.startRunningLocked();
         }
-        String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false,
-                allowBackgroundActivityStarts);
+        String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
         if (error != null) {
             return new ComponentName("!!", error);
         }
@@ -765,6 +760,12 @@
                     SystemClock.uptimeMillis());
         }
         service.callStart = false;
+
+        // the service will not necessarily be brought down, so only clear the whitelisting state
+        // for start-based bg activity starts now, and drop any existing future cleanup callback
+        service.setHasStartedWhitelistingBgActivityStarts(false);
+        mAm.mHandler.removeCallbacks(service.startedWhitelistingBgActivityStartsCleanUp);
+
         bringDownServiceIfNeededLocked(service, false, false);
     }
 
@@ -788,9 +789,6 @@
             if (r.record != null) {
                 final long origId = Binder.clearCallingIdentity();
                 try {
-                    // immediately remove bg activity whitelisting token if there was one
-                    removeAllowBackgroundActivityStartsServiceToken(callerApp, r.record,
-                            0 /* delayMillis */);
                     stopServiceLocked(r.record);
                 } finally {
                     Binder.restoreCallingIdentity(origId);
@@ -1602,6 +1600,11 @@
                     "BIND_TREAT_LIKE_ACTIVITY");
         }
 
+        if ((flags & Context.BIND_SCHEDULE_LIKE_TOP_APP) != 0 && !isCallerSystem) {
+            throw new SecurityException("Non-system caller (pid=" + Binder.getCallingPid()
+                    + ") set BIND_SCHEDULE_LIKE_TOP_APP when binding service " + service);
+        }
+
         if ((flags & Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0 && !isCallerSystem) {
             throw new SecurityException(
                     "Non-system caller " + caller + " (pid=" + Binder.getCallingPid()
@@ -1614,6 +1617,12 @@
                             + ") set BIND_ALLOW_INSTANT when binding service " + service);
         }
 
+        if ((flags & Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS) != 0) {
+            mAm.enforceCallingPermission(
+                    android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND,
+                    "BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS");
+        }
+
         final boolean callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
         final boolean isBindExternal = (flags & Context.BIND_EXTERNAL_SERVICE) != 0;
         final boolean allowInstant = (flags & Context.BIND_ALLOW_INSTANT) != 0;
@@ -1672,7 +1681,7 @@
                                 try {
                                     bringUpServiceLocked(serviceRecord,
                                             serviceIntent.getFlags(),
-                                            callerFg, false, false, false);
+                                            callerFg, false, false);
                                 } catch (RemoteException e) {
                                     /* ignore - local call */
                                 }
@@ -1762,6 +1771,9 @@
             if ((c.flags&Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0) {
                 s.whitelistManager = true;
             }
+            if ((flags & Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS) != 0) {
+                s.setHasBindingWhitelistingBgActivityStarts(true);
+            }
             if (s.app != null) {
                 updateServiceClientActivitiesLocked(s.app, c, true);
             }
@@ -1775,7 +1787,7 @@
             if ((flags&Context.BIND_AUTO_CREATE) != 0) {
                 s.lastActivity = SystemClock.uptimeMillis();
                 if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
-                        permissionsReviewRequired, false) != null) {
+                        permissionsReviewRequired) != null) {
                     return 0;
                 }
             }
@@ -2445,8 +2457,7 @@
             return;
         }
         try {
-            bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true, false,
-                    false);
+            bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true, false);
         } catch (TransactionTooLargeException e) {
             // Ignore, it's been logged and nothing upstack cares.
         }
@@ -2491,11 +2502,8 @@
     }
 
     private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
-            boolean whileRestarting, boolean permissionsReviewRequired,
-            boolean allowBackgroundActivityStarts) throws TransactionTooLargeException {
-        //Slog.i(TAG, "Bring up service:");
-        //r.dump("  ");
-
+            boolean whileRestarting, boolean permissionsReviewRequired)
+            throws TransactionTooLargeException {
         if (r.app != null && r.app.thread != null) {
             sendServiceArgsLocked(r, execInFg, false);
             return null;
@@ -2603,13 +2611,6 @@
             }
         }
 
-        if (app != null && allowBackgroundActivityStarts) {
-            app.addAllowBackgroundActivityStartsToken(r);
-            // schedule removal of the whitelisting token after the timeout
-            removeAllowBackgroundActivityStartsServiceToken(app, r,
-                    SERVICE_BG_ACTIVITY_START_TIMEOUT_MS);
-        }
-
         if (r.fgRequired) {
             if (DEBUG_FOREGROUND_SERVICE) {
                 Slog.v(TAG, "Whitelisting " + UserHandle.formatUid(r.appInfo.uid)
@@ -2646,6 +2647,11 @@
         }
     }
 
+    /**
+     * Note the name of this method should not be confused with the started services concept.
+     * The "start" here means bring up the instance in the client, and this method is called
+     * from bindService() as well.
+     */
     private final void realStartServiceLocked(ServiceRecord r,
             ProcessRecord app, boolean execInFg) throws RemoteException {
         if (app.thread == null) {
@@ -3085,6 +3091,10 @@
                     updateWhitelistManagerLocked(s.app);
                 }
             }
+            // And do the same for bg activity starts whitelisting.
+            if ((c.flags & Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS) != 0) {
+                s.updateHasBindingWhitelistingBgActivityStarts();
+            }
             if (s.app != null) {
                 updateServiceClientActivitiesLocked(s.app, c, true);
             }
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index f9fcef6..1751856 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -69,6 +69,7 @@
     static final String KEY_SERVICE_MIN_RESTART_TIME_BETWEEN = "service_min_restart_time_between";
     static final String KEY_MAX_SERVICE_INACTIVITY = "service_max_inactivity";
     static final String KEY_BG_START_TIMEOUT = "service_bg_start_timeout";
+    static final String KEY_SERVICE_BG_ACTIVITY_START_TIMEOUT = "service_bg_activity_start_timeout";
     static final String KEY_BOUND_SERVICE_CRASH_RESTART_DURATION = "service_crash_restart_duration";
     static final String KEY_BOUND_SERVICE_CRASH_MAX_RETRY = "service_crash_max_retry";
     static final String KEY_PROCESS_START_ASYNC = "process_start_async";
@@ -99,6 +100,7 @@
     private static final long DEFAULT_SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
     private static final long DEFAULT_MAX_SERVICE_INACTIVITY = 30*60*1000;
     private static final long DEFAULT_BG_START_TIMEOUT = 15*1000;
+    private static final long DEFAULT_SERVICE_BG_ACTIVITY_START_TIMEOUT = 10_000;
     private static final long DEFAULT_BOUND_SERVICE_CRASH_RESTART_DURATION = 30*60_000;
     private static final int DEFAULT_BOUND_SERVICE_CRASH_MAX_RETRY = 16;
     private static final boolean DEFAULT_PROCESS_START_ASYNC = true;
@@ -212,6 +214,9 @@
     // allowing the next pending start to run.
     public long BG_START_TIMEOUT = DEFAULT_BG_START_TIMEOUT;
 
+    // For how long after a whitelisted service's start its process can start a background activity
+    public long SERVICE_BG_ACTIVITY_START_TIMEOUT = DEFAULT_SERVICE_BG_ACTIVITY_START_TIMEOUT;
+
     // Initial backoff delay for retrying bound foreground services
     public long BOUND_SERVICE_CRASH_RESTART_DURATION = DEFAULT_BOUND_SERVICE_CRASH_RESTART_DURATION;
 
@@ -398,6 +403,9 @@
                     DEFAULT_MAX_SERVICE_INACTIVITY);
             BG_START_TIMEOUT = mParser.getLong(KEY_BG_START_TIMEOUT,
                     DEFAULT_BG_START_TIMEOUT);
+            SERVICE_BG_ACTIVITY_START_TIMEOUT = mParser.getLong(
+                    KEY_SERVICE_BG_ACTIVITY_START_TIMEOUT,
+                    DEFAULT_SERVICE_BG_ACTIVITY_START_TIMEOUT);
             BOUND_SERVICE_CRASH_RESTART_DURATION = mParser.getLong(
                 KEY_BOUND_SERVICE_CRASH_RESTART_DURATION,
                 DEFAULT_BOUND_SERVICE_CRASH_RESTART_DURATION);
@@ -518,6 +526,8 @@
         pw.println(MAX_SERVICE_INACTIVITY);
         pw.print("  "); pw.print(KEY_BG_START_TIMEOUT); pw.print("=");
         pw.println(BG_START_TIMEOUT);
+        pw.print("  "); pw.print(KEY_SERVICE_BG_ACTIVITY_START_TIMEOUT); pw.print("=");
+        pw.println(SERVICE_BG_ACTIVITY_START_TIMEOUT);
         pw.print("  "); pw.print(KEY_BOUND_SERVICE_CRASH_RESTART_DURATION); pw.print("=");
         pw.println(BOUND_SERVICE_CRASH_RESTART_DURATION);
         pw.print("  "); pw.print(KEY_BOUND_SERVICE_CRASH_MAX_RETRY); pw.print("=");
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 0a80d45..8225476 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -251,6 +251,7 @@
 import android.os.Message;
 import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
+import android.os.PowerManager;
 import android.os.PowerManager.ServiceType;
 import android.os.PowerManagerInternal;
 import android.os.Process;
@@ -268,6 +269,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.WorkSource;
+import android.os.storage.IStorageManager;
 import android.os.storage.StorageManager;
 import android.provider.Settings;
 import android.sysprop.VoldProperties;
@@ -306,6 +308,7 @@
 import com.android.internal.app.ProcessMap;
 import com.android.internal.app.SystemUserHomeActivity;
 import com.android.internal.app.procstats.ProcessStats;
+import com.android.internal.content.PackageHelper;
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.os.BackgroundThread;
@@ -2931,8 +2934,8 @@
                         taskRoot);
             }
         }
-        if (mContentCaptureService != null
-                && (event == Event.ACTIVITY_PAUSED || event == Event.ACTIVITY_RESUMED)) {
+        if (mContentCaptureService != null && (event == Event.ACTIVITY_PAUSED
+                || event == Event.ACTIVITY_RESUMED || event == Event.ACTIVITY_STOPPED)) {
             mContentCaptureService.notifyActivityEvent(userId, activity, event);
         }
     }
@@ -5020,6 +5023,16 @@
             }
         }, dumpheapFilter);
 
+        // Inform checkpointing systems of success
+        try {
+            IStorageManager storageManager = PackageHelper.getStorageManager();
+            storageManager.commitChanges();
+        } catch (Exception e) {
+            PowerManager pm = (PowerManager)
+                     mInjector.getContext().getSystemService(Context.POWER_SERVICE);
+            pm.reboot("Checkpoint commit failed");
+        }
+
         // Let system services know.
         mSystemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETED);
 
@@ -5479,6 +5492,12 @@
         }
     }
 
+    private boolean isAppBad(ApplicationInfo info) {
+        synchronized (this) {
+            return mAppErrors.isBadProcessLocked(info);
+        }
+    }
+
     // NOTE: this is an internal method used by the OnShellCommand implementation only and should
     // be guarded by permission checking.
     int getUidState(int uid) {
@@ -18065,6 +18084,11 @@
         }
 
         @Override
+        public boolean isAppBad(ApplicationInfo info) {
+            return ActivityManagerService.this.isAppBad(info);
+        }
+
+        @Override
         public void clearPendingBackup(int userId) {
             ActivityManagerService.this.clearPendingBackup(userId);
         }
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 57ce98c..cc90182 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -65,6 +65,7 @@
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.IProgressListener;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteCallback;
 import android.os.RemoteCallback.OnResultListener;
@@ -103,6 +104,7 @@
 import java.util.List;
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 import javax.microedition.khronos.egl.EGL10;
 import javax.microedition.khronos.egl.EGLConfig;
@@ -114,6 +116,8 @@
     public static final String NO_CLASS_ERROR_CODE = "Error type 3";
     private static final String SHELL_PACKAGE_NAME = "com.android.shell";
 
+    private static final int USER_OPERATION_TIMEOUT_MS = 2 * 60 * 1000; // 2 minutes
+
     // IPC interface to activity manager -- don't need to do additional security checks.
     final IActivityManager mInterface;
     final IActivityTaskManager mTaskInterface;
@@ -377,6 +381,30 @@
         });
     }
 
+    private class ProgressWaiter extends IProgressListener.Stub {
+        private final CountDownLatch mFinishedLatch = new CountDownLatch(1);
+
+        @Override
+        public void onStarted(int id, Bundle extras) {}
+
+        @Override
+        public void onProgress(int id, int progress, Bundle extras) {}
+
+        @Override
+        public void onFinished(int id, Bundle extras) {
+            mFinishedLatch.countDown();
+        }
+
+        public boolean waitForFinish(long timeoutMillis) {
+            try {
+                return mFinishedLatch.await(timeoutMillis, TimeUnit.MILLISECONDS);
+            } catch (InterruptedException e) {
+                System.err.println("Thread interrupted unexpectedly.");
+                return false;
+            }
+        }
+    }
+
     int runStartActivity(PrintWriter pw) throws RemoteException {
         Intent intent;
         try {
@@ -1692,8 +1720,24 @@
     }
 
     int runStartUser(PrintWriter pw) throws RemoteException {
-        String user = getNextArgRequired();
-        boolean success = mInterface.startUserInBackground(Integer.parseInt(user));
+        boolean wait = false;
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            if ("-w".equals(opt)) {
+                wait = true;
+            } else {
+                getErrPrintWriter().println("Error: unknown option: " + opt);
+                return -1;
+            }
+        }
+        int userId = Integer.parseInt(getNextArgRequired());
+
+        final ProgressWaiter waiter = wait ? new ProgressWaiter() : null;
+        boolean success = mInterface.startUserInBackgroundWithListener(userId, waiter);
+        if (wait && success) {
+            success = waiter.waitForFinish(USER_OPERATION_TIMEOUT_MS);
+        }
+
         if (success) {
             pw.println("Success: user started");
         } else {
@@ -3023,9 +3067,10 @@
             pw.println("      execution of that user if it is currently stopped.");
             pw.println("  get-current-user");
             pw.println("      Returns id of the current foreground user.");
-            pw.println("  start-user <USER_ID>");
+            pw.println("  start-user [-w] <USER_ID>");
             pw.println("      Start USER_ID in background if it is currently stopped;");
-            pw.println("      use switch-user if you want to start the user in foreground");
+            pw.println("      use switch-user if you want to start the user in foreground.");
+            pw.println("      -w: wait for start-user to complete and the user to be unlocked.");
             pw.println("  unlock-user <USER_ID> [TOKEN_HEX]");
             pw.println("      Attempt to unlock the given user using the given authorization token.");
             pw.println("  stop-user [-w] [-f] <USER_ID>");
diff --git a/services/core/java/com/android/server/am/AppCompactor.java b/services/core/java/com/android/server/am/AppCompactor.java
index 1f21160..438538f 100644
--- a/services/core/java/com/android/server/am/AppCompactor.java
+++ b/services/core/java/com/android/server/am/AppCompactor.java
@@ -211,7 +211,7 @@
         mPendingCompactionProcesses.add(app);
         mCompactionHandler.sendMessage(
             mCompactionHandler.obtainMessage(
-                COMPACT_PROCESS_MSG, app.curAdj, app.setProcState));
+                COMPACT_PROCESS_MSG, app.setAdj, app.setProcState));
     }
 
     @GuardedBy("mAm")
@@ -220,7 +220,7 @@
         mPendingCompactionProcesses.add(app);
         mCompactionHandler.sendMessage(
             mCompactionHandler.obtainMessage(
-                COMPACT_PROCESS_MSG, app.curAdj, app.setProcState));
+                COMPACT_PROCESS_MSG, app.setAdj, app.setProcState));
 
     }
 
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 70733ef..ea23081 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -477,14 +477,22 @@
         // when processNextBroadcastLocked() next finds this uid as a receiver identity.
         if (!r.timeoutExempt) {
             if (mConstants.SLOW_TIME > 0 && elapsed > mConstants.SLOW_TIME) {
-                if (DEBUG_BROADCAST_DEFERRAL) {
-                    Slog.i(TAG_BROADCAST, "Broadcast receiver " + (r.nextReceiver - 1)
-                            + " was slow: " + receiver + " br=" + r);
-                }
-                if (r.curApp != null) {
-                    mDispatcher.startDeferring(r.curApp.uid);
+                // Core system packages are exempt from deferral policy
+                if (!UserHandle.isCore(r.curApp.uid)) {
+                    if (DEBUG_BROADCAST_DEFERRAL) {
+                        Slog.i(TAG_BROADCAST, "Broadcast receiver " + (r.nextReceiver - 1)
+                                + " was slow: " + receiver + " br=" + r);
+                    }
+                    if (r.curApp != null) {
+                        mDispatcher.startDeferring(r.curApp.uid);
+                    } else {
+                        Slog.d(TAG_BROADCAST, "finish receiver curApp is null? " + r);
+                    }
                 } else {
-                    Slog.d(TAG_BROADCAST, "finish receiver curApp is null? " + r);
+                    if (DEBUG_BROADCAST_DEFERRAL) {
+                        Slog.i(TAG_BROADCAST, "Core uid " + r.curApp.uid
+                                + " receiver was slow but not deferring: " + receiver + " br=" + r);
+                    }
                 }
             }
         } else {
diff --git a/services/core/java/com/android/server/am/ConnectionRecord.java b/services/core/java/com/android/server/am/ConnectionRecord.java
index af1031e..a1c941e 100644
--- a/services/core/java/com/android/server/am/ConnectionRecord.java
+++ b/services/core/java/com/android/server/am/ConnectionRecord.java
@@ -192,6 +192,9 @@
         if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
             sb.append("LACT ");
         }
+        if ((flags & Context.BIND_SCHEDULE_LIKE_TOP_APP) != 0) {
+            sb.append("SLTA ");
+        }
         if ((flags&Context.BIND_VISIBLE) != 0) {
             sb.append("VIS ");
         }
diff --git a/services/core/java/com/android/server/am/MemoryStatUtil.java b/services/core/java/com/android/server/am/MemoryStatUtil.java
index a584914..0d03580 100644
--- a/services/core/java/com/android/server/am/MemoryStatUtil.java
+++ b/services/core/java/com/android/server/am/MemoryStatUtil.java
@@ -57,15 +57,18 @@
     private static final String PROC_STATUS_FILE_FMT = "/proc/%d/status";
     /** Path to procfs cmdline file. Used with pid: /proc/pid/cmdline. */
     private static final String PROC_CMDLINE_FILE_FMT = "/proc/%d/cmdline";
+    /** Path to debugfs file for the system ion heap. */
+    private static final String DEBUG_SYSTEM_ION_HEAP_FILE = "/sys/kernel/debug/ion/heaps/system";
 
     private static final Pattern PGFAULT = Pattern.compile("total_pgfault (\\d+)");
     private static final Pattern PGMAJFAULT = Pattern.compile("total_pgmajfault (\\d+)");
     private static final Pattern RSS_IN_BYTES = Pattern.compile("total_rss (\\d+)");
     private static final Pattern CACHE_IN_BYTES = Pattern.compile("total_cache (\\d+)");
     private static final Pattern SWAP_IN_BYTES = Pattern.compile("total_swap (\\d+)");
-
     private static final Pattern RSS_HIGH_WATERMARK_IN_BYTES =
             Pattern.compile("VmHWM:\\s*(\\d+)\\s*kB");
+    private static final Pattern ION_HEAP_SIZE_IN_BYTES =
+            Pattern.compile("\n\\s*total\\s*(\\d+)\\s*\n");
 
     private static final int PGFAULT_INDEX = 9;
     private static final int PGMAJFAULT_INDEX = 11;
@@ -127,6 +130,16 @@
         return parseCmdlineFromProcfs(readFileContents(path));
     }
 
+    /**
+     * Reads size of the system ion heap from debugfs.
+     *
+     * Returns value of the total size in bytes of the system ion heap from
+     * /sys/kernel/debug/ion/heaps/system.
+     */
+    public static long readSystemIonHeapSizeFromDebugfs() {
+        return parseIonHeapSizeFromDebugfs(readFileContents(DEBUG_SYSTEM_ION_HEAP_FILE));
+    }
+
     private static String readFileContents(String path) {
         final File file = new File(path);
         if (!file.exists()) {
@@ -228,6 +241,19 @@
     }
 
     /**
+     * Parses the ion heap size from the contents of a file under /sys/kernel/debug/ion/heaps in
+     * debugfs. The returned value is in bytes.
+     */
+    @VisibleForTesting
+    static long parseIonHeapSizeFromDebugfs(String contents) {
+        if (contents == null || contents.isEmpty()) {
+            return 0;
+        }
+        Matcher m = ION_HEAP_SIZE_IN_BYTES.matcher(contents);
+        return m.find() ? Long.parseLong(m.group(1)) : 0;
+    }
+
+    /**
      * Returns whether per-app memcg is available on device.
      */
     static boolean hasMemcg() {
diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS
index e483b26..877bef7 100644
--- a/services/core/java/com/android/server/am/OWNERS
+++ b/services/core/java/com/android/server/am/OWNERS
@@ -23,6 +23,9 @@
 svetoslavganov@google.com
 toddke@google.com
 
+# Battery Stats
+joeo@google.com
+
 # Londoners
 michaelwr@google.com
 narayan@google.com
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 4e03b72..9056f76 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -1294,6 +1294,11 @@
                                         ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
                             }
                         }
+                        if (schedGroup < ProcessList.SCHED_GROUP_TOP_APP
+                                && (cr.flags & Context.BIND_SCHEDULE_LIKE_TOP_APP) != 0) {
+                            schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
+                        }
+
                         if (!trackedProcState) {
                             cr.trackProcState(clientProcState, mAdjSeq, now);
                         }
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 0387774..eeaa7de 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -125,6 +125,14 @@
     int pendingConnectionGroup;        // To be filled in to ProcessRecord once it connects
     int pendingConnectionImportance;   // To be filled in to ProcessRecord once it connects
 
+    // any current binding to this service has BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS flag?
+    private boolean hasBindingWhitelistingBgActivityStarts;
+    // is this service currently whitelisted to start activities from background by providing
+    // allowBackgroundActivityStarts=true to startServiceLocked()?
+    boolean hasStartedWhitelistingBgActivityStarts;
+    // used to clean up the state of hasStartedWhitelistingBgActivityStarts after a timeout
+    Runnable startedWhitelistingBgActivityStartsCleanUp;
+
     String stringName;      // caching of toString
 
     private int lastStartId;    // identifier of most recent start request.
@@ -371,6 +379,14 @@
         if (whitelistManager) {
             pw.print(prefix); pw.print("whitelistManager="); pw.println(whitelistManager);
         }
+        if (hasBindingWhitelistingBgActivityStarts) {
+            pw.print(prefix); pw.print("hasBindingWhitelistingBgActivityStarts=");
+            pw.println(hasBindingWhitelistingBgActivityStarts);
+        }
+        if (hasStartedWhitelistingBgActivityStarts) {
+            pw.print(prefix); pw.print("hasStartedWhitelistingBgActivityStarts=");
+            pw.println(hasStartedWhitelistingBgActivityStarts);
+        }
         if (delayed) {
             pw.print(prefix); pw.print("delayed="); pw.println(delayed);
         }
@@ -518,6 +534,15 @@
     }
 
     public void setProcess(ProcessRecord _proc) {
+        if (_proc != null) {
+            if (hasStartedWhitelistingBgActivityStarts || hasBindingWhitelistingBgActivityStarts) {
+                _proc.addAllowBackgroundActivityStartsToken(this);
+            } else {
+                _proc.removeAllowBackgroundActivityStartsToken(this);
+            }
+        } else if (app != null) {
+            app.removeAllowBackgroundActivityStartsToken(this);
+        }
         app = _proc;
         if (pendingConnectionGroup > 0 && _proc != null) {
             _proc.connectionService = this;
@@ -540,6 +565,62 @@
         }
     }
 
+    void updateHasBindingWhitelistingBgActivityStarts() {
+        boolean hasWhitelistingBinding = false;
+        for (int conni = connections.size() - 1; conni >= 0; conni--) {
+            ArrayList<ConnectionRecord> cr = connections.valueAt(conni);
+            for (int i = 0; i < cr.size(); i++) {
+                if ((cr.get(i).flags & Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS) != 0) {
+                    hasWhitelistingBinding = true;
+                    break;
+                }
+            }
+            if (hasWhitelistingBinding) {
+                break;
+            }
+        }
+        if (hasBindingWhitelistingBgActivityStarts != hasWhitelistingBinding) {
+            hasBindingWhitelistingBgActivityStarts = hasWhitelistingBinding;
+            updateParentProcessBgActivityStartsWhitelistingToken();
+        }
+    }
+
+    void setHasBindingWhitelistingBgActivityStarts(boolean newValue) {
+        if (hasBindingWhitelistingBgActivityStarts != newValue) {
+            hasBindingWhitelistingBgActivityStarts = newValue;
+            updateParentProcessBgActivityStartsWhitelistingToken();
+        }
+    }
+
+    void setHasStartedWhitelistingBgActivityStarts(boolean newValue) {
+        if (hasStartedWhitelistingBgActivityStarts != newValue) {
+            hasStartedWhitelistingBgActivityStarts = newValue;
+            updateParentProcessBgActivityStartsWhitelistingToken();
+        }
+    }
+
+    /**
+     * Whether the process this service runs in should be temporarily whitelisted to start
+     * activities from background depends on the current state of both
+     * {@code hasStartedWhitelistingBgActivityStarts} and
+     * {@code hasBindingWhitelistingBgActivityStarts}. If either is true, this ServiceRecord
+     * should be contributing as a token in parent ProcessRecord.
+     *
+     * @see com.android.server.am.ProcessRecord#mAllowBackgroundActivityStartsTokens
+     */
+    private void updateParentProcessBgActivityStartsWhitelistingToken() {
+        if (app == null) {
+            return;
+        }
+        if (hasStartedWhitelistingBgActivityStarts || hasBindingWhitelistingBgActivityStarts) {
+            // if the token is already there it's safe to "re-add it" - we're deadling with
+            // a set of Binder objects
+            app.addAllowBackgroundActivityStartsToken(this);
+        } else {
+            app.removeAllowBackgroundActivityStartsToken(this);
+        }
+    }
+
     public AppBindRecord retrieveAppBindingLocked(Intent intent,
             ProcessRecord app) {
         Intent.FilterComparison filter = new Intent.FilterComparison(intent);
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index 194549f..99380c9 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -83,8 +83,8 @@
         DeviceConfig.NAMESPACE_INPUT_NATIVE_BOOT,
         DeviceConfig.NAMESPACE_MEDIA_NATIVE,
         DeviceConfig.NAMESPACE_NETD_NATIVE,
+        DeviceConfig.NAMESPACE_RUNTIME_NATIVE,
         DeviceConfig.NAMESPACE_RUNTIME_NATIVE_BOOT,
-        DeviceConfig.RuntimeNative.NAMESPACE,
     };
 
     private final String[] mGlobalSettings;
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 1e406c0..029c3fb 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -67,7 +67,6 @@
 import android.os.IUserManager;
 import android.os.Looper;
 import android.os.Message;
-import android.os.PowerManager;
 import android.os.Process;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
@@ -335,14 +334,6 @@
                 return;
             }
         }
-        // Inform checkpointing systems of success
-        try {
-            getStorageManager().commitChanges();
-        } catch (Exception e) {
-            PowerManager pm = (PowerManager)
-                     mInjector.getContext().getSystemService(Context.POWER_SERVICE);
-            pm.reboot("Checkpoint commit failed");
-        }
 
         // We always walk through all the user lifecycle states to send
         // consistent developer events. We step into RUNNING_LOCKED here,
@@ -938,6 +929,7 @@
      *
      * @param userId ID of the user to start
      * @param foreground true if user should be brought to the foreground
+     * @param unlockListener Listener to be informed when the user has started and unlocked.
      * @return true if the user has been successfully started
      */
     boolean startUser(
@@ -962,6 +954,15 @@
         try {
             final int oldUserId = getCurrentUserId();
             if (oldUserId == userId) {
+                final UserState state = getStartedUserState(userId);
+                if (state != null && state.state == STATE_RUNNING_UNLOCKED) {
+                    // We'll skip all later code, so we must tell listener it's already unlocked.
+                    try {
+                        unlockListener.onFinished(userId, null);
+                    } catch (RemoteException ignore) {
+                        // Ignore.
+                    }
+                }
                 return true;
             }
 
@@ -1547,8 +1548,8 @@
                     }
                     builder.append(" asks to run as user ");
                     builder.append(userId);
-                    builder.append(" but is calling from user ");
-                    builder.append(UserHandle.getUserId(callingUid));
+                    builder.append(" but is calling from uid ");
+                    UserHandle.formatUid(builder, callingUid);
                     builder.append("; this requires ");
                     builder.append(INTERACT_ACROSS_USERS_FULL);
                     if (allowMode != ALLOW_FULL_ONLY) {
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index ba7288e..9c26526 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -1742,10 +1742,31 @@
         return checkOperationUnchecked(code, uid, resolvedPackageName, raw);
     }
 
-    private int checkOperationUnchecked(int code, int uid, String packageName,
-                boolean raw) {
+    /**
+     * @see #checkOperationUnchecked(int, int, String, boolean, boolean)
+     */
+    private @Mode int checkOperationUnchecked(int code, int uid, @NonNull String packageName,
+            boolean raw) {
+        return checkOperationUnchecked(code, uid, packageName, raw, true);
+    }
+
+    /**
+     * Get the mode of an app-op.
+     *
+     * @param code The code of the op
+     * @param uid The uid of the package the op belongs to
+     * @param packageName The package the op belongs to
+     * @param raw If the raw state of eval-ed state should be checked.
+     * @param verify If the code should check the package belongs to the uid
+     *
+     * @return The mode of the op
+     */
+    private @Mode int checkOperationUnchecked(int code, int uid, @NonNull String packageName,
+                boolean raw, boolean verify) {
         synchronized (this) {
-            checkPackage(uid, packageName);
+            if (verify) {
+                checkPackage(uid, packageName);
+            }
             if (isOpRestrictedLocked(uid, code, packageName)) {
                 return AppOpsManager.MODE_IGNORED;
             }
@@ -1756,7 +1777,7 @@
                 final int rawMode = uidState.opModes.get(code);
                 return raw ? rawMode : uidState.evalMode(code, rawMode);
             }
-            Op op = getOpLocked(code, uid, packageName, false, true, false);
+            Op op = getOpLocked(code, uid, packageName, false, verify, false);
             if (op == null) {
                 return AppOpsManager.opToDefaultMode(code);
             }
@@ -2359,7 +2380,7 @@
         throw new IllegalArgumentException("Bad operation #" + op);
     }
 
-    private @NonNull UidState getUidStateLocked(int uid, boolean edit) {
+    private @Nullable UidState getUidStateLocked(int uid, boolean edit) {
         UidState uidState = mUidStates.get(uid);
         if (uidState == null) {
             if (!edit) {
@@ -4535,5 +4556,10 @@
         public void setAllPkgModesToDefault(int code, int uid) {
             AppOpsService.this.setAllPkgModesToDefault(code, uid);
         }
+
+        @Override
+        public @Mode int checkOperationUnchecked(int code, int uid, @NonNull String packageName) {
+            return AppOpsService.this.checkOperationUnchecked(code, uid, packageName, true, false);
+        }
     }
 }
diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java
index 5965d59..4e0380d 100644
--- a/services/core/java/com/android/server/attention/AttentionManagerService.java
+++ b/services/core/java/com/android/server/attention/AttentionManagerService.java
@@ -16,9 +16,7 @@
 
 package com.android.server.attention;
 
-import static android.provider.DeviceConfig.AttentionManagerService.COMPONENT_NAME;
-import static android.provider.DeviceConfig.AttentionManagerService.NAMESPACE;
-import static android.provider.DeviceConfig.AttentionManagerService.SERVICE_ENABLED;
+import static android.provider.DeviceConfig.NAMESPACE_ATTENTION_MANAGER_SERVICE;
 
 import android.Manifest;
 import android.annotation.Nullable;
@@ -61,6 +59,7 @@
 import com.android.internal.util.Preconditions;
 import com.android.server.SystemService;
 
+import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
 /**
@@ -80,6 +79,12 @@
     /** If the check attention called within that period - cached value will be returned. */
     private static final long STALE_AFTER_MILLIS = 5_000;
 
+    /** DeviceConfig flag name, if {@code true}, enables AttentionManagerService features. */
+    private static final String SERVICE_ENABLED = "service_enabled";
+
+    /** DeviceConfig flag name, allows a CTS to inject a fake implementation. */
+    private static final String COMPONENT_NAME = "component_name";
+
     private final Context mContext;
     private final PowerManager mPowerManager;
     private final Object mLock;
@@ -99,6 +104,7 @@
 
     @Override
     public void onStart() {
+        publishBinderService(Context.ATTENTION_SERVICE, new BinderService());
         publishLocalService(AttentionManagerInternal.class, new LocalService());
     }
 
@@ -122,12 +128,13 @@
     /**
      * Returns {@code true} if attention service is supported on this device.
      */
-    public boolean isAttentionServiceSupported() {
+    private boolean isAttentionServiceSupported() {
         return isServiceEnabled() && isServiceAvailable();
     }
 
     private boolean isServiceEnabled() {
-        return DeviceConfig.getBoolean(NAMESPACE, SERVICE_ENABLED, DEFAULT_SERVICE_ENABLED);
+        return DeviceConfig.getBoolean(NAMESPACE_ATTENTION_MANAGER_SERVICE, SERVICE_ENABLED,
+                DEFAULT_SERVICE_ENABLED);
     }
 
     /**
@@ -135,7 +142,7 @@
      *
      * @return {@code true} if the framework was able to send the provided callback to the service
      */
-    public boolean checkAttention(int requestCode, long timeout,
+    private boolean checkAttention(int requestCode, long timeout,
             AttentionCallbackInternal callback) {
         Preconditions.checkNotNull(callback);
 
@@ -213,7 +220,7 @@
     }
 
     /** Cancels the specified attention check. */
-    public void cancelAttentionCheck(int requestCode) {
+    private void cancelAttentionCheck(int requestCode) {
         synchronized (mLock) {
             final UserState userState = peekCurrentUserStateLocked();
             if (userState == null) {
@@ -283,7 +290,8 @@
      * system.
      */
     private static ComponentName resolveAttentionService(Context context) {
-        final String flag = DeviceConfig.getProperty(NAMESPACE, COMPONENT_NAME);
+        final String flag = DeviceConfig.getProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE,
+                COMPONENT_NAME);
 
         final String componentNameString = flag != null ? flag : context.getString(
                 R.string.config_defaultAttentionService);
@@ -323,17 +331,15 @@
         return null;
     }
 
-    private void dumpInternal(PrintWriter pw) {
-        if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
-        IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
-        ipw.println("Attention Manager Service (dumpsys attention)\n");
+    private void dumpInternal(IndentingPrintWriter ipw) {
+        ipw.println("Attention Manager Service (dumpsys attention) state:\n");
 
         ipw.printPair("context", mContext);
-        pw.println();
+        ipw.println();
         synchronized (mLock) {
             int size = mUserStates.size();
             ipw.print("Number user states: ");
-            pw.println(size);
+            ipw.println(size);
             if (size > 0) {
                 ipw.increaseIndent();
                 for (int i = 0; i < size; i++) {
@@ -585,4 +591,15 @@
             }
         }
     }
+
+    private final class BinderService extends Binder {
+        @Override
+        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+            if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) {
+                return;
+            }
+
+            dumpInternal(new IndentingPrintWriter(pw, "  "));
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 451fd66..69a9e7e 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -230,17 +230,13 @@
         sendLMsgNoDelay(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info);
     }
 
-    /*package*/ int handleBluetoothA2dpActiveDeviceChange(
+    /*package*/ void postBluetoothA2dpDeviceConfigChangeExt(
             @NonNull BluetoothDevice device,
             @AudioService.BtProfileConnectionState int state, int profile,
             boolean suppressNoisyIntent, int a2dpVolume) {
-        // FIXME method was added by @a8439e2 but never used, and now conflicts with async behavior
-        //   of handleBluetoothA2dpDeviceConfigChange and
-        //   setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
-        synchronized (mDeviceStateLock) {
-            return mDeviceInventory.handleBluetoothA2dpActiveDeviceChange(device, state, profile,
-                    suppressNoisyIntent, a2dpVolume);
-        }
+        final BtDeviceConnectionInfo info = new BtDeviceConnectionInfo(device, state, profile,
+                suppressNoisyIntent, a2dpVolume);
+        sendLMsgNoDelay(MSG_L_A2DP_ACTIVE_DEVICE_CHANGE_EXT, SENDMSG_QUEUE, info);
     }
 
     private static final class HearingAidDeviceConnectionInfo {
@@ -542,7 +538,8 @@
         mBrokerHandler.removeMessages(MSG_IL_BTA2DP_DOCK_TIMEOUT);
     }
 
-    /*package*/ void postA2dpActiveDeviceChange(BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) {
+    /*package*/ void postA2dpActiveDeviceChange(
+                    @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) {
         sendLMsgNoDelay(MSG_L_A2DP_ACTIVE_DEVICE_CHANGE, SENDMSG_QUEUE, btDeviceInfo);
     }
 
@@ -714,8 +711,9 @@
                     final BluetoothDevice btDevice = (BluetoothDevice) msg.obj;
                     synchronized (mDeviceStateLock) {
                         a2dpCodec = mBtHelper.getA2dpCodec(btDevice);
-                        mDeviceInventory.onBluetoothA2dpDeviceConfigChange(
-                                new BtHelper.BluetoothA2dpDeviceInfo(btDevice, -1, a2dpCodec));
+                        mDeviceInventory.onBluetoothA2dpActiveDeviceChange(
+                                new BtHelper.BluetoothA2dpDeviceInfo(btDevice, -1, a2dpCodec),
+                                        BtHelper.EVENT_DEVICE_CONFIG_CHANGE);
                     }
                     break;
                 case MSG_BROADCAST_AUDIO_BECOMING_NOISY:
@@ -744,7 +742,8 @@
                 case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE:
                     synchronized (mDeviceStateLock) {
                         mDeviceInventory.onBluetoothA2dpActiveDeviceChange(
-                                (BtHelper.BluetoothA2dpDeviceInfo) msg.obj);
+                                (BtHelper.BluetoothA2dpDeviceInfo) msg.obj,
+                                 BtHelper.EVENT_ACTIVE_DEVICE_CHANGE);
                     }
                     break;
                 case MSG_DISCONNECT_A2DP:
@@ -816,6 +815,22 @@
                                 info.mDevice, info.mState, info.mSupprNoisy, info.mMusicDevice);
                     }
                 } break;
+                case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE_EXT: {
+                    final BtDeviceConnectionInfo info = (BtDeviceConnectionInfo) msg.obj;
+                    AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
+                            "handleBluetoothA2dpActiveDeviceChangeExt "
+                                    + " state=" + info.mState
+                                    // only querying address as this is the only readily available
+                                    // field on the device
+                                    + " addr=" + info.mDevice.getAddress()
+                                    + " prof=" + info.mProfile + " supprNoisy=" + info.mSupprNoisy
+                                    + " vol=" + info.mVolume)).printLog(TAG));
+                    synchronized (mDeviceStateLock) {
+                        mDeviceInventory.handleBluetoothA2dpActiveDeviceChangeExt(
+                                info.mDevice, info.mState, info.mProfile,
+                                info.mSupprNoisy, info.mVolume);
+                    }
+                } break;
                 default:
                     Log.wtf(TAG, "Invalid message " + msg.what);
             }
@@ -863,6 +878,8 @@
     private static final int MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT = 27;
     // process external command to (dis)connect a hearing aid device
     private static final int MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT = 28;
+    // process external command to (dis)connect or change active A2DP device
+    private static final int MSG_L_A2DP_ACTIVE_DEVICE_CHANGE_EXT = 29;
 
 
     private static boolean isMessageHandledUnderWakelock(int msgId) {
@@ -877,6 +894,7 @@
             case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE:
             case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT:
             case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT:
+            case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE_EXT:
                 return true;
             default:
                 return false;
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 41a3c98..5ec8cfa 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -263,74 +263,25 @@
         }
     }
 
-    /*package*/ void onBluetoothA2dpDeviceConfigChange(
-            @NonNull BtHelper.BluetoothA2dpDeviceInfo btInfo) {
+    /*package*/ void onBluetoothA2dpActiveDeviceChange(
+            @NonNull BtHelper.BluetoothA2dpDeviceInfo btInfo, int event) {
         final BluetoothDevice btDevice = btInfo.getBtDevice();
-        if (AudioService.DEBUG_DEVICES) {
-            Log.d(TAG, "onBluetoothA2dpDeviceConfigChange btDevice=" + btDevice);
-        }
         if (btDevice == null) {
             return;
         }
-        String address = btDevice.getAddress();
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            address = "";
-        }
-        AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
-                "onBluetoothA2dpDeviceConfigChange addr=" + address));
-
-        final int a2dpCodec = btInfo.getCodec();
-
-        synchronized (mConnectedDevices) {
-            if (mDeviceBroker.hasScheduledA2dpSinkConnectionState(btDevice)) {
-                AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
-                        "A2dp config change ignored"));
-                return;
-            }
-            final String key =
-                    DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address);
-            final DeviceInfo di = mConnectedDevices.get(key);
-            if (di == null) {
-                Log.e(TAG, "invalid null DeviceInfo in onBluetoothA2dpDeviceConfigChange");
-                return;
-            }
-            // Device is connected
-            if (di.mDeviceCodecFormat != a2dpCodec) {
-                di.mDeviceCodecFormat = a2dpCodec;
-                mConnectedDevices.replace(key, di);
-            }
-            if (AudioService.DEBUG_DEVICES) {
-                Log.d(TAG, "onBluetoothA2dpDeviceConfigChange: codec="
-                        + di.mDeviceCodecFormat);
-            }
-            if (AudioSystem.handleDeviceConfigChange(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address,
-                    btDevice.getName(), di.mDeviceCodecFormat) != AudioSystem.AUDIO_STATUS_OK) {
-                // force A2DP device disconnection in case of error so that AudioService state
-                // is consistent with audio policy manager state
-                final int musicDevice = mDeviceBroker.getDeviceForStream(AudioSystem.STREAM_MUSIC);
-                setBluetoothA2dpDeviceConnectionState(
-                        btDevice, BluetoothA2dp.STATE_DISCONNECTED, BluetoothProfile.A2DP,
-                        false /* suppressNoisyIntent */, musicDevice,
-                        -1 /* a2dpVolume */);
-            }
-        }
-    }
-
-    /*package*/ void onBluetoothA2dpActiveDeviceChange(
-            @NonNull BtHelper.BluetoothA2dpDeviceInfo btInfo) {
-        final BluetoothDevice btDevice = btInfo.getBtDevice();
-        int a2dpVolume = btInfo.getVolume();
-        final int a2dpCodec = btInfo.getCodec();
-
         if (AudioService.DEBUG_DEVICES) {
             Log.d(TAG, "onBluetoothA2dpActiveDeviceChange btDevice=" + btDevice);
         }
+        int a2dpVolume = btInfo.getVolume();
+        final int a2dpCodec = btInfo.getCodec();
+
         String address = btDevice.getAddress();
         if (!BluetoothAdapter.checkBluetoothAddress(address)) {
             address = "";
         }
         AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
-                "onBluetoothA2dpActiveDeviceChange addr=" + address));
+                "onBluetoothA2dpActiveDeviceChange addr=" + address
+                    + " event=" + BtHelper.a2dpDeviceEventToString(event)));
 
         synchronized (mConnectedDevices) {
             //TODO original CL is not consistent between BluetoothDevice and BluetoothA2dpDeviceInfo
@@ -344,20 +295,28 @@
                     AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address);
             final DeviceInfo di = mConnectedDevices.get(key);
             if (di == null) {
+                Log.e(TAG, "invalid null DeviceInfo in onBluetoothA2dpActiveDeviceChange");
                 return;
             }
 
-            // Device is connected
-            if (a2dpVolume != -1) {
-                final AudioService.VolumeStreamState streamState =
-                        mDeviceBroker.getStreamState(AudioSystem.STREAM_MUSIC);
-                // Convert index to internal representation in VolumeStreamState
-                a2dpVolume = a2dpVolume * 10;
-                streamState.setIndex(a2dpVolume, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
-                        "onBluetoothA2dpActiveDeviceChange");
-                mDeviceBroker.setDeviceVolume(streamState, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
+            if (event == BtHelper.EVENT_ACTIVE_DEVICE_CHANGE) {
+                // Device is connected
+                if (a2dpVolume != -1) {
+                    final AudioService.VolumeStreamState streamState =
+                            mDeviceBroker.getStreamState(AudioSystem.STREAM_MUSIC);
+                    // Convert index to internal representation in VolumeStreamState
+                    a2dpVolume = a2dpVolume * 10;
+                    streamState.setIndex(a2dpVolume, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
+                            "onBluetoothA2dpActiveDeviceChange");
+                    mDeviceBroker.setDeviceVolume(
+                            streamState, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
+                }
+            } else if (event == BtHelper.EVENT_DEVICE_CONFIG_CHANGE) {
+                if (di.mDeviceCodecFormat != a2dpCodec) {
+                    di.mDeviceCodecFormat = a2dpCodec;
+                    mConnectedDevices.replace(key, di);
+                }
             }
-
             if (AudioSystem.handleDeviceConfigChange(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address,
                     btDevice.getName(), a2dpCodec) != AudioSystem.AUDIO_STATUS_OK) {
                 int musicDevice = mDeviceBroker.getDeviceForStream(AudioSystem.STREAM_MUSIC);
@@ -616,52 +575,48 @@
         }
     }
 
-    /*package*/ int handleBluetoothA2dpActiveDeviceChange(
+    /*package*/ void handleBluetoothA2dpActiveDeviceChangeExt(
             @NonNull BluetoothDevice device,
             @AudioService.BtProfileConnectionState int state, int profile,
             boolean suppressNoisyIntent, int a2dpVolume) {
-        // method was added by QC but never used, and now conflicts with async behavior of
-        // handleBluetoothA2dpDeviceConfigChange and
-        // setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
-        if (false) {
-            if (state == BluetoothProfile.STATE_DISCONNECTED) {
-                setBluetoothA2dpDeviceConnectionState(device, state, profile,
-                        suppressNoisyIntent, AudioSystem.DEVICE_NONE, a2dpVolume);
+        if (state == BluetoothProfile.STATE_DISCONNECTED) {
+            mDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
+                           device, state, profile, suppressNoisyIntent, a2dpVolume);
+            return;
+        }
+        // state == BluetoothProfile.STATE_CONNECTED
+        synchronized (mConnectedDevices) {
+            final String address = device.getAddress();
+            final int a2dpCodec = mDeviceBroker.getA2dpCodec(device);
+            final String deviceKey = DeviceInfo.makeDeviceListKey(
+                        AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address);
+            DeviceInfo deviceInfo = mConnectedDevices.get(deviceKey);
+            if (deviceInfo != null) {
+                // Device config change for matching A2DP device
+                mDeviceBroker.postBluetoothA2dpDeviceConfigChange(device);
+                return;
             }
-            // state == BluetoothProfile.STATE_CONNECTED
-            synchronized (mConnectedDevices) {
-                for (int i = 0; i < mConnectedDevices.size(); i++) {
-                    final DeviceInfo deviceInfo = mConnectedDevices.valueAt(i);
-                    if (deviceInfo.mDeviceType != AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) {
-                        continue;
-                    }
-                    // If A2DP device exists, this is either an active device change or
-                    // device config change
-                    final String existingDevicekey = mConnectedDevices.keyAt(i);
-                    final String deviceName = device.getName();
-                    final String address = device.getAddress();
-                    final String newDeviceKey = DeviceInfo.makeDeviceListKey(
-                            AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address);
-                    int a2dpCodec = mDeviceBroker.getA2dpCodec(device);
-                    // Device not equal to existing device, active device change
-                    if (!TextUtils.equals(existingDevicekey, newDeviceKey)) {
-                        mConnectedDevices.remove(existingDevicekey);
-                        mConnectedDevices.put(newDeviceKey, new DeviceInfo(
-                                AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, deviceName,
-                                address, a2dpCodec));
-                        mDeviceBroker.postA2dpActiveDeviceChange(
-                                new BtHelper.BluetoothA2dpDeviceInfo(
-                                        device, a2dpVolume, a2dpCodec));
-                        return 0;
-                    } else {
-                        // Device config change for existing device
-                        mDeviceBroker.postBluetoothA2dpDeviceConfigChange(device);
-                        return 0;
-                    }
+            for (int i = 0; i < mConnectedDevices.size(); i++) {
+                deviceInfo = mConnectedDevices.valueAt(i);
+                if (deviceInfo.mDeviceType != AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) {
+                    continue;
                 }
+                // A2DP device exists, handle active device change
+                final String existingDevicekey = mConnectedDevices.keyAt(i);
+                final String deviceName = device.getName();
+                mConnectedDevices.remove(existingDevicekey);
+                mConnectedDevices.put(deviceKey, new DeviceInfo(
+                        AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, deviceName,
+                        address, a2dpCodec));
+                mDeviceBroker.postA2dpActiveDeviceChange(
+                        new BtHelper.BluetoothA2dpDeviceInfo(
+                            device, a2dpVolume, a2dpCodec));
+                return;
             }
         }
-        return 0;
+        // New A2DP device connection
+        mDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
+                           device, state, profile, suppressNoisyIntent, a2dpVolume);
     }
 
     /*package*/ int setWiredDeviceConnectionState(int type, @AudioService.ConnectionState int state,
@@ -858,11 +813,20 @@
         if (musicDevice == AudioSystem.DEVICE_NONE) {
             musicDevice = mDeviceBroker.getDeviceForStream(AudioSystem.STREAM_MUSIC);
         }
-        // ignore condition on device being actually used for music when in communication
+
+        // always ignore condition on device being actually used for music when in communication
         // because music routing is altered in this case.
-        // also checks whether media routing if affected by a dynamic policy
+        // also checks whether media routing if affected by a dynamic policy or mirroring
         if (((device == musicDevice) || mDeviceBroker.isInCommunication())
-                && (device == devices) && !mDeviceBroker.hasMediaDynamicPolicy()) {
+                && (device == devices) && !mDeviceBroker.hasMediaDynamicPolicy()
+                        && ((musicDevice & AudioSystem.DEVICE_OUT_REMOTE_SUBMIX) == 0)) {
+            if (!AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0 /*not looking in past*/)) {
+                // no media playback, not a "becoming noisy" situation, otherwise it could cause
+                // the pausing of some apps that are playing remotely
+                AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
+                        "dropping ACTION_AUDIO_BECOMING_NOISY, no media playback")).printLog(TAG));
+                return 0;
+            }
             mDeviceBroker.postBroadcastBecomingNoisy();
             delay = 1000;
         }
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 91d19de..68f76ab 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -4094,12 +4094,9 @@
      * @see AudioManager#handleBluetoothA2dpActiveDeviceChange(BluetoothDevice, int, int,
      *                                                          boolean, int)
      */
-    public int handleBluetoothA2dpActiveDeviceChange(
+    public void handleBluetoothA2dpActiveDeviceChange(
             BluetoothDevice device, int state, int profile, boolean suppressNoisyIntent,
             int a2dpVolume) {
-        // FIXME method was added by @a8439e2 but never used, and now conflicts with async behavior
-        //   of handleBluetoothA2dpDeviceConfigChange and
-        //   setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
         if (device == null) {
             throw new IllegalArgumentException("Illegal null device");
         }
@@ -4110,7 +4107,7 @@
                 && state != BluetoothProfile.STATE_DISCONNECTED) {
             throw new IllegalArgumentException("Invalid state " + state);
         }
-        return mDeviceBroker.handleBluetoothA2dpActiveDeviceChange(device, state, profile,
+        mDeviceBroker.postBluetoothA2dpDeviceConfigChangeExt(device, state, profile,
                 suppressNoisyIntent, a2dpVolume);
     }
 
@@ -5956,6 +5953,14 @@
         pw.print("  mVolumePolicy="); pw.println(mVolumePolicy);
         pw.print("  mAvrcpAbsVolSupported=");
         pw.println(mDeviceBroker.isAvrcpAbsoluteVolumeSupported());
+        pw.print("  mIsSingleVolume="); pw.println(mIsSingleVolume);
+        pw.print("  mUseFixedVolume="); pw.println(mUseFixedVolume);
+        pw.print("  mFixedVolumeDevices=0x"); pw.println(Integer.toHexString(mFixedVolumeDevices));
+        pw.print("  mHdmiCecSink="); pw.println(mHdmiCecSink);
+        pw.print("  mHdmiAudioSystemClient="); pw.println(mHdmiAudioSystemClient);
+        pw.print("  mHdmiPlaybackClient="); pw.println(mHdmiPlaybackClient);
+        pw.print("  mHdmiTvClient="); pw.println(mHdmiTvClient);
+        pw.print("  mHdmiSystemAudioSupported="); pw.println(mHdmiSystemAudioSupported);
 
         dumpAudioPolicies(pw);
         mDynPolicyLogger.dump(pw);
@@ -6387,7 +6392,28 @@
         return mProjectionService;
     }
 
-    public void unregisterAudioPolicyAsync(IAudioPolicyCallback pcb) {
+    /**
+     * See {@link AudioManager#unregisterAudioPolicyAsync(AudioPolicy)}
+     * Declared oneway
+     * @param pcb nullable because on service interface
+     */
+    public void unregisterAudioPolicyAsync(@Nullable IAudioPolicyCallback pcb) {
+        unregisterAudioPolicy(pcb);
+    }
+
+    /**
+     * See {@link AudioManager#unregisterAudioPolicy(AudioPolicy)}
+     * @param pcb nullable because on service interface
+     */
+    public void unregisterAudioPolicy(@Nullable IAudioPolicyCallback pcb) {
+        if (pcb == null) {
+            return;
+        }
+        unregisterAudioPolicyInt(pcb);
+    }
+
+
+    private void unregisterAudioPolicyInt(@NonNull IAudioPolicyCallback pcb) {
         mDynPolicyLogger.log((new AudioEventLogger.StringEvent("unregisterAudioPolicyAsync for "
                 + pcb.asBinder()).printLog(TAG)));
         synchronized (mAudioPolicies) {
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index 04073cb..522a55d 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -139,6 +139,19 @@
         }
     }
 
+    // A2DP device events
+    /*package*/ static final int EVENT_DEVICE_CONFIG_CHANGE = 0;
+    /*package*/ static final int EVENT_ACTIVE_DEVICE_CHANGE = 1;
+
+    /*package*/ static String a2dpDeviceEventToString(int event) {
+        switch (event) {
+            case EVENT_DEVICE_CONFIG_CHANGE: return "DEVICE_CONFIG_CHANGE";
+            case EVENT_ACTIVE_DEVICE_CHANGE: return "ACTIVE_DEVICE_CHANGE";
+            default:
+                return new String("invalid event:" + event);
+        }
+    }
+
     //----------------------------------------------------------------------
     // Interface for AudioDeviceBroker
 
diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java
index b4bbbc7..d028e88 100644
--- a/services/core/java/com/android/server/audio/MediaFocusControl.java
+++ b/services/core/java/com/android/server/audio/MediaFocusControl.java
@@ -543,16 +543,17 @@
     }
 
     /**
-     * Called synchronized on mAudioFocusLock
+     * Called synchronized on mAudioFocusLock.
+     * Can only be called with an external focus policy installed (mFocusPolicy != null)
      * @param afi
-     * @param requestResult
-     * @return true if the external audio focus policy (if any) is handling the focus request
+     * @param fd
+     * @param cb binder of the focus requester
+     * @return true if the external audio focus policy (if any) can handle the focus request,
+     *     and false if there was any error handling the request (e.g. error talking to policy,
+     *     focus requester is already dead)
      */
     boolean notifyExtFocusPolicyFocusRequest_syncAf(AudioFocusInfo afi,
-            IAudioFocusDispatcher fd, IBinder cb) {
-        if (mFocusPolicy == null) {
-            return false;
-        }
+            IAudioFocusDispatcher fd, @NonNull IBinder cb) {
         if (DEBUG) {
             Log.v(TAG, "notifyExtFocusPolicyFocusRequest client="+afi.getClientId()
             + " dispatcher=" + fd);
@@ -561,19 +562,28 @@
             afi.setGen(mExtFocusChangeCounter++);
         }
         final FocusRequester existingFr = mFocusOwnersForFocusPolicy.get(afi.getClientId());
+        boolean keepTrack = false;
         if (existingFr != null) {
             if (!existingFr.hasSameDispatcher(fd)) {
                 existingFr.release();
-                final AudioFocusDeathHandler hdlr = new AudioFocusDeathHandler(cb);
-                mFocusOwnersForFocusPolicy.put(afi.getClientId(),
-                        new FocusRequester(afi, fd, cb, hdlr, this));
+                keepTrack = true;
             }
         } else {
-            // new focus (future) focus owner to keep track of
+            keepTrack = true;
+        }
+        if (keepTrack) {
             final AudioFocusDeathHandler hdlr = new AudioFocusDeathHandler(cb);
+            try {
+                cb.linkToDeath(hdlr, 0);
+            } catch (RemoteException e) {
+                // client has already died!
+                return false;
+            }
+            // new focus (future) focus owner to keep track of
             mFocusOwnersForFocusPolicy.put(afi.getClientId(),
                     new FocusRequester(afi, fd, cb, hdlr, this));
         }
+
         try {
             //oneway
             mFocusPolicy.notifyAudioFocusRequest(afi, AudioManager.AUDIOFOCUS_REQUEST_GRANTED);
@@ -600,7 +610,6 @@
     /**
      * Called synchronized on mAudioFocusLock
      * @param afi
-     * @param requestResult
      * @return true if the external audio focus policy (if any) is handling the focus request
      */
     boolean notifyExtFocusPolicyFocusAbandon_syncAf(AudioFocusInfo afi) {
@@ -767,10 +776,15 @@
             }
 
             // external focus policy?
-            if (notifyExtFocusPolicyFocusRequest_syncAf(
-                    afiForExtPolicy, fd, cb)) {
-                // stop handling focus request here as it is handled by external audio focus policy
-                return AudioManager.AUDIOFOCUS_REQUEST_WAITING_FOR_EXT_POLICY;
+            if (mFocusPolicy != null) {
+                if (notifyExtFocusPolicyFocusRequest_syncAf(afiForExtPolicy, fd, cb)) {
+                    // stop handling focus request here as it is handled by external audio
+                    // focus policy (return code will be handled in AudioManager)
+                    return AudioManager.AUDIOFOCUS_REQUEST_WAITING_FOR_EXT_POLICY;
+                } else {
+                    // an error occured, client already dead, bail early
+                    return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
+                }
             }
 
             // handle the potential premature death of the new holder of the focus
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index ddd416e..f313e1d 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -57,6 +57,7 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
+import android.os.Message;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
@@ -68,6 +69,7 @@
 import android.util.StatsLog;
 
 import com.android.internal.R;
+import com.android.internal.os.SomeArgs;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.server.SystemService;
 
@@ -85,22 +87,137 @@
 
     private static final String TAG = "BiometricService";
 
+    private static final int MSG_ON_TASK_STACK_CHANGED = 1;
+    private static final int MSG_ON_AUTHENTICATION_SUCCEEDED = 2;
+    private static final int MSG_ON_AUTHENTICATION_FAILED = 3;
+    private static final int MSG_ON_ERROR = 4;
+    private static final int MSG_ON_ACQUIRED = 5;
+    private static final int MSG_ON_DISMISSED = 6;
+    private static final int MSG_ON_TRY_AGAIN_PRESSED = 7;
+    private static final int MSG_ON_READY_FOR_AUTHENTICATION = 8;
+    private static final int MSG_AUTHENTICATE = 9;
+    private static final int MSG_CANCEL_AUTHENTICATION = 10;
+
     private static final int[] FEATURE_ID = {
         TYPE_FINGERPRINT,
         TYPE_IRIS,
         TYPE_FACE
     };
 
+    /**
+     * Authentication either just called and we have not transitioned to the CALLED state, or
+     * authentication terminated (success or error).
+     */
+    private static final int STATE_AUTH_IDLE = 0;
+    /**
+     * Authentication was called and we are waiting for the <Biometric>Services to return their
+     * cookies before starting the hardware and showing the BiometricPrompt.
+     */
+    private static final int STATE_AUTH_CALLED = 1;
+    /**
+     * Authentication started, BiometricPrompt is showing and the hardware is authenticating.
+     */
+    private static final int STATE_AUTH_STARTED = 2;
+    /**
+     * Authentication is paused, waiting for the user to press "try again" button. Only
+     * passive modalities such as Face or Iris should have this state. Note that for passive
+     * modalities, the HAL enters the idle state after onAuthenticated(false) which differs from
+     * fingerprint.
+     */
+    private static final int STATE_AUTH_PAUSED = 3;
+    /**
+     * Authentication is successful, but we're waiting for the user to press "confirm" button.
+     */
+    private static final int STATE_AUTH_PENDING_CONFIRM = 5;
+
+    private final class AuthSession {
+        // Map of Authenticator/Cookie pairs. We expect to receive the cookies back from
+        // <Biometric>Services before we can start authenticating. Pairs that have been returned
+        // are moved to mModalitiesMatched.
+        final HashMap<Integer, Integer> mModalitiesWaiting;
+        // Pairs that have been matched.
+        final HashMap<Integer, Integer> mModalitiesMatched = new HashMap<>();
+
+        // The following variables are passed to authenticateInternal, which initiates the
+        // appropriate <Biometric>Services.
+        final IBinder mToken;
+        final long mSessionId;
+        final int mUserId;
+        // Original receiver from BiometricPrompt.
+        final IBiometricServiceReceiver mClientReceiver;
+        final String mOpPackageName;
+        // Info to be shown on BiometricDialog when all cookies are returned.
+        final Bundle mBundle;
+        final int mCallingUid;
+        final int mCallingPid;
+        final int mCallingUserId;
+        // Continue authentication with the same modality/modalities after "try again" is
+        // pressed
+        final int mModality;
+        final boolean mRequireConfirmation;
+
+        // The current state, which can be either idle, called, or started
+        private int mState = STATE_AUTH_IDLE;
+        // For explicit confirmation, do not send to keystore until the user has confirmed
+        // the authentication.
+        byte[] mTokenEscrow;
+
+        // Timestamp when hardware authentication occurred
+        private long mAuthenticatedTimeMs;
+
+        AuthSession(HashMap<Integer, Integer> modalities, IBinder token, long sessionId,
+                int userId, IBiometricServiceReceiver receiver, String opPackageName,
+                Bundle bundle, int callingUid, int callingPid, int callingUserId,
+                int modality, boolean requireConfirmation) {
+            mModalitiesWaiting = modalities;
+            mToken = token;
+            mSessionId = sessionId;
+            mUserId = userId;
+            mClientReceiver = receiver;
+            mOpPackageName = opPackageName;
+            mBundle = bundle;
+            mCallingUid = callingUid;
+            mCallingPid = callingPid;
+            mCallingUserId = callingUserId;
+            mModality = modality;
+            mRequireConfirmation = requireConfirmation;
+        }
+
+        boolean isCrypto() {
+            return mSessionId != 0;
+        }
+
+        boolean containsCookie(int cookie) {
+            if (mModalitiesWaiting != null && mModalitiesWaiting.containsValue(cookie)) {
+                return true;
+            }
+            if (mModalitiesMatched != null && mModalitiesMatched.containsValue(cookie)) {
+                return true;
+            }
+            return false;
+        }
+    }
+
+    private final class BiometricTaskStackListener extends TaskStackListener {
+        @Override
+        public void onTaskStackChanged() {
+            mHandler.sendEmptyMessage(MSG_ON_TASK_STACK_CHANGED);
+        }
+    }
+
     private final AppOpsManager mAppOps;
-    private final Handler mHandler;
     private final boolean mHasFeatureFingerprint;
     private final boolean mHasFeatureIris;
     private final boolean mHasFeatureFace;
     private final SettingObserver mSettingObserver;
     private final List<EnabledOnKeyguardCallback> mEnabledOnKeyguardCallbacks;
+    private final BiometricTaskStackListener mTaskStackListener = new BiometricTaskStackListener();
+    private final Random mRandom = new Random();
 
     private IFingerprintService mFingerprintService;
     private IFaceService mFaceService;
+    private IActivityTaskManager mActivityTaskManager;
+    private IStatusBarService mStatusBarService;
 
     // Get and cache the available authenticator (manager) classes. Used since aidl doesn't support
     // polymorphism :/
@@ -113,6 +230,108 @@
     // should be safe.
     private int mCurrentModality;
 
+    // The current authentication session, null if idle/done. We need to track both the current
+    // and pending sessions since errors may be sent to either.
+    private AuthSession mCurrentAuthSession;
+    private AuthSession mPendingAuthSession;
+
+    private final Handler mHandler = new Handler(Looper.getMainLooper()) {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_ON_TASK_STACK_CHANGED: {
+                    handleTaskStackChanged();
+                    break;
+                }
+
+                case MSG_ON_AUTHENTICATION_SUCCEEDED: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    handleAuthenticationSucceeded(
+                            (boolean) args.arg1 /* requireConfirmation */,
+                            (byte[]) args.arg2 /* token */);
+                    args.recycle();
+                    break;
+                }
+
+                case MSG_ON_AUTHENTICATION_FAILED: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    handleAuthenticationFailed(
+                            args.argi1 /* cookie */,
+                            (boolean) args.arg1 /* requireConfirmation */);
+                    args.recycle();
+                    break;
+                }
+
+                case MSG_ON_ERROR: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    handleOnError(
+                            args.argi1 /* cookie */,
+                            args.argi2 /* error */,
+                            (String) args.arg1 /* message */);
+                    args.recycle();
+                    break;
+                }
+
+                case MSG_ON_ACQUIRED: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    handleOnAcquired(
+                            args.argi1 /* acquiredInfo */,
+                            (String) args.arg1 /* message */);
+                    args.recycle();
+                    break;
+                }
+
+                case MSG_ON_DISMISSED: {
+                    handleOnDismissed(msg.arg1);
+                    break;
+                }
+
+                case MSG_ON_TRY_AGAIN_PRESSED: {
+                    handleOnTryAgainPressed();
+                    break;
+                }
+
+                case MSG_ON_READY_FOR_AUTHENTICATION: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    handleOnReadyForAuthentication(
+                            args.argi1 /* cookie */,
+                            (boolean) args.arg1 /* requireConfirmation */,
+                            args.argi2 /* userId */);
+                    args.recycle();
+                    break;
+                }
+
+                case MSG_AUTHENTICATE: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    handleAuthenticate(
+                            (IBinder) args.arg1 /* token */,
+                            (long) args.arg2 /* sessionId */,
+                            args.argi1 /* userid */,
+                            (IBiometricServiceReceiver) args.arg3 /* receiver */,
+                            (String) args.arg4 /* opPackageName */,
+                            (Bundle) args.arg5 /* bundle */,
+                            args.argi2 /* callingUid */,
+                            args.argi3 /* callingPid */,
+                            args.argi4 /* callingUserId */);
+                    args.recycle();
+                    break;
+                }
+
+                case MSG_CANCEL_AUTHENTICATION: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    handleCancelAuthentication(
+                            (IBinder) args.arg1 /* token */,
+                            (String) args.arg2 /* opPackageName */);
+                    args.recycle();
+                    break;
+                }
+
+                default:
+                    break;
+            }
+        }
+    };
+
     private final class Authenticator {
         int mType;
         BiometricAuthenticator mAuthenticator;
@@ -251,142 +470,62 @@
         }
     }
 
+    // Wrap the client's receiver so we can do things with the BiometricDialog first
+    private final IBiometricServiceReceiverInternal mInternalReceiver =
+            new IBiometricServiceReceiverInternal.Stub() {
+        @Override
+        public void onAuthenticationSucceeded(boolean requireConfirmation, byte[] token)
+                throws RemoteException {
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = requireConfirmation;
+            args.arg2 = token;
+            mHandler.obtainMessage(MSG_ON_AUTHENTICATION_SUCCEEDED, args).sendToTarget();
+        }
+
+        @Override
+        public void onAuthenticationFailed(int cookie, boolean requireConfirmation)
+                throws RemoteException {
+            SomeArgs args = SomeArgs.obtain();
+            args.argi1 = cookie;
+            args.arg1 = requireConfirmation;
+            mHandler.obtainMessage(MSG_ON_AUTHENTICATION_FAILED, args).sendToTarget();
+        }
+
+        @Override
+        public void onError(int cookie, int error, String message) throws RemoteException {
+            SomeArgs args = SomeArgs.obtain();
+            args.argi1 = cookie;
+            args.argi2 = error;
+            args.arg1 = message;
+            mHandler.obtainMessage(MSG_ON_ERROR, args).sendToTarget();
+        }
+
+        @Override
+        public void onAcquired(int acquiredInfo, String message) throws RemoteException {
+            SomeArgs args = SomeArgs.obtain();
+            args.argi1 = acquiredInfo;
+            args.arg1 = message;
+            mHandler.obtainMessage(MSG_ON_ACQUIRED, args).sendToTarget();
+        }
+
+        @Override
+        public void onDialogDismissed(int reason) throws RemoteException {
+            mHandler.obtainMessage(MSG_ON_DISMISSED, reason, 0 /* arg2 */).sendToTarget();
+        }
+
+        @Override
+        public void onTryAgainPressed() {
+            mHandler.sendEmptyMessage(MSG_ON_TRY_AGAIN_PRESSED);
+        }
+    };
+
+
     /**
      * This is just a pass-through service that wraps Fingerprint, Iris, Face services. This service
      * should not carry any state. The reality is we need to keep a tiny amount of state so that
      * cancelAuthentication() can go to the right place.
      */
     private final class BiometricServiceWrapper extends IBiometricService.Stub {
-
-        /**
-         * Authentication either just called and we have not transitioned to the CALLED state, or
-         * authentication terminated (success or error).
-         */
-        private static final int STATE_AUTH_IDLE = 0;
-        /**
-         * Authentication was called and we are waiting for the <Biometric>Services to return their
-         * cookies before starting the hardware and showing the BiometricPrompt.
-         */
-        private static final int STATE_AUTH_CALLED = 1;
-        /**
-         * Authentication started, BiometricPrompt is showing and the hardware is authenticating.
-         */
-        private static final int STATE_AUTH_STARTED = 2;
-        /**
-         * Authentication is paused, waiting for the user to press "try again" button. Only
-         * passive modalities such as Face or Iris should have this state. Note that for passive
-         * modalities, the HAL enters the idle state after onAuthenticated(false) which differs from
-         * fingerprint.
-         */
-        private static final int STATE_AUTH_PAUSED = 3;
-        /**
-         * Authentication is successful, but we're waiting for the user to press "confirm" button.
-         */
-        private static final int STATE_AUTH_PENDING_CONFIRM = 5;
-
-        final class AuthSession {
-            // Map of Authenticator/Cookie pairs. We expect to receive the cookies back from
-            // <Biometric>Services before we can start authenticating. Pairs that have been returned
-            // are moved to mModalitiesMatched.
-            final HashMap<Integer, Integer> mModalitiesWaiting;
-            // Pairs that have been matched.
-            final HashMap<Integer, Integer> mModalitiesMatched = new HashMap<>();
-
-            // The following variables are passed to authenticateInternal, which initiates the
-            // appropriate <Biometric>Services.
-            final IBinder mToken;
-            final long mSessionId;
-            final int mUserId;
-            // Original receiver from BiometricPrompt.
-            final IBiometricServiceReceiver mClientReceiver;
-            final String mOpPackageName;
-            // Info to be shown on BiometricDialog when all cookies are returned.
-            final Bundle mBundle;
-            final int mCallingUid;
-            final int mCallingPid;
-            final int mCallingUserId;
-            // Continue authentication with the same modality/modalities after "try again" is
-            // pressed
-            final int mModality;
-            final boolean mRequireConfirmation;
-
-            // The current state, which can be either idle, called, or started
-            private int mState = STATE_AUTH_IDLE;
-            // For explicit confirmation, do not send to keystore until the user has confirmed
-            // the authentication.
-            byte[] mTokenEscrow;
-
-            // Timestamp when hardware authentication occurred
-            private long mAuthenticatedTimeMs;
-
-            AuthSession(HashMap<Integer, Integer> modalities, IBinder token, long sessionId,
-                    int userId, IBiometricServiceReceiver receiver, String opPackageName,
-                    Bundle bundle, int callingUid, int callingPid, int callingUserId,
-                    int modality, boolean requireConfirmation) {
-                mModalitiesWaiting = modalities;
-                mToken = token;
-                mSessionId = sessionId;
-                mUserId = userId;
-                mClientReceiver = receiver;
-                mOpPackageName = opPackageName;
-                mBundle = bundle;
-                mCallingUid = callingUid;
-                mCallingPid = callingPid;
-                mCallingUserId = callingUserId;
-                mModality = modality;
-                mRequireConfirmation = requireConfirmation;
-            }
-
-            boolean isCrypto() {
-                return mSessionId != 0;
-            }
-
-            boolean containsCookie(int cookie) {
-                if (mModalitiesWaiting != null && mModalitiesWaiting.containsValue(cookie)) {
-                    return true;
-                }
-                if (mModalitiesMatched != null && mModalitiesMatched.containsValue(cookie)) {
-                    return true;
-                }
-                return false;
-            }
-        }
-
-        final class BiometricTaskStackListener extends TaskStackListener {
-            @Override
-            public void onTaskStackChanged() {
-                try {
-                    final List<ActivityManager.RunningTaskInfo> runningTasks =
-                            mActivityTaskManager.getTasks(1);
-                    if (!runningTasks.isEmpty()) {
-                        final String topPackage = runningTasks.get(0).topActivity.getPackageName();
-                        if (mCurrentAuthSession != null
-                                && !topPackage.contentEquals(mCurrentAuthSession.mOpPackageName)) {
-                            mStatusBarService.hideBiometricDialog();
-                            mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
-                            mCurrentAuthSession.mClientReceiver.onError(
-                                    BiometricConstants.BIOMETRIC_ERROR_CANCELED,
-                                    getContext().getString(
-                                            com.android.internal.R.string.biometric_error_canceled)
-                            );
-                            mCurrentAuthSession.mState = STATE_AUTH_IDLE;
-                            mCurrentAuthSession = null;
-                        }
-                    }
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Unable to get running tasks", e);
-                }
-            }
-        }
-
-        private final IActivityTaskManager mActivityTaskManager = getContext().getSystemService(
-                ActivityTaskManager.class).getService();
-        private final IStatusBarService mStatusBarService = IStatusBarService.Stub.asInterface(
-                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
-        private final BiometricTaskStackListener mTaskStackListener =
-                new BiometricTaskStackListener();
-        private final Random mRandom = new Random();
-
         // TODO(b/123378871): Remove when moved.
         // When BiometricPrompt#setAllowDeviceCredentials is set to true, we need to store the
         // client (app) receiver. BiometricService internally launches CDCA which invokes
@@ -395,331 +534,15 @@
         // to this receiver.
         private IBiometricServiceReceiver mConfirmDeviceCredentialReceiver;
 
-        // The current authentication session, null if idle/done. We need to track both the current
-        // and pending sessions since errors may be sent to either.
-        private AuthSession mCurrentAuthSession;
-        private AuthSession mPendingAuthSession;
-
-        // Wrap the client's receiver so we can do things with the BiometricDialog first
-        private final IBiometricServiceReceiverInternal mInternalReceiver =
-                new IBiometricServiceReceiverInternal.Stub() {
-            @Override
-            public void onAuthenticationSucceeded(boolean requireConfirmation, byte[] token)
-                    throws RemoteException {
-                try {
-                    // Should never happen, log this to catch bad HAL behavior (e.g. auth succeeded
-                    // after user dismissed/canceled dialog).
-                    if (mCurrentAuthSession == null) {
-                        Slog.e(TAG, "onAuthenticationSucceeded(): Auth session is null");
-                        return;
-                    }
-
-                    if (!requireConfirmation) {
-                        mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
-                        KeyStore.getInstance().addAuthToken(token);
-                        mCurrentAuthSession.mClientReceiver.onAuthenticationSucceeded();
-                        mCurrentAuthSession.mState = STATE_AUTH_IDLE;
-                        mCurrentAuthSession = null;
-                    } else {
-                        mCurrentAuthSession.mAuthenticatedTimeMs = System.currentTimeMillis();
-                        // Store the auth token and submit it to keystore after the confirmation
-                        // button has been pressed.
-                        mCurrentAuthSession.mTokenEscrow = token;
-                        mCurrentAuthSession.mState = STATE_AUTH_PENDING_CONFIRM;
-                    }
-
-                    // Notify SysUI that the biometric has been authenticated. SysUI already knows
-                    // the implicit/explicit state and will react accordingly.
-                    mStatusBarService.onBiometricAuthenticated(true);
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Remote exception", e);
-                }
-            }
-
-            @Override
-            public void onAuthenticationFailed(int cookie, boolean requireConfirmation)
-                    throws RemoteException {
-                try {
-                    // Should never happen, log this to catch bad HAL behavior (e.g. auth succeeded
-                    // after user dismissed/canceled dialog).
-                    if (mCurrentAuthSession == null) {
-                        Slog.e(TAG, "onAuthenticationFailed(): Auth session is null");
-                        return;
-                    }
-
-                    mStatusBarService.onBiometricAuthenticated(false);
-
-                    // TODO: This logic will need to be updated if BP is multi-modal
-                    if ((mCurrentAuthSession.mModality & TYPE_FACE) != 0) {
-                        // Pause authentication. onBiometricAuthenticated(false) causes the
-                        // dialog to show a "try again" button for passive modalities.
-                        mCurrentAuthSession.mState = STATE_AUTH_PAUSED;
-                    }
-
-                    mCurrentAuthSession.mClientReceiver.onAuthenticationFailed();
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Remote exception", e);
-                }
-            }
-
-            @Override
-            public void onError(int cookie, int error, String message) throws RemoteException {
-                Slog.d(TAG, "Error: " + error + " cookie: " + cookie);
-                // Errors can either be from the current auth session or the pending auth session.
-                // The pending auth session may receive errors such as ERROR_LOCKOUT before
-                // it becomes the current auth session. Similarly, the current auth session may
-                // receive errors such as ERROR_CANCELED while the pending auth session is preparing
-                // to be started. Thus we must match error messages with their cookies to be sure
-                // of their intended receivers.
-                try {
-                    if (mCurrentAuthSession != null && mCurrentAuthSession.containsCookie(cookie)) {
-                        if (mCurrentAuthSession.mState == STATE_AUTH_STARTED) {
-                            mStatusBarService.onBiometricError(message);
-                            if (error == BiometricConstants.BIOMETRIC_ERROR_CANCELED) {
-                                    mActivityTaskManager.unregisterTaskStackListener(
-                                            mTaskStackListener);
-                                    mCurrentAuthSession.mClientReceiver.onError(error, message);
-                                    mCurrentAuthSession.mState = STATE_AUTH_IDLE;
-                                    mCurrentAuthSession = null;
-                                    mStatusBarService.hideBiometricDialog();
-                            } else {
-                                // Send errors after the dialog is dismissed.
-                                mHandler.postDelayed(() -> {
-                                    try {
-                                        if (mCurrentAuthSession != null) {
-                                            mActivityTaskManager.unregisterTaskStackListener(
-                                                    mTaskStackListener);
-                                            mCurrentAuthSession.mClientReceiver.onError(error,
-                                                    message);
-                                            mCurrentAuthSession.mState = STATE_AUTH_IDLE;
-                                            mCurrentAuthSession = null;
-                                        }
-                                    } catch (RemoteException e) {
-                                        Slog.e(TAG, "Remote exception", e);
-                                    }
-                                }, BiometricPrompt.HIDE_DIALOG_DELAY);
-                            }
-                        } else if (mCurrentAuthSession.mState == STATE_AUTH_PAUSED) {
-                            // In the "try again" state, we should forward canceled errors to
-                            // the client and and clean up.
-                            mCurrentAuthSession.mClientReceiver.onError(error, message);
-                            mStatusBarService.onBiometricError(message);
-                            mActivityTaskManager.unregisterTaskStackListener(
-                                    mTaskStackListener);
-                            mCurrentAuthSession.mState = STATE_AUTH_IDLE;
-                            mCurrentAuthSession = null;
-                        } else {
-                            Slog.e(TAG, "Impossible session error state: "
-                                    + mCurrentAuthSession.mState);
-                        }
-                    } else if (mPendingAuthSession != null
-                            && mPendingAuthSession.containsCookie(cookie)) {
-                        if (mPendingAuthSession.mState == STATE_AUTH_CALLED) {
-                            mPendingAuthSession.mClientReceiver.onError(error, message);
-                            mPendingAuthSession.mState = STATE_AUTH_IDLE;
-                            mPendingAuthSession = null;
-                        } else {
-                            Slog.e(TAG, "Impossible pending session error state: "
-                                    + mPendingAuthSession.mState);
-                        }
-                    }
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Remote exception", e);
-                }
-            }
-
-            @Override
-            public void onAcquired(int acquiredInfo, String message) throws RemoteException {
-                // Should never happen, log this to catch bad HAL behavior (e.g. auth succeeded
-                // after user dismissed/canceled dialog).
-                if (mCurrentAuthSession == null) {
-                    Slog.e(TAG, "onAcquired(): Auth session is null");
-                    return;
-                }
-
-                if (acquiredInfo != BiometricConstants.BIOMETRIC_ACQUIRED_GOOD) {
-                    try {
-                        mStatusBarService.onBiometricHelp(message);
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "Remote exception", e);
-                    }
-                }
-            }
-
-            @Override
-            public void onDialogDismissed(int reason) throws RemoteException {
-                if (mCurrentAuthSession == null) {
-                    Slog.e(TAG, "onDialogDismissed: " + reason + ", auth session null");
-                    return;
-                }
-
-                logDialogDismissed(reason);
-
-                if (reason != BiometricPrompt.DISMISSED_REASON_POSITIVE) {
-                    // Positive button is used by passive modalities as a "confirm" button,
-                    // do not send to client
-                    mCurrentAuthSession.mClientReceiver.onDialogDismissed(reason);
-                    // Cancel authentication. Skip the token/package check since we are cancelling
-                    // from system server. The interface is permission protected so this is fine.
-                    cancelInternal(null /* token */, null /* package */, false /* fromClient */);
-                }
-                if (reason == BiometricPrompt.DISMISSED_REASON_USER_CANCEL) {
-                    mCurrentAuthSession.mClientReceiver.onError(
-                            BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED,
-                            getContext().getString(
-                                    com.android.internal.R.string.biometric_error_user_canceled));
-                } else if (reason == BiometricPrompt.DISMISSED_REASON_POSITIVE) {
-                    // Have the service send the token to KeyStore, and send onAuthenticated
-                    // to the application
-                    KeyStore.getInstance().addAuthToken(mCurrentAuthSession.mTokenEscrow);
-                    mCurrentAuthSession.mClientReceiver.onAuthenticationSucceeded();
-                }
-                mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
-                mCurrentAuthSession.mState = STATE_AUTH_IDLE;
-                mCurrentAuthSession = null;
-            }
-
-            @Override
-            public void onTryAgainPressed() {
-                Slog.d(TAG, "onTryAgainPressed");
-                // No need to check permission, since it can only be invoked by SystemUI
-                // (or system server itself).
-                mHandler.post(() -> {
-                    authenticateInternal(mCurrentAuthSession.mToken,
-                            mCurrentAuthSession.mSessionId,
-                            mCurrentAuthSession.mUserId,
-                            mCurrentAuthSession.mClientReceiver,
-                            mCurrentAuthSession.mOpPackageName,
-                            mCurrentAuthSession.mBundle,
-                            mCurrentAuthSession.mCallingUid,
-                            mCurrentAuthSession.mCallingPid,
-                            mCurrentAuthSession.mCallingUserId,
-                            mCurrentAuthSession.mModality);
-                });
-            }
-
-            private void logDialogDismissed(int reason) {
-                if (reason == BiometricPrompt.DISMISSED_REASON_POSITIVE) {
-                    // Explicit auth, authentication confirmed.
-                    // Latency in this case is authenticated -> confirmed. <Biometric>Service
-                    // should have the first half (first acquired -> authenticated).
-                    final long latency = System.currentTimeMillis()
-                            - mCurrentAuthSession.mAuthenticatedTimeMs;
-
-                    if (LoggableMonitor.DEBUG) {
-                        Slog.v(LoggableMonitor.TAG, "Confirmed! Modality: " + statsModality()
-                                + ", User: " + mCurrentAuthSession.mUserId
-                                + ", IsCrypto: " + mCurrentAuthSession.isCrypto()
-                                + ", Client: " + BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT
-                                + ", RequireConfirmation: "
-                                    + mCurrentAuthSession.mRequireConfirmation
-                                + ", State: " + StatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED
-                                + ", Latency: " + latency);
-                    }
-
-                    StatsLog.write(StatsLog.BIOMETRIC_AUTHENTICATED,
-                            statsModality(),
-                            mCurrentAuthSession.mUserId,
-                            mCurrentAuthSession.isCrypto(),
-                            BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT,
-                            mCurrentAuthSession.mRequireConfirmation,
-                            StatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED,
-                            latency);
-                } else {
-                    int error = reason == BiometricPrompt.DISMISSED_REASON_NEGATIVE
-                            ? BiometricConstants.BIOMETRIC_ERROR_NEGATIVE_BUTTON
-                            : reason == BiometricPrompt.DISMISSED_REASON_USER_CANCEL
-                                    ? BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED
-                                    : 0;
-                    if (LoggableMonitor.DEBUG) {
-                        Slog.v(LoggableMonitor.TAG, "Dismissed! Modality: " + statsModality()
-                                + ", User: " + mCurrentAuthSession.mUserId
-                                + ", IsCrypto: " + mCurrentAuthSession.isCrypto()
-                                + ", Action: " + BiometricsProtoEnums.ACTION_AUTHENTICATE
-                                + ", Client: " + BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT
-                                + ", Error: " + error);
-                    }
-                    // Auth canceled
-                    StatsLog.write(StatsLog.BIOMETRIC_ERROR_OCCURRED,
-                            statsModality(),
-                            mCurrentAuthSession.mUserId,
-                            mCurrentAuthSession.isCrypto(),
-                            BiometricsProtoEnums.ACTION_AUTHENTICATE,
-                            BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT,
-                            error,
-                            0 /* vendorCode */);
-                }
-            }
-
-            private int statsModality() {
-                int modality = 0;
-                if (mCurrentAuthSession == null) {
-                    return BiometricsProtoEnums.MODALITY_UNKNOWN;
-                }
-                if ((mCurrentAuthSession.mModality & BiometricAuthenticator.TYPE_FINGERPRINT)
-                        != 0) {
-                    modality |= BiometricsProtoEnums.MODALITY_FINGERPRINT;
-                }
-                if ((mCurrentAuthSession.mModality & BiometricAuthenticator.TYPE_IRIS) != 0) {
-                    modality |= BiometricsProtoEnums.MODALITY_IRIS;
-                }
-                if ((mCurrentAuthSession.mModality & BiometricAuthenticator.TYPE_FACE) != 0) {
-                    modality |= BiometricsProtoEnums.MODALITY_FACE;
-                }
-                return modality;
-            }
-        };
-
         @Override // Binder call
         public void onReadyForAuthentication(int cookie, boolean requireConfirmation, int userId) {
             checkInternalPermission();
 
-            Iterator it = mPendingAuthSession.mModalitiesWaiting.entrySet().iterator();
-            while (it.hasNext()) {
-                Map.Entry<Integer, Integer> pair = (Map.Entry) it.next();
-                if (pair.getValue() == cookie) {
-                    mPendingAuthSession.mModalitiesMatched.put(pair.getKey(), pair.getValue());
-                    mPendingAuthSession.mModalitiesWaiting.remove(pair.getKey());
-                    Slog.d(TAG, "Matched cookie: " + cookie + ", "
-                            + mPendingAuthSession.mModalitiesWaiting.size() + " remaining");
-                    break;
-                }
-            }
-
-            if (mPendingAuthSession.mModalitiesWaiting.isEmpty()) {
-                final boolean continuing = mCurrentAuthSession != null &&
-                        (mCurrentAuthSession.mState == STATE_AUTH_PAUSED);
-
-                mCurrentAuthSession = mPendingAuthSession;
-                mPendingAuthSession = null;
-
-                mCurrentAuthSession.mState = STATE_AUTH_STARTED;
-                try {
-                    int modality = TYPE_NONE;
-                    it = mCurrentAuthSession.mModalitiesMatched.entrySet().iterator();
-                    while (it.hasNext()) {
-                        Map.Entry<Integer, Integer> pair = (Map.Entry) it.next();
-                        if (pair.getKey() == TYPE_FINGERPRINT) {
-                            mFingerprintService.startPreparedClient(pair.getValue());
-                        } else if (pair.getKey() == TYPE_IRIS) {
-                            Slog.e(TAG, "Iris unsupported");
-                        } else if (pair.getKey() == TYPE_FACE) {
-                            mFaceService.startPreparedClient(pair.getValue());
-                        } else {
-                            Slog.e(TAG, "Unknown modality: " + pair.getKey());
-                        }
-                        modality |= pair.getKey();
-                    }
-
-                    if (!continuing) {
-                        mStatusBarService.showBiometricDialog(mCurrentAuthSession.mBundle,
-                                mInternalReceiver, modality, requireConfirmation, userId);
-                        mActivityTaskManager.registerTaskStackListener(mTaskStackListener);
-                    }
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Remote exception", e);
-                }
-            }
+            SomeArgs args = SomeArgs.obtain();
+            args.argi1 = cookie;
+            args.arg1 = requireConfirmation;
+            args.argi2 = userId;
+            mHandler.obtainMessage(MSG_ON_READY_FOR_AUTHENTICATION, args).sendToTarget();
         }
 
         @Override // Binder call
@@ -754,25 +577,23 @@
                 checkInternalPermission();
                 // Set the default title if necessary
                 try {
-                    if (useDefaultTitle) {
-                        final List<ActivityManager.RunningAppProcessInfo> procs =
-                                ActivityManager.getService().getRunningAppProcesses();
-                        for (int i = 0; i < procs.size(); i++) {
-                            final ActivityManager.RunningAppProcessInfo info = procs.get(i);
-                            if (info.uid == callingUid
-                                    && info.importance == IMPORTANCE_FOREGROUND) {
-                                PackageManager pm = getContext().getPackageManager();
-                                final CharSequence label = pm.getApplicationLabel(
-                                        pm.getApplicationInfo(info.processName,
-                                                PackageManager.GET_META_DATA));
-                                final String title = getContext()
-                                        .getString(R.string.biometric_dialog_default_title, label);
-                                if (TextUtils.isEmpty(
-                                        bundle.getCharSequence(BiometricPrompt.KEY_TITLE))) {
-                                    bundle.putCharSequence(BiometricPrompt.KEY_TITLE, title);
-                                }
-                                break;
+                    final List<ActivityManager.RunningAppProcessInfo> procs =
+                            ActivityManager.getService().getRunningAppProcesses();
+                    for (int i = 0; i < procs.size(); i++) {
+                        final ActivityManager.RunningAppProcessInfo info = procs.get(i);
+                        if (info.uid == callingUid
+                                && info.importance == IMPORTANCE_FOREGROUND) {
+                            PackageManager pm = getContext().getPackageManager();
+                            final CharSequence label = pm.getApplicationLabel(
+                                    pm.getApplicationInfo(info.processName,
+                                            PackageManager.GET_META_DATA));
+                            final String title = getContext()
+                                    .getString(R.string.biometric_dialog_default_title, label);
+                            if (TextUtils.isEmpty(
+                                    bundle.getCharSequence(BiometricPrompt.KEY_TITLE))) {
+                                bundle.putCharSequence(BiometricPrompt.KEY_TITLE, title);
                             }
+                            break;
                         }
                     }
                 } catch (RemoteException e) {
@@ -792,7 +613,8 @@
                             KeyguardManager.class);
                     if (!kgm.isDeviceSecure()) {
                         try {
-                            receiver.onError(BiometricConstants.BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL,
+                            receiver.onError(
+                                    BiometricConstants.BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL,
                                     getContext().getString(
                                             R.string.biometric_error_device_not_secured));
                         } catch (RemoteException e) {
@@ -811,160 +633,63 @@
                 return;
             }
 
-            mHandler.post(() -> {
-                final Pair<Integer, Integer> result = checkAndGetBiometricModality(userId);
-                final int modality = result.first;
-                final int error = result.second;
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = token;
+            args.arg2 = sessionId;
+            args.argi1 = userId;
+            args.arg3 = receiver;
+            args.arg4 = opPackageName;
+            args.arg5 = bundle;
+            args.argi2 = callingUid;
+            args.argi3 = callingPid;
+            args.argi4 = callingUserId;
 
-                // Check for errors, notify callback, and return
-                if (error != BiometricConstants.BIOMETRIC_SUCCESS) {
-                    try {
-                        final String hardwareUnavailable =
-                                getContext().getString(R.string.biometric_error_hw_unavailable);
-                        switch (error) {
-                            case BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT:
-                                receiver.onError(error, hardwareUnavailable);
-                                break;
-                            case BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE:
-                                receiver.onError(error, hardwareUnavailable);
-                                break;
-                            case BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS:
-                                receiver.onError(error,
-                                        getErrorString(modality, error, 0 /* vendorCode */));
-                                break;
-                            default:
-                                Slog.e(TAG, "Unhandled error");
-                                break;
-                        }
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "Unable to send error", e);
-                    }
-                    return;
-                }
-
-                mCurrentModality = modality;
-
-                // Start preparing for authentication. Authentication starts when
-                // all modalities requested have invoked onReadyForAuthentication.
-                authenticateInternal(token, sessionId, userId, receiver, opPackageName, bundle,
-                        callingUid, callingPid, callingUserId, modality);
-            });
+            mHandler.obtainMessage(MSG_AUTHENTICATE, args).sendToTarget();
         }
 
         @Override // Binder call
         public void onConfirmDeviceCredentialSuccess() {
             checkInternalPermission();
-            if (mConfirmDeviceCredentialReceiver == null) {
-                Slog.w(TAG, "onCDCASuccess null!");
-                return;
-            }
-            try {
-                mConfirmDeviceCredentialReceiver.onAuthenticationSucceeded();
-            } catch (RemoteException e) {
-                Slog.e(TAG, "RemoteException", e);
-            }
-            mConfirmDeviceCredentialReceiver = null;
+            mHandler.post(() -> {
+                if (mConfirmDeviceCredentialReceiver == null) {
+                    Slog.w(TAG, "onCDCASuccess null!");
+                    return;
+                }
+                try {
+                    mConfirmDeviceCredentialReceiver.onAuthenticationSucceeded();
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "RemoteException", e);
+                }
+                mConfirmDeviceCredentialReceiver = null;
+            });
         }
 
         @Override // Binder call
         public void onConfirmDeviceCredentialError(int error, String message) {
             checkInternalPermission();
-            if (mConfirmDeviceCredentialReceiver == null) {
-                Slog.w(TAG, "onCDCAError null! Error: " + error + " " + message);
-                return;
-            }
-            try {
-                mConfirmDeviceCredentialReceiver.onError(error, message);
-            } catch (RemoteException e) {
-                Slog.e(TAG, "RemoteException", e);
-            }
-            mConfirmDeviceCredentialReceiver = null;
-        }
-
-        /**
-         * authenticate() (above) which is called from BiometricPrompt determines which
-         * modality/modalities to start authenticating with. authenticateInternal() should only be
-         * used for:
-         * 1) Preparing <Biometric>Services for authentication when BiometricPrompt#authenticate is,
-         *    invoked, shortly after which BiometricPrompt is shown and authentication starts
-         * 2) Preparing <Biometric>Services for authentication when BiometricPrompt is already shown
-         *    and the user has pressed "try again"
-         */
-        private void authenticateInternal(IBinder token, long sessionId, int userId,
-                IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle,
-                int callingUid, int callingPid, int callingUserId, int modality) {
-            try {
-                boolean requireConfirmation = bundle.getBoolean(
-                        BiometricPrompt.KEY_REQUIRE_CONFIRMATION, true /* default */);
-                if ((modality & TYPE_FACE) != 0) {
-                    // Check if the user has forced confirmation to be required in Settings.
-                    requireConfirmation = requireConfirmation
-                            || mSettingObserver.getFaceAlwaysRequireConfirmation();
+            mHandler.post(() -> {
+                if (mConfirmDeviceCredentialReceiver == null) {
+                    Slog.w(TAG, "onCDCAError null! Error: " + error + " " + message);
+                    return;
                 }
-                // Generate random cookies to pass to the services that should prepare to start
-                // authenticating. Store the cookie here and wait for all services to "ack"
-                // with the cookie. Once all cookies are received, we can show the prompt
-                // and let the services start authenticating. The cookie should be non-zero.
-                final int cookie = mRandom.nextInt(Integer.MAX_VALUE - 1) + 1;
-                Slog.d(TAG, "Creating auth session. Modality: " + modality
-                        + ", cookie: " + cookie);
-                final HashMap<Integer, Integer> authenticators = new HashMap<>();
-                authenticators.put(modality, cookie);
-                mPendingAuthSession = new AuthSession(authenticators, token, sessionId, userId,
-                        receiver, opPackageName, bundle, callingUid, callingPid, callingUserId,
-                        modality, requireConfirmation);
-                mPendingAuthSession.mState = STATE_AUTH_CALLED;
-                // No polymorphism :(
-                if ((modality & TYPE_FINGERPRINT) != 0) {
-                    mFingerprintService.prepareForAuthentication(token, sessionId, userId,
-                            mInternalReceiver, opPackageName, cookie,
-                            callingUid, callingPid, callingUserId);
+                try {
+                    mConfirmDeviceCredentialReceiver.onError(error, message);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "RemoteException", e);
                 }
-                if ((modality & TYPE_IRIS) != 0) {
-                    Slog.w(TAG, "Iris unsupported");
-                }
-                if ((modality & TYPE_FACE) != 0) {
-                    mFaceService.prepareForAuthentication(requireConfirmation,
-                            token, sessionId, userId, mInternalReceiver, opPackageName,
-                            cookie, callingUid, callingPid, callingUserId);
-                }
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Unable to start authentication", e);
-            }
+                mConfirmDeviceCredentialReceiver = null;
+            });
         }
 
         @Override // Binder call
         public void cancelAuthentication(IBinder token, String opPackageName)
                 throws RemoteException {
             checkPermission();
-            if (token == null || opPackageName == null) {
-                Slog.e(TAG, "Unable to cancel, one or more null arguments");
-                return;
-            }
 
-            // We need to check the current authenticators state. If we're pending confirm
-            // or idle, we need to dismiss the dialog and send an ERROR_CANCELED to the client,
-            // since we won't be getting an onError from the driver.
-            if (mCurrentAuthSession != null && mCurrentAuthSession.mState != STATE_AUTH_STARTED) {
-                mHandler.post(() -> {
-                    try {
-                        // Send error to client
-                        mCurrentAuthSession.mClientReceiver.onError(
-                                BiometricConstants.BIOMETRIC_ERROR_CANCELED,
-                                getContext().getString(
-                                        com.android.internal.R.string.biometric_error_user_canceled)
-                        );
-
-                        mCurrentAuthSession.mState = STATE_AUTH_IDLE;
-                        mCurrentAuthSession = null;
-                        mStatusBarService.hideBiometricDialog();
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "Remote exception", e);
-                    }
-                });
-            } else {
-                cancelInternal(token, opPackageName, true /* fromClient */);
-            }
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = token;
+            args.arg2 = opPackageName;
+            mHandler.obtainMessage(MSG_CANCEL_AUTHENTICATION, args).sendToTarget();
         }
 
         @Override // Binder call
@@ -1027,31 +752,6 @@
                 Binder.restoreCallingIdentity(ident);
             }
         }
-
-        void cancelInternal(IBinder token, String opPackageName, boolean fromClient) {
-            final int callingUid = Binder.getCallingUid();
-            final int callingPid = Binder.getCallingPid();
-            final int callingUserId = UserHandle.getCallingUserId();
-            mHandler.post(() -> {
-                try {
-                    // TODO: For multiple modalities, send a single ERROR_CANCELED only when all
-                    // drivers have canceled authentication.
-                    if ((mCurrentModality & TYPE_FINGERPRINT) != 0) {
-                        mFingerprintService.cancelAuthenticationFromService(token, opPackageName,
-                                callingUid, callingPid, callingUserId, fromClient);
-                    }
-                    if ((mCurrentModality & TYPE_IRIS) != 0) {
-                        Slog.w(TAG, "Iris unsupported");
-                    }
-                    if ((mCurrentModality & TYPE_FACE) != 0) {
-                        mFaceService.cancelAuthenticationFromService(token, opPackageName,
-                                callingUid, callingPid, callingUserId, fromClient);
-                    }
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Unable to cancel authentication");
-                }
-            });
-        }
     }
 
     private void checkAppOp(String opPackageName, int callingUid) {
@@ -1088,7 +788,6 @@
         super(context);
 
         mAppOps = context.getSystemService(AppOpsManager.class);
-        mHandler = new Handler(Looper.getMainLooper());
         mEnabledOnKeyguardCallbacks = new ArrayList<>();
         mSettingObserver = new SettingObserver(mHandler);
 
@@ -1123,6 +822,10 @@
                     ServiceManager.getService(Context.FACE_SERVICE));
         }
 
+        mActivityTaskManager = ActivityTaskManager.getService();
+        mStatusBarService = IStatusBarService.Stub.asInterface(
+                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+
         // Cache the authenticators
         for (int i = 0; i < FEATURE_ID.length; i++) {
             if (hasFeature(FEATURE_ID[i])) {
@@ -1259,4 +962,491 @@
                 return false;
         }
     }
+
+    private void logDialogDismissed(int reason) {
+        if (reason == BiometricPrompt.DISMISSED_REASON_POSITIVE) {
+            // Explicit auth, authentication confirmed.
+            // Latency in this case is authenticated -> confirmed. <Biometric>Service
+            // should have the first half (first acquired -> authenticated).
+            final long latency = System.currentTimeMillis()
+                    - mCurrentAuthSession.mAuthenticatedTimeMs;
+
+            if (LoggableMonitor.DEBUG) {
+                Slog.v(LoggableMonitor.TAG, "Confirmed! Modality: " + statsModality()
+                        + ", User: " + mCurrentAuthSession.mUserId
+                        + ", IsCrypto: " + mCurrentAuthSession.isCrypto()
+                        + ", Client: " + BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT
+                        + ", RequireConfirmation: "
+                        + mCurrentAuthSession.mRequireConfirmation
+                        + ", State: " + StatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED
+                        + ", Latency: " + latency);
+            }
+
+            StatsLog.write(StatsLog.BIOMETRIC_AUTHENTICATED,
+                    statsModality(),
+                    mCurrentAuthSession.mUserId,
+                    mCurrentAuthSession.isCrypto(),
+                    BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT,
+                    mCurrentAuthSession.mRequireConfirmation,
+                    StatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED,
+                    latency);
+        } else {
+            int error = reason == BiometricPrompt.DISMISSED_REASON_NEGATIVE
+                    ? BiometricConstants.BIOMETRIC_ERROR_NEGATIVE_BUTTON
+                    : reason == BiometricPrompt.DISMISSED_REASON_USER_CANCEL
+                            ? BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED
+                            : 0;
+            if (LoggableMonitor.DEBUG) {
+                Slog.v(LoggableMonitor.TAG, "Dismissed! Modality: " + statsModality()
+                        + ", User: " + mCurrentAuthSession.mUserId
+                        + ", IsCrypto: " + mCurrentAuthSession.isCrypto()
+                        + ", Action: " + BiometricsProtoEnums.ACTION_AUTHENTICATE
+                        + ", Client: " + BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT
+                        + ", Error: " + error);
+            }
+            // Auth canceled
+            StatsLog.write(StatsLog.BIOMETRIC_ERROR_OCCURRED,
+                    statsModality(),
+                    mCurrentAuthSession.mUserId,
+                    mCurrentAuthSession.isCrypto(),
+                    BiometricsProtoEnums.ACTION_AUTHENTICATE,
+                    BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT,
+                    error,
+                    0 /* vendorCode */);
+        }
+    }
+
+    private int statsModality() {
+        int modality = 0;
+        if (mCurrentAuthSession == null) {
+            return BiometricsProtoEnums.MODALITY_UNKNOWN;
+        }
+        if ((mCurrentAuthSession.mModality & BiometricAuthenticator.TYPE_FINGERPRINT)
+                != 0) {
+            modality |= BiometricsProtoEnums.MODALITY_FINGERPRINT;
+        }
+        if ((mCurrentAuthSession.mModality & BiometricAuthenticator.TYPE_IRIS) != 0) {
+            modality |= BiometricsProtoEnums.MODALITY_IRIS;
+        }
+        if ((mCurrentAuthSession.mModality & BiometricAuthenticator.TYPE_FACE) != 0) {
+            modality |= BiometricsProtoEnums.MODALITY_FACE;
+        }
+        return modality;
+    }
+
+    private void handleTaskStackChanged() {
+        try {
+            final List<ActivityManager.RunningTaskInfo> runningTasks =
+                    mActivityTaskManager.getTasks(1);
+            if (!runningTasks.isEmpty()) {
+                final String topPackage = runningTasks.get(0).topActivity.getPackageName();
+                if (mCurrentAuthSession != null
+                        && !topPackage.contentEquals(mCurrentAuthSession.mOpPackageName)) {
+                    mStatusBarService.hideBiometricDialog();
+                    mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
+                    mCurrentAuthSession.mClientReceiver.onError(
+                            BiometricConstants.BIOMETRIC_ERROR_CANCELED,
+                            getContext().getString(
+                                    com.android.internal.R.string.biometric_error_canceled)
+                    );
+                    mCurrentAuthSession.mState = STATE_AUTH_IDLE;
+                    mCurrentAuthSession = null;
+                }
+            }
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Unable to get running tasks", e);
+        }
+    }
+
+    private void handleAuthenticationSucceeded(boolean requireConfirmation, byte[] token) {
+
+        try {
+            // Should never happen, log this to catch bad HAL behavior (e.g. auth succeeded
+            // after user dismissed/canceled dialog).
+            if (mCurrentAuthSession == null) {
+                Slog.e(TAG, "onAuthenticationSucceeded(): Auth session is null");
+                return;
+            }
+
+            if (!requireConfirmation) {
+                mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
+                KeyStore.getInstance().addAuthToken(token);
+                mCurrentAuthSession.mClientReceiver.onAuthenticationSucceeded();
+                mCurrentAuthSession.mState = STATE_AUTH_IDLE;
+                mCurrentAuthSession = null;
+            } else {
+                mCurrentAuthSession.mAuthenticatedTimeMs = System.currentTimeMillis();
+                // Store the auth token and submit it to keystore after the confirmation
+                // button has been pressed.
+                mCurrentAuthSession.mTokenEscrow = token;
+                mCurrentAuthSession.mState = STATE_AUTH_PENDING_CONFIRM;
+            }
+
+            // Notify SysUI that the biometric has been authenticated. SysUI already knows
+            // the implicit/explicit state and will react accordingly.
+            mStatusBarService.onBiometricAuthenticated(true);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Remote exception", e);
+        }
+    }
+
+    private void handleAuthenticationFailed(int cookie, boolean requireConfirmation) {
+        try {
+            // Should never happen, log this to catch bad HAL behavior (e.g. auth succeeded
+            // after user dismissed/canceled dialog).
+            if (mCurrentAuthSession == null) {
+                Slog.e(TAG, "onAuthenticationFailed(): Auth session is null");
+                return;
+            }
+
+            mStatusBarService.onBiometricAuthenticated(false);
+
+            // TODO: This logic will need to be updated if BP is multi-modal
+            if ((mCurrentAuthSession.mModality & TYPE_FACE) != 0) {
+                // Pause authentication. onBiometricAuthenticated(false) causes the
+                // dialog to show a "try again" button for passive modalities.
+                mCurrentAuthSession.mState = STATE_AUTH_PAUSED;
+            }
+
+            mCurrentAuthSession.mClientReceiver.onAuthenticationFailed();
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Remote exception", e);
+        }
+    }
+
+    private void handleOnError(int cookie, int error, String message) {
+        Slog.d(TAG, "Error: " + error + " cookie: " + cookie);
+        // Errors can either be from the current auth session or the pending auth session.
+        // The pending auth session may receive errors such as ERROR_LOCKOUT before
+        // it becomes the current auth session. Similarly, the current auth session may
+        // receive errors such as ERROR_CANCELED while the pending auth session is preparing
+        // to be started. Thus we must match error messages with their cookies to be sure
+        // of their intended receivers.
+        try {
+            if (mCurrentAuthSession != null && mCurrentAuthSession.containsCookie(cookie)) {
+                if (mCurrentAuthSession.mState == STATE_AUTH_STARTED) {
+                    mStatusBarService.onBiometricError(message);
+                    if (error == BiometricConstants.BIOMETRIC_ERROR_CANCELED) {
+                        mActivityTaskManager.unregisterTaskStackListener(
+                                mTaskStackListener);
+                        mCurrentAuthSession.mClientReceiver.onError(error, message);
+                        mCurrentAuthSession.mState = STATE_AUTH_IDLE;
+                        mCurrentAuthSession = null;
+                        mStatusBarService.hideBiometricDialog();
+                    } else {
+                        // Send errors after the dialog is dismissed.
+                        mHandler.postDelayed(() -> {
+                            try {
+                                if (mCurrentAuthSession != null) {
+                                    mActivityTaskManager.unregisterTaskStackListener(
+                                            mTaskStackListener);
+                                    mCurrentAuthSession.mClientReceiver.onError(error,
+                                            message);
+                                    mCurrentAuthSession.mState = STATE_AUTH_IDLE;
+                                    mCurrentAuthSession = null;
+                                }
+                            } catch (RemoteException e) {
+                                Slog.e(TAG, "Remote exception", e);
+                            }
+                        }, BiometricPrompt.HIDE_DIALOG_DELAY);
+                    }
+                } else if (mCurrentAuthSession.mState == STATE_AUTH_PAUSED) {
+                    // In the "try again" state, we should forward canceled errors to
+                    // the client and and clean up.
+                    mCurrentAuthSession.mClientReceiver.onError(error, message);
+                    mStatusBarService.onBiometricError(message);
+                    mActivityTaskManager.unregisterTaskStackListener(
+                            mTaskStackListener);
+                    mCurrentAuthSession.mState = STATE_AUTH_IDLE;
+                    mCurrentAuthSession = null;
+                } else {
+                    Slog.e(TAG, "Impossible session error state: "
+                            + mCurrentAuthSession.mState);
+                }
+            } else if (mPendingAuthSession != null
+                    && mPendingAuthSession.containsCookie(cookie)) {
+                if (mPendingAuthSession.mState == STATE_AUTH_CALLED) {
+                    mPendingAuthSession.mClientReceiver.onError(error, message);
+                    mPendingAuthSession.mState = STATE_AUTH_IDLE;
+                    mPendingAuthSession = null;
+                } else {
+                    Slog.e(TAG, "Impossible pending session error state: "
+                            + mPendingAuthSession.mState);
+                }
+            }
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Remote exception", e);
+        }
+    }
+
+    private void handleOnAcquired(int acquiredInfo, String message) {
+        // Should never happen, log this to catch bad HAL behavior (e.g. auth succeeded
+        // after user dismissed/canceled dialog).
+        if (mCurrentAuthSession == null) {
+            Slog.e(TAG, "onAcquired(): Auth session is null");
+            return;
+        }
+
+        if (acquiredInfo != BiometricConstants.BIOMETRIC_ACQUIRED_GOOD) {
+            try {
+                mStatusBarService.onBiometricHelp(message);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Remote exception", e);
+            }
+        }
+    }
+
+    private void handleOnDismissed(int reason) {
+        if (mCurrentAuthSession == null) {
+            Slog.e(TAG, "onDialogDismissed: " + reason + ", auth session null");
+            return;
+        }
+
+        logDialogDismissed(reason);
+
+        try {
+            if (reason != BiometricPrompt.DISMISSED_REASON_POSITIVE) {
+                // Positive button is used by passive modalities as a "confirm" button,
+                // do not send to client
+                mCurrentAuthSession.mClientReceiver.onDialogDismissed(reason);
+                // Cancel authentication. Skip the token/package check since we are cancelling
+                // from system server. The interface is permission protected so this is fine.
+                cancelInternal(null /* token */, null /* package */, false /* fromClient */);
+            }
+            if (reason == BiometricPrompt.DISMISSED_REASON_USER_CANCEL) {
+                mCurrentAuthSession.mClientReceiver.onError(
+                        BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED,
+                        getContext().getString(
+                                com.android.internal.R.string.biometric_error_user_canceled));
+            } else if (reason == BiometricPrompt.DISMISSED_REASON_POSITIVE) {
+                // Have the service send the token to KeyStore, and send onAuthenticated
+                // to the application
+                KeyStore.getInstance().addAuthToken(mCurrentAuthSession.mTokenEscrow);
+                mCurrentAuthSession.mClientReceiver.onAuthenticationSucceeded();
+            }
+            mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
+            mCurrentAuthSession.mState = STATE_AUTH_IDLE;
+            mCurrentAuthSession = null;
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Remote exception", e);
+        }
+    }
+
+    private void handleOnTryAgainPressed() {
+        Slog.d(TAG, "onTryAgainPressed");
+        // No need to check permission, since it can only be invoked by SystemUI
+        // (or system server itself).
+        authenticateInternal(mCurrentAuthSession.mToken,
+                mCurrentAuthSession.mSessionId,
+                mCurrentAuthSession.mUserId,
+                mCurrentAuthSession.mClientReceiver,
+                mCurrentAuthSession.mOpPackageName,
+                mCurrentAuthSession.mBundle,
+                mCurrentAuthSession.mCallingUid,
+                mCurrentAuthSession.mCallingPid,
+                mCurrentAuthSession.mCallingUserId,
+                mCurrentAuthSession.mModality);
+    }
+
+    private void handleOnReadyForAuthentication(int cookie, boolean requireConfirmation,
+            int userId) {
+        Iterator it = mPendingAuthSession.mModalitiesWaiting.entrySet().iterator();
+        while (it.hasNext()) {
+            Map.Entry<Integer, Integer> pair = (Map.Entry) it.next();
+            if (pair.getValue() == cookie) {
+                mPendingAuthSession.mModalitiesMatched.put(pair.getKey(), pair.getValue());
+                mPendingAuthSession.mModalitiesWaiting.remove(pair.getKey());
+                Slog.d(TAG, "Matched cookie: " + cookie + ", "
+                        + mPendingAuthSession.mModalitiesWaiting.size() + " remaining");
+                break;
+            }
+        }
+
+        if (mPendingAuthSession.mModalitiesWaiting.isEmpty()) {
+            final boolean continuing = mCurrentAuthSession != null
+                    && mCurrentAuthSession.mState == STATE_AUTH_PAUSED;
+
+            mCurrentAuthSession = mPendingAuthSession;
+            mPendingAuthSession = null;
+
+            mCurrentAuthSession.mState = STATE_AUTH_STARTED;
+            try {
+                int modality = TYPE_NONE;
+                it = mCurrentAuthSession.mModalitiesMatched.entrySet().iterator();
+                while (it.hasNext()) {
+                    Map.Entry<Integer, Integer> pair = (Map.Entry) it.next();
+                    if (pair.getKey() == TYPE_FINGERPRINT) {
+                        mFingerprintService.startPreparedClient(pair.getValue());
+                    } else if (pair.getKey() == TYPE_IRIS) {
+                        Slog.e(TAG, "Iris unsupported");
+                    } else if (pair.getKey() == TYPE_FACE) {
+                        mFaceService.startPreparedClient(pair.getValue());
+                    } else {
+                        Slog.e(TAG, "Unknown modality: " + pair.getKey());
+                    }
+                    modality |= pair.getKey();
+                }
+
+                if (!continuing) {
+                    mStatusBarService.showBiometricDialog(mCurrentAuthSession.mBundle,
+                            mInternalReceiver, modality, requireConfirmation, userId);
+                    mActivityTaskManager.registerTaskStackListener(mTaskStackListener);
+                }
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Remote exception", e);
+            }
+        }
+    }
+
+    private void handleAuthenticate(IBinder token, long sessionId, int userId,
+            IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle,
+            int callingUid, int callingPid, int callingUserId) {
+
+        mHandler.post(() -> {
+            final Pair<Integer, Integer> result = checkAndGetBiometricModality(userId);
+            final int modality = result.first;
+            final int error = result.second;
+
+            // Check for errors, notify callback, and return
+            if (error != BiometricConstants.BIOMETRIC_SUCCESS) {
+                try {
+                    final String hardwareUnavailable =
+                            getContext().getString(R.string.biometric_error_hw_unavailable);
+                    switch (error) {
+                        case BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT:
+                            receiver.onError(error, hardwareUnavailable);
+                            break;
+                        case BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE:
+                            receiver.onError(error, hardwareUnavailable);
+                            break;
+                        case BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS:
+                            receiver.onError(error,
+                                    getErrorString(modality, error, 0 /* vendorCode */));
+                            break;
+                        default:
+                            Slog.e(TAG, "Unhandled error");
+                            break;
+                    }
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Unable to send error", e);
+                }
+                return;
+            }
+
+            mCurrentModality = modality;
+
+            // Start preparing for authentication. Authentication starts when
+            // all modalities requested have invoked onReadyForAuthentication.
+            authenticateInternal(token, sessionId, userId, receiver, opPackageName, bundle,
+                    callingUid, callingPid, callingUserId, modality);
+        });
+    }
+
+    /**
+     * authenticate() (above) which is called from BiometricPrompt determines which
+     * modality/modalities to start authenticating with. authenticateInternal() should only be
+     * used for:
+     * 1) Preparing <Biometric>Services for authentication when BiometricPrompt#authenticate is,
+     *    invoked, shortly after which BiometricPrompt is shown and authentication starts
+     * 2) Preparing <Biometric>Services for authentication when BiometricPrompt is already shown
+     *    and the user has pressed "try again"
+     */
+    private void authenticateInternal(IBinder token, long sessionId, int userId,
+            IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle,
+            int callingUid, int callingPid, int callingUserId, int modality) {
+        try {
+            boolean requireConfirmation = bundle.getBoolean(
+                    BiometricPrompt.KEY_REQUIRE_CONFIRMATION, true /* default */);
+            if ((modality & TYPE_FACE) != 0) {
+                // Check if the user has forced confirmation to be required in Settings.
+                requireConfirmation = requireConfirmation
+                        || mSettingObserver.getFaceAlwaysRequireConfirmation();
+            }
+            // Generate random cookies to pass to the services that should prepare to start
+            // authenticating. Store the cookie here and wait for all services to "ack"
+            // with the cookie. Once all cookies are received, we can show the prompt
+            // and let the services start authenticating. The cookie should be non-zero.
+            final int cookie = mRandom.nextInt(Integer.MAX_VALUE - 1) + 1;
+            Slog.d(TAG, "Creating auth session. Modality: " + modality
+                    + ", cookie: " + cookie);
+            final HashMap<Integer, Integer> authenticators = new HashMap<>();
+            authenticators.put(modality, cookie);
+            mPendingAuthSession = new AuthSession(authenticators, token, sessionId, userId,
+                    receiver, opPackageName, bundle, callingUid, callingPid, callingUserId,
+                    modality, requireConfirmation);
+            mPendingAuthSession.mState = STATE_AUTH_CALLED;
+            // No polymorphism :(
+            if ((modality & TYPE_FINGERPRINT) != 0) {
+                mFingerprintService.prepareForAuthentication(token, sessionId, userId,
+                        mInternalReceiver, opPackageName, cookie,
+                        callingUid, callingPid, callingUserId);
+            }
+            if ((modality & TYPE_IRIS) != 0) {
+                Slog.w(TAG, "Iris unsupported");
+            }
+            if ((modality & TYPE_FACE) != 0) {
+                mFaceService.prepareForAuthentication(requireConfirmation,
+                        token, sessionId, userId, mInternalReceiver, opPackageName,
+                        cookie, callingUid, callingPid, callingUserId);
+            }
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Unable to start authentication", e);
+        }
+    }
+
+    private void handleCancelAuthentication(IBinder token, String opPackageName) {
+        if (token == null || opPackageName == null) {
+            Slog.e(TAG, "Unable to cancel, one or more null arguments");
+            return;
+        }
+
+        // We need to check the current authenticators state. If we're pending confirm
+        // or idle, we need to dismiss the dialog and send an ERROR_CANCELED to the client,
+        // since we won't be getting an onError from the driver.
+        if (mCurrentAuthSession != null && mCurrentAuthSession.mState != STATE_AUTH_STARTED) {
+            try {
+                // Send error to client
+                mCurrentAuthSession.mClientReceiver.onError(
+                        BiometricConstants.BIOMETRIC_ERROR_CANCELED,
+                        getContext().getString(
+                                com.android.internal.R.string.biometric_error_user_canceled)
+                );
+
+                mCurrentAuthSession.mState = STATE_AUTH_IDLE;
+                mCurrentAuthSession = null;
+                mStatusBarService.hideBiometricDialog();
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Remote exception", e);
+            }
+        } else {
+            cancelInternal(token, opPackageName, true /* fromClient */);
+        }
+    }
+
+
+    void cancelInternal(IBinder token, String opPackageName, boolean fromClient) {
+        final int callingUid = Binder.getCallingUid();
+        final int callingPid = Binder.getCallingPid();
+        final int callingUserId = UserHandle.getCallingUserId();
+        mHandler.post(() -> {
+            try {
+                // TODO: For multiple modalities, send a single ERROR_CANCELED only when all
+                // drivers have canceled authentication.
+                if ((mCurrentModality & TYPE_FINGERPRINT) != 0) {
+                    mFingerprintService.cancelAuthenticationFromService(token, opPackageName,
+                            callingUid, callingPid, callingUserId, fromClient);
+                }
+                if ((mCurrentModality & TYPE_IRIS) != 0) {
+                    Slog.w(TAG, "Iris unsupported");
+                }
+                if ((mCurrentModality & TYPE_FACE) != 0) {
+                    mFaceService.cancelAuthenticationFromService(token, opPackageName,
+                            callingUid, callingPid, callingUserId, fromClient);
+                }
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Unable to cancel authentication");
+            }
+        });
+    }
+
 }
diff --git a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
index d787758..3e48445 100644
--- a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
+++ b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
@@ -43,6 +43,7 @@
 import android.os.IHwBinder;
 import android.os.IRemoteCallback;
 import android.os.PowerManager;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
@@ -958,6 +959,10 @@
             int pid, int userId) {
         checkUseBiometricPermission();
 
+
+        if (Binder.getCallingUid() == Process.SYSTEM_UID) {
+            return true; // System process (BiometricService, etc) is always allowed
+        }
         if (isKeyguard(opPackageName)) {
             return true; // Keyguard is always allowed
         }
@@ -1218,6 +1223,9 @@
                     BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_HAL);
         } else {
             clearEnumerateState();
+            if (mPendingClient != null) {
+                startClient(mPendingClient, false /* initiatedByClient */);
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/biometrics/face/FaceService.java b/services/core/java/com/android/server/biometrics/face/FaceService.java
index feeb16b..c385991 100644
--- a/services/core/java/com/android/server/biometrics/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/face/FaceService.java
@@ -633,11 +633,19 @@
         }
 
         @Override
-        public void onRemoved(final long deviceId, final int faceId, final int userId,
-                final int remaining) {
+        public void onRemoved(final long deviceId, ArrayList<Integer> faceIds, final int userId) {
             mHandler.post(() -> {
-                final Face face = new Face("", faceId, deviceId);
-                FaceService.super.handleRemoved(face, remaining);
+                if (!faceIds.isEmpty()) {
+                    for (int i = 0; i < faceIds.size(); i++) {
+                        final Face face = new Face("", faceIds.get(i), deviceId);
+                        // Convert to old behavior
+                        FaceService.super.handleRemoved(face, faceIds.size() - i - 1);
+                    }
+                } else {
+                    final Face face = new Face("", 0 /* identifier */, deviceId);
+                    FaceService.super.handleRemoved(face, 0 /* remaining */);
+                }
+
             });
         }
 
diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
index cc4c173..35d6860 100644
--- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
+++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
@@ -21,8 +21,8 @@
 import static android.net.NetworkAgent.CMD_REMOVE_KEEPALIVE_PACKET_FILTER;
 import static android.net.NetworkAgent.CMD_START_SOCKET_KEEPALIVE;
 import static android.net.NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE;
-import static android.net.NetworkAgent.EVENT_SOCKET_KEEPALIVE;
 import static android.net.SocketKeepalive.BINDER_DIED;
+import static android.net.SocketKeepalive.DATA_RECEIVED;
 import static android.net.SocketKeepalive.ERROR_INVALID_INTERVAL;
 import static android.net.SocketKeepalive.ERROR_INVALID_IP_ADDRESS;
 import static android.net.SocketKeepalive.ERROR_INVALID_NETWORK;
@@ -34,6 +34,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.net.ISocketKeepaliveCallback;
 import android.net.KeepalivePacketData;
 import android.net.NattKeepalivePacketData;
 import android.net.NetworkAgent;
@@ -47,7 +48,6 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
-import android.os.Messenger;
 import android.os.Process;
 import android.os.RemoteException;
 import android.system.ErrnoException;
@@ -99,8 +99,7 @@
      */
     class KeepaliveInfo implements IBinder.DeathRecipient {
         // Bookkeeping data.
-        private final Messenger mMessenger;
-        private final IBinder mBinder;
+        private final ISocketKeepaliveCallback mCallback;
         private final int mUid;
         private final int mPid;
         private final NetworkAgentInfo mNai;
@@ -124,15 +123,13 @@
         private static final int STARTED = 3;
         private int mStartedState = NOT_STARTED;
 
-        KeepaliveInfo(@NonNull Messenger messenger,
-                @NonNull IBinder binder,
+        KeepaliveInfo(@NonNull ISocketKeepaliveCallback callback,
                 @NonNull NetworkAgentInfo nai,
                 @NonNull KeepalivePacketData packet,
                 int interval,
                 int type,
                 @NonNull FileDescriptor fd) {
-            mMessenger = messenger;
-            mBinder = binder;
+            mCallback = callback;
             mPid = Binder.getCallingPid();
             mUid = Binder.getCallingUid();
 
@@ -143,7 +140,7 @@
             mFd = fd;
 
             try {
-                mBinder.linkToDeath(this, 0);
+                mCallback.asBinder().linkToDeath(this, 0);
             } catch (RemoteException e) {
                 binderDied();
             }
@@ -176,22 +173,14 @@
                     + " ]";
         }
 
-        /** Sends a message back to the application via its SocketKeepalive.Callback. */
-        void notifyMessenger(int slot, int err) {
-            if (DBG) {
-                Log.d(TAG, "notify keepalive " + mSlot + " on " + mNai.network + " for " + err);
-            }
-            KeepaliveTracker.this.notifyMessenger(mMessenger, slot, err);
-        }
-
         /** Called when the application process is killed. */
         public void binderDied() {
             stop(BINDER_DIED);
         }
 
         void unlinkDeathRecipient() {
-            if (mBinder != null) {
-                mBinder.unlinkToDeath(this, 0);
+            if (mCallback != null) {
+                mCallback.asBinder().unlinkToDeath(this, 0);
             }
         }
 
@@ -283,9 +272,23 @@
                     Log.wtf(TAG, "Stopping keepalive with unknown type: " + mType);
                 }
             }
-            // TODO: at the moment we unconditionally return failure here. In cases where the
-            // NetworkAgent is alive, should we ask it to reply, so it can return failure?
-            notifyMessenger(mSlot, reason);
+
+            if (reason == SUCCESS) {
+                try {
+                    mCallback.onStopped();
+                } catch (RemoteException e) {
+                    Log.w(TAG, "Discarded onStop callback: " + reason);
+                }
+            } else if (reason == DATA_RECEIVED) {
+                try {
+                    mCallback.onDataReceived();
+                } catch (RemoteException e) {
+                    Log.w(TAG, "Discarded onDataReceived callback: " + reason);
+                }
+            } else {
+                notifyErrorCallback(mCallback, reason);
+            }
+
             unlinkDeathRecipient();
         }
 
@@ -294,16 +297,12 @@
         }
     }
 
-    void notifyMessenger(Messenger messenger, int slot, int err) {
-        Message message = Message.obtain();
-        message.what = EVENT_SOCKET_KEEPALIVE;
-        message.arg1 = slot;
-        message.arg2 = err;
-        message.obj = null;
+    void notifyErrorCallback(ISocketKeepaliveCallback cb, int error) {
+        if (DBG) Log.w(TAG, "Sending onError(" + error + ") callback");
         try {
-            messenger.send(message);
+            cb.onError(error);
         } catch (RemoteException e) {
-            // Process died?
+            Log.w(TAG, "Discarded onError(" + error + ") callback");
         }
     }
 
@@ -414,7 +413,11 @@
             // Keepalive successfully started.
             if (DBG) Log.d(TAG, "Started keepalive " + slot + " on " + nai.name());
             ki.mStartedState = KeepaliveInfo.STARTED;
-            ki.notifyMessenger(slot, reason);
+            try {
+                ki.mCallback.onStarted(slot);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Discarded onStarted(" + slot + ") callback");
+            }
         } else {
             // Keepalive successfully stopped, or error.
             ki.mStartedState = KeepaliveInfo.NOT_STARTED;
@@ -436,14 +439,13 @@
      **/
     public void startNattKeepalive(@Nullable NetworkAgentInfo nai,
             int intervalSeconds,
-            @NonNull Messenger messenger,
-            @NonNull IBinder binder,
+            @NonNull ISocketKeepaliveCallback cb,
             @NonNull String srcAddrString,
             int srcPort,
             @NonNull String dstAddrString,
             int dstPort) {
         if (nai == null) {
-            notifyMessenger(messenger, NO_KEEPALIVE, ERROR_INVALID_NETWORK);
+            notifyErrorCallback(cb, ERROR_INVALID_NETWORK);
             return;
         }
 
@@ -452,7 +454,7 @@
             srcAddress = NetworkUtils.numericToInetAddress(srcAddrString);
             dstAddress = NetworkUtils.numericToInetAddress(dstAddrString);
         } catch (IllegalArgumentException e) {
-            notifyMessenger(messenger, NO_KEEPALIVE, ERROR_INVALID_IP_ADDRESS);
+            notifyErrorCallback(cb, ERROR_INVALID_IP_ADDRESS);
             return;
         }
 
@@ -461,11 +463,12 @@
             packet = NattKeepalivePacketData.nattKeepalivePacket(
                     srcAddress, srcPort, dstAddress, NATT_PORT);
         } catch (InvalidPacketException e) {
-            notifyMessenger(messenger, NO_KEEPALIVE, e.error);
+            notifyErrorCallback(cb, e.error);
             return;
         }
-        KeepaliveInfo ki = new KeepaliveInfo(messenger, binder, nai, packet, intervalSeconds,
+        KeepaliveInfo ki = new KeepaliveInfo(cb, nai, packet, intervalSeconds,
                 KeepaliveInfo.TYPE_NATT, null);
+        Log.d(TAG, "Created keepalive: " + ki.toString());
         mConnectivityServiceHandler.obtainMessage(
                 NetworkAgent.CMD_START_SOCKET_KEEPALIVE, ki).sendToTarget();
     }
@@ -483,10 +486,9 @@
     public void startTcpKeepalive(@Nullable NetworkAgentInfo nai,
             @NonNull FileDescriptor fd,
             int intervalSeconds,
-            @NonNull Messenger messenger,
-            @NonNull IBinder binder) {
+            @NonNull ISocketKeepaliveCallback cb) {
         if (nai == null) {
-            notifyMessenger(messenger, NO_KEEPALIVE, ERROR_INVALID_NETWORK);
+            notifyErrorCallback(cb, ERROR_INVALID_NETWORK);
             return;
         }
 
@@ -500,10 +502,10 @@
             } catch (ErrnoException e1) {
                 Log.e(TAG, "Couldn't move fd out of repair mode after failure to start keepalive");
             }
-            notifyMessenger(messenger, NO_KEEPALIVE, e.error);
+            notifyErrorCallback(cb, e.error);
             return;
         }
-        KeepaliveInfo ki = new KeepaliveInfo(messenger, binder, nai, packet, intervalSeconds,
+        KeepaliveInfo ki = new KeepaliveInfo(cb, nai, packet, intervalSeconds,
                 KeepaliveInfo.TYPE_TCP, fd);
         Log.d(TAG, "Created keepalive: " + ki.toString());
         mConnectivityServiceHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE, ki).sendToTarget();
@@ -520,14 +522,13 @@
             @Nullable FileDescriptor fd,
             int resourceId,
             int intervalSeconds,
-            @NonNull Messenger messenger,
-            @NonNull IBinder binder,
+            @NonNull ISocketKeepaliveCallback cb,
             @NonNull String srcAddrString,
             @NonNull String dstAddrString,
             int dstPort) {
         // Ensure that the socket is created by IpSecService.
         if (!isNattKeepaliveSocketValid(fd, resourceId)) {
-            notifyMessenger(messenger, NO_KEEPALIVE, ERROR_INVALID_SOCKET);
+            notifyErrorCallback(cb, ERROR_INVALID_SOCKET);
         }
 
         // Get src port to adopt old API.
@@ -536,11 +537,11 @@
             final SocketAddress srcSockAddr = Os.getsockname(fd);
             srcPort = ((InetSocketAddress) srcSockAddr).getPort();
         } catch (ErrnoException e) {
-            notifyMessenger(messenger, NO_KEEPALIVE, ERROR_INVALID_SOCKET);
+            notifyErrorCallback(cb, ERROR_INVALID_SOCKET);
         }
 
         // Forward request to old API.
-        startNattKeepalive(nai, intervalSeconds, messenger, binder, srcAddrString, srcPort,
+        startNattKeepalive(nai, intervalSeconds, cb, srcAddrString, srcPort,
                 dstAddrString, dstPort);
     }
 
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index 053da0d..828a1e5 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -28,6 +28,7 @@
 import android.content.res.Resources;
 import android.net.wifi.WifiInfo;
 import android.os.UserHandle;
+import android.telephony.AccessNetworkConstants.TransportType;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.Slog;
@@ -92,7 +93,7 @@
         return -1;
     }
 
-    private static String getTransportName(int transportType) {
+    private static String getTransportName(@TransportType int transportType) {
         Resources r = Resources.getSystem();
         String[] networkTypes = r.getStringArray(R.array.network_switch_type_name);
         try {
diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
index d84a4d2..123564e 100644
--- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java
+++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
@@ -46,13 +46,11 @@
 import android.util.Slog;
 import android.util.SparseIntArray;
 
-import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 import com.android.server.LocalServices;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -84,20 +82,14 @@
     // Keys are App IDs. Values are true for SYSTEM permission and false for NETWORK permission.
     private final Map<Integer, Boolean> mApps = new HashMap<>();
 
-    // Keys are App packageNames, Values are app uids. . We need to keep track of this information
-    // because PackageListObserver#onPackageRemoved does not pass the UID.
-    @GuardedBy("mPackageNameUidMap")
-    private final Map<String, Integer> mPackageNameUidMap = new HashMap<>();
-
     private class PackageListObserver implements PackageManagerInternal.PackageListObserver {
         @Override
-        public void onPackageAdded(String packageName) {
+        public void onPackageAdded(String packageName, int uid) {
             final PackageInfo app = getPackageInfo(packageName);
             if (app == null) {
                 Slog.wtf(TAG, "Failed to get information of installed package: " + packageName);
                 return;
             }
-            int uid = (app.applicationInfo != null) ? app.applicationInfo.uid : INVALID_UID;
             if (uid == INVALID_UID) {
                 Slog.wtf(TAG, "Failed to get the uid of installed package: " + packageName
                         + "uid: " + uid);
@@ -107,29 +99,21 @@
                 return;
             }
             sendPackagePermissionsForUid(uid,
-                    filterPermission(Arrays.asList(app.requestedPermissions)));
-            synchronized (mPackageNameUidMap) {
-                mPackageNameUidMap.put(packageName, uid);
-            }
+                    getNetdPermissionMask(app.requestedPermissions));
         }
 
         @Override
-        public void onPackageRemoved(String packageName) {
-            int uid;
-            synchronized (mPackageNameUidMap) {
-                if (!mPackageNameUidMap.containsKey(packageName)) {
-                    return;
-                }
-                uid = mPackageNameUidMap.get(packageName);
-                mPackageNameUidMap.remove(packageName);
-            }
+        public void onPackageRemoved(String packageName, int uid) {
             int permission = 0;
+            // If there are still packages remain under the same uid, check the permission of the
+            // remaining packages. We only remove the permission for a given uid when all packages
+            // for that uid no longer have that permission.
             String[] packages = mPackageManager.getPackagesForUid(uid);
             if (packages != null && packages.length > 0) {
                 for (String name : packages) {
                     final PackageInfo app = getPackageInfo(name);
                     if (app != null && app.requestedPermissions != null) {
-                        permission |= filterPermission(Arrays.asList(app.requestedPermissions));
+                        permission |= getNetdPermissionMask(app.requestedPermissions);
                     }
                 }
             }
@@ -184,12 +168,9 @@
 
             //TODO: unify the management of the permissions into one codepath.
             if (app.requestedPermissions != null) {
-                int otherNetdPerms = filterPermission(Arrays.asList(app.requestedPermissions));
+                int otherNetdPerms = getNetdPermissionMask(app.requestedPermissions);
                 if (otherNetdPerms != 0) {
                     netdPermsUids.put(uid, netdPermsUids.get(uid) | otherNetdPerms);
-                    synchronized (mPackageNameUidMap) {
-                        mPackageNameUidMap.put(app.applicationInfo.packageName, uid);
-                    }
                 }
             }
         }
@@ -422,13 +403,15 @@
         }
     }
 
-    private static int filterPermission(List<String> requestedPermissions) {
+    private static int getNetdPermissionMask(String[] requestedPermissions) {
         int permissions = 0;
-        if (requestedPermissions.contains(INTERNET)) {
-            permissions |= INetd.PERMISSION_INTERNET;
-        }
-        if (requestedPermissions.contains(UPDATE_DEVICE_STATS)) {
-            permissions |= INetd.PERMISSION_UPDATE_DEVICE_STATS;
+        for (String permissionName : requestedPermissions) {
+            if (permissionName.equals(INTERNET)) {
+                permissions |= INetd.PERMISSION_INTERNET;
+            }
+            if (permissionName.equals(UPDATE_DEVICE_STATS)) {
+                permissions |= INetd.PERMISSION_UPDATE_DEVICE_STATS;
+            }
         }
         return permissions;
     }
@@ -439,8 +422,6 @@
                     | MATCH_ANY_USER);
             return app;
         } catch (NameNotFoundException e) {
-            // App not found.
-            loge("NameNotFoundException " + packageName);
             return null;
         }
     }
diff --git a/services/core/java/com/android/server/display/color/ColorDisplayService.java b/services/core/java/com/android/server/display/color/ColorDisplayService.java
index 2311776..45567e5 100644
--- a/services/core/java/com/android/server/display/color/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/color/ColorDisplayService.java
@@ -402,6 +402,10 @@
         cr.registerContentObserver(Secure.getUriFor(Secure.DISPLAY_WHITE_BALANCE_ENABLED),
                 false /* notifyForDescendants */, mContentObserver, mCurrentUser);
 
+        // Apply the accessibility settings first, since they override most other settings.
+        onAccessibilityInversionChanged();
+        onAccessibilityDaltonizerChanged();
+
         // Set the color mode, if valid, and immediately apply the updated tint matrix based on the
         // existing activated state. This ensures consistency of tint across the color mode change.
         onDisplayColorModeChanged(getColorModeInternal());
diff --git a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
index d2ccfcc..3c27bf2 100644
--- a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
+++ b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
@@ -126,8 +126,26 @@
     private final SparseArray<S> mServicesCache = new SparseArray<>();
 
     /**
+     * Whether the per-user service should be removed from the cache when its apk is updated.
+     */
+    private final boolean mRefreshServiceOnPackageUpdate;
+
+    /**
+     * Name of the service's package that was active but then was removed because its package
+     * update.
+     *
+     * <p>It's a temporary state set / used by the {@link PackageMonitor} implementation, but
+     * defined here so it can be dumped.
+     */
+    @GuardedBy("mLock")
+    private String mLastActivePackageName;
+
+    /**
      * Default constructor.
      *
+     * <p>When using this constructor, the {@link AbstractPerUserSystemService} is removed from
+     * the cache (and re-added) when the service package is updated.
+     *
      * @param context system context.
      * @param serviceNameResolver resolver for
      * {@link com.android.internal.infra.AbstractRemoteService} instances, or
@@ -139,8 +157,32 @@
     protected AbstractMasterSystemService(@NonNull Context context,
             @Nullable ServiceNameResolver serviceNameResolver,
             @Nullable String disallowProperty) {
+        this(context, serviceNameResolver, disallowProperty,
+                /* refreshServiceOnPackageUpdate=*/ true);
+    }
+
+    /**
+     * Full constructor.
+     *
+     * @param context system context.
+     * @param serviceNameResolver resolver for
+     * {@link com.android.internal.infra.AbstractRemoteService} instances, or
+     * {@code null} when the service doesn't bind to remote services.
+     * @param disallowProperty when not {@code null}, defines a {@link UserManager} restriction that
+     *        disables the service. <b>NOTE: </b> you'll also need to add it to
+     *        {@code UserRestrictionsUtils.USER_RESTRICTIONS}.
+     * @param refreshServiceOnPackageUpdate when {@code true}, the
+     *        {@link AbstractPerUserSystemService} is removed from the cache (and re-added) when the
+     *        service package is updated; when {@code false}, the service is untouched during the
+     *        update.
+     */
+    protected AbstractMasterSystemService(@NonNull Context context,
+            @Nullable ServiceNameResolver serviceNameResolver,
+            @Nullable String disallowProperty, boolean refreshServiceOnPackageUpdate) {
         super(context);
 
+        mRefreshServiceOnPackageUpdate = refreshServiceOnPackageUpdate;
+
         mServiceNameResolver = serviceNameResolver;
         if (mServiceNameResolver != null) {
             mServiceNameResolver
@@ -280,9 +322,6 @@
                 oldService.removeSelfFromCacheLocked();
             }
             mServiceNameResolver.setTemporaryService(userId, componentName, durationMs);
-
-            // Must update the service on cache so its initialization code is triggered
-            updateCachedServiceLocked(userId);
         }
     }
 
@@ -553,6 +592,8 @@
             final int size = mServicesCache.size();
             pw.print(prefix); pw.print("Debug: "); pw.print(realDebug);
             pw.print(" Verbose: "); pw.println(realVerbose);
+            pw.print(" Refresh on package update: "); pw.println(mRefreshServiceOnPackageUpdate);
+            pw.print(" Last active service on update: "); pw.println(mLastActivePackageName);
             if (mServiceNameResolver != null) {
                 pw.print(prefix); pw.print("Name resolver: ");
                 mServiceNameResolver.dumpShort(pw); pw.println();
@@ -590,21 +631,42 @@
     }
 
     private void startTrackingPackageChanges() {
-        PackageMonitor monitor = new PackageMonitor() {
+        final PackageMonitor monitor = new PackageMonitor() {
+
             @Override
-            public void onSomePackagesChanged() {
+            public void onPackageUpdateStarted(String packageName, int uid) {
                 synchronized (mLock) {
-                    updateCachedServiceLocked(getChangingUserId());
+                    final String activePackageName = getActiveServicePackageNameLocked();
+                    if (packageName.equals(activePackageName)) {
+                        final int userId = getChangingUserId();
+                        if (mRefreshServiceOnPackageUpdate) {
+                            if (debug) {
+                                Slog.d(mTag, "Removing service for user " + userId
+                                        + " because package " + activePackageName
+                                        + " is being updated");
+                            }
+                            mLastActivePackageName = activePackageName;
+                            removeCachedServiceLocked(userId);
+                        } else {
+                            if (debug) {
+                                Slog.d(mTag, "Holding service for user " + userId
+                                        + " while package " + activePackageName
+                                        + " is being updated");
+                            }
+                        }
+                    }
                 }
             }
 
             @Override
             public void onPackageUpdateFinished(String packageName, int uid) {
                 synchronized (mLock) {
-                    final String activePackageName = getActiveServicePackageName();
-                    if (packageName.equals(activePackageName)) {
-                        removeCachedServiceLocked(getChangingUserId());
-                    } else {
+                    String activePackageName = getActiveServicePackageNameLocked();
+                    if (activePackageName == null) {
+                        activePackageName = mLastActivePackageName;
+                        mLastActivePackageName = null;
+                    }
+                    if (!packageName.equals(activePackageName)) {
                         handlePackageUpdateLocked(packageName);
                     }
                 }
@@ -630,7 +692,7 @@
             public boolean onHandleForceStop(Intent intent, String[] packages,
                     int uid, boolean doit) {
                 synchronized (mLock) {
-                    final String activePackageName = getActiveServicePackageName();
+                    final String activePackageName = getActiveServicePackageNameLocked();
                     for (String pkg : packages) {
                         if (pkg.equals(activePackageName)) {
                             if (!doit) {
@@ -646,7 +708,9 @@
             }
 
             private void handleActiveServiceRemoved(@UserIdInt int userId) {
-                removeCachedServiceLocked(userId);
+                synchronized (mLock) {
+                    removeCachedServiceLocked(userId);
+                }
                 final String serviceSettingsProperty = getServiceSettingsProperty();
                 if (serviceSettingsProperty != null) {
                     Settings.Secure.putStringForUser(getContext().getContentResolver(),
@@ -654,7 +718,7 @@
                 }
             }
 
-            private String getActiveServicePackageName() {
+            private String getActiveServicePackageNameLocked() {
                 final int userId = getChangingUserId();
                 final S service = peekServiceForUserLocked(userId);
                 if (service == null) {
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 150303a..647e952 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -231,7 +231,8 @@
             Context.BIND_AUTO_CREATE
             | Context.BIND_TREAT_LIKE_ACTIVITY
             | Context.BIND_FOREGROUND_SERVICE
-            | Context.BIND_SHOWING_UI;
+            | Context.BIND_SHOWING_UI
+            | Context.BIND_SCHEDULE_LIKE_TOP_APP;
 
     @Retention(SOURCE)
     @IntDef({HardKeyboardBehavior.WIRELESS_AFFORDANCE, HardKeyboardBehavior.WIRED_AFFORDANCE})
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index cefe583..14b7301 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -2494,24 +2494,33 @@
             }
         }
 
-        // The expensive check last: validate that the defined package+service is
+        // The expensive check: validate that the defined package+service is
         // still present & viable.
-        final boolean componentPresent;
+        final ServiceInfo service;
         try {
-            componentPresent = (AppGlobals.getPackageManager().getServiceInfo(
+            service = AppGlobals.getPackageManager().getServiceInfo(
                     job.getServiceComponent(), PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
-                    job.getUserId()) != null);
+                    job.getUserId());
         } catch (RemoteException e) {
             throw e.rethrowAsRuntimeException();
         }
 
-        if (DEBUG) {
-            Slog.v(TAG, "isReadyToBeExecutedLocked: " + job.toShortString()
-                    + " componentPresent=" + componentPresent);
+        if (service == null) {
+            if (DEBUG) {
+                Slog.v(TAG, "isReadyToBeExecutedLocked: " + job.toShortString()
+                        + " component not present");
+            }
+            return false;
         }
 
         // Everything else checked out so far, so this is the final yes/no check
-        return componentPresent;
+        final boolean appIsBad = mActivityManagerInternal.isAppBad(service.applicationInfo);
+        if (DEBUG) {
+            if (appIsBad) {
+                Slog.i(TAG, "App is bad for " + job.toShortString() + " so not runnable");
+            }
+        }
+        return !appIsBad;
     }
 
     private void evaluateControllerStatesLocked(final JobStatus job) {
diff --git a/services/core/java/com/android/server/lights/Light.java b/services/core/java/com/android/server/lights/Light.java
index b5ec603..717e3da 100644
--- a/services/core/java/com/android/server/lights/Light.java
+++ b/services/core/java/com/android/server/lights/Light.java
@@ -16,8 +16,8 @@
 
 package com.android.server.lights;
 
-import android.hardware.light.V2_0.Flash;
 import android.hardware.light.V2_0.Brightness;
+import android.hardware.light.V2_0.Flash;
 
 public abstract class Light {
     public static final int LIGHT_FLASH_NONE = Flash.NONE;
@@ -39,8 +39,16 @@
      */
     public static final int BRIGHTNESS_MODE_LOW_PERSISTENCE = Brightness.LOW_PERSISTENCE;
 
+    /**
+     * Set the brightness of a display.
+     */
     public abstract void setBrightness(int brightness);
+
+    /**
+     * Set the brightness and mode of a display.
+     */
     public abstract void setBrightness(int brightness, int brightnessMode);
+
     public abstract void setColor(int color);
     public abstract void setFlashing(int color, int mode, int onMS, int offMS);
     public abstract void pulse();
diff --git a/services/core/java/com/android/server/lights/LightsService.java b/services/core/java/com/android/server/lights/LightsService.java
index a94ed60..ac906bb 100644
--- a/services/core/java/com/android/server/lights/LightsService.java
+++ b/services/core/java/com/android/server/lights/LightsService.java
@@ -15,15 +15,18 @@
 
 package com.android.server.lights;
 
-import com.android.server.SystemService;
-
 import android.app.ActivityManager;
 import android.content.Context;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.Message;
+import android.os.PowerManager;
 import android.os.Trace;
 import android.provider.Settings;
 import android.util.Slog;
+import android.view.SurfaceControl;
+
+import com.android.server.SystemService;
 
 public class LightsService extends SystemService {
     static final String TAG = "LightsService";
@@ -33,8 +36,25 @@
 
     private final class LightImpl extends Light {
 
-        private LightImpl(int id) {
+        private final IBinder mDisplayToken;
+        private final int mSurfaceControlMaximumBrightness;
+
+        private LightImpl(Context context, int id) {
             mId = id;
+            mDisplayToken = SurfaceControl.getInternalDisplayToken();
+            final boolean brightnessSupport = SurfaceControl.getDisplayBrightnessSupport(
+                    mDisplayToken);
+            if (DEBUG) {
+                Slog.d(TAG, "Display brightness support: " + brightnessSupport);
+            }
+            int maximumBrightness = 0;
+            if (brightnessSupport) {
+                PowerManager pm = context.getSystemService(PowerManager.class);
+                if (pm != null) {
+                    maximumBrightness = pm.getMaximumScreenBrightnessSetting();
+                }
+            }
+            mSurfaceControlMaximumBrightness = maximumBrightness;
         }
 
         @Override
@@ -51,10 +71,26 @@
                             ": brightness=0x" + Integer.toHexString(brightness));
                     return;
                 }
-
-                int color = brightness & 0x000000ff;
-                color = 0xff000000 | (color << 16) | (color << 8) | color;
-                setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);
+                // Ideally, we'd like to set the brightness mode through the SF/HWC as well, but
+                // right now we just fall back to the old path through Lights brightessMode is
+                // anything but USER or the device shouldBeInLowPersistenceMode().
+                if (brightnessMode == BRIGHTNESS_MODE_USER && !shouldBeInLowPersistenceMode()
+                        && mSurfaceControlMaximumBrightness == 255) {
+                    // TODO: the last check should be mSurfaceControlMaximumBrightness != 0; the
+                    // reason we enforce 255 right now is to stay consistent with the old path. In
+                    // the future, the framework should be refactored so that brightness is a float
+                    // between 0.0f and 1.0f, and the actual number of supported brightness levels
+                    // is determined in the device-specific implementation.
+                    if (DEBUG) {
+                        Slog.d(TAG, "Using new setBrightness path!");
+                    }
+                    SurfaceControl.setDisplayBrightness(mDisplayToken,
+                            (float) brightness / mSurfaceControlMaximumBrightness);
+                } else {
+                    int color = brightness & 0x000000ff;
+                    color = 0xff000000 | (color << 16) | (color << 8) | color;
+                    setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);
+                }
             }
         }
 
@@ -172,7 +208,7 @@
         super(context);
 
         for (int i = 0; i < LightsManager.LIGHT_ID_COUNT; i++) {
-            mLights[i] = new LightImpl(i);
+            mLights[i] = new LightImpl(context, i);
         }
     }
 
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index a53ab84..293813a 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -2699,6 +2699,14 @@
         }
     }
 
+    @Override
+    public boolean hasPendingEscrowToken(int userId) {
+        checkPasswordReadPermission(userId);
+        synchronized (mSpManager) {
+            return !mSpManager.getPendingTokensForUser(userId).isEmpty();
+        }
+    }
+
     private boolean removeEscrowToken(long handle, int userId) {
         synchronized (mSpManager) {
             if (handle == getSyntheticPasswordHandleLocked(userId)) {
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
index 98f1740..2ede384 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
@@ -29,7 +29,6 @@
 import android.os.Environment;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.os.storage.StorageManager;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.util.Slog;
@@ -49,6 +48,7 @@
 import java.io.IOException;
 import java.io.RandomAccessFile;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 
@@ -808,7 +808,7 @@
         }
 
         byte[] peekFile(String fileName) {
-            return (byte[]) peek(CacheKey.TYPE_FILE, fileName, -1 /* userId */);
+            return copyOf((byte[]) peek(CacheKey.TYPE_FILE, fileName, -1 /* userId */));
         }
 
         boolean hasFile(String fileName) {
@@ -816,11 +816,11 @@
         }
 
         void putFile(String key, byte[] value) {
-            put(CacheKey.TYPE_FILE, key, value, -1 /* userId */);
+            put(CacheKey.TYPE_FILE, key, copyOf(value), -1 /* userId */);
         }
 
         void putFileIfUnchanged(String key, byte[] value, int version) {
-            putIfUnchanged(CacheKey.TYPE_FILE, key, value, -1 /* userId */, version);
+            putIfUnchanged(CacheKey.TYPE_FILE, key, copyOf(value), -1 /* userId */, version);
         }
 
         void setFetched(int userId) {
@@ -868,6 +868,10 @@
             mVersion++;
         }
 
+        private byte[] copyOf(byte[] data) {
+            return data != null ? Arrays.copyOf(data, data.length) : null;
+        }
+
         synchronized void purgePath(String path) {
             for (int i = mCache.size() - 1; i >= 0; i--) {
                 CacheKey entry = mCache.keyAt(i);
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
index 142ad53..1ba0e8c 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
@@ -751,7 +751,7 @@
 
     /**
      * Create a token based Synthetic password for the given user.
-     * @return
+     * @return the handle of the token
      */
     public long createTokenBasedSyntheticPassword(byte[] token, int userId,
             @Nullable EscrowTokenStateChangeCallback changeCallback) {
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 152cf7f..7b691b4 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -24,17 +24,18 @@
 import android.media.AudioManagerInternal;
 import android.media.AudioSystem;
 import android.media.MediaMetadata;
+import android.media.MediaParceledListSlice;
 import android.media.Rating;
 import android.media.VolumeProvider;
 import android.media.session.ControllerCallbackLink;
-import android.media.session.ControllerLink;
+import android.media.session.ISession;
+import android.media.session.ISessionController;
 import android.media.session.MediaController;
 import android.media.session.MediaController.PlaybackInfo;
 import android.media.session.MediaSession;
 import android.media.session.MediaSession.QueueItem;
 import android.media.session.PlaybackState;
 import android.media.session.SessionCallbackLink;
-import android.media.session.SessionLink;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
@@ -44,6 +45,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.Process;
+import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.SystemClock;
 import android.util.Log;
@@ -78,9 +80,9 @@
     private final String mPackageName;
     private final String mTag;
     private final Bundle mSessionInfo;
-    private final ControllerLink mController;
+    private final ControllerStub mController;
     private final MediaSession.Token mSessionToken;
-    private final SessionLink mSession;
+    private final SessionStub mSession;
     private final SessionCb mSessionCb;
     private final MediaSessionService.ServiceImpl mService;
     private final Context mContext;
@@ -130,9 +132,9 @@
         mPackageName = ownerPackageName;
         mTag = tag;
         mSessionInfo = sessionInfo;
-        mController = new ControllerLink(new ControllerStub());
+        mController = new ControllerStub();
         mSessionToken = new MediaSession.Token(mController);
-        mSession = new SessionLink(new SessionStub());
+        mSession = new SessionStub();
         mSessionCb = new SessionCb(cb);
         mService = service;
         mContext = mService.getContext();
@@ -143,20 +145,20 @@
     }
 
     /**
-     * Get the session link for the {@link MediaSession}.
+     * Get the session binder for the {@link MediaSession}.
      *
-     * @return The session link apps talk to.
+     * @return The session binder apps talk to.
      */
-    public SessionLink getSessionBinder() {
+    public ISession getSessionBinder() {
         return mSession;
     }
 
     /**
-     * Get the controller link for the {@link MediaController}.
+     * Get the controller binder for the {@link MediaController}.
      *
-     * @return The controller link apps talk to.
+     * @return The controller binder apps talk to.
      */
-    public ControllerLink getControllerLink() {
+    public ISessionController getControllerBinder() {
         return mController;
     }
 
@@ -817,9 +819,9 @@
         }
     };
 
-    private final class SessionStub extends SessionLink.SessionStub {
+    private final class SessionStub extends ISession.Stub {
         @Override
-        public void destroySession() {
+        public void destroySession() throws RemoteException {
             final long token = Binder.clearCallingIdentity();
             try {
                 mService.destroySession(MediaSessionRecord.this);
@@ -829,18 +831,18 @@
         }
 
         @Override
-        public void sendEvent(String event, Bundle data) {
+        public void sendEvent(String event, Bundle data) throws RemoteException {
             mHandler.post(MessageHandler.MSG_SEND_EVENT, event,
                     data == null ? null : new Bundle(data));
         }
 
         @Override
-        public ControllerLink getController() {
+        public ISessionController getController() throws RemoteException {
             return mController;
         }
 
         @Override
-        public void setActive(boolean active) {
+        public void setActive(boolean active) throws RemoteException {
             mIsActive = active;
             final long token = Binder.clearCallingIdentity();
             try {
@@ -852,7 +854,7 @@
         }
 
         @Override
-        public void setFlags(int flags) {
+        public void setFlags(int flags) throws RemoteException {
             if ((flags & MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY) != 0) {
                 int pid = Binder.getCallingPid();
                 int uid = Binder.getCallingUid();
@@ -871,7 +873,7 @@
         }
 
         @Override
-        public void setMediaButtonReceiver(PendingIntent pi) {
+        public void setMediaButtonReceiver(PendingIntent pi) throws RemoteException {
             mMediaButtonReceiver = pi;
             final long token = Binder.clearCallingIdentity();
             try {
@@ -882,12 +884,13 @@
         }
 
         @Override
-        public void setLaunchPendingIntent(PendingIntent pi) {
+        public void setLaunchPendingIntent(PendingIntent pi) throws RemoteException {
             mLaunchIntent = pi;
         }
 
         @Override
-        public void setMetadata(MediaMetadata metadata, long duration, String metadataDescription) {
+        public void setMetadata(MediaMetadata metadata, long duration, String metadataDescription)
+                throws RemoteException {
             synchronized (mLock) {
                 MediaMetadata temp = metadata == null ? null : new MediaMetadata.Builder(metadata)
                         .build();
@@ -905,7 +908,7 @@
         }
 
         @Override
-        public void setPlaybackState(PlaybackState state) {
+        public void setPlaybackState(PlaybackState state) throws RemoteException {
             int oldState = mPlaybackState == null
                     ? PlaybackState.STATE_NONE : mPlaybackState.getState();
             int newState = state == null
@@ -923,21 +926,21 @@
         }
 
         @Override
-        public void setQueue(List<QueueItem> queue) {
+        public void setQueue(MediaParceledListSlice queue) throws RemoteException {
             synchronized (mLock) {
-                mQueue = queue;
+                mQueue = queue == null ? null : (List<QueueItem>) queue.getList();
             }
             mHandler.post(MessageHandler.MSG_UPDATE_QUEUE);
         }
 
         @Override
-        public void setQueueTitle(CharSequence title) {
+        public void setQueueTitle(CharSequence title) throws RemoteException {
             mQueueTitle = title;
             mHandler.post(MessageHandler.MSG_UPDATE_QUEUE_TITLE);
         }
 
         @Override
-        public void setExtras(Bundle extras) {
+        public void setExtras(Bundle extras) throws RemoteException {
             synchronized (mLock) {
                 mExtras = extras == null ? null : new Bundle(extras);
             }
@@ -945,18 +948,18 @@
         }
 
         @Override
-        public void setRatingType(int type) {
+        public void setRatingType(int type) throws RemoteException {
             mRatingType = type;
         }
 
         @Override
-        public void setCurrentVolume(int volume) {
+        public void setCurrentVolume(int volume) throws RemoteException {
             mCurrentVolume = volume;
             mHandler.post(MessageHandler.MSG_UPDATE_VOLUME);
         }
 
         @Override
-        public void setPlaybackToLocal(AudioAttributes attributes) {
+        public void setPlaybackToLocal(AudioAttributes attributes) throws RemoteException {
             boolean typeChanged;
             synchronized (mLock) {
                 typeChanged = mVolumeType == PlaybackInfo.PLAYBACK_TYPE_REMOTE;
@@ -979,7 +982,7 @@
         }
 
         @Override
-        public void setPlaybackToRemote(int control, int max) {
+        public void setPlaybackToRemote(int control, int max) throws RemoteException {
             boolean typeChanged;
             synchronized (mLock) {
                 typeChanged = mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL;
@@ -1248,7 +1251,7 @@
         }
     }
 
-    class ControllerStub extends ControllerLink.ControllerStub {
+    class ControllerStub extends ISessionController.Stub {
         @Override
         public void sendCommand(String packageName, ControllerCallbackLink caller,
                 String command, Bundle args, ResultReceiver cb) {
@@ -1488,9 +1491,9 @@
         }
 
         @Override
-        public List<QueueItem> getQueue() {
+        public MediaParceledListSlice getQueue() {
             synchronized (mLock) {
-                return mQueue;
+                return mQueue == null ? null : new MediaParceledListSlice<>(mQueue);
             }
         }
 
diff --git a/services/core/java/com/android/server/media/MediaSessionServiceImpl.java b/services/core/java/com/android/server/media/MediaSessionServiceImpl.java
index b86328b..7c8dc74 100644
--- a/services/core/java/com/android/server/media/MediaSessionServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaSessionServiceImpl.java
@@ -49,12 +49,12 @@
 import android.media.session.ICallback;
 import android.media.session.IOnMediaKeyListener;
 import android.media.session.IOnVolumeKeyLongPressListener;
+import android.media.session.ISession;
 import android.media.session.ISession2TokensListener;
 import android.media.session.ISessionManager;
 import android.media.session.MediaSession;
 import android.media.session.MediaSessionManager;
 import android.media.session.SessionCallbackLink;
-import android.media.session.SessionLink;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
@@ -64,6 +64,7 @@
 import android.os.Message;
 import android.os.PowerManager;
 import android.os.Process;
+import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
@@ -138,9 +139,9 @@
     private MediaSessionRecord mGlobalPrioritySession;
     private AudioPlayerStateMonitor mAudioPlayerStateMonitor;
 
-    // Used to notify system UI when remote volume was changed. TODO find a
-    // better way to handle this.
-    private IRemoteVolumeController mRvc;
+    // Used to notify System UI and Settings when remote volume was changed.
+    final RemoteCallbackList<IRemoteVolumeController> mRemoteVolumeControllers =
+            new RemoteCallbackList<>();
 
     public MediaSessionServiceImpl(Context context) {
         mContext = context;
@@ -281,20 +282,23 @@
     }
 
     /**
-     * Tells the system UI that volume has changed on an active remote session.
+     * Tells the System UI and Settings app that volume has changed on an active remote session.
      */
     public void notifyRemoteVolumeChanged(int flags, MediaSessionRecord session) {
-        synchronized (mLock) {
-            if (mRvc == null || !session.isActive()) {
-                return;
-            }
+        if (!session.isActive()) {
+            return;
+        }
+        int size = mRemoteVolumeControllers.beginBroadcast();
+        MediaSession.Token token = session.getSessionToken();
+        for (int i = size - 1; i >= 0; i--) {
             try {
-                mRvc.remoteVolumeChanged(session.getSessionToken(), flags);
+                IRemoteVolumeController cb = mRemoteVolumeControllers.getBroadcastItem(i);
+                cb.remoteVolumeChanged(token, flags);
             } catch (Exception e) {
-                Log.w(TAG, "Error sending volume change to system UI.", e);
-                mRvc = null;
+                Log.w(TAG, "Error sending volume change.", e);
             }
         }
+        mRemoteVolumeControllers.finishBroadcast();
     }
 
     @Override
@@ -497,7 +501,7 @@
      */
     private void enforceMediaPermissions(ComponentName compName, int pid, int uid,
             int resolvedUserId) {
-        if (isCurrentVolumeController(pid, uid)) return;
+        if (hasStatusBarServicePermission(pid, uid)) return;
         if (mContext
                 .checkPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL, pid, uid)
                 != PackageManager.PERMISSION_GRANTED
@@ -507,14 +511,14 @@
         }
     }
 
-    private boolean isCurrentVolumeController(int pid, int uid) {
+    private boolean hasStatusBarServicePermission(int pid, int uid) {
         return mContext.checkPermission(android.Manifest.permission.STATUS_BAR_SERVICE,
                 pid, uid) == PackageManager.PERMISSION_GRANTED;
     }
 
-    private void enforceSystemUiPermission(String action, int pid, int uid) {
-        if (!isCurrentVolumeController(pid, uid)) {
-            throw new SecurityException("Only system ui may " + action);
+    private void enforceStatusBarServicePermission(String action, int pid, int uid) {
+        if (!hasStatusBarServicePermission(pid, uid)) {
+            throw new SecurityException("Only System UI and Settings may " + action);
         }
     }
 
@@ -638,20 +642,25 @@
     }
 
     private void pushRemoteVolumeUpdateLocked(int userId) {
-        if (mRvc != null) {
+        FullUserRecord user = getFullUserRecordLocked(userId);
+        if (user == null) {
+            Log.w(TAG, "pushRemoteVolumeUpdateLocked failed. No user with id=" + userId);
+            return;
+        }
+
+        int size = mRemoteVolumeControllers.beginBroadcast();
+        MediaSessionRecord record = user.mPriorityStack.getDefaultRemoteSession(userId);
+        MediaSession.Token token = record == null ? null : record.getSessionToken();
+
+        for (int i = size - 1; i >= 0; i--) {
             try {
-                FullUserRecord user = getFullUserRecordLocked(userId);
-                if (user == null) {
-                    Log.w(TAG, "pushRemoteVolumeUpdateLocked failed. No user with id=" + userId);
-                    return;
-                }
-                MediaSessionRecord record = user.mPriorityStack.getDefaultRemoteSession(userId);
-                mRvc.updateRemoteController(record == null ? null : record.getSessionToken());
-            } catch (RemoteException e) {
-                Log.w(TAG, "Error sending default remote volume to sys ui.", e);
-                mRvc = null;
+                IRemoteVolumeController cb = mRemoteVolumeControllers.getBroadcastItem(i);
+                cb.updateRemoteController(token);
+            } catch (Exception e) {
+                Log.w(TAG, "Error sending default remote volume.", e);
             }
         }
+        mRemoteVolumeControllers.finishBroadcast();
     }
 
     void pushSession2TokensChangedLocked(int userId) {
@@ -992,7 +1001,7 @@
         private boolean mVoiceButtonHandled = false;
 
         @Override
-        public SessionLink createSession(String packageName, SessionCallbackLink cb, String tag,
+        public ISession createSession(String packageName, SessionCallbackLink cb, String tag,
                 Bundle sessionInfo, int userId) throws RemoteException {
             final int pid = Binder.getCallingPid();
             final int uid = Binder.getCallingUid();
@@ -1661,15 +1670,26 @@
         }
 
         @Override
-        public void setRemoteVolumeController(IRemoteVolumeController rvc) {
+        public void registerRemoteVolumeController(IRemoteVolumeController rvc) {
             final int pid = Binder.getCallingPid();
             final int uid = Binder.getCallingUid();
             final long token = Binder.clearCallingIdentity();
             try {
-                enforceSystemUiPermission("listen for volume changes", pid, uid);
-                synchronized (mLock) {
-                    mRvc = rvc;
-                }
+                enforceStatusBarServicePermission("listen for volume changes", pid, uid);
+                mRemoteVolumeControllers.register(rvc);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public void unregisterRemoteVolumeController(IRemoteVolumeController rvc) {
+            final int pid = Binder.getCallingPid();
+            final int uid = Binder.getCallingUid();
+            final long token = Binder.clearCallingIdentity();
+            try {
+                enforceStatusBarServicePermission("listen for volume changes", pid, uid);
+                mRemoteVolumeControllers.unregister(rvc);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -1755,8 +1775,8 @@
 
         private boolean hasMediaControlPermission(int resolvedUserId, String packageName,
                 int pid, int uid) throws RemoteException {
-            // Allow API calls from the System UI
-            if (isCurrentVolumeController(pid, uid)) {
+            // Allow API calls from the System UI and Settings
+            if (hasStatusBarServicePermission(pid, uid)) {
                 return true;
             }
 
diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java
index 9ba50ee..a5e7d8e 100644
--- a/services/core/java/com/android/server/media/MediaSessionStack.java
+++ b/services/core/java/com/android/server/media/MediaSessionStack.java
@@ -144,7 +144,7 @@
      */
     public MediaSessionRecord getMediaSessionRecord(MediaSession.Token sessionToken) {
         for (MediaSessionRecord record : mSessions) {
-            if (Objects.equals(record.getControllerLink(), sessionToken.getControllerLink())) {
+            if (Objects.equals(record.getControllerBinder(), sessionToken.getBinder())) {
                 return record;
             }
         }
diff --git a/services/core/java/com/android/server/media/OWNERS b/services/core/java/com/android/server/media/OWNERS
index 8adea0e..4bc9373 100644
--- a/services/core/java/com/android/server/media/OWNERS
+++ b/services/core/java/com/android/server/media/OWNERS
@@ -1,4 +1,6 @@
-lajos@google.com
 elaurent@google.com
-sungsoo@google.com
+hdmoon@google.com
+insun@google.com
 jaewan@google.com
+lajos@google.com
+sungsoo@google.com
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 88e697c..4a215cf 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2504,15 +2504,20 @@
         }
 
         @Override
-        public boolean canNotifyAsPackage(String callingPkg, String targetPkg) {
+        public boolean canNotifyAsPackage(String callingPkg, String targetPkg, int userId) {
             checkCallerIsSameApp(callingPkg);
             final int callingUid = Binder.getCallingUid();
             UserHandle user = UserHandle.getUserHandleForUid(callingUid);
+            if (user.getIdentifier() != userId) {
+                getContext().enforceCallingPermission(
+                        android.Manifest.permission.INTERACT_ACROSS_USERS,
+                        "canNotifyAsPackage for user " + userId);
+            }
             try {
                 ApplicationInfo info =
                         mPackageManager.getApplicationInfo(targetPkg,
                                 MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
-                                user.getIdentifier());
+                                userId);
                 if (info != null) {
                     return mPreferencesHelper.isDelegateAllowed(
                             targetPkg, info.uid, callingPkg, callingUid);
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 46ce4bf..d9ab132 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -149,7 +149,10 @@
     private int mImportance = IMPORTANCE_UNSPECIFIED;
     // Field used in global sort key to bypass normal notifications
     private int mCriticality = CriticalNotificationExtractor.NORMAL;
-    private CharSequence mImportanceExplanation = null;
+    // A MetricsEvent.NotificationImportanceExplanation, tracking source of mImportance.
+    private int mImportanceExplanationCode = MetricsEvent.IMPORTANCE_EXPLANATION_UNKNOWN;
+    // A MetricsEvent.NotificationImportanceExplanation for initial importance.
+    private int mInitialImportanceExplanationCode = MetricsEvent.IMPORTANCE_EXPLANATION_UNKNOWN;
 
     private int mSuppressedVisualEffects = 0;
     private String mUserExplanation;
@@ -332,14 +335,18 @@
 
     private int calculateInitialImportance() {
         final Notification n = sbn.getNotification();
-        int importance = getChannel().getImportance();
-        int requestedImportance = IMPORTANCE_DEFAULT;
+        int importance = getChannel().getImportance();  // Post-channels notifications use this
+        mInitialImportanceExplanationCode = getChannel().hasUserSetImportance()
+                ? MetricsEvent.IMPORTANCE_EXPLANATION_USER
+                : MetricsEvent.IMPORTANCE_EXPLANATION_APP;
 
-        // Migrate notification flags to scores
+        // Migrate notification priority flag to a priority value.
         if (0 != (n.flags & Notification.FLAG_HIGH_PRIORITY)) {
             n.priority = Notification.PRIORITY_MAX;
         }
 
+        // Convert priority value to an importance value, used only for pre-channels notifications.
+        int requestedImportance = IMPORTANCE_DEFAULT;
         n.priority = NotificationManagerService.clamp(n.priority, Notification.PRIORITY_MIN,
                 Notification.PRIORITY_MAX);
         switch (n.priority) {
@@ -360,10 +367,11 @@
         stats.requestedImportance = requestedImportance;
         stats.isNoisy = mSound != null || mVibration != null;
 
+        // For pre-channels notifications, apply system overrides and then use requestedImportance
+        // as importance.
         if (mPreChannelsNotification
                 && (importance == IMPORTANCE_UNSPECIFIED
-                || (getChannel().getUserLockedFields()
-                & USER_LOCKED_IMPORTANCE) == 0)) {
+                || (!getChannel().hasUserSetImportance()))) {
             if (!stats.isNoisy && requestedImportance > IMPORTANCE_LOW) {
                 requestedImportance = IMPORTANCE_LOW;
             }
@@ -378,6 +386,8 @@
                 requestedImportance = IMPORTANCE_HIGH;
             }
             importance = requestedImportance;
+            mInitialImportanceExplanationCode =
+                    MetricsEvent.IMPORTANCE_EXPLANATION_APP_PRE_CHANNELS;
         }
 
         stats.naturalImportance = importance;
@@ -540,7 +550,7 @@
                 + NotificationListenerService.Ranking.importanceToString(mAssistantImportance));
         pw.println(prefix + "mImportance="
                 + NotificationListenerService.Ranking.importanceToString(mImportance));
-        pw.println(prefix + "mImportanceExplanation=" + mImportanceExplanation);
+        pw.println(prefix + "mImportanceExplanation=" + getImportanceExplanation());
         pw.println(prefix + "mIsAppImportanceLocked=" + mIsAppImportanceLocked);
         pw.println(prefix + "mIntercept=" + mIntercept);
         pw.println(prefix + "mHidden==" + mHidden);
@@ -760,23 +770,23 @@
     }
 
     /**
-     * Recalculates the importance of the record after fields affecting importance have changed
+     * Recalculates the importance of the record after fields affecting importance have changed,
+     * and records an explanation.
      */
     protected void calculateImportance() {
         mImportance = calculateInitialImportance();
-        mImportanceExplanation = "app";
-        if (getChannel().hasUserSetImportance()) {
-            mImportanceExplanation = "user";
-        }
+        mImportanceExplanationCode = mInitialImportanceExplanationCode;
+
+        // Consider Notification Assistant and system overrides to importance. If both, system wins.
         if (!getChannel().hasUserSetImportance()
                 && mAssistantImportance != IMPORTANCE_UNSPECIFIED
                 && !getChannel().isImportanceLockedByOEM()) {
             mImportance = mAssistantImportance;
-            mImportanceExplanation = "asst";
+            mImportanceExplanationCode = MetricsEvent.IMPORTANCE_EXPLANATION_ASST;
         }
         if (mSystemImportance != IMPORTANCE_UNSPECIFIED) {
             mImportance = mSystemImportance;
-            mImportanceExplanation = "system";
+            mImportanceExplanationCode = MetricsEvent.IMPORTANCE_EXPLANATION_SYSTEM;
         }
     }
 
@@ -785,7 +795,20 @@
     }
 
     public CharSequence getImportanceExplanation() {
-        return mImportanceExplanation;
+        switch (mImportanceExplanationCode) {
+            case MetricsEvent.IMPORTANCE_EXPLANATION_UNKNOWN:
+                return null;
+            case MetricsEvent.IMPORTANCE_EXPLANATION_APP:
+            case MetricsEvent.IMPORTANCE_EXPLANATION_APP_PRE_CHANNELS:
+                return "app";
+            case MetricsEvent.IMPORTANCE_EXPLANATION_USER:
+                return "user";
+            case MetricsEvent.IMPORTANCE_EXPLANATION_ASST:
+                return "asst";
+            case MetricsEvent.IMPORTANCE_EXPLANATION_SYSTEM:
+                return "system";
+        }
+        return null;
     }
 
     public boolean setIntercepted(boolean intercept) {
@@ -1242,14 +1265,37 @@
     }
 
     public LogMaker getLogMaker(long now) {
-        return sbn.getLogMaker()
-                .clearTaggedData(MetricsEvent.NOTIFICATION_SHADE_INDEX)
+        LogMaker lm = sbn.getLogMaker()
                 .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_IMPORTANCE, mImportance)
                 .addTaggedData(MetricsEvent.NOTIFICATION_SINCE_CREATE_MILLIS, getLifespanMs(now))
                 .addTaggedData(MetricsEvent.NOTIFICATION_SINCE_UPDATE_MILLIS, getFreshnessMs(now))
                 .addTaggedData(MetricsEvent.NOTIFICATION_SINCE_VISIBLE_MILLIS, getExposureMs(now))
                 .addTaggedData(MetricsEvent.NOTIFICATION_SINCE_INTERRUPTION_MILLIS,
                         getInterruptionMs(now));
+        // Record results of the calculateImportance() calculation if available.
+        if (mImportanceExplanationCode != MetricsEvent.IMPORTANCE_EXPLANATION_UNKNOWN) {
+            lm.addTaggedData(MetricsEvent.FIELD_NOTIFICATION_IMPORTANCE_EXPLANATION,
+                    mImportanceExplanationCode);
+            // To avoid redundancy, we log the initial importance information only if it was
+            // overridden.
+            if (((mImportanceExplanationCode == MetricsEvent.IMPORTANCE_EXPLANATION_ASST)
+                    || (mImportanceExplanationCode == MetricsEvent.IMPORTANCE_EXPLANATION_SYSTEM))
+                    && (stats.naturalImportance != IMPORTANCE_UNSPECIFIED)) {
+                // stats.naturalImportance is due to one of the 3 sources of initial importance.
+                lm.addTaggedData(MetricsEvent.FIELD_NOTIFICATION_IMPORTANCE_INITIAL_EXPLANATION,
+                        mInitialImportanceExplanationCode);
+                lm.addTaggedData(MetricsEvent.FIELD_NOTIFICATION_IMPORTANCE_INITIAL,
+                        stats.naturalImportance);
+            }
+            // Log Assistant override if it was itself overridden by System. Since System can't be
+            // overridden, it never needs logging.
+            if (mImportanceExplanationCode == MetricsEvent.IMPORTANCE_EXPLANATION_SYSTEM
+                    && mAssistantImportance != IMPORTANCE_UNSPECIFIED) {
+                lm.addTaggedData(MetricsEvent.FIELD_NOTIFICATION_IMPORTANCE_ASST,
+                        mAssistantImportance);
+            }
+        }
+        return lm;
     }
 
     public LogMaker getLogMaker() {
diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java
index 9e0cb0f..fd68a8b 100644
--- a/services/core/java/com/android/server/om/IdmapManager.java
+++ b/services/core/java/com/android/server/om/IdmapManager.java
@@ -82,7 +82,7 @@
         final String overlayPath = overlayPackage.applicationInfo.getBaseCodePath();
         try {
             if (FEATURE_FLAG_IDMAP2) {
-                int policies = determineFulfilledPolicies(targetPackage, overlayPackage, userId);
+                int policies = calculateFulfilledPolicies(targetPackage, overlayPackage, userId);
                 boolean enforce = enforceOverlayable(overlayPackage);
                 if (mIdmap2Service.verifyIdmap(overlayPath, policies, enforce, userId)) {
                     return true;
@@ -184,28 +184,25 @@
             return true;
         }
 
-        if (ai.isVendor() && !VENDOR_IS_Q_OR_LATER) {
+        if (ai.isVendor()) {
             // If the overlay is on a pre-Q vendor partition, do not enforce overlayable
             // restrictions on this overlay because the pre-Q platform has no understanding of
             // overlayable.
-            return false;
+            return VENDOR_IS_Q_OR_LATER;
         }
 
-        // Do not enforce overlayable restrictions on pre-Q overlays signed with the
-        // platform signature.
-        return !ai.isSignedWithPlatformKey();
+        // Do not enforce overlayable restrictions on pre-Q overlays that are signed with the
+        // platform signature or that are preinstalled.
+        return !(ai.isSystemApp() || ai.isSignedWithPlatformKey());
     }
 
     /**
-     * Retrieves a bitmask for idmap2 that represents the policies the specified overlay fulfills.
-     * @throws SecurityException if the overlay is not allowed to overlay any resource
+     * Retrieves a bitmask for idmap2 that represents the policies the overlay fulfills.
      */
-    private int determineFulfilledPolicies(@NonNull final PackageInfo targetPackage,
-            @NonNull final PackageInfo overlayPackage, int userId) throws SecurityException {
+    private int calculateFulfilledPolicies(@NonNull final PackageInfo targetPackage,
+            @NonNull final PackageInfo overlayPackage, int userId)  {
         final ApplicationInfo ai = overlayPackage.applicationInfo;
-        final boolean overlayIsQOrLater = ai.targetSdkVersion >= VERSION_CODES.Q;
-
-        int fulfilledPolicies = 0;
+        int fulfilledPolicies = IIdmap2.POLICY_PUBLIC;
 
         // Overlay matches target signature
         if (mPackageManager.signaturesMatching(targetPackage.packageName,
@@ -215,32 +212,25 @@
 
         // Vendor partition (/vendor)
         if (ai.isVendor()) {
-            if (overlayIsQOrLater) {
-                fulfilledPolicies |= IIdmap2.POLICY_VENDOR_PARTITION;
-            } else if (VENDOR_IS_Q_OR_LATER) {
-                throw new SecurityException("Overlay must target Q sdk or higher");
-            }
+            return fulfilledPolicies | IIdmap2.POLICY_VENDOR_PARTITION;
         }
 
         // Product partition (/product)
         if (ai.isProduct()) {
-            if (overlayIsQOrLater) {
-                fulfilledPolicies |= IIdmap2.POLICY_PRODUCT_PARTITION;
-            } else {
-                throw new SecurityException("Overlay must target Q sdk or higher");
-            }
+            return fulfilledPolicies | IIdmap2.POLICY_PRODUCT_PARTITION;
         }
 
-        // System partition (/system)
+        // Check partitions for which there exists no policy so overlays on these partitions will
+        // not fulfill the system policy.
+        if (ai.isOem() || ai.isProductServices()) {
+            return fulfilledPolicies;
+        }
+
+        // Check this last since every partition except for data is scanned as system in the PMS.
         if (ai.isSystemApp()) {
-            if (overlayIsQOrLater) {
-                fulfilledPolicies |= IIdmap2.POLICY_SYSTEM_PARTITION;
-            } else {
-                throw new SecurityException("Overlay must target Q sdk or higher");
-            }
+            return fulfilledPolicies | IIdmap2.POLICY_SYSTEM_PARTITION;
         }
 
-        // All overlays can overlay resources with the public policy
-        return fulfilledPolicies | IIdmap2.POLICY_PUBLIC;
+        return fulfilledPolicies;
     }
 }
diff --git a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
index 64f31cd..5c0874d 100644
--- a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
+++ b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
@@ -40,10 +40,6 @@
 
 import java.io.FileDescriptor;
 
-// TODO(b/111441001):
-// Intercept onFinished() & implement death recipient here and shutdown
-// bugreportd service.
-
 /**
  * Implementation of the service that provides a privileged API to capture and consume bugreports.
  *
@@ -171,9 +167,12 @@
             reportError(listener, IDumpstateListener.BUGREPORT_ERROR_RUNTIME_ERROR);
             return;
         }
+
+        // Wrap the listener so we can intercept binder events directly.
+        IDumpstateListener myListener = new DumpstateListener(listener, ds);
         try {
             ds.startBugreport(callingUid, callingPackage,
-                    bugreportFd, screenshotFd, bugreportMode, listener);
+                    bugreportFd, screenshotFd, bugreportMode, myListener);
         } catch (RemoteException e) {
             reportError(listener, IDumpstateListener.BUGREPORT_ERROR_RUNTIME_ERROR);
         }
@@ -240,4 +239,73 @@
         Slog.w(TAG, message);
         throw new IllegalArgumentException(message);
     }
+
+
+    private final class DumpstateListener extends IDumpstateListener.Stub
+            implements DeathRecipient {
+        private final IDumpstateListener mListener;
+        private final IDumpstate mDs;
+        private boolean mDone = false;
+
+        DumpstateListener(IDumpstateListener listener, IDumpstate ds) {
+            mListener = listener;
+            mDs = ds;
+            try {
+                mDs.asBinder().linkToDeath(this, 0);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Unable to register Death Recipient for IDumpstate", e);
+            }
+        }
+
+        @Override
+        public void onProgress(int progress) throws RemoteException {
+            mListener.onProgress(progress);
+        }
+
+        @Override
+        public void onError(int errorCode) throws RemoteException {
+            synchronized (mLock) {
+                mDone = true;
+            }
+            mListener.onError(errorCode);
+        }
+
+        @Override
+        public void onFinished() throws RemoteException {
+            synchronized (mLock) {
+                mDone = true;
+            }
+            mListener.onFinished();
+        }
+
+        @Override
+        public void binderDied() {
+            synchronized (mLock) {
+                if (!mDone) {
+                    // If we have not gotten a "done" callback this must be a crash.
+                    Slog.e(TAG, "IDumpstate likely crashed. Notifying listener");
+                    try {
+                        mListener.onError(IDumpstateListener.BUGREPORT_ERROR_RUNTIME_ERROR);
+                    } catch (RemoteException ignored) {
+                        // If listener is not around, there isn't anything to do here.
+                    }
+                }
+            }
+            mDs.asBinder().unlinkToDeath(this, 0);
+        }
+
+        // Old methods; unused in the API flow.
+        @Override
+        public void onProgressUpdated(int progress) throws RemoteException {
+        }
+
+        @Override
+        public void onMaxProgressUpdated(int maxProgress) throws RemoteException {
+        }
+
+        @Override
+        public void onSectionComplete(String title, int status, int size, int durationMs)
+                throws RemoteException {
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index a4c04b2..5fdd872 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -41,6 +41,7 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.function.Function;
@@ -135,6 +136,17 @@
     }
 
     /**
+     * Checks if {@code packageName} is an apex package.
+     *
+     * @param packageName package to check.
+     * @return {@code true} if {@code packageName} is an apex package.
+     */
+    boolean isApexPackage(String packageName) {
+        populateActivePackagesCacheIfNeeded();
+        return mActivePackagesCache.containsKey(packageName);
+    }
+
+    /**
      * Retrieves information about an apexd staged session i.e. the internal state used by apexd to
      * track the different states of a session.
      *
@@ -246,6 +258,23 @@
     }
 
     /**
+     * Uninstalls given {@code apexPackage}.
+     *
+     * <p>NOTE. Device must be rebooted in order for uninstall to take effect.
+     *
+     * @param apexPackagePath package to uninstall.
+     * @return {@code true} upon successful uninstall, {@code false} otherwise.
+     */
+    boolean uninstallApex(String apexPackagePath) {
+        try {
+            mApexService.unstagePackages(Collections.singletonList(apexPackagePath));
+            return true;
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    /**
      * Dumps various state information to the provided {@link PrintWriter} object.
      *
      * @param pw the {@link PrintWriter} object to send information to.
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 05af13a..18cfa4a 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -45,8 +45,6 @@
 import android.content.pm.ShortcutInfo;
 import android.content.pm.ShortcutServiceInternal;
 import android.content.pm.ShortcutServiceInternal.ShortcutChangeListener;
-import android.content.pm.Signature;
-import android.content.pm.SigningInfo;
 import android.content.pm.UserInfo;
 import android.graphics.Rect;
 import android.net.Uri;
@@ -62,31 +60,21 @@
 import android.os.UserManager;
 import android.os.UserManagerInternal;
 import android.provider.Settings;
-import android.util.ByteStringUtils;
 import android.util.Log;
 import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.os.BackgroundThread;
-import com.android.internal.util.DumpUtils;
 import com.android.internal.util.Preconditions;
-import com.android.internal.util.StatLogger;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.wm.ActivityTaskManagerInternal;
 
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * Service that manages requests and callbacks for launchers that support
@@ -125,16 +113,6 @@
         private static final boolean DEBUG = false;
         private static final String TAG = "LauncherAppsService";
 
-        // Stats
-        @VisibleForTesting
-        interface Stats {
-            int INIT_VOUCHED_SIGNATURES = 0;
-            int COUNT = INIT_VOUCHED_SIGNATURES + 1;
-        }
-        private final StatLogger mStatLogger = new StatLogger(new String[] {
-                "initVouchedSignatures"
-        });
-
         private final Context mContext;
         private final UserManager mUm;
         private final UserManagerInternal mUserManagerInternal;
@@ -145,16 +123,11 @@
         private final PackageCallbackList<IOnAppsChangedListener> mListeners
                 = new PackageCallbackList<IOnAppsChangedListener>();
         private final DevicePolicyManager mDpm;
-        private final ConcurrentHashMap<UserHandle, Set<String>> mVouchedSignaturesByUser;
-        private final Set<String> mVouchProviders;
 
         private final MyPackageMonitor mPackageMonitor = new MyPackageMonitor();
-        private final VouchesChangedMonitor mVouchesChangedMonitor = new VouchesChangedMonitor();
 
         private final Handler mCallbackHandler;
 
-        private final Object mVouchedSignaturesLocked = new Object();
-
         private PackageInstallerService mPackageInstallerService;
 
         public LauncherAppsImpl(Context context) {
@@ -173,9 +146,6 @@
             mShortcutServiceInternal.addListener(mPackageMonitor);
             mCallbackHandler = BackgroundThread.getHandler();
             mDpm = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
-            mVouchedSignaturesByUser = new ConcurrentHashMap<>();
-            mVouchProviders = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>());
-            mVouchesChangedMonitor.register(mContext, UserHandle.ALL, true, mCallbackHandler);
         }
 
         @VisibleForTesting
@@ -432,7 +402,7 @@
                     }
                     ApplicationInfo appInfo = pmInt.getApplicationInfo(packageName, /*flags*/ 0,
                             callingUid, user.getIdentifier());
-                    if (shouldShowHiddenApp(user, appInfo)) {
+                    if (shouldShowSyntheticActivity(user, appInfo)) {
                         ResolveInfo info = getHiddenAppActivityInfo(packageName, callingUid, user);
                         if (info != null) {
                             result.add(info);
@@ -448,7 +418,7 @@
                         user.getIdentifier(), callingUid);
                 for (ApplicationInfo applicationInfo : installedPackages) {
                     if (!visiblePackages.contains(applicationInfo.packageName)) {
-                        if (!shouldShowHiddenApp(user, applicationInfo)) {
+                        if (!shouldShowSyntheticActivity(user, applicationInfo)) {
                             continue;
                         }
                         ResolveInfo info = getHiddenAppActivityInfo(applicationInfo.packageName,
@@ -464,36 +434,13 @@
             }
         }
 
-        private boolean shouldShowHiddenApp(UserHandle user, ApplicationInfo appInfo) {
+        private boolean shouldShowSyntheticActivity(UserHandle user, ApplicationInfo appInfo) {
             if (appInfo == null || appInfo.isSystemApp() || appInfo.isUpdatedSystemApp()) {
                 return false;
             }
-            if (!mVouchedSignaturesByUser.containsKey(user)) {
-                initVouchedSignatures(user);
-            }
             if (isManagedProfileAdmin(user, appInfo.packageName)) {
                 return false;
             }
-            if (mVouchProviders.contains(appInfo.packageName)) {
-                // If it's a vouching packages then we must show hidden app
-                return true;
-            }
-            // If app's signature is in vouch list, do not show hidden app
-            final Set<String> vouches = mVouchedSignaturesByUser.get(user);
-            try {
-                final PackageInfo pkgInfo = mContext.getPackageManager().getPackageInfo(
-                        appInfo.packageName, PackageManager.GET_SIGNING_CERTIFICATES);
-                final Signature[] signatures = getLatestSignatures(pkgInfo.signingInfo);
-                // If any of the signatures appears in vouches, then we don't show hidden app
-                for (Signature signature : signatures) {
-                    final String certDigest = computePackageCertDigest(signature);
-                    if (vouches.contains(certDigest)) {
-                        return false;
-                    }
-                }
-            } catch (PackageManager.NameNotFoundException e) {
-                // Should not happen
-            }
             return true;
         }
 
@@ -515,100 +462,6 @@
             return false;
         }
 
-        @VisibleForTesting
-        static String computePackageCertDigest(Signature signature) {
-            MessageDigest messageDigest;
-            try {
-                messageDigest = MessageDigest.getInstance("SHA1");
-            } catch (NoSuchAlgorithmException e) {
-                // Should not happen
-                return null;
-            }
-            messageDigest.update(signature.toByteArray());
-            final byte[] digest = messageDigest.digest();
-            return ByteStringUtils.toHexString(digest);
-        }
-
-        @VisibleForTesting
-        static Signature[] getLatestSignatures(SigningInfo signingInfo) {
-            if (signingInfo.hasMultipleSigners()) {
-                return signingInfo.getApkContentsSigners();
-            } else {
-                final Signature[] signatures = signingInfo.getSigningCertificateHistory();
-                return new Signature[]{signatures[0]};
-            }
-        }
-
-        private void updateVouches(String packageName, UserHandle user) {
-            final PackageManagerInternal pmInt =
-                    LocalServices.getService(PackageManagerInternal.class);
-            ApplicationInfo appInfo = pmInt.getApplicationInfo(packageName,
-                    PackageManager.GET_META_DATA, Binder.getCallingUid(), user.getIdentifier());
-            if (appInfo == null) {
-                Log.w(TAG, "appInfo " + packageName + " is null");
-                return;
-            }
-            updateVouches(appInfo, user);
-        }
-
-        private void updateVouches(ApplicationInfo appInfo, UserHandle user) {
-            if (appInfo == null || appInfo.metaData == null) {
-                // No meta-data
-                return;
-            }
-            int tokenResourceId = appInfo.metaData.getInt(LauncherApps.VOUCHED_CERTS_KEY);
-            if (tokenResourceId == 0) {
-                // No xml file
-                return;
-            }
-            mVouchProviders.add(appInfo.packageName);
-            Set<String> vouches = mVouchedSignaturesByUser.get(user);
-            try {
-                List<String> signatures = Arrays.asList(
-                        mContext.getPackageManager().getResourcesForApplication(
-                                appInfo.packageName).getStringArray(tokenResourceId));
-                for (String signature : signatures) {
-                    vouches.add(signature.toUpperCase());
-                }
-            } catch (PackageManager.NameNotFoundException e) {
-                // Should not happen
-            }
-        }
-
-        private void initVouchedSignatures(UserHandle user) {
-            synchronized (mVouchedSignaturesLocked) {
-                if (mVouchedSignaturesByUser.contains(user)) {
-                    return;
-                }
-                final long startTime = mStatLogger.getTime();
-
-                Set<String> vouches = Collections.newSetFromMap(
-                        new ConcurrentHashMap<String, Boolean>());
-
-                final int callingUid = injectBinderCallingUid();
-                long ident = Binder.clearCallingIdentity();
-                try {
-                    final PackageManagerInternal pmInt =
-                            LocalServices.getService(PackageManagerInternal.class);
-                    List<ApplicationInfo> installedPackages = pmInt.getInstalledApplications(
-                            PackageManager.GET_META_DATA, user.getIdentifier(), callingUid);
-                    for (ApplicationInfo appInfo : installedPackages) {
-                        updateVouches(appInfo, user);
-                    }
-                } finally {
-                    Binder.restoreCallingIdentity(ident);
-                }
-                mVouchedSignaturesByUser.putIfAbsent(user, vouches);
-                mStatLogger.logDurationStat(Stats.INIT_VOUCHED_SIGNATURES, startTime);
-            }
-        }
-
-        @Override
-        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
-            mStatLogger.dump(pw, "  ");
-        }
-
         @Override
         public ActivityInfo resolveActivity(
                 String callingPackage, ComponentName component, UserHandle user)
@@ -1022,18 +875,6 @@
             mCallbackHandler.post(r);
         }
 
-        private class VouchesChangedMonitor extends PackageMonitor {
-            @Override
-            public void onPackageAdded(String packageName, int uid) {
-                updateVouches(packageName, new UserHandle(getChangingUserId()));
-            }
-
-            @Override
-            public void onPackageModified(String packageName) {
-                updateVouches(packageName, new UserHandle(getChangingUserId()));
-            }
-        }
-
         private class MyPackageMonitor extends PackageMonitor implements ShortcutChangeListener {
 
             // TODO Simplify with lambdas.
diff --git a/services/core/java/com/android/server/pm/OWNERS b/services/core/java/com/android/server/pm/OWNERS
index 3c1ee3e..af9b12a 100644
--- a/services/core/java/com/android/server/pm/OWNERS
+++ b/services/core/java/com/android/server/pm/OWNERS
@@ -10,76 +10,48 @@
 toddke@google.com
 
 # apex support
-per-file ApexManager.java = dariofreni@google.com, narayan@google.com, toddke@android.com, toddke@google.com
-per-file StagingManager.java = dariofreni@google.com, narayan@google.com, toddke@android.com, toddke@google.com
+per-file ApexManager.java = dariofreni@google.com
+per-file StagingManager.java = dariofreni@google.com
 
 # dex
-per-file AbstractStatsBase.java = agampe@google.com, toddke@google.com, svetoslavganov@google.com
-per-file AbstractStatsBase.java = calin@google.com, toddke@google.com, svetoslavganov@google.com
-per-file AbstractStatsBase.java = ngeoffray@google.com, toddke@google.com, svetoslavganov@google.com
-per-file BackgroundDexOptService.java = agampe@google.com, toddke@google.com, svetoslavganov@google.com
-per-file BackgroundDexOptService.java = calin@google.com, toddke@google.com, svetoslavganov@google.com
-per-file BackgroundDexOptService.java = ngeoffray@google.com, toddke@google.com, svetoslavganov@google.com
-per-file CompilerStats.java = agampe@google.com, toddke@google.com, svetoslavganov@google.com
-per-file CompilerStats.java = calin@google.com, toddke@google.com, svetoslavganov@google.com
-per-file CompilerStats.java = ngeoffray@google.com, toddke@google.com, svetoslavganov@google.com
-per-file DynamicCodeLoggingService.java = agampe@google.com, toddke@google.com, svetoslavganov@google.com
-per-file DynamicCodeLoggingService.java = calin@google.com, toddke@google.com, svetoslavganov@google.com
-per-file DynamicCodeLoggingService.java = ngeoffray@google.com, toddke@google.com, svetoslavganov@google.com
-per-file InstructionSets.java = agampe@google.com, toddke@google.com, svetoslavganov@google.com
-per-file InstructionSets.java = calin@google.com, toddke@google.com, svetoslavganov@google.com
-per-file InstructionSets.java = ngeoffray@google.com, toddke@google.com, svetoslavganov@google.com
-per-file OtaDexoptService.java = agampe@google.com, toddke@google.com, svetoslavganov@google.com
-per-file OtaDexoptService.java = calin@google.com, toddke@google.com, svetoslavganov@google.com
-per-file OtaDexoptService.java = ngeoffray@google.com, toddke@google.com, svetoslavganov@google.com
-per-file OtaDexoptShellCommand.java = agampe@google.com, toddke@google.com, svetoslavganov@google.com
-per-file OtaDexoptShellCommand.java = calin@google.com, toddke@google.com, svetoslavganov@google.com
-per-file OtaDexoptShellCommand.java = ngeoffray@google.com, toddke@google.com, svetoslavganov@google.com
-per-file PackageDexOptimizer.java = agampe@google.com, toddke@google.com, svetoslavganov@google.com
-per-file PackageDexOptimizer.java = calin@google.com, toddke@google.com, svetoslavganov@google.com
-per-file PackageDexOptimizer.java = ngeoffray@google.com, toddke@google.com, svetoslavganov@google.com
-per-file PackageManagerServiceCompilerMapping.java = agampe@google.com, toddke@google.com, svetoslavganov@google.com
-per-file PackageManagerServiceCompilerMapping.java = calin@google.com, toddke@google.com, svetoslavganov@google.com
-per-file PackageManagerServiceCompilerMapping.java = ngeoffray@google.com, toddke@google.com, svetoslavganov@google.com
-per-file PackageUsage.java = agampe@google.com, toddke@google.com, svetoslavganov@google.com
-per-file PackageUsage.java = calin@google.com, toddke@google.com, svetoslavganov@google.com
-per-file PackageUsage.java = ngeoffray@google.com, toddke@google.com, svetoslavganov@google.com
+per-file AbstractStatsBase.java = agampe@google.com, calin@google.com, ngeoffray@google.com
+per-file BackgroundDexOptService.java = agampe@google.com, calin@google.com, ngeoffray@google.com
+per-file CompilerStats.java = agampe@google.com, calin@google.com, ngeoffray@google.com
+per-file DynamicCodeLoggingService.java = alanstokes@google.com, agampe@google.com, calin@google.com, ngeoffray@google.com
+per-file InstructionSets.java = agampe@google.com, calin@google.com, ngeoffray@google.com
+per-file OtaDexoptService.java = agampe@google.com, calin@google.com, ngeoffray@google.com
+per-file OtaDexoptShellCommand.java = agampe@google.com, calin@google.com, ngeoffray@google.com
+per-file PackageDexOptimizer.java = agampe@google.com, calin@google.com, ngeoffray@google.com
+per-file PackageManagerServiceCompilerMapping.java = agampe@google.com, calin@google.com, ngeoffray@google.com
+per-file PackageUsage.java = agampe@google.com, calin@google.com, ngeoffray@google.com
 
 # multi user / cross profile
-per-file CrossProfileAppsServiceImpl.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file CrossProfileAppsServiceImpl.java = yamasani@google.com, omakoto@google.com, hackbod@google.com
-per-file CrossProfileAppsService.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file CrossProfileAppsService.java = yamasani@google.com, omakoto@google.com, hackbod@google.com
-per-file CrossProfileIntentFilter.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file CrossProfileIntentFilter.java = yamasani@google.com, omakoto@google.com, hackbod@google.com
-per-file CrossProfileIntentResolver.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file CrossProfileIntentResolver.java = yamasani@google.com, omakoto@google.com, hackbod@google.com
-per-file UserManagerService.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file UserManagerService.java = yamasani@google.com, omakoto@google.com, hackbod@google.com
-per-file UserRestrictionsUtils.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file UserRestrictionsUtils.java = yamasani@google.com, omakoto@google.com, hackbod@google.com
-per-file UserRestrictionsUtils.java = rubinxu@google.com, yamasani@google.com, hackbod@google.com
-per-file UserRestrictionsUtils.java = sandness@google.com, yamasani@google.com, hackbod@google.com
+per-file CrossProfileAppsServiceImpl.java = omakoto@google.com, yamasani@google.com
+per-file CrossProfileAppsService.java = omakoto@google.com, yamasani@google.com
+per-file CrossProfileIntentFilter.java = omakoto@google.com, yamasani@google.com
+per-file CrossProfileIntentResolver.java = omakoto@google.com, yamasani@google.com
+per-file UserManagerService.java = omakoto@google.com, yamasani@google.com
+per-file UserRestrictionsUtils.java = omakoto@google.com, rubinxu@google.com, sandness@google.com, yamasani@google.com
 
 # security
-per-file KeySetHandle.java = cbrubaker@google.com, svetoslavganov@google.com, hackbod@google.com
-per-file KeySetManagerService.java = cbrubaker@google.com, svetoslavganov@google.com, hackbod@google.com
-per-file PackageKeySetData.java = cbrubaker@google.com, svetoslavganov@google.com, hackbod@google.com
-per-file PackageSignatures.java = cbrubaker@google.com, svetoslavganov@google.com, hackbod@google.com
-per-file SELinuxMMAC.java = cbrubaker@google.com, svetoslavganov@google.com, hackbod@google.com
+per-file KeySetHandle.java = cbrubaker@google.com
+per-file KeySetManagerService.java = cbrubaker@google.com
+per-file PackageKeySetData.java = cbrubaker@google.com
+per-file PackageSignatures.java = cbrubaker@google.com
+per-file SELinuxMMAC.java = cbrubaker@google.com
 
 # shortcuts
-per-file LauncherAppsService.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file ShareTargetInfo.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file ShortcutBitmapSaver.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file ShortcutDumpFiles.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file ShortcutLauncher.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file ShortcutNonPersistentUser.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file ShortcutPackage.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file ShortcutPackageInfo.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file ShortcutPackageItem.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file ShortcutParser.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file ShortcutRequestPinProcessor.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file ShortcutService.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file ShortcutUser.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
+per-file LauncherAppsService.java = omakoto@google.com, yamasani@google.com
+per-file ShareTargetInfo.java = omakoto@google.com, yamasani@google.com
+per-file ShortcutBitmapSaver.java = omakoto@google.com, yamasani@google.com
+per-file ShortcutDumpFiles.java = omakoto@google.com, yamasani@google.com
+per-file ShortcutLauncher.java = omakoto@google.com, yamasani@google.com
+per-file ShortcutNonPersistentUser.java = omakoto@google.com, yamasani@google.com
+per-file ShortcutPackage.java = omakoto@google.com, yamasani@google.com
+per-file ShortcutPackageInfo.java = omakoto@google.com, yamasani@google.com
+per-file ShortcutPackageItem.java = omakoto@google.com, yamasani@google.com
+per-file ShortcutParser.java = omakoto@google.com, yamasani@google.com
+per-file ShortcutRequestPinProcessor.java = omakoto@google.com, yamasani@google.com
+per-file ShortcutService.java = omakoto@google.com, yamasani@google.com
+per-file ShortcutUser.java = omakoto@google.com, yamasani@google.com
 
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 3a4bcca..181b7a2 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -27,6 +27,7 @@
 import android.app.NotificationManager;
 import android.app.PackageDeleteObserver;
 import android.app.PackageInstallObserver;
+import android.app.admin.DevicePolicyEventLogger;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.content.Context;
 import android.content.Intent;
@@ -59,6 +60,7 @@
 import android.os.SELinux;
 import android.os.UserManager;
 import android.os.storage.StorageManager;
+import android.stats.devicepolicy.DevicePolicyEnums;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.text.TextUtils;
@@ -205,7 +207,7 @@
 
         mApexManager = am;
 
-        mStagingManager = new StagingManager(pm, this, am, context);
+        mStagingManager = new StagingManager(this, am, context);
     }
 
     boolean okToSendBroadcasts()  {
@@ -589,7 +591,7 @@
         session = new PackageInstallerSession(mInternalCallback, mContext, mPm, this,
                 mInstallThread.getLooper(), mStagingManager, sessionId, userId,
                 installerPackageName, callingUid, params, createdMillis, stageDir, stageCid, false,
-                false, null, SessionInfo.INVALID_ID, false, false, false,
+                false, false, null, SessionInfo.INVALID_ID, false, false, false,
                 SessionInfo.STAGED_SESSION_NO_ERROR, "");
 
         synchronized (mSessions) {
@@ -810,6 +812,10 @@
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
+            DevicePolicyEventLogger
+                    .createEvent(DevicePolicyEnums.UNINSTALL_PACKAGE)
+                    .setAdmin(callerPackageName)
+                    .write();
         } else {
             ApplicationInfo appInfo = mPm.getApplicationInfo(callerPackageName, 0, userId);
             if (appInfo.targetSdkVersion >= Build.VERSION_CODES.P) {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 45b3b5b..6451b56 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -44,6 +44,7 @@
 import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.admin.DevicePolicyEventLogger;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.content.Context;
 import android.content.IIntentReceiver;
@@ -82,6 +83,7 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.storage.StorageManager;
+import android.stats.devicepolicy.DevicePolicyEnums;
 import android.system.ErrnoException;
 import android.system.Int64Ref;
 import android.system.Os;
@@ -145,6 +147,7 @@
     private static final String ATTR_SESSION_STAGE_DIR = "sessionStageDir";
     private static final String ATTR_SESSION_STAGE_CID = "sessionStageCid";
     private static final String ATTR_PREPARED = "prepared";
+    private static final String ATTR_COMMITTED = "committed";
     private static final String ATTR_SEALED = "sealed";
     private static final String ATTR_MULTI_PACKAGE = "multiPackage";
     private static final String ATTR_PARENT_SESSION_ID = "parentSessionId";
@@ -401,7 +404,7 @@
             PackageSessionProvider sessionProvider, Looper looper, StagingManager stagingManager,
             int sessionId, int userId,
             String installerPackageName, int installerUid, SessionParams params, long createdMillis,
-            File stageDir, String stageCid, boolean prepared, boolean sealed,
+            File stageDir, String stageCid, boolean prepared, boolean committed, boolean sealed,
             @Nullable int[] childSessionIds, int parentSessionId, boolean isReady,
             boolean isFailed, boolean isApplied, int stagedSessionErrorCode,
             String stagedSessionErrorMessage) {
@@ -434,6 +437,7 @@
         }
 
         mPrepared = prepared;
+        mCommitted = committed;
         mStagedSessionReady = isReady;
         mStagedSessionFailed = isFailed;
         mStagedSessionApplied = isApplied;
@@ -510,6 +514,13 @@
         }
     }
 
+    /** {@hide} */
+    boolean isCommitted() {
+        synchronized (mLock) {
+            return mCommitted;
+        }
+    }
+
     @GuardedBy("mLock")
     private void assertPreparedAndNotSealedLocked(String cookie) {
         assertPreparedAndNotCommittedOrDestroyedLocked(cookie);
@@ -984,6 +995,19 @@
 
         mSealed = true;
 
+        if (params.isStaged) {
+            final PackageInstallerSession activeSession = mStagingManager.getActiveSession();
+            final boolean anotherSessionAlreadyInProgress =
+                    activeSession != null && sessionId != activeSession.sessionId
+                            && mParentSessionId != activeSession.sessionId;
+            if (anotherSessionAlreadyInProgress) {
+                throw new PackageManagerException(
+                        PackageManager.INSTALL_FAILED_OTHER_STAGED_SESSION_IN_PROGRESS,
+                        "There is already in-progress committed staged session "
+                                + activeSession.sessionId, null);
+            }
+        }
+
         // Read transfers from the original owner stay open, but as the session's data
         // cannot be modified anymore, there is no leak of information. For staged sessions,
         // further validation is performed by the staging manager.
@@ -1063,6 +1087,12 @@
     }
 
     private void handleCommit() {
+        if (isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked()) {
+            DevicePolicyEventLogger
+                    .createEvent(DevicePolicyEnums.INSTALL_PACKAGE)
+                    .setAdmin(mInstallerPackageName)
+                    .write();
+        }
         if (params.isStaged) {
             mStagingManager.commitSession(this);
             destroyInternal();
@@ -2143,6 +2173,7 @@
 
         pw.printPair("mClientProgress", mClientProgress);
         pw.printPair("mProgress", mProgress);
+        pw.printPair("mCommitted", mCommitted);
         pw.printPair("mSealed", mSealed);
         pw.printPair("mPermissionsManuallyAccepted", mPermissionsManuallyAccepted);
         pw.printPair("mRelinquished", mRelinquished);
@@ -2201,6 +2232,7 @@
                 writeStringAttribute(out, ATTR_SESSION_STAGE_CID, stageCid);
             }
             writeBooleanAttribute(out, ATTR_PREPARED, isPrepared());
+            writeBooleanAttribute(out, ATTR_COMMITTED, isCommitted());
             writeBooleanAttribute(out, ATTR_SEALED, isSealed());
 
             writeBooleanAttribute(out, ATTR_MULTI_PACKAGE, params.isMultiPackage);
@@ -2298,6 +2330,7 @@
         final File stageDir = (stageDirRaw != null) ? new File(stageDirRaw) : null;
         final String stageCid = readStringAttribute(in, ATTR_SESSION_STAGE_CID);
         final boolean prepared = readBooleanAttribute(in, ATTR_PREPARED, true);
+        final boolean committed = readBooleanAttribute(in, ATTR_COMMITTED);
         final boolean sealed = readBooleanAttribute(in, ATTR_SEALED);
         final int parentSessionId = readIntAttribute(in, ATTR_PARENT_SESSION_ID,
                 SessionInfo.INVALID_ID);
@@ -2374,8 +2407,8 @@
 
         return new PackageInstallerSession(callback, context, pm, sessionProvider,
                 installerThread, stagingManager, sessionId, userId, installerPackageName,
-                installerUid, params, createdMillis, stageDir, stageCid, prepared, sealed,
-                childSessionIdsArray, parentSessionId, isReady, isFailed, isApplied,
+                installerUid, params, createdMillis, stageDir, stageCid, prepared, committed,
+                sealed, childSessionIdsArray, parentSessionId, isReady, isFailed, isApplied,
                 stagedSessionErrorCode, stagedSessionErrorMessage);
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 4dcab5e..4e8ef71 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -162,6 +162,7 @@
 import android.content.pm.IntentFilterVerificationInfo;
 import android.content.pm.KeySet;
 import android.content.pm.ModuleInfo;
+import android.content.pm.PackageBackwardCompatibility;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageInfoLite;
 import android.content.pm.PackageInstaller;
@@ -231,6 +232,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.UserManagerInternal;
+import android.os.storage.DiskInfo;
 import android.os.storage.IStorageManager;
 import android.os.storage.StorageEventListener;
 import android.os.storage.StorageManager;
@@ -244,6 +246,7 @@
 import android.security.KeyStore;
 import android.security.SystemKeyStore;
 import android.service.pm.PackageServiceDumpProto;
+import android.stats.storage.StorageEnums;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.text.TextUtils;
@@ -268,6 +271,7 @@
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
+import android.util.StatsLog;
 import android.util.TimingsTraceLog;
 import android.util.Xml;
 import android.util.jar.StrictJarFile;
@@ -1911,6 +1915,15 @@
 
                 // Send broadcast package appeared if external for all users
                 if (isExternal(res.pkg)) {
+                    if (!update) {
+                        int packageExternalStorageType =
+                                getPackageExternalStorageType(res.pkg);
+                        // If the package was installed externally, log it.
+                        if (packageExternalStorageType != StorageEnums.UNKNOWN) {
+                            StatsLog.write(StatsLog.APP_INSTALL_ON_EXTERNAL_STORAGE_REPORTED,
+                                    packageExternalStorageType, res.pkg.packageName);
+                        }
+                    }
                     if (DEBUG_INSTALL) {
                         Slog.i(TAG, "upgrading pkg " + res.pkg + " is external");
                     }
@@ -1952,7 +1965,7 @@
             }
 
             if (allNewUsers && !update) {
-                notifyPackageAdded(packageName);
+                notifyPackageAdded(packageName, res.uid);
             }
 
             // Log current value of "unknown sources" setting
@@ -1999,6 +2012,32 @@
         }
     }
 
+    /**
+     * Gets the type of the external storage a package is installed on.
+     * @param pkg The package for which to get the external storage type.
+     * @return {@link StorageEnum#TYPE_UNKNOWN} if it is not stored externally or the corresponding
+     * {@link StorageEnum} storage type value if it is.
+     */
+    private int getPackageExternalStorageType(PackageParser.Package pkg) {
+        final StorageManager storage = mContext.getSystemService(StorageManager.class);
+        VolumeInfo volume = storage.findVolumeByUuid(pkg.applicationInfo.storageUuid.toString());
+        if (volume != null) {
+            DiskInfo disk = volume.getDisk();
+            if (disk != null) {
+                if (disk.isSd()) {
+                    return StorageEnums.SD_CARD;
+                }
+                if (disk.isUsb()) {
+                    return StorageEnums.USB;
+                }
+                if (isExternal(pkg)) {
+                    return StorageEnums.OTHER;
+                }
+            }
+        }
+        return StorageEnums.UNKNOWN;
+    }
+
     private StorageEventListener mStorageListener = new StorageEventListener() {
         @Override
         public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
@@ -11058,6 +11097,8 @@
             pkg.mRealPackage = null;
             pkg.mAdoptPermissions = null;
         }
+
+        PackageBackwardCompatibility.modifySharedLibraries(pkg);
     }
 
     private static @NonNull <T> T assertNotNull(@Nullable T object, String message)
@@ -12317,7 +12358,7 @@
     }
 
     @Override
-    public void notifyPackageAdded(String packageName) {
+    public void notifyPackageAdded(String packageName, int uid) {
         final PackageListObserver[] observers;
         synchronized (mPackages) {
             if (mPackageListObservers.size() == 0) {
@@ -12328,7 +12369,7 @@
             observers = mPackageListObservers.toArray(observerArray);
         }
         for (int i = observers.length - 1; i >= 0; --i) {
-            observers[i].onPackageAdded(packageName);
+            observers[i].onPackageAdded(packageName, uid);
         }
     }
 
@@ -12339,7 +12380,7 @@
     };
 
     @Override
-    public void notifyPackageRemoved(String packageName) {
+    public void notifyPackageRemoved(String packageName, int uid) {
         final PackageListObserver[] observers;
         synchronized (mPackages) {
             if (mPackageListObservers.size() == 0) {
@@ -12350,7 +12391,7 @@
             observers = mPackageListObservers.toArray(observerArray);
         }
         for (int i = observers.length - 1; i >= 0; --i) {
-            observers[i].onPackageRemoved(packageName);
+            observers[i].onPackageRemoved(packageName, uid);
         }
     }
 
@@ -12937,6 +12978,8 @@
         final List<String> changedPackagesList = new ArrayList<>(packageNames.length);
         final IntArray changedUids = new IntArray(packageNames.length);
         final List<String> unactionedPackages = new ArrayList<>(packageNames.length);
+        final boolean[] canRestrict = (restrictionFlags != 0) ? canSuspendPackageForUserInternal(
+                packageNames, userId) : null;
 
         for (int i = 0; i < packageNames.length; i++) {
             final String packageName = packageNames[i];
@@ -12950,7 +12993,7 @@
                     continue;
                 }
             }
-            if (restrictionFlags != 0 && !canSuspendPackageForUserInternal(packageName, userId)) {
+            if (canRestrict != null && !canRestrict[i]) {
                 unactionedPackages.add(packageName);
                 continue;
             }
@@ -13007,6 +13050,8 @@
         final List<String> changedPackagesList = new ArrayList<>(packageNames.length);
         final IntArray changedUids = new IntArray(packageNames.length);
         final List<String> unactionedPackages = new ArrayList<>(packageNames.length);
+        final boolean[] canSuspend = suspended ? canSuspendPackageForUserInternal(packageNames,
+                userId) : null;
 
         for (int i = 0; i < packageNames.length; i++) {
             final String packageName = packageNames[i];
@@ -13026,7 +13071,7 @@
                     continue;
                 }
             }
-            if (suspended && !canSuspendPackageForUserInternal(packageName, userId)) {
+            if (canSuspend != null && !canSuspend[i]) {
                 unactionedPackages.add(packageName);
                 continue;
             }
@@ -13190,87 +13235,97 @@
                     + " cannot query getUnsuspendablePackagesForUser for user " + userId);
         }
         final ArraySet<String> unactionablePackages = new ArraySet<>();
-        for (String packageName : packageNames) {
-            if (!canSuspendPackageForUserInternal(packageName, userId)) {
-                unactionablePackages.add(packageName);
+        final boolean[] canSuspend = canSuspendPackageForUserInternal(packageNames, userId);
+        for (int i = 0; i < packageNames.length; i++) {
+            if (!canSuspend[i]) {
+                unactionablePackages.add(packageNames[i]);
             }
         }
         return unactionablePackages.toArray(new String[unactionablePackages.size()]);
     }
 
-    private boolean canSuspendPackageForUserInternal(String packageName, int userId) {
+    /**
+     * Returns an array of booleans, such that the ith boolean denotes whether the ith package can
+     * be suspended or not.
+     *
+     * @param packageNames  The package names to check suspendability for.
+     * @param userId The user to check in
+     * @return An array containing results of the checks
+     */
+    @NonNull
+    private boolean[] canSuspendPackageForUserInternal(@NonNull String[] packageNames, int userId) {
+        final boolean[] canSuspend = new boolean[packageNames.length];
         final long callingId = Binder.clearCallingIdentity();
         try {
-            if (isPackageDeviceAdmin(packageName, userId)) {
-                Slog.w(TAG, "Cannot suspend package \"" + packageName
-                        + "\": has an active device admin");
-                return false;
-            }
+            final String activeLauncherPackageName = getActiveLauncherPackageName(userId);
+            final String dialerPackageName = getDefaultDialerPackageName(userId);
+            for (int i = 0; i < packageNames.length; i++) {
+                canSuspend[i] = false;
+                final String packageName = packageNames[i];
 
-            String activeLauncherPackageName = getActiveLauncherPackageName(userId);
-            if (packageName.equals(activeLauncherPackageName)) {
-                Slog.w(TAG, "Cannot suspend package \"" + packageName
-                        + "\": contains the active launcher");
-                return false;
-            }
-
-            if (packageName.equals(mRequiredInstallerPackage)) {
-                Slog.w(TAG, "Cannot suspend package \"" + packageName
-                        + "\": required for package installation");
-                return false;
-            }
-
-            if (packageName.equals(mRequiredUninstallerPackage)) {
-                Slog.w(TAG, "Cannot suspend package \"" + packageName
-                        + "\": required for package uninstallation");
-                return false;
-            }
-
-            if (packageName.equals(mRequiredVerifierPackage)) {
-                Slog.w(TAG, "Cannot suspend package \"" + packageName
-                        + "\": required for package verification");
-                return false;
-            }
-
-            if (packageName.equals(getDefaultDialerPackageName(userId))) {
-                Slog.w(TAG, "Cannot suspend package \"" + packageName
-                        + "\": is the default dialer");
-                return false;
-            }
-
-            if (packageName.equals(mRequiredPermissionControllerPackage)) {
-                Slog.w(TAG, "Cannot suspend package \"" + packageName
-                        + "\": required for permissions management");
-                return false;
-            }
-
-            synchronized (mPackages) {
-                if (mProtectedPackages.isPackageStateProtected(userId, packageName)) {
+                if (isPackageDeviceAdmin(packageName, userId)) {
                     Slog.w(TAG, "Cannot suspend package \"" + packageName
-                            + "\": protected package");
-                    return false;
+                            + "\": has an active device admin");
+                    continue;
                 }
-
-                // Cannot suspend static shared libs as they are considered
-                // a part of the using app (emulating static linking). Also
-                // static libs are installed always on internal storage.
-                PackageParser.Package pkg = mPackages.get(packageName);
-                if (pkg != null && pkg.applicationInfo.isStaticSharedLibrary()) {
-                    Slog.w(TAG, "Cannot suspend package: " + packageName
-                            + " providing static shared library: "
-                            + pkg.staticSharedLibName);
-                    return false;
+                if (packageName.equals(activeLauncherPackageName)) {
+                    Slog.w(TAG, "Cannot suspend package \"" + packageName
+                            + "\": contains the active launcher");
+                    continue;
                 }
-            }
+                if (packageName.equals(mRequiredInstallerPackage)) {
+                    Slog.w(TAG, "Cannot suspend package \"" + packageName
+                            + "\": required for package installation");
+                    continue;
+                }
+                if (packageName.equals(mRequiredUninstallerPackage)) {
+                    Slog.w(TAG, "Cannot suspend package \"" + packageName
+                            + "\": required for package uninstallation");
+                    continue;
+                }
+                if (packageName.equals(mRequiredVerifierPackage)) {
+                    Slog.w(TAG, "Cannot suspend package \"" + packageName
+                            + "\": required for package verification");
+                    continue;
+                }
+                if (packageName.equals(dialerPackageName)) {
+                    Slog.w(TAG, "Cannot suspend package \"" + packageName
+                            + "\": is the default dialer");
+                    continue;
+                }
+                if (packageName.equals(mRequiredPermissionControllerPackage)) {
+                    Slog.w(TAG, "Cannot suspend package \"" + packageName
+                            + "\": required for permissions management");
+                    continue;
+                }
+                synchronized (mPackages) {
+                    if (mProtectedPackages.isPackageStateProtected(userId, packageName)) {
+                        Slog.w(TAG, "Cannot suspend package \"" + packageName
+                                + "\": protected package");
+                        continue;
+                    }
 
-            if (PLATFORM_PACKAGE_NAME.equals(packageName)) {
-                Slog.w(TAG, "Cannot suspend the platform package: " + packageName);
-                return false;
+                    // Cannot suspend static shared libs as they are considered
+                    // a part of the using app (emulating static linking). Also
+                    // static libs are installed always on internal storage.
+                    PackageParser.Package pkg = mPackages.get(packageName);
+                    if (pkg != null && pkg.applicationInfo.isStaticSharedLibrary()) {
+                        Slog.w(TAG, "Cannot suspend package: " + packageName
+                                + " providing static shared library: "
+                                + pkg.staticSharedLibName);
+                        continue;
+                    }
+                }
+                if (PLATFORM_PACKAGE_NAME.equals(packageName)) {
+                    Slog.w(TAG, "Cannot suspend the platform package: " + packageName);
+                    continue;
+                }
+                canSuspend[i] = true;
             }
-            return true;
         } finally {
             Binder.restoreCallingIdentity(callingId);
         }
+        return canSuspend;
     }
 
     private String getActiveLauncherPackageName(int userId) {
@@ -17904,7 +17959,8 @@
                 return;
             }
             Bundle extras = new Bundle(2);
-            extras.putInt(Intent.EXTRA_UID, removedAppId >= 0  ? removedAppId : uid);
+            final int removedUid = removedAppId >= 0  ? removedAppId : uid;
+            extras.putInt(Intent.EXTRA_UID, removedUid);
             extras.putBoolean(Intent.EXTRA_DATA_REMOVED, dataRemoved);
             extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, !killApp);
             if (isUpdate || isRemovedPackageSystemUpdate) {
@@ -17925,7 +17981,7 @@
                         removedPackage, extras,
                         Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND,
                         null, null, broadcastUsers, instantUserIds);
-                    packageSender.notifyPackageRemoved(removedPackage);
+                    packageSender.notifyPackageRemoved(removedPackage, removedUid);
                 }
             }
             if (removedAppId >= 0) {
@@ -23901,6 +23957,50 @@
                 mDefaultHomeProvider = provider;
             }
         }
+
+        @Override
+        public boolean isApexPackage(String packageName) {
+            return PackageManagerService.this.mApexManager.isApexPackage(packageName);
+        }
+
+        @Override
+        public void uninstallApex(String packageName, long versionCode, int userId,
+                IntentSender intentSender) {
+            final int callerUid = Binder.getCallingUid();
+            if (callerUid != Process.ROOT_UID && callerUid != Process.SHELL_UID) {
+                throw new SecurityException("Not allowed to uninstall apexes");
+            }
+            PackageInstallerService.PackageDeleteObserverAdapter adapter =
+                    new PackageInstallerService.PackageDeleteObserverAdapter(
+                            PackageManagerService.this.mContext, intentSender, packageName,
+                            false, userId);
+            if (userId != UserHandle.USER_ALL) {
+                adapter.onPackageDeleted(packageName, PackageManager.DELETE_FAILED_ABORTED,
+                        "Can't uninstall an apex for a single user");
+                return;
+            }
+            final ApexManager am = PackageManagerService.this.mApexManager;
+            PackageInfo activePackage = am.getActivePackage(packageName);
+            if (activePackage == null) {
+                adapter.onPackageDeleted(packageName, PackageManager.DELETE_FAILED_ABORTED,
+                        packageName + " is not an apex package");
+                return;
+            }
+            if (versionCode != PackageManager.VERSION_CODE_HIGHEST
+                    && activePackage.getLongVersionCode() != versionCode) {
+                adapter.onPackageDeleted(packageName, PackageManager.DELETE_FAILED_ABORTED,
+                        "Active version " + activePackage.getLongVersionCode()
+                                + " is not equal to " + versionCode + "]");
+                return;
+            }
+            if (!am.uninstallApex(activePackage.applicationInfo.sourceDir)) {
+                adapter.onPackageDeleted(packageName, PackageManager.DELETE_FAILED_ABORTED,
+                        "Failed to uninstall apex " + packageName);
+            } else {
+                adapter.onPackageDeleted(packageName, PackageManager.DELETE_SUCCEEDED,
+                        null);
+            }
+        }
     }
 
     @GuardedBy("mPackages")
@@ -24410,6 +24510,6 @@
         final IIntentReceiver finishedReceiver, final int[] userIds, int[] instantUserIds);
     void sendPackageAddedForNewUsers(String packageName, boolean sendBootCompleted,
         boolean includeStopped, int appId, int[] userIds, int[] instantUserIds);
-    void notifyPackageAdded(String packageName);
-    void notifyPackageRemoved(String packageName);
+    void notifyPackageAdded(String packageName, int uid);
+    void notifyPackageRemoved(String packageName, int uid);
 }
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 912a50e..2d1afa7 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -1619,30 +1619,36 @@
         }
 
         userId = translateUserId(userId, true /*allowAll*/, "runUninstall");
-        if (userId == UserHandle.USER_ALL) {
-            userId = UserHandle.USER_SYSTEM;
-            flags |= PackageManager.DELETE_ALL_USERS;
-        } else {
-            final PackageInfo info = mInterface.getPackageInfo(packageName,
-                    PackageManager.MATCH_STATIC_SHARED_LIBRARIES, userId);
-            if (info == null) {
-                pw.println("Failure [not installed for " + userId + "]");
-                return 1;
-            }
-            final boolean isSystem =
-                    (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
-            // If we are being asked to delete a system app for just one
-            // user set flag so it disables rather than reverting to system
-            // version of the app.
-            if (isSystem) {
-                flags |= PackageManager.DELETE_SYSTEM_APP;
-            }
-        }
-
         final LocalIntentReceiver receiver = new LocalIntentReceiver();
-        mInterface.getPackageInstaller().uninstall(new VersionedPackage(packageName,
-                versionCode), null /*callerPackageName*/, flags,
-                receiver.getIntentSender(), userId);
+        PackageManagerInternal internal = LocalServices.getService(PackageManagerInternal.class);
+
+        if (internal.isApexPackage(packageName)) {
+            internal.uninstallApex(packageName, versionCode, userId, receiver.getIntentSender());
+        } else {
+            if (userId == UserHandle.USER_ALL) {
+                userId = UserHandle.USER_SYSTEM;
+                flags |= PackageManager.DELETE_ALL_USERS;
+            } else {
+                final PackageInfo info = mInterface.getPackageInfo(packageName,
+                        PackageManager.MATCH_STATIC_SHARED_LIBRARIES, userId);
+                if (info == null) {
+                    pw.println("Failure [not installed for " + userId + "]");
+                    return 1;
+                }
+                final boolean isSystem =
+                        (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
+                // If we are being asked to delete a system app for just one
+                // user set flag so it disables rather than reverting to system
+                // version of the app.
+                if (isSystem) {
+                    flags |= PackageManager.DELETE_SYSTEM_APP;
+                }
+            }
+
+            mInterface.getPackageInstaller().uninstall(new VersionedPackage(packageName,
+                            versionCode), null /*callerPackageName*/, flags,
+                    receiver.getIntentSender(), userId);
+        }
 
         final Intent result = receiver.getResult();
         final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 4ee6eaf..39c731c 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -17,6 +17,7 @@
 package com.android.server.pm;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.apex.ApexInfo;
 import android.apex.ApexInfoList;
 import android.apex.ApexSessionInfo;
@@ -68,7 +69,6 @@
     private static final String TAG = "StagingManager";
 
     private final PackageInstallerService mPi;
-    private final PackageManagerService mPm;
     private final ApexManager mApexManager;
     private final PowerManager mPowerManager;
     private final Handler mBgHandler;
@@ -76,9 +76,7 @@
     @GuardedBy("mStagedSessions")
     private final SparseArray<PackageInstallerSession> mStagedSessions = new SparseArray<>();
 
-    StagingManager(PackageManagerService pm, PackageInstallerService pi, ApexManager am,
-            Context context) {
-        mPm = pm;
+    StagingManager(PackageInstallerService pi, ApexManager am, Context context) {
         mPi = pi;
         mApexManager = am;
         mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
@@ -484,6 +482,27 @@
         mBgHandler.post(() -> preRebootVerification(session));
     }
 
+    @Nullable
+    PackageInstallerSession getActiveSession() {
+        synchronized (mStagedSessions) {
+            for (int i = 0; i < mStagedSessions.size(); i++) {
+                final PackageInstallerSession session = mStagedSessions.valueAt(i);
+                if (!session.isCommitted()) {
+                    continue;
+                }
+                if (session.hasParentSessionId()) {
+                    // Staging manager will finalize only parent session. Ignore child sessions
+                    // picking the active.
+                    continue;
+                }
+                if (!session.isStagedSessionApplied() && !session.isStagedSessionFailed()) {
+                    return session;
+                }
+            }
+        }
+        return null;
+    }
+
     void createSession(@NonNull PackageInstallerSession sessionInfo) {
         synchronized (mStagedSessions) {
             mStagedSessions.append(sessionInfo.sessionId, sessionInfo);
@@ -498,7 +517,7 @@
 
     void abortCommittedSession(@NonNull PackageInstallerSession session) {
         if (session.isStagedSessionApplied()) {
-            Slog.w(TAG, "Cannot abort applied session!");
+            Slog.w(TAG, "Cannot abort applied session : " + session.sessionId);
             return;
         }
         abortSession(session);
@@ -574,6 +593,10 @@
     }
 
     private void checkStateAndResume(@NonNull PackageInstallerSession session) {
+        if (!session.isCommitted()) {
+            // Session hasn't been committed yet, ignore.
+            return;
+        }
         // Check the state of the session and decide what to do next.
         if (session.isStagedSessionFailed() || session.isStagedSessionApplied()) {
             // Final states, nothing to do.
diff --git a/services/core/java/com/android/server/pm/TEST_MAPPING b/services/core/java/com/android/server/pm/TEST_MAPPING
index 24b38e7..15dc6ae 100644
--- a/services/core/java/com/android/server/pm/TEST_MAPPING
+++ b/services/core/java/com/android/server/pm/TEST_MAPPING
@@ -12,7 +12,7 @@
   ],
   "imports": [
     {
-      "path": "system/apex/tests"
+      "path": "frameworks/base/core/java/android/content/pm"
     }
   ]
 }
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 3744f68..316a9c0 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1144,6 +1144,19 @@
     }
 
     @Override
+    public String getUserName() {
+        if (!hasManageUsersOrPermission(android.Manifest.permission.GET_ACCOUNTS_PRIVILEGED)) {
+            throw new SecurityException("You need MANAGE_USERS or GET_ACCOUNTS_PRIVILEGED "
+                    + "permissions to: get user name");
+        }
+        final int userId = UserHandle.getUserId(Binder.getCallingUid());
+        synchronized (mUsersLock) {
+            UserInfo userInfo = userWithName(getUserInfoLU(userId));
+            return userInfo == null ? "" : userInfo.name;
+        }
+    }
+
+    @Override
     public long getUserStartRealtime() {
         final int userId = UserHandle.getUserId(Binder.getCallingUid());
         synchronized (mUsersLock) {
@@ -1299,7 +1312,12 @@
             }
         }
         if (changed) {
-            sendUserInfoChangedBroadcast(userId);
+            long ident = Binder.clearCallingIdentity();
+            try {
+                sendUserInfoChangedBroadcast(userId);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
         }
     }
 
@@ -1324,7 +1342,10 @@
 
     @Override
     public ParcelFileDescriptor getUserIcon(int targetUserId) {
-        checkManageUsersPermission("get user icon");
+        if (!hasManageUsersOrPermission(android.Manifest.permission.GET_ACCOUNTS_PRIVILEGED)) {
+            throw new SecurityException("You need MANAGE_USERS or GET_ACCOUNTS_PRIVILEGED "
+                    + "permissions to: get user icon");
+        }
         String iconPath;
         synchronized (mPackagesLock) {
             UserInfo targetUserInfo = getUserInfoNoChecks(targetUserId);
@@ -1941,15 +1962,23 @@
 
     /**
      * @return whether the calling UID is system UID or root's UID or the calling app has the
-     * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} or
-     * {@link android.Manifest.permission#CREATE_USERS CREATE_USERS}.
+     * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} or the provided permission.
      */
-    private static final boolean hasManageOrCreateUsersPermission() {
+    private static final boolean hasManageUsersOrPermission(String alternativePermission) {
         final int callingUid = Binder.getCallingUid();
         return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
                 || callingUid == Process.ROOT_UID
                 || hasPermissionGranted(android.Manifest.permission.MANAGE_USERS, callingUid)
-                || hasPermissionGranted(android.Manifest.permission.CREATE_USERS, callingUid);
+                || hasPermissionGranted(alternativePermission, callingUid);
+    }
+
+    /**
+     * @return whether the calling UID is system UID or root's UID or the calling app has the
+     * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} or
+     * {@link android.Manifest.permission#CREATE_USERS CREATE_USERS}.
+     */
+    private static final boolean hasManageOrCreateUsersPermission() {
+        return hasManageUsersOrPermission(android.Manifest.permission.CREATE_USERS);
     }
 
     /**
diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java
index 3b805d51..f56231f 100644
--- a/services/core/java/com/android/server/pm/dex/DexManager.java
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -16,7 +16,7 @@
 
 package com.android.server.pm.dex;
 
-import static android.provider.DeviceConfig.DexBoot;
+import static android.provider.DeviceConfig.NAMESPACE_DEX_BOOT;
 
 import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
 import static com.android.server.pm.dex.PackageDexUsage.DexUseInfo;
@@ -72,6 +72,10 @@
     private static final String PROPERTY_NAME_PM_DEXOPT_PRIV_APPS_OOB_LIST =
             "pm.dexopt.priv-apps-oob-list";
 
+    // flags for Device Config API
+    private static final String PRIV_APPS_OOB_ENABLED = "priv_apps_oob_enabled";
+    private static final String PRIV_APPS_OOB_WHITELIST = "priv_apps_oob_whitelist";
+
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private final Context mContext;
@@ -713,8 +717,8 @@
         return isPackageSelectedToRunOobInternal(
                 SystemProperties.getBoolean(PROPERTY_NAME_PM_DEXOPT_PRIV_APPS_OOB, false),
                 SystemProperties.get(PROPERTY_NAME_PM_DEXOPT_PRIV_APPS_OOB_LIST, "ALL"),
-                DeviceConfig.getProperty(DexBoot.NAMESPACE, DexBoot.PRIV_APPS_OOB_ENABLED),
-                DeviceConfig.getProperty(DexBoot.NAMESPACE, DexBoot.PRIV_APPS_OOB_WHITELIST),
+                DeviceConfig.getProperty(NAMESPACE_DEX_BOOT, PRIV_APPS_OOB_ENABLED),
+                DeviceConfig.getProperty(NAMESPACE_DEX_BOOT, PRIV_APPS_OOB_WHITELIST),
                 packageNamesInSameProcess);
     }
 
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index b877fe7..e9077a9 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -155,11 +155,6 @@
         ACTIVITY_RECOGNITION_PERMISSIONS.add(Manifest.permission.ACTIVITY_RECOGNITION);
     }
 
-    private static final Set<String> COARSE_LOCATION_PERMISSIONS = new ArraySet<>();
-    static {
-        COARSE_LOCATION_PERMISSIONS.add(Manifest.permission.ACCESS_COARSE_LOCATION);
-    }
-
     private static final Set<String> CALENDAR_PERMISSIONS = new ArraySet<>();
     static {
         CALENDAR_PERMISSIONS.add(Manifest.permission.READ_CALENDAR);
@@ -709,6 +704,12 @@
                         TelephonyManager.ACTION_EMERGENCY_ASSISTANCE, userId),
                 userId, CONTACTS_PERMISSIONS, PHONE_PERMISSIONS);
 
+        // STOPSHIP(b/128289173): remove once EmergencyInfo app was replaced.
+        grantSystemFixedPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackage(
+                        "com.android.emergency.action.EMERGENCY_ASSISTANCE", userId),
+                userId, CONTACTS_PERMISSIONS, PHONE_PERMISSIONS);
+
         // NFC Tag viewer
         Intent nfcTagIntent = new Intent(Intent.ACTION_VIEW)
                 .setType("vnd.android.cursor.item/ndef_msg");
@@ -803,8 +804,7 @@
 
     private void grantDefaultPermissionsToDefaultSystemUseOpenWifiApp(
             String useOpenWifiPackage, int userId) {
-        grantPermissionsToSystemPackage(
-                useOpenWifiPackage, userId, COARSE_LOCATION_PERMISSIONS);
+        grantPermissionsToSystemPackage(useOpenWifiPackage, userId, ALWAYS_LOCATION_PERMISSIONS);
     }
 
     public void grantDefaultPermissionsToDefaultSmsApp(String packageName, int userId) {
@@ -824,7 +824,7 @@
 
     public void grantDefaultPermissionsToDefaultUseOpenWifiApp(String packageName, int userId) {
         Log.i(TAG, "Granting permissions to default Use Open WiFi app for user:" + userId);
-        grantIgnoringSystemPackage(packageName, userId, COARSE_LOCATION_PERMISSIONS);
+        grantIgnoringSystemPackage(packageName, userId, ALWAYS_LOCATION_PERMISSIONS);
     }
 
     public void grantDefaultPermissionsToDefaultSimCallManager(String packageName, int userId) {
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index f7d8e0e..897b885 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -1273,7 +1273,7 @@
             @NonNull ArraySet<String> sourcePerms, @NonNull String newPerm,
             @NonNull PermissionsState ps, @NonNull PackageParser.Package pkg,
             @UserIdInt int userId) {
-        AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class);
+        AppOpsManagerInternal appOpsManager = LocalServices.getService(AppOpsManagerInternal.class);
         String pkgName = pkg.packageName;
 
         if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
@@ -1287,10 +1287,10 @@
                     String sourcePerm = sourcePerms.valueAt(i);
 
                     if (ps.hasRuntimePermission(sourcePerm, userId)) {
-                        String sourceOp = permissionToOp(sourcePerm);
+                        int sourceOp = permissionToOpCode(sourcePerm);
 
-                        if (sourceOp != null) {
-                            int mode = appOpsManager.unsafeCheckOpRaw(sourceOp,
+                        if (sourceOp != OP_NONE) {
+                            int mode = appOpsManager.checkOperationUnchecked(sourceOp,
                                     getUid(userId, getAppId(pkg.applicationInfo.uid)), pkgName);
 
                             if (mode == MODE_FOREGROUND || mode == MODE_ERRORED) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index c0e5974..e7c9a08 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -44,7 +44,6 @@
 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
 import static android.view.WindowManager.LayoutParams.LAST_SYSTEM_WINDOW;
-import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
@@ -105,7 +104,6 @@
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
-import android.app.ActivityOptions;
 import android.app.ActivityTaskManager;
 import android.app.AppOpsManager;
 import android.app.IUiModeManager;
@@ -127,7 +125,6 @@
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.database.ContentObserver;
-import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.hardware.display.DisplayManager;
@@ -211,7 +208,6 @@
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.ScreenshotHelper;
-import com.android.internal.widget.PointerLocationView;
 import com.android.server.ExtconStateObserver;
 import com.android.server.ExtconUEventObserver;
 import com.android.server.GestureLauncherService;
@@ -494,9 +490,6 @@
 
     private boolean mHandleVolumeKeysInWM;
 
-    int mPointerLocationMode = 0; // guarded by mLock
-    PointerLocationView mPointerLocationView;
-
     private boolean mPendingKeyguardOccluded;
     private boolean mKeyguardOccludedChanged;
     private boolean mNotifyUserActivity;
@@ -619,8 +612,6 @@
     private boolean mPerDisplayFocusEnabled = false;
     private volatile int mTopFocusedDisplayId = INVALID_DISPLAY;
 
-    private static final int MSG_ENABLE_POINTER_LOCATION = 1;
-    private static final int MSG_DISABLE_POINTER_LOCATION = 2;
     private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
     private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4;
     private static final int MSG_KEYGUARD_DRAWN_COMPLETE = 5;
@@ -651,12 +642,6 @@
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
-                case MSG_ENABLE_POINTER_LOCATION:
-                    enablePointerLocation();
-                    break;
-                case MSG_DISABLE_POINTER_LOCATION:
-                    disablePointerLocation();
-                    break;
                 case MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK:
                     dispatchMediaKeyWithWakeLock((KeyEvent)msg.obj);
                     break;
@@ -779,9 +764,6 @@
             resolver.registerContentObserver(Settings.System.getUriFor(
                     Settings.System.SCREEN_OFF_TIMEOUT), false, this,
                     UserHandle.USER_ALL);
-            resolver.registerContentObserver(Settings.System.getUriFor(
-                    Settings.System.POINTER_LOCATION), false, this,
-                    UserHandle.USER_ALL);
             resolver.registerContentObserver(Settings.Secure.getUriFor(
                     Settings.Secure.DEFAULT_INPUT_METHOD), false, this,
                     UserHandle.USER_ALL);
@@ -2007,15 +1989,6 @@
                 updateWakeGestureListenerLp();
             }
 
-            if (mSystemReady) {
-                int pointerLocation = Settings.System.getIntForUser(resolver,
-                        Settings.System.POINTER_LOCATION, 0, UserHandle.USER_CURRENT);
-                if (mPointerLocationMode != pointerLocation) {
-                    mPointerLocationMode = pointerLocation;
-                    mHandler.sendEmptyMessage(pointerLocation != 0 ?
-                            MSG_ENABLE_POINTER_LOCATION : MSG_DISABLE_POINTER_LOCATION);
-                }
-            }
             // use screen off timeout setting as the timeout for the lockscreen
             mLockScreenTimeout = Settings.System.getIntForUser(resolver,
                     Settings.System.SCREEN_OFF_TIMEOUT, 0, UserHandle.USER_CURRENT);
@@ -2047,46 +2020,6 @@
                 && mWakeGestureListener.isSupported();
     }
 
-    private void enablePointerLocation() {
-        if (mPointerLocationView == null) {
-            mPointerLocationView = new PointerLocationView(mContext);
-            mPointerLocationView.setPrintCoords(false);
-            WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
-                    WindowManager.LayoutParams.MATCH_PARENT,
-                    WindowManager.LayoutParams.MATCH_PARENT);
-            lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
-            lp.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN
-                    | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
-                    | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
-                    | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
-            lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-            if (ActivityManager.isHighEndGfx()) {
-                lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
-                lp.privateFlags |=
-                        WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
-            }
-            lp.format = PixelFormat.TRANSLUCENT;
-            lp.setTitle("PointerLocation");
-            WindowManager wm = (WindowManager) mContext.getSystemService(WINDOW_SERVICE);
-            lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
-            wm.addView(mPointerLocationView, lp);
-            //TODO (b/111365687) : make system context per display.
-            mWindowManagerFuncs.registerPointerEventListener(mPointerLocationView, DEFAULT_DISPLAY);
-        }
-    }
-
-    private void disablePointerLocation() {
-        if (mPointerLocationView != null) {
-            //TODO (b/111365687) : make system context per display.
-            mWindowManagerFuncs.unregisterPointerEventListener(mPointerLocationView,
-                    DEFAULT_DISPLAY);
-            WindowManager wm = (WindowManager) mContext.getSystemService(WINDOW_SERVICE);
-            wm.removeView(mPointerLocationView);
-            mPointerLocationView = null;
-        }
-    }
-
-
     /** {@inheritDoc} */
     @Override
     public int checkAddPermission(WindowManager.LayoutParams attrs, int[] outAppOp) {
@@ -5180,6 +5113,7 @@
             awakenDreams();
         }
 
+        // Start dock.
         Intent dock = createHomeDockIntent();
         if (dock != null) {
             try {
@@ -5192,21 +5126,9 @@
             }
         }
 
-        Intent intent;
-
-        if (fromHomeKey) {
-            intent = new Intent(mHomeIntent);
-            intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
-        } else {
-            intent = mHomeIntent;
-        }
-        final Bundle bundle = getLaunchDisplayIdBundle(displayId);
-        startActivityAsUser(intent, bundle, UserHandle.CURRENT);
-    }
-
-    private @Nullable Bundle getLaunchDisplayIdBundle(int displayId) {
-        return (displayId == INVALID_DISPLAY) ? null
-                : ActivityOptions.makeBasic().setLaunchDisplayId(displayId).toBundle();
+        // Start home.
+        mActivityTaskManagerInternal.startHomeOnDisplay(mCurrentUserId, "startDockOrHome",
+                displayId, fromHomeKey);
     }
 
     /**
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index d58707c..2af2342 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -443,7 +443,7 @@
          * Returns true if the window is current in multi-windowing mode. i.e. it shares the
          * screen with other application windows.
          */
-        public boolean isInMultiWindowMode();
+        boolean inMultiWindowMode();
 
         public int getRotationAnimationHint();
 
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index bb23bc0..9b427f5 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -4474,7 +4474,7 @@
         }
 
         @Override // Binder call
-        public boolean setPowerSaveMode(boolean enabled) {
+        public boolean setPowerSaveModeEnabled(boolean enabled) {
             if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.POWER_SAVER)
                     != PackageManager.PERMISSION_GRANTED) {
                 mContext.enforceCallingOrSelfPermission(
diff --git a/services/core/java/com/android/server/power/PowerManagerShellCommand.java b/services/core/java/com/android/server/power/PowerManagerShellCommand.java
index 18b8f0e..edaa6d9 100644
--- a/services/core/java/com/android/server/power/PowerManagerShellCommand.java
+++ b/services/core/java/com/android/server/power/PowerManagerShellCommand.java
@@ -68,7 +68,7 @@
             pw.println("Error: " + ex.toString());
             return -1;
         }
-        mInterface.setPowerSaveMode(mode == LOW_POWER_MODE_ON);
+        mInterface.setPowerSaveModeEnabled(mode == LOW_POWER_MODE_ON);
         return 0;
     }
 
diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
index 5adcf35..f0e4625 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
@@ -115,9 +115,41 @@
     public static final int REASON_SETTING_CHANGED = 8;
     public static final int REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_ON = 9;
     public static final int REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_OFF = 10;
-    public static final int REASON_STICKY_RESTORE_OFF = 11;
-    public static final int REASON_ADAPTIVE_DYNAMIC_POWER_SAVINGS_CHANGED = 12;
-    public static final int REASON_TIMEOUT = 13;
+    public static final int REASON_ADAPTIVE_DYNAMIC_POWER_SAVINGS_CHANGED = 11;
+    public static final int REASON_TIMEOUT = 12;
+
+    static String reasonToString(int reason) {
+        switch (reason) {
+            case BatterySaverController.REASON_PERCENTAGE_AUTOMATIC_ON:
+                return "Percentage Auto ON";
+            case BatterySaverController.REASON_PERCENTAGE_AUTOMATIC_OFF:
+                return "Percentage Auto OFF";
+            case BatterySaverController.REASON_MANUAL_ON:
+                return "Manual ON";
+            case BatterySaverController.REASON_MANUAL_OFF:
+                return "Manual OFF";
+            case BatterySaverController.REASON_STICKY_RESTORE:
+                return "Sticky restore";
+            case BatterySaverController.REASON_INTERACTIVE_CHANGED:
+                return "Interactivity changed";
+            case BatterySaverController.REASON_POLICY_CHANGED:
+                return "Policy changed";
+            case BatterySaverController.REASON_PLUGGED_IN:
+                return "Plugged in";
+            case BatterySaverController.REASON_SETTING_CHANGED:
+                return "Setting changed";
+            case BatterySaverController.REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_ON:
+                return "Dynamic Warning Auto ON";
+            case BatterySaverController.REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_OFF:
+                return "Dynamic Warning Auto OFF";
+            case BatterySaverController.REASON_ADAPTIVE_DYNAMIC_POWER_SAVINGS_CHANGED:
+                return "Adaptive Power Savings changed";
+            case BatterySaverController.REASON_TIMEOUT:
+                return "timeout";
+            default:
+                return "Unknown reason: " + reason;
+        }
+    }
 
     /**
      * Plugin interface. All methods are guaranteed to be called on the same (handler) thread.
diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java
index af78995..8f2e997 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java
@@ -15,6 +15,8 @@
  */
 package com.android.server.power.batterysaver;
 
+import static com.android.server.power.batterysaver.BatterySaverController.reasonToString;
+
 import android.app.Notification;
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
@@ -49,6 +51,42 @@
  * Do not call out with the lock held. (Settings provider is okay.)
  *
  * Test: atest com.android.server.power.batterysaver.BatterySaverStateMachineTest
+ *
+ * Current state machine. This can be visualized using Graphviz:
+   <pre>
+
+   digraph {
+     STATE_OFF
+     STATE_MANUAL_ON [label="STATE_MANUAL_ON\nTurned on manually by the user"]
+     STATE_AUTOMATIC_ON [label="STATE_AUTOMATIC_ON\nTurned on automatically by the system"]
+     STATE_OFF_AUTOMATIC_SNOOZED [
+       label="STATE_OFF_AUTOMATIC_SNOOZED\nTurned off manually by the user."
+           + " The system should not turn it back on automatically."
+     ]
+     STATE_PENDING_STICKY_ON [
+       label="STATE_PENDING_STICKY_ON\n"
+           + " Turned on manually by the user and then plugged in. Will turn back on after unplug."
+     ]
+
+     STATE_OFF -> STATE_MANUAL_ON [label="manual"]
+     STATE_OFF -> STATE_AUTOMATIC_ON [label="Auto on AND charge <= auto threshold"]
+
+     STATE_MANUAL_ON -> STATE_OFF [label="manual\nOR\nPlugged & sticky disabled"]
+     STATE_MANUAL_ON -> STATE_PENDING_STICKY_ON [label="Plugged & sticky enabled"]
+
+     STATE_PENDING_STICKY_ON -> STATE_MANUAL_ON [label="Unplugged & sticky enabled"]
+     STATE_PENDING_STICKY_ON -> STATE_OFF [
+       label="Sticky disabled\nOR\nSticky auto off enabled AND charge >= sticky auto off threshold"
+     ]
+
+     STATE_AUTOMATIC_ON -> STATE_OFF [label="Plugged"]
+     STATE_AUTOMATIC_ON -> STATE_OFF_AUTOMATIC_SNOOZED [label="Manual"]
+
+     STATE_OFF_AUTOMATIC_SNOOZED -> STATE_OFF [label="Plug\nOR\nCharge > auto threshold"]
+     STATE_OFF_AUTOMATIC_SNOOZED -> STATE_MANUAL_ON [label="manual"]
+
+     </pre>
+   }
  */
 public class BatterySaverStateMachine {
     private static final String TAG = "BatterySaverStateMachine";
@@ -60,6 +98,25 @@
 
     private static final long ADAPTIVE_CHANGE_TIMEOUT_MS = 24 * 60 * 60 * 1000L;
 
+    /** Turn off adaptive battery saver if the device has charged above this level. */
+    private static final int ADAPTIVE_AUTO_DISABLE_BATTERY_LEVEL = 80;
+
+    private static final int STATE_OFF = BatterySaverStateMachineProto.STATE_OFF;
+
+    /** Turned on manually by the user. */
+    private static final int STATE_MANUAL_ON = BatterySaverStateMachineProto.STATE_MANUAL_ON;
+
+    /** Turned on automatically by the system. */
+    private static final int STATE_AUTOMATIC_ON = BatterySaverStateMachineProto.STATE_AUTOMATIC_ON;
+
+    /** Turned off manually by the user. The system should not turn it back on automatically. */
+    private static final int STATE_OFF_AUTOMATIC_SNOOZED =
+            BatterySaverStateMachineProto.STATE_OFF_AUTOMATIC_SNOOZED;
+
+    /** Turned on manually by the user and then plugged in. Will turn back on after unplug. */
+    private static final int STATE_PENDING_STICKY_ON =
+            BatterySaverStateMachineProto.STATE_PENDING_STICKY_ON;
+
     private final Context mContext;
     private final BatterySaverController mBatterySaverController;
 
@@ -75,6 +132,9 @@
     @GuardedBy("mLock")
     private boolean mBatteryStatusSet;
 
+    @GuardedBy("mLock")
+    private int mState;
+
     /** Whether the device is connected to any power source. */
     @GuardedBy("mLock")
     private boolean mIsPowered;
@@ -142,13 +202,6 @@
     private boolean mDynamicPowerSavingsBatterySaver;
 
     /**
-     * Whether BS has been manually disabled while the battery level is low, in which case we
-     * shouldn't auto re-enable it until the battery level is not low.
-     */
-    @GuardedBy("mLock")
-    private boolean mBatterySaverSnoozing;
-
-    /**
      * Last reason passed to {@link #enableBatterySaverLocked}.
      */
     @GuardedBy("mLock")
@@ -181,6 +234,7 @@
         mLock = lock;
         mContext = context;
         mBatterySaverController = batterySaverController;
+        mState = STATE_OFF;
 
         mBatterySaverStickyBehaviourDisabled = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_batterySaverStickyBehaviourDisabled);
@@ -188,8 +242,36 @@
                 com.android.internal.R.integer.config_dynamicPowerSavingsDefaultDisableThreshold);
     }
 
-    private boolean isAutoBatterySaverConfiguredLocked() {
-        return mSettingBatterySaverTriggerThreshold > 0;
+    /** @return true if the automatic percentage based mode should be used */
+    private boolean isAutomaticModeActiveLocked() {
+        return mSettingAutomaticBatterySaver == PowerManager.POWER_SAVER_MODE_PERCENTAGE
+                && mSettingBatterySaverTriggerThreshold > 0;
+    }
+
+    /**
+     * The returned value won't necessarily make sense if {@link #isAutomaticModeActiveLocked()}
+     * returns {@code false}.
+     *
+     * @return true if the battery level is below automatic's threshold.
+     */
+    private boolean isInAutomaticLowZoneLocked() {
+        return mIsBatteryLevelLow;
+    }
+
+    /** @return true if the dynamic mode should be used */
+    private boolean isDynamicModeActiveLocked() {
+        return mSettingAutomaticBatterySaver == PowerManager.POWER_SAVER_MODE_DYNAMIC
+                && mDynamicPowerSavingsBatterySaver;
+    }
+
+    /**
+     * The returned value won't necessarily make sense if {@link #isDynamicModeActiveLocked()}
+     * returns {@code false}.
+     *
+     * @return true if the battery level is below dynamic's threshold.
+     */
+    private boolean isInDynamicLowZoneLocked() {
+        return mBatteryLevel <= mDynamicPowerSavingsDisableThreshold;
     }
 
     /**
@@ -233,7 +315,14 @@
                     Settings.Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_LEVEL),
                     false, mSettingsObserver, UserHandle.USER_SYSTEM);
 
+
             synchronized (mLock) {
+                final boolean lowPowerModeEnabledSticky = getGlobalSetting(
+                        Settings.Global.LOW_POWER_MODE_STICKY, 0) != 0;
+
+                if (lowPowerModeEnabledSticky) {
+                    mState = STATE_PENDING_STICKY_ON;
+                }
 
                 mBootCompleted = true;
 
@@ -362,6 +451,8 @@
                     ? "Global.low_power changed to 1" : "Global.low_power changed to 0";
             enableBatterySaverLocked(/*enable=*/ batterySaverEnabled, /*manual=*/ true,
                     BatterySaverController.REASON_SETTING_CHANGED, reason);
+        } else {
+            doAutoBatterySaverLocked();
         }
     }
 
@@ -428,17 +519,6 @@
         }
     }
 
-    @GuardedBy("mLock")
-    private boolean isBatteryLowLocked() {
-        final boolean percentageLow =
-                mSettingAutomaticBatterySaver == PowerManager.POWER_SAVER_MODE_PERCENTAGE
-                && mIsBatteryLevelLow;
-        final boolean dynamicPowerSavingsLow =
-                mSettingAutomaticBatterySaver == PowerManager.POWER_SAVER_MODE_DYNAMIC
-                && mBatteryLevel <= mDynamicPowerSavingsDisableThreshold;
-        return percentageLow || dynamicPowerSavingsLow;
-    }
-
     /**
      * Decide whether to auto-start / stop battery saver.
      */
@@ -449,7 +529,6 @@
                     + " mSettingsLoaded=" + mSettingsLoaded
                     + " mBatteryStatusSet=" + mBatteryStatusSet
                     + " mIsBatteryLevelLow=" + mIsBatteryLevelLow
-                    + " mBatterySaverSnoozing=" + mBatterySaverSnoozing
                     + " mIsPowered=" + mIsPowered
                     + " mSettingAutomaticBatterySaver=" + mSettingAutomaticBatterySaver
                     + " mSettingBatterySaverEnabledSticky=" + mSettingBatterySaverEnabledSticky
@@ -460,71 +539,171 @@
             return; // Not fully initialized yet.
         }
 
-        if (!isBatteryLowLocked()) {
-            updateSnoozingLocked(false, "Battery not low");
-        }
+        updateStateLocked(false, false);
 
+        // Adaptive control.
         if (SystemClock.elapsedRealtime() - mLastAdaptiveBatterySaverChangedExternallyElapsed
                 > ADAPTIVE_CHANGE_TIMEOUT_MS) {
             mBatterySaverController.setAdaptivePolicyEnabledLocked(
                     false, BatterySaverController.REASON_TIMEOUT);
             mBatterySaverController.resetAdaptivePolicyLocked(
                     BatterySaverController.REASON_TIMEOUT);
+        } else if (mIsPowered && mBatteryLevel >= ADAPTIVE_AUTO_DISABLE_BATTERY_LEVEL) {
+            mBatterySaverController.setAdaptivePolicyEnabledLocked(false,
+                    BatterySaverController.REASON_PLUGGED_IN);
+        }
+    }
+
+    /**
+     * Update the state machine based on the current settings and battery/charge status.
+     *
+     * @param manual Whether the change was made by the user.
+     * @param enable Whether the user wants to turn battery saver on or off. Is only used if {@param
+     *               manual} is true.
+     */
+    @GuardedBy("mLock")
+    private void updateStateLocked(boolean manual, boolean enable) {
+        if (!manual && !(mBootCompleted && mSettingsLoaded && mBatteryStatusSet)) {
+            return; // Not fully initialized yet.
         }
 
-        if (mIsPowered) {
-            updateSnoozingLocked(false, "Plugged in");
-            enableBatterySaverLocked(/*enable=*/ false, /*manual=*/ false,
-                    BatterySaverController.REASON_PLUGGED_IN,
-                    "Plugged in");
-
-            if (mBatteryLevel >= 80 /* Arbitrary level */) {
-                mBatterySaverController.setAdaptivePolicyEnabledLocked(
-                        false, BatterySaverController.REASON_PLUGGED_IN);
+        switch (mState) {
+            case STATE_OFF: {
+                if (!mIsPowered) {
+                    if (manual) {
+                        if (!enable) {
+                            Slog.e(TAG, "Tried to disable BS when it's already OFF");
+                            return;
+                        }
+                        enableBatterySaverLocked(/*enable*/ true, /*manual*/ true,
+                                BatterySaverController.REASON_MANUAL_ON);
+                        mState = STATE_MANUAL_ON;
+                    } else if (isAutomaticModeActiveLocked() && isInAutomaticLowZoneLocked()) {
+                        enableBatterySaverLocked(/*enable*/ true, /*manual*/ false,
+                                BatterySaverController.REASON_PERCENTAGE_AUTOMATIC_ON);
+                        mState = STATE_AUTOMATIC_ON;
+                    } else if (isDynamicModeActiveLocked() && isInDynamicLowZoneLocked()) {
+                        enableBatterySaverLocked(/*enable*/ true, /*manual*/ false,
+                                BatterySaverController.REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_ON);
+                        mState = STATE_AUTOMATIC_ON;
+                    }
+                }
+                break;
             }
 
-        } else if (mSettingBatterySaverEnabledSticky && !mBatterySaverStickyBehaviourDisabled) {
-            if (mSettingBatterySaverStickyAutoDisableEnabled
-                    && mBatteryLevel >= mSettingBatterySaverStickyAutoDisableThreshold) {
-                setStickyActive(false);
-            } else {
-                // Re-enable BS.
-                enableBatterySaverLocked(/*enable=*/ true, /*manual=*/ true,
-                        BatterySaverController.REASON_STICKY_RESTORE,
-                        "Sticky restore");
+            case STATE_MANUAL_ON: {
+                if (manual) {
+                    if (enable) {
+                        Slog.e(TAG, "Tried to enable BS when it's already MANUAL_ON");
+                        return;
+                    }
+                    enableBatterySaverLocked(/*enable*/ false, /*manual*/ true,
+                            BatterySaverController.REASON_MANUAL_OFF);
+                    mState = STATE_OFF;
+                } else if (mIsPowered) {
+                    enableBatterySaverLocked(/*enable*/ false, /*manual*/ false,
+                            BatterySaverController.REASON_PLUGGED_IN);
+                    if (mSettingBatterySaverEnabledSticky
+                            && !mBatterySaverStickyBehaviourDisabled) {
+                        mState = STATE_PENDING_STICKY_ON;
+                    } else {
+                        mState = STATE_OFF;
+                    }
+                }
+                break;
             }
 
-        } else if (mSettingAutomaticBatterySaver
-                == PowerManager.POWER_SAVER_MODE_PERCENTAGE
-                && isAutoBatterySaverConfiguredLocked()) {
-            if (mIsBatteryLevelLow && !mBatterySaverSnoozing) {
-                enableBatterySaverLocked(/*enable=*/ true, /*manual=*/ false,
-                        BatterySaverController.REASON_PERCENTAGE_AUTOMATIC_ON,
-                        "Percentage Auto ON");
-            } else {
-                // Battery not low
-                enableBatterySaverLocked(/*enable=*/ false, /*manual=*/ false,
-                        BatterySaverController.REASON_PERCENTAGE_AUTOMATIC_OFF,
-                        "Percentage Auto OFF");
+            case STATE_AUTOMATIC_ON: {
+                if (mIsPowered) {
+                    enableBatterySaverLocked(/*enable*/ false, /*manual*/ false,
+                            BatterySaverController.REASON_PLUGGED_IN);
+                    mState = STATE_OFF;
+                } else if (manual) {
+                    if (enable) {
+                        Slog.e(TAG, "Tried to enable BS when it's already AUTO_ON");
+                        return;
+                    }
+                    enableBatterySaverLocked(/*enable*/ false, /*manual*/ true,
+                            BatterySaverController.REASON_MANUAL_OFF);
+                    // When battery saver is disabled manually (while battery saver is enabled)
+                    // when the battery level is low, we "snooze" BS -- i.e. disable auto battery
+                    // saver.
+                    // We resume auto-BS once the battery level is not low, or the device is
+                    // plugged in.
+                    mState = STATE_OFF_AUTOMATIC_SNOOZED;
+                } else if (isAutomaticModeActiveLocked() && !isInAutomaticLowZoneLocked()) {
+                    enableBatterySaverLocked(/*enable*/ false, /*manual*/ false,
+                            BatterySaverController.REASON_PERCENTAGE_AUTOMATIC_OFF);
+                    mState = STATE_OFF;
+                } else if (isDynamicModeActiveLocked() && !isInDynamicLowZoneLocked()) {
+                    enableBatterySaverLocked(/*enable*/ false, /*manual*/ false,
+                            BatterySaverController.REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_OFF);
+                    mState = STATE_OFF;
+                } else if (!isAutomaticModeActiveLocked() && !isDynamicModeActiveLocked()) {
+                    enableBatterySaverLocked(/*enable*/ false, /*manual*/ false,
+                            BatterySaverController.REASON_SETTING_CHANGED);
+                    mState = STATE_OFF;
+                }
+                break;
             }
-        } else if (mSettingAutomaticBatterySaver
-                == PowerManager.POWER_SAVER_MODE_DYNAMIC) {
-            if (mBatteryLevel >= mDynamicPowerSavingsDisableThreshold) {
-                enableBatterySaverLocked(/*enable=*/ false, /*manual=*/ false,
-                        BatterySaverController.REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_OFF,
-                        "Dynamic Warning Auto OFF");
-            } else if (mDynamicPowerSavingsBatterySaver && !mBatterySaverSnoozing) {
-                enableBatterySaverLocked(/*enable=*/ true, /*manual=*/ false,
-                        BatterySaverController.REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_ON,
-                        "Dynamic Warning Auto ON");
+
+            case STATE_OFF_AUTOMATIC_SNOOZED: {
+                if (manual) {
+                    if (!enable) {
+                        Slog.e(TAG, "Tried to disable BS when it's already AUTO_SNOOZED");
+                        return;
+                    }
+                    enableBatterySaverLocked(/*enable*/ true, /*manual*/ true,
+                            BatterySaverController.REASON_MANUAL_ON);
+                    mState = STATE_MANUAL_ON;
+                } else if (mIsPowered // Plugging in resets snooze.
+                        || (isAutomaticModeActiveLocked() && !isInAutomaticLowZoneLocked())
+                        || (isDynamicModeActiveLocked() && !isInDynamicLowZoneLocked())
+                        || (!isAutomaticModeActiveLocked() && !isDynamicModeActiveLocked())) {
+                    mState = STATE_OFF;
+                }
+                break;
             }
+
+            case STATE_PENDING_STICKY_ON: {
+                if (manual) {
+                    // This shouldn't be possible. We'll only be in this state when the device is
+                    // plugged in, so the user shouldn't be able to manually change state.
+                    Slog.e(TAG, "Tried to manually change BS state from PENDING_STICKY_ON");
+                    return;
+                }
+                final boolean shouldTurnOffSticky = mSettingBatterySaverStickyAutoDisableEnabled
+                        && mBatteryLevel >= mSettingBatterySaverStickyAutoDisableThreshold;
+                final boolean isStickyDisabled =
+                        mBatterySaverStickyBehaviourDisabled || !mSettingBatterySaverEnabledSticky;
+                if (isStickyDisabled || shouldTurnOffSticky) {
+                    setStickyActive(false);
+                    mState = STATE_OFF;
+                } else if (!mIsPowered) {
+                    // Re-enable BS.
+                    enableBatterySaverLocked(/*enable*/ true, /*manual*/ true,
+                            BatterySaverController.REASON_STICKY_RESTORE);
+                    mState = STATE_MANUAL_ON;
+                }
+                break;
+            }
+
+            default:
+                Slog.wtf(TAG, "Unknown state: " + mState);
+                break;
         }
-        // do nothing if automatic battery saver mode = PERCENTAGE and low warning threshold = 0%
+    }
+
+    @VisibleForTesting
+    int getState() {
+        synchronized (mLock) {
+            return mState;
+        }
     }
 
     /**
      * {@link com.android.server.power.PowerManagerService} calls it when
-     * {@link android.os.PowerManager#setPowerSaveMode} is called.
+     * {@link android.os.PowerManager#setPowerSaveModeEnabled} is called.
      *
      * Note this could? be called before {@link #onBootCompleted} too.
      */
@@ -533,13 +712,17 @@
             Slog.d(TAG, "setBatterySaverEnabledManually: enabled=" + enabled);
         }
         synchronized (mLock) {
-            enableBatterySaverLocked(/*enable=*/ enabled, /*manual=*/ true,
-                    (enabled ? BatterySaverController.REASON_MANUAL_ON
-                            : BatterySaverController.REASON_MANUAL_OFF),
-                    (enabled ? "Manual ON" : "Manual OFF"));
+            updateStateLocked(true, enabled);
+            // TODO: maybe turn off adaptive if it's on and advertiseIsEnabled is true and
+            //  enabled is false
         }
     }
 
+    @GuardedBy("mLock")
+    private void enableBatterySaverLocked(boolean enable, boolean manual, int intReason) {
+        enableBatterySaverLocked(enable, manual, intReason, reasonToString(intReason));
+    }
+
     /**
      * Actually enable / disable battery saver. Write the new state to the global settings
      * and propagate it to {@link #mBatterySaverController}.
@@ -566,20 +749,6 @@
         mLastChangedIntReason = intReason;
         mLastChangedStrReason = strReason;
 
-        if (manual) {
-            if (enable) {
-                updateSnoozingLocked(false, "Manual snooze OFF");
-            } else {
-                // When battery saver is disabled manually (while battery saver is enabled)
-                // when the battery level is low, we "snooze" BS -- i.e. disable auto battery saver.
-                // We resume auto-BS once the battery level is not low, or the device is plugged in.
-                if (mBatterySaverController.isFullEnabled() && isBatteryLowLocked()) {
-                    updateSnoozingLocked(true, "Manual snooze");
-                }
-                // TODO: maybe turn off adaptive if it's on and advertiseIsEnabled is true
-            }
-        }
-
         mSettingBatterySaverEnabled = enable;
         putGlobalSetting(Settings.Global.LOW_POWER_MODE, enable ? 1 : 0);
 
@@ -641,15 +810,6 @@
         manager.cancel(DYNAMIC_MODE_NOTIFICATION_ID);
     }
 
-    @GuardedBy("mLock")
-    private void updateSnoozingLocked(boolean snoozing, String reason) {
-        if (mBatterySaverSnoozing == snoozing) {
-            return;
-        }
-        if (DEBUG) Slog.d(TAG, "Snooze: " + (snoozing ? "start" : "stop")  + " reason=" + reason);
-        mBatterySaverSnoozing = snoozing;
-    }
-
     private void setStickyActive(boolean active) {
         mSettingBatterySaverEnabledSticky = active;
         putGlobalSetting(Settings.Global.LOW_POWER_MODE_STICKY,
@@ -684,6 +844,8 @@
                 pw.print(")");
             }
             pw.println();
+            pw.print("  mState=");
+            pw.println(mState);
 
             pw.print("  mLastChangedIntReason=");
             pw.println(mLastChangedIntReason);
@@ -697,9 +859,6 @@
             pw.print("  mBatteryStatusSet=");
             pw.println(mBatteryStatusSet);
 
-            pw.print("  mBatterySaverSnoozing=");
-            pw.println(mBatterySaverSnoozing);
-
             pw.print("  mIsPowered=");
             pw.println(mIsPowered);
             pw.print("  mBatteryLevel=");
@@ -731,6 +890,7 @@
 
             proto.write(BatterySaverStateMachineProto.ENABLED,
                     mBatterySaverController.isEnabled());
+            proto.write(BatterySaverStateMachineProto.STATE, mState);
             proto.write(BatterySaverStateMachineProto.IS_FULL_ENABLED,
                     mBatterySaverController.isFullEnabled());
             proto.write(BatterySaverStateMachineProto.IS_ADAPTIVE_ENABLED,
@@ -742,8 +902,6 @@
             proto.write(BatterySaverStateMachineProto.SETTINGS_LOADED, mSettingsLoaded);
             proto.write(BatterySaverStateMachineProto.BATTERY_STATUS_SET, mBatteryStatusSet);
 
-            proto.write(BatterySaverStateMachineProto.BATTERY_SAVER_SNOOZING,
-                    mBatterySaverSnoozing);
 
             proto.write(BatterySaverStateMachineProto.IS_POWERED, mIsPowered);
             proto.write(BatterySaverStateMachineProto.BATTERY_LEVEL, mBatteryLevel);
diff --git a/services/core/java/com/android/server/rollback/RollbackData.java b/services/core/java/com/android/server/rollback/RollbackData.java
index 8a95877..b37e268 100644
--- a/services/core/java/com/android/server/rollback/RollbackData.java
+++ b/services/core/java/com/android/server/rollback/RollbackData.java
@@ -23,9 +23,11 @@
 import java.io.File;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.text.ParseException;
 import java.time.Instant;
 import java.util.ArrayList;
 
+
 /**
  * Information about a rollback available for a set of atomically installed
  * packages.
@@ -138,4 +140,27 @@
     public boolean isStaged() {
         return info.isStaged();
     }
+
+    static String rollbackStateToString(@RollbackState int state) {
+        switch (state) {
+            case RollbackData.ROLLBACK_STATE_ENABLING: return "enabling";
+            case RollbackData.ROLLBACK_STATE_AVAILABLE: return "available";
+            case RollbackData.ROLLBACK_STATE_COMMITTED: return "committed";
+        }
+        throw new AssertionError("Invalid rollback state: " + state);
+    }
+
+    static @RollbackState int rollbackStateFromString(String state)
+            throws ParseException {
+        switch (state) {
+            case "enabling": return RollbackData.ROLLBACK_STATE_ENABLING;
+            case "available": return RollbackData.ROLLBACK_STATE_AVAILABLE;
+            case "committed": return RollbackData.ROLLBACK_STATE_COMMITTED;
+        }
+        throw new ParseException("Invalid rollback state: " + state, 0);
+    }
+
+    public String getStateAsString() {
+        return rollbackStateToString(state);
+    }
 }
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 952399b..83d18a6 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -50,11 +50,14 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.LocalServices;
 import com.android.server.pm.Installer;
 
 import java.io.File;
+import java.io.FileDescriptor;
 import java.io.IOException;
+import java.io.PrintWriter;
 import java.security.SecureRandom;
 import java.time.Instant;
 import java.time.temporal.ChronoUnit;
@@ -873,6 +876,11 @@
             return false;
         }
 
+        if (session.resolvedBaseCodePath == null) {
+            Log.e(TAG, "Session code path has not been resolved.");
+            return false;
+        }
+
         // Get information about the package to be installed.
         PackageParser.PackageLite newPackage = null;
         try {
@@ -1268,4 +1276,39 @@
                     + rollbackData.info.getRollbackId(), ioe);
         }
     }
+
+    @Override
+    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
+        synchronized (mLock) {
+            for (RollbackData data : mRollbacks) {
+                RollbackInfo info = data.info;
+                ipw.println(info.getRollbackId() + ":");
+                ipw.increaseIndent();
+                ipw.println("-state: " + data.getStateAsString());
+                ipw.println("-timestamp: " + data.timestamp);
+                if (data.stagedSessionId != -1) {
+                    ipw.println("-stagedSessionId: " + data.stagedSessionId);
+                }
+                ipw.println("-packages:");
+                ipw.increaseIndent();
+                for (PackageRollbackInfo pkg : info.getPackages()) {
+                    ipw.println(pkg.getPackageName()
+                            + " " + pkg.getVersionRolledBackFrom().getLongVersionCode()
+                            + " -> " + pkg.getVersionRolledBackTo().getLongVersionCode());
+                }
+                ipw.decreaseIndent();
+                if (data.state == RollbackData.ROLLBACK_STATE_COMMITTED) {
+                    ipw.println("-causePackages:");
+                    ipw.increaseIndent();
+                    for (VersionedPackage cPkg : info.getCausePackages()) {
+                        ipw.println(cPkg.getPackageName() + " " + cPkg.getLongVersionCode());
+                    }
+                    ipw.decreaseIndent();
+                    ipw.println("-committedSessionId: " + info.getCommittedSessionId());
+                }
+                ipw.decreaseIndent();
+            }
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java
index 4f8f685..2cfa465 100644
--- a/services/core/java/com/android/server/rollback/RollbackStore.java
+++ b/services/core/java/com/android/server/rollback/RollbackStore.java
@@ -16,6 +16,9 @@
 
 package com.android.server.rollback;
 
+import static com.android.server.rollback.RollbackData.rollbackStateFromString;
+import static com.android.server.rollback.RollbackData.rollbackStateToString;
+
 import android.annotation.NonNull;
 import android.content.pm.VersionedPackage;
 import android.content.rollback.PackageRollbackInfo;
@@ -401,23 +404,4 @@
             file.delete();
         }
     }
-
-    private static String rollbackStateToString(@RollbackData.RollbackState int state) {
-        switch (state) {
-            case RollbackData.ROLLBACK_STATE_ENABLING: return "enabling";
-            case RollbackData.ROLLBACK_STATE_AVAILABLE: return "available";
-            case RollbackData.ROLLBACK_STATE_COMMITTED: return "committed";
-        }
-        throw new AssertionError("Invalid rollback state: " + state);
-    }
-
-    private static @RollbackData.RollbackState int rollbackStateFromString(String state)
-            throws ParseException {
-        switch (state) {
-            case "enabling": return RollbackData.ROLLBACK_STATE_ENABLING;
-            case "available": return RollbackData.ROLLBACK_STATE_AVAILABLE;
-            case "committed": return RollbackData.ROLLBACK_STATE_COMMITTED;
-        }
-        throw new ParseException("Invalid rollback state: " + state, 0);
-    }
 }
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 4815e5c..2b17d19 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -24,6 +24,7 @@
 import static com.android.server.am.MemoryStatUtil.readCmdlineFromProcfs;
 import static com.android.server.am.MemoryStatUtil.readMemoryStatFromProcfs;
 import static com.android.server.am.MemoryStatUtil.readRssHighWaterMarkFromProcfs;
+import static com.android.server.am.MemoryStatUtil.readSystemIonHeapSizeFromDebugfs;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -1182,6 +1183,15 @@
         SystemProperties.set("sys.rss_hwm_reset.on", "1");
     }
 
+    private void pullSystemIonHeapSize(
+            int tagId, long elapsedNanos, long wallClockNanos,
+            List<StatsLogEventWrapper> pulledData) {
+        final long systemIonHeapSizeInBytes = readSystemIonHeapSizeFromDebugfs();
+        StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
+        e.writeLong(systemIonHeapSizeInBytes);
+        pulledData.add(e);
+    }
+
     private void pullBinderCallsStats(
             int tagId, long elapsedNanos, long wallClockNanos,
             List<StatsLogEventWrapper> pulledData) {
@@ -2068,6 +2078,10 @@
                 pullProcessMemoryHighWaterMark(tagId, elapsedNanos, wallClockNanos, ret);
                 break;
             }
+            case StatsLog.SYSTEM_ION_HEAP_SIZE: {
+                pullSystemIonHeapSize(tagId, elapsedNanos, wallClockNanos, ret);
+                break;
+            }
             case StatsLog.BINDER_CALLS: {
                 pullBinderCallsStats(tagId, elapsedNanos, wallClockNanos, ret);
                 break;
diff --git a/services/core/java/com/android/server/testharness/TestHarnessModeService.java b/services/core/java/com/android/server/testharness/TestHarnessModeService.java
index ec62ec7..9f9b797 100644
--- a/services/core/java/com/android/server/testharness/TestHarnessModeService.java
+++ b/services/core/java/com/android/server/testharness/TestHarnessModeService.java
@@ -18,6 +18,8 @@
 
 import android.annotation.Nullable;
 import android.app.KeyguardManager;
+import android.app.Notification;
+import android.app.NotificationManager;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -35,6 +37,8 @@
 import android.provider.Settings;
 import android.util.Slog;
 
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.internal.notification.SystemNotificationChannels;
 import com.android.server.LocalServices;
 import com.android.server.PersistentDataBlockManagerInternal;
 import com.android.server.SystemService;
@@ -87,6 +91,7 @@
             case PHASE_BOOT_COMPLETED:
                 disableAutoSync();
                 configureSettings();
+                showNotification();
                 break;
         }
         super.onBootPhase(phase);
@@ -99,19 +104,29 @@
             // There's no data to apply, so leave it as-is.
             return;
         }
+        PersistentData persistentData;
+        try {
+            persistentData = PersistentData.fromBytes(testHarnessModeData);
+        } catch (SetUpTestHarnessModeException e) {
+            Slog.e(TAG, "Failed to set up Test Harness Mode. Bad data.", e);
+            return;
+        } finally {
+            // Clear out the Test Harness Mode data. It's now in memory if successful or we should
+            // skip setting up.
+            getPersistentDataBlock().clearTestHarnessModeData();
+        }
         mShouldSetUpTestHarnessMode = true;
-        setUpAdb(testHarnessModeData);
+        setUpAdb(persistentData);
         setDeviceProvisioned();
     }
 
-    private void setUpAdb(byte[] testHarnessModeData) {
+    private void setUpAdb(PersistentData persistentData) {
         ContentResolver cr = getContext().getContentResolver();
+
         // Disable the TTL for ADB keys before enabling ADB
         Settings.Global.putLong(cr, Settings.Global.ADB_ALLOWED_CONNECTION_TIME, 0);
 
-        PersistentData persistentData = PersistentData.fromBytes(testHarnessModeData);
-
-        SystemProperties.set(TEST_HARNESS_MODE_PROPERTY, persistentData.mEnabled ? "1" : "0");
+        SystemProperties.set(TEST_HARNESS_MODE_PROPERTY, "1");
         writeAdbKeysFile(persistentData);
     }
 
@@ -145,9 +160,6 @@
 
         writeBytesToFile(persistentData.mAdbKeys, adbManager.getAdbKeysFile().toPath());
         writeBytesToFile(persistentData.mAdbTempKeys, adbManager.getAdbTempKeysFile().toPath());
-
-        // Clear out the data block so that we don't revert the ADB keys on every boot.
-        getPersistentDataBlock().clearTestHarnessModeData();
     }
 
     private void writeBytesToFile(byte[] keys, Path adbKeys) {
@@ -177,6 +189,36 @@
                 UserHandle.USER_CURRENT);
     }
 
+    private void showNotification() {
+        if (!SystemProperties.getBoolean(TEST_HARNESS_MODE_PROPERTY, false)) {
+            return;
+        }
+        String title = getContext()
+                .getString(com.android.internal.R.string.test_harness_mode_notification_title);
+        String message = getContext()
+                .getString(com.android.internal.R.string.test_harness_mode_notification_message);
+
+        Notification notification =
+                new Notification.Builder(getContext(), SystemNotificationChannels.DEVELOPER)
+                        .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
+                        .setWhen(0)
+                        .setOngoing(true)
+                        .setTicker(title)
+                        .setDefaults(0)  // please be quiet
+                        .setColor(getContext().getColor(
+                                com.android.internal.R.color
+                                        .system_notification_accent_color))
+                        .setContentTitle(title)
+                        .setContentText(message)
+                        .setVisibility(Notification.VISIBILITY_PUBLIC)
+                        .build();
+
+        NotificationManager notificationManager =
+                getContext().getSystemService(NotificationManager.class);
+        notificationManager.notifyAsUser(
+                null, SystemMessage.NOTE_TEST_HARNESS_MODE_ENABLED, notification, UserHandle.ALL);
+    }
+
     @Nullable
     private PersistentDataBlockManagerInternal getPersistentDataBlock() {
         if (mPersistentDataBlockManagerInternal == null) {
@@ -248,8 +290,7 @@
                 byte[] adbKeysBytes = getBytesFromFile(adbKeys);
                 byte[] adbTempKeysBytes = getBytesFromFile(adbTempKeys);
 
-                PersistentData persistentData =
-                        new PersistentData(true, adbKeysBytes, adbTempKeysBytes);
+                PersistentData persistentData = new PersistentData(adbKeysBytes, adbTempKeysBytes);
                 getPersistentDataBlock().setTestHarnessModeData(persistentData.toBytes());
             } catch (IOException e) {
                 Slog.e(TAG, "Failed to store ADB keys.", e);
@@ -316,37 +357,40 @@
      */
     public static class PersistentData {
         static final byte VERSION_1 = 1;
+        static final byte VERSION_2 = 2;
 
         final int mVersion;
-        final boolean mEnabled;
         final byte[] mAdbKeys;
         final byte[] mAdbTempKeys;
 
-        PersistentData(boolean enabled, byte[] adbKeys, byte[] adbTempKeys) {
-            this(VERSION_1, enabled, adbKeys, adbTempKeys);
+        PersistentData(byte[] adbKeys, byte[] adbTempKeys) {
+            this(VERSION_2, adbKeys, adbTempKeys);
         }
 
-        PersistentData(int version, boolean enabled, byte[] adbKeys, byte[] adbTempKeys) {
+        PersistentData(int version, byte[] adbKeys, byte[] adbTempKeys) {
             this.mVersion = version;
-            this.mEnabled = enabled;
             this.mAdbKeys = adbKeys;
             this.mAdbTempKeys = adbTempKeys;
         }
 
-        static PersistentData fromBytes(byte[] bytes) {
+        static PersistentData fromBytes(byte[] bytes) throws SetUpTestHarnessModeException {
             try {
                 DataInputStream is = new DataInputStream(new ByteArrayInputStream(bytes));
                 int version = is.readInt();
-                boolean enabled = is.readBoolean();
+                if (version == VERSION_1) {
+                    // Version 1 of Test Harness Mode contained an "enabled" bit that we need to
+                    // skip. If we don't, the binary format will be bad and it will fail to set up.
+                    is.readBoolean();
+                }
                 int adbKeysLength = is.readInt();
                 byte[] adbKeys = new byte[adbKeysLength];
                 is.readFully(adbKeys);
                 int adbTempKeysLength = is.readInt();
                 byte[] adbTempKeys = new byte[adbTempKeysLength];
                 is.readFully(adbTempKeys);
-                return new PersistentData(version, enabled, adbKeys, adbTempKeys);
+                return new PersistentData(version, adbKeys, adbTempKeys);
             } catch (IOException e) {
-                throw new RuntimeException(e);
+                throw new SetUpTestHarnessModeException(e);
             }
         }
 
@@ -354,8 +398,7 @@
             try {
                 ByteArrayOutputStream os = new ByteArrayOutputStream();
                 DataOutputStream dos = new DataOutputStream(os);
-                dos.writeInt(VERSION_1);
-                dos.writeBoolean(mEnabled);
+                dos.writeInt(VERSION_2);
                 dos.writeInt(mAdbKeys.length);
                 dos.write(mAdbKeys);
                 dos.writeInt(mAdbTempKeys.length);
@@ -367,4 +410,18 @@
             }
         }
     }
+
+    /**
+     * An exception thrown when Test Harness Mode fails to set up.
+     *
+     * <p>In the event that Test Harness Mode fails to set up, all of the data should be discarded
+     * and the Test Harness Mode portion of the persistent data block should be wiped. This will
+     * prevent the device from becoming stuck, as there is no way (without rooting the device) to
+     * clear the persistent data block.
+     */
+    private static class SetUpTestHarnessModeException extends Exception {
+        SetUpTestHarnessModeException(Exception e) {
+            super(e);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 9a5ec2a..d7c9bc7 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -2453,46 +2453,43 @@
                 mService.getTaskChangeNotificationController()
                         .notifyActivityLaunchOnSecondaryDisplayFailed(task.getTaskInfo(),
                                 preferredDisplayId);
-                return;
-            } else if (!forceNonResizable && handleForcedResizableTask(task,
-                    FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY)) {
-                return;
+            } else if (!forceNonResizable) {
+                handleForcedResizableTaskIfNeeded(task, FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY);
             }
+            // The information about not support secondary display should already be notified, we
+            // don't want to show another message on default display about split-screen. And it may
+            // be the case that a resizable activity is launched on a non-resizable task.
+            return;
         }
 
         if (!task.supportsSplitScreenWindowingMode() || forceNonResizable) {
-            // Display a warning toast that we tried to put an app that doesn't support split-screen
-            // in split-screen.
-            mService.getTaskChangeNotificationController().notifyActivityDismissingDockedStack();
-
             // Dismiss docked stack. If task appeared to be in docked stack but is not resizable -
             // we need to move it to top of fullscreen stack, otherwise it will be covered.
 
             final ActivityStack dockedStack =
                     task.getStack().getDisplay().getSplitScreenPrimaryStack();
             if (dockedStack != null) {
+                // Display a warning toast that we tried to put an app that doesn't support
+                // split-screen in split-screen.
+                mService.getTaskChangeNotificationController()
+                        .notifyActivityDismissingDockedStack();
                 moveTasksToFullscreenStackLocked(dockedStack, actualStack == dockedStack);
             }
             return;
         }
 
-        handleForcedResizableTask(task, FORCED_RESIZEABLE_REASON_SPLIT_SCREEN);
+        handleForcedResizableTaskIfNeeded(task, FORCED_RESIZEABLE_REASON_SPLIT_SCREEN);
     }
 
-    /**
-     * @return {@code true} if the top activity of the task is forced to be resizable and the user
-     *         was notified about activity being forced resized.
-     */
-    private boolean handleForcedResizableTask(TaskRecord task, int reason) {
+    /** Notifies that the top activity of the task is forced to be resizeable. */
+    private void handleForcedResizableTaskIfNeeded(TaskRecord task, int reason) {
         final ActivityRecord topActivity = task.getTopActivity();
-        if (topActivity != null && topActivity.isNonResizableOrForcedResizable()
-                && !topActivity.noDisplay) {
-            final String packageName = topActivity.appInfo.packageName;
-            mService.getTaskChangeNotificationController().notifyActivityForcedResizable(
-                    task.taskId, reason, packageName);
-            return true;
+        if (topActivity == null || topActivity.noDisplay
+                || !topActivity.isNonResizableOrForcedResizable()) {
+            return;
         }
-        return false;
+        mService.getTaskChangeNotificationController().notifyActivityForcedResizable(
+                task.taskId, reason, topActivity.appInfo.packageName);
     }
 
     void activityRelaunchedLocked(IBinder token) {
@@ -2736,6 +2733,9 @@
         if (activityOptions != null) {
             activityType = activityOptions.getLaunchActivityType();
             windowingMode = activityOptions.getLaunchWindowingMode();
+            if (activityOptions.freezeRecentTasksReordering()) {
+                mRecentTasks.setFreezeTaskListReordering();
+            }
         }
         if (activityType == ACTIVITY_TYPE_HOME || activityType == ACTIVITY_TYPE_RECENTS) {
             throw new IllegalArgumentException("startActivityFromRecents: Task "
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index 5a20959..b262a00 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -352,6 +352,19 @@
     /** @return The intent used to launch the home activity. */
     public abstract Intent getHomeIntent();
     public abstract boolean startHomeActivity(int userId, String reason);
+    /**
+     * This starts home activity on displays that can have system decorations based on displayId -
+     * Default display always use primary home component.
+     * For Secondary displays, the home activity must have category SECONDARY_HOME and then resolves
+     * according to the priorities listed below.
+     *  - If default home is not set, always use the secondary home defined in the config.
+     *  - Use currently selected primary home activity.
+     *  - Use the activity in the same package as currently selected primary home activity.
+     *    If there are multiple activities matched, use first one.
+     *  - Use the secondary home defined in the config.
+     */
+    public abstract boolean startHomeOnDisplay(int userId, String reason, int displayId,
+            boolean fromHomeKey);
     /** Start home activities on all displays that support system decorations. */
     public abstract boolean startHomeOnAllDisplays(int userId, String reason);
     /** @return true if the given process is the factory test process. */
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 794a4b8..118eb5b 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -748,6 +748,7 @@
             mWindowManager.setSupportsPictureInPicture(mSupportsPictureInPicture);
             mWindowManager.setSupportsFreeformWindowManagement(mSupportsFreeformWindowManagement);
             mWindowManager.setIsPc(isPc);
+            mWindowManager.mRoot.onSettingsRetrieved();
             // This happens before any activities are started, so we can change global configuration
             // in-place.
             updateConfigurationLocked(configuration, null, true);
@@ -6490,6 +6491,13 @@
         }
 
         @Override
+        public boolean startHomeOnDisplay(int userId, String reason, int displayId,
+                boolean fromHomeKey) {
+            return mRootActivityContainer.startHomeOnDisplay(userId, reason, displayId,
+                    fromHomeKey);
+        }
+
+        @Override
         public boolean startHomeOnAllDisplays(int userId, String reason) {
             synchronized (mGlobalLock) {
                 return mRootActivityContainer.startHomeOnAllDisplays(userId, reason);
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index bb5a221..af05a27 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -2237,6 +2237,10 @@
                 || transit == TRANSIT_ACTIVITY_RELAUNCH;
     }
 
+    static boolean isChangeTransit(int transit) {
+        return transit == TRANSIT_TASK_CHANGE_WINDOWING_MODE;
+    }
+
     /**
      * @return whether the transition should show the thumbnail being scaled down.
      */
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index 8f0a7c0..f6326957 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -513,8 +513,11 @@
         // Given no app transition pass it through instead of a wallpaper transition.
         // Never convert the crashing transition.
         // Never update the transition for the wallpaper if we are just docking from recents
+        // Never convert a change transition since the top activity isn't changing and will likely
+        // still be above an opening wallpaper.
         if (transit == TRANSIT_NONE || transit == TRANSIT_CRASHING_ACTIVITY_CLOSE
-                || transit == TRANSIT_DOCK_TASK_FROM_RECENTS) {
+                || transit == TRANSIT_DOCK_TASK_FROM_RECENTS
+                || AppTransition.isChangeTransit(transit)) {
             return transit;
         }
 
@@ -601,6 +604,10 @@
      */
     @VisibleForTesting
     int maybeUpdateTransitToTranslucentAnim(int transit) {
+        if (AppTransition.isChangeTransit(transit)) {
+            // There's no special animation to handle change animations with translucent apps
+            return transit;
+        }
         final boolean taskOrActivity = AppTransition.isTaskTransit(transit)
                 || AppTransition.isActivityTransit(transit);
         boolean allOpeningVisible = true;
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 220370c..ea3a7d5 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1747,7 +1747,7 @@
     }
 
     boolean isInChangeTransition() {
-        return mTransitChangeLeash != null || isChangeTransition(mTransit);
+        return mTransitChangeLeash != null || AppTransition.isChangeTransit(mTransit);
     }
 
     @VisibleForTesting
@@ -1979,7 +1979,14 @@
                 mLetterbox.attachInput(w);
             }
             getPosition(mTmpPoint);
-            mLetterbox.layout(getParent().getBounds(), w.getFrameLw(), mTmpPoint);
+            // Get the bounds of the "space-to-fill". We union the Task and the Stack bounds here
+            // to handle both split window (where task-bounds can be larger) and orientation
+            // letterbox (where the task is letterboxed within stack).
+            Rect spaceToFill = getTask().getBounds();
+            if (getStack() != null) {
+                spaceToFill.union(getStack().getBounds());
+            }
+            mLetterbox.layout(spaceToFill, w.getFrameLw(), mTmpPoint);
         } else if (mLetterbox != null) {
             mLetterbox.hide();
         }
@@ -2448,30 +2455,6 @@
         return boundsLayer;
     }
 
-    /** Get position and crop region of animation. */
-    @VisibleForTesting
-    void getAnimationBounds(Point outPosition, Rect outBounds) {
-        outPosition.set(0, 0);
-        outBounds.setEmpty();
-
-        final TaskStack stack = getStack();
-        final Task task = getTask();
-        if (task != null && task.inFreeformWindowingMode()) {
-            task.getRelativeDisplayedPosition(outPosition);
-        } else if (stack != null) {
-            stack.getRelativeDisplayedPosition(outPosition);
-        }
-
-        // Always use stack bounds in order to have the ability to animate outside the task region.
-        // It also needs to be consistent when {@link #mNeedsAnimationBoundsLayer} is set that crops
-        // according to the bounds.
-        if (stack != null) {
-            stack.getBounds(outBounds);
-        }
-        // We have the relative position so the local position can be removed from bounds.
-        outBounds.offsetTo(0, 0);
-    }
-
     @Override
     Rect getDisplayedBounds() {
         final Task task = getTask();
@@ -2484,10 +2467,6 @@
         return getBounds();
     }
 
-    private static boolean isChangeTransition(int transit) {
-        return transit == TRANSIT_TASK_CHANGE_WINDOWING_MODE;
-    }
-
     boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
             boolean isVoiceInteraction) {
 
@@ -2507,9 +2486,15 @@
         if (okToAnimate()) {
             final AnimationAdapter adapter;
             AnimationAdapter thumbnailAdapter = null;
-            getAnimationBounds(mTmpPoint, mTmpRect);
 
-            boolean isChanging = isChangeTransition(transit) && enter;
+            // Separate position and size for use in animators. Use task-bounds for now so
+            // that activity-level letterbox (maxAspectRatio) is included in the animation.
+            mTmpRect.set(getTask() != null ? getTask().getBounds() : getBounds());
+            mTmpPoint.set(mTmpRect.left, mTmpRect.top);
+            mTmpRect.offsetTo(0, 0);
+
+            final boolean isChanging = AppTransition.isChangeTransit(transit) && enter
+                    && getDisplayContent().mChangingApps.contains(this);
 
             // Delaying animation start isn't compatible with remote animations at all.
             if (getDisplayContent().mAppTransition.getRemoteAnimationController() != null
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index db59030..b00cafd 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -41,12 +41,14 @@
 import static android.view.WindowManager.DOCKED_BOTTOM;
 import static android.view.WindowManager.DOCKED_INVALID;
 import static android.view.WindowManager.DOCKED_TOP;
+import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
 import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
+import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE;
 import static android.view.WindowManager.LayoutParams.NEEDS_MENU_UNSET;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
@@ -182,6 +184,8 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.util.ToBooleanFunction;
 import com.android.internal.util.function.TriConsumer;
+import com.android.internal.util.function.pooled.PooledConsumer;
+import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.AnimationThread;
 import com.android.server.policy.WindowManagerPolicy;
 import com.android.server.wm.utils.DisplayRotationUtil;
@@ -887,6 +891,10 @@
         mTapDetector = new TaskTapPointerEventListener(mWmService, this);
         registerPointerEventListener(mTapDetector);
         registerPointerEventListener(mWmService.mMousePositionTracker);
+        if (mWmService.mAtmService.getRecentTasks() != null) {
+            registerPointerEventListener(
+                    mWmService.mAtmService.getRecentTasks().getInputListener());
+        }
 
         mDisplayPolicy = new DisplayPolicy(service, this);
         mDisplayRotation = new DisplayRotation(service, this);
@@ -2381,6 +2389,27 @@
     }
 
     /**
+     * Returns true if the input point is within an app window.
+     */
+    boolean pointWithinAppWindow(int x, int y) {
+        final int[] targetWindowType = {-1};
+        final Consumer fn = PooledLambda.obtainConsumer((w, nonArg) -> {
+            if (targetWindowType[0] != -1) {
+                return;
+            }
+
+            if (w.isOnScreen() && w.isVisibleLw() && w.getFrameLw().contains(x, y)) {
+                targetWindowType[0] = w.mAttrs.type;
+                return;
+            }
+        }, PooledLambda.__(WindowState.class), mTmpRect);
+        forAllWindows(fn, true /* traverseTopToBottom */);
+        ((PooledConsumer) fn).recycle();
+        return FIRST_APPLICATION_WINDOW <= targetWindowType[0]
+                        && targetWindowType[0] <= LAST_APPLICATION_WINDOW;
+    }
+
+    /**
      * Find the task whose outside touch area (for resizing) (x, y) falls within.
      * Returns null if the touch doesn't fall into a resizing area.
      */
@@ -3255,7 +3284,11 @@
     }
 
     private void updateImeParent() {
-        final SurfaceControl newParent = computeImeParent();
+        // Force attaching IME to the display when magnifying, or it would be magnified with
+        // target app together.
+        final boolean shouldAttachToDisplay = (mMagnificationSpec != null);
+        final SurfaceControl newParent =
+                shouldAttachToDisplay ? mWindowingLayer : computeImeParent();
         if (newParent != null) {
             mPendingTransaction.reparent(mImeWindowsContainers.mSurfaceControl, newParent);
             scheduleAnimation();
@@ -3271,8 +3304,11 @@
         // Attach it to app if the target is part of an app and such app is covering the entire
         // screen. If it's not covering the entire screen the IME might extend beyond the apps
         // bounds.
-        if (mInputMethodTarget != null && mInputMethodTarget.mAppToken != null &&
-                mInputMethodTarget.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
+        if (mInputMethodTarget != null && mInputMethodTarget.mAppToken != null
+                && mInputMethodTarget.getWindowingMode() == WINDOWING_MODE_FULLSCREEN
+                // An activity with override bounds should be letterboxed inside its parent bounds,
+                // so it doesn't fill the screen.
+                && mInputMethodTarget.mAppToken.matchParentBounds()) {
             return mInputMethodTarget.mAppToken.getSurfaceControl();
         }
 
@@ -4667,6 +4703,8 @@
         } else {
             mMagnificationSpec = null;
         }
+        // Re-parent IME's SurfaceControl when MagnificationSpec changed.
+        updateImeParent();
 
         applyMagnificationSpec(getPendingTransaction(), spec);
         getPendingTransaction().apply();
@@ -4885,12 +4923,11 @@
      * @see Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
      */
     boolean supportsSystemDecorations() {
-        return mWmService.mDisplayWindowSettings.shouldShowSystemDecorsLocked(this)
+        return (mWmService.mDisplayWindowSettings.shouldShowSystemDecorsLocked(this)
                 || (mDisplay.getFlags() & FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS) != 0
-                // TODO (b/111363427): Remove this and set the new FLAG_SHOULD_SHOW_LAUNCHER flag
-                // whenever vr 2d display id is set.
-                || mDisplayId == mWmService.mVr2dDisplayId
-                || mWmService.mForceDesktopModeOnExternalDisplays;
+                || mWmService.mForceDesktopModeOnExternalDisplays)
+                // VR virtual display will be used to run and render 2D app within a VR experience.
+                && mDisplayId != mWmService.mVr2dDisplayId;
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index e48361f..ba1dfbb 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -44,8 +44,8 @@
 import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
-import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
+import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR;
@@ -113,6 +113,7 @@
 import android.content.Intent;
 import android.content.res.Resources;
 import android.graphics.Insets;
+import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.hardware.input.InputManager;
 import android.hardware.power.V1_0.PowerHint;
@@ -149,6 +150,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ScreenShapeHelper;
 import com.android.internal.util.ScreenshotHelper;
+import com.android.internal.widget.PointerLocationView;
 import com.android.server.LocalServices;
 import com.android.server.UiThread;
 import com.android.server.policy.WindowManagerPolicy;
@@ -343,6 +345,8 @@
 
     private InputConsumer mInputConsumer = null;
 
+    private PointerLocationView mPointerLocationView;
+
     /**
      * The area covered by system windows which belong to another display. Forwarded insets is set
      * in case this is a virtual display, this is displayed on another display that has insets, and
@@ -357,6 +361,8 @@
     private static final int MSG_UPDATE_DREAMING_SLEEP_TOKEN = 1;
     private static final int MSG_REQUEST_TRANSIENT_BARS = 2;
     private static final int MSG_DISPOSE_INPUT_CONSUMER = 3;
+    private static final int MSG_ENABLE_POINTER_LOCATION = 4;
+    private static final int MSG_DISABLE_POINTER_LOCATION = 5;
 
     private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0;
     private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1;
@@ -383,6 +389,12 @@
                 case MSG_DISPOSE_INPUT_CONSUMER:
                     disposeInputConsumer((InputConsumer) msg.obj);
                     break;
+                case MSG_ENABLE_POINTER_LOCATION:
+                    enablePointerLocation();
+                    break;
+                case MSG_DISABLE_POINTER_LOCATION:
+                    disablePointerLocation();
+                    break;
             }
         }
     }
@@ -541,6 +553,9 @@
 
     void systemReady() {
         mSystemGestures.systemReady();
+        if (mService.mPointerLocationEnabled) {
+            setPointerLocationEnabled(true);
+        }
     }
 
     private int getDisplayId() {
@@ -747,7 +762,7 @@
             case TYPE_WALLPAPER:
                 // Dreams and wallpapers don't have an app window token and can thus not be
                 // letterboxed. Hence always let them extend under the cutout.
-                attrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+                attrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
                 break;
             case TYPE_STATUS_BAR:
 
@@ -2095,7 +2110,7 @@
 
         // Ensure that windows with a DEFAULT or NEVER display cutout mode are laid out in
         // the cutout safe zone.
-        if (cutoutMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS) {
+        if (cutoutMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES) {
             final Rect displayCutoutSafeExceptMaybeBars = sTmpDisplayCutoutSafeExceptMaybeBarsRect;
             displayCutoutSafeExceptMaybeBars.set(displayFrames.mDisplayCutoutSafe);
             if (layoutInScreen && layoutInsetDecor && !requestedFullscreen
@@ -2146,7 +2161,7 @@
         // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
         // Also, we don't allow windows in multi-window mode to extend out of the screen.
         if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && type != TYPE_SYSTEM_ERROR
-                && !win.isInMultiWindowMode()) {
+                && !win.inMultiWindowMode()) {
             df.left = df.top = -10000;
             df.right = df.bottom = 10000;
             if (type != TYPE_WALLPAPER) {
@@ -3414,4 +3429,57 @@
         pw.print(prefix); pw.println("Looper state:");
         mHandler.getLooper().dump(new PrintWriterPrinter(pw), prefix + "  ");
     }
+
+    private boolean supportsPointerLocation() {
+        return mDisplayContent.isDefaultDisplay || !mDisplayContent.isPrivate();
+    }
+
+    void setPointerLocationEnabled(boolean pointerLocationEnabled) {
+        if (!supportsPointerLocation()) {
+            return;
+        }
+
+        mHandler.sendEmptyMessage(pointerLocationEnabled
+                ? MSG_ENABLE_POINTER_LOCATION : MSG_DISABLE_POINTER_LOCATION);
+    }
+
+    private void enablePointerLocation() {
+        if (mPointerLocationView != null) {
+            return;
+        }
+
+        mPointerLocationView = new PointerLocationView(mContext);
+        mPointerLocationView.setPrintCoords(false);
+        final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+                WindowManager.LayoutParams.MATCH_PARENT,
+                WindowManager.LayoutParams.MATCH_PARENT);
+        lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
+        lp.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN
+                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+        lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
+        if (ActivityManager.isHighEndGfx()) {
+            lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+            lp.privateFlags |=
+                    WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
+        }
+        lp.format = PixelFormat.TRANSLUCENT;
+        lp.setTitle("PointerLocation - display " + getDisplayId());
+        lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
+        final WindowManager wm = mContext.getSystemService(WindowManager.class);
+        wm.addView(mPointerLocationView, lp);
+        mDisplayContent.registerPointerEventListener(mPointerLocationView);
+    }
+
+    private void disablePointerLocation() {
+        if (mPointerLocationView == null) {
+            return;
+        }
+
+        mDisplayContent.unregisterPointerEventListener(mPointerLocationView);
+        final WindowManager wm = mContext.getSystemService(WindowManager.class);
+        wm.removeView(mPointerLocationView);
+        mPointerLocationView = null;
+    }
 }
diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
index 4617890..db96847 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
@@ -352,6 +352,24 @@
         dc.mDisplayScalingDisabled = entry.mForcedScalingMode == FORCE_SCALING_MODE_DISABLED;
     }
 
+    /**
+     * Updates settings for the given display after system features are loaded into window manager
+     * service, e.g. if this device is PC and if this device supports freeform.
+     *
+     * @param dc the given display.
+     * @return {@code true} if any settings for this display has changed; {@code false} if nothing
+     * changed.
+     */
+    boolean updateSettingsForDisplay(DisplayContent dc) {
+        if (dc.getWindowingMode() != getWindowingModeLocked(dc)) {
+            // For the time being the only thing that may change is windowing mode, so just update
+            // that.
+            dc.setWindowingMode(getWindowingModeLocked(dc));
+            return true;
+        }
+        return false;
+    }
+
     private void readSettings() {
         FileInputStream stream;
         try {
diff --git a/services/core/java/com/android/server/wm/DragDropController.java b/services/core/java/com/android/server/wm/DragDropController.java
index a667d67..716e4ef 100644
--- a/services/core/java/com/android/server/wm/DragDropController.java
+++ b/services/core/java/com/android/server/wm/DragDropController.java
@@ -73,17 +73,6 @@
         return mDragState != null && !mDragState.isClosing();
     }
 
-    void showInputSurface(SurfaceControl.Transaction t, int displayId) {
-        mDragState.showInputSurface(t, displayId);
-    }
-
-    void hideInputSurface(SurfaceControl.Transaction t, int displayId) {
-        if (mDragState != null) {
-            // TODO: Are we guaranteed to get here?
-            mDragState.hideInputSurface(t, displayId);
-        }
-    }
-
     void registerCallback(IDragDropCallback callback) {
         Preconditions.checkNotNull(callback);
         mCallback.set(callback);
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 2b2231a..c438966 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -120,7 +120,7 @@
     // A surface used to catch input events for the drag-and-drop operation.
     SurfaceControl mInputSurface;
 
-    private final SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction();
+    private final SurfaceControl.Transaction mTransaction;
 
     private final Rect mTmpClipRect = new Rect();
 
@@ -140,31 +140,24 @@
         mFlags = flags;
         mLocalWin = localWin;
         mNotifiedWindows = new ArrayList<WindowState>();
-
+        mTransaction = service.mTransactionFactory.make();
     }
 
     boolean isClosing() {
         return mIsClosing;
     }
 
-    void hideInputSurface(SurfaceControl.Transaction t, int displayId) {
-        if (displayId != mDisplayContent.getDisplayId()) {
-            return;
-        }
-
+    private void hideInputSurface() {
         if (mInputSurface != null) {
-            t.hide(mInputSurface);
+            mTransaction.hide(mInputSurface).apply();
         }
     }
 
-    void showInputSurface(SurfaceControl.Transaction t, int displayId) {
-        if (displayId != mDisplayContent.getDisplayId()) {
-            return;
-        }
-
+    private void showInputSurface() {
         if (mInputSurface == null) {
-            mInputSurface = mService.makeSurfaceBuilder(mService.mRoot.getDisplayContent(displayId)
-                    .getSession()).setContainerLayer()
+            mInputSurface = mService.makeSurfaceBuilder(
+                    mService.mRoot.getDisplayContent(mDisplayContent.getDisplayId()).getSession())
+                    .setContainerLayer()
                     .setName("Drag and Drop Input Consumer").build();
         }
         final InputWindowHandle h = getInputWindowHandle();
@@ -174,14 +167,16 @@
             return;
         }
 
-        t.show(mInputSurface);
-        t.setInputWindowInfo(mInputSurface, h);
-        t.setLayer(mInputSurface, Integer.MAX_VALUE);
+        mTransaction.show(mInputSurface);
+        mTransaction.setInputWindowInfo(mInputSurface, h);
+        mTransaction.setLayer(mInputSurface, Integer.MAX_VALUE);
 
         mTmpClipRect.set(0, 0, mDisplaySize.x, mDisplaySize.y);
-        t.setWindowCrop(mInputSurface, mTmpClipRect);
-        t.transferTouchFocus(mTransferTouchFromToken, h.token);
+        mTransaction.setWindowCrop(mInputSurface, mTmpClipRect);
+        mTransaction.transferTouchFocus(mTransferTouchFromToken, h.token);
         mTransferTouchFromToken = null;
+
+        mTransaction.apply();
     }
 
     /**
@@ -199,9 +194,10 @@
             mDragDropController.sendHandlerMessage(
                     MSG_TEAR_DOWN_DRAG_AND_DROP_INPUT, mInputInterceptor);
             mInputInterceptor = null;
-            mDisplayContent.getInputMonitor().updateInputWindowsLw(true /*force*/);
         }
 
+        hideInputSurface();
+
         // Send drag end broadcast if drag start has been sent.
         if (mDragInProgress) {
             final int myPid = Process.myPid();
@@ -352,7 +348,7 @@
             Slog.e(TAG_WM, "Duplicate register of drag input channel");
         } else {
             mInputInterceptor = new InputInterceptor(display);
-            mDisplayContent.getInputMonitor().updateInputWindowsLw(true /*force*/);
+            showInputSurface();
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 2a9c2b0..5669451 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -25,7 +25,6 @@
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
@@ -129,15 +128,6 @@
 
                 // If there's a drag in flight, provide a pseudo-window to catch drag input
                 final boolean inDrag = mService.mDragDropController.dragDropActiveLocked();
-                if (inDrag) {
-                    if (DEBUG_DRAG) {
-                        Log.d(TAG_WM, "Inserting drag window");
-                    }
-                    mService.mDragDropController.showInputSurface(mInputTransaction, mDisplayId);
-                } else {
-                    mService.mDragDropController.hideInputSurface(mInputTransaction, mDisplayId);
-                }
-
                 final boolean inPositioning =
                         mService.mTaskPositioningController.isPositioningLocked();
                 if (inPositioning) {
diff --git a/services/core/java/com/android/server/wm/LaunchParamsPersister.java b/services/core/java/com/android/server/wm/LaunchParamsPersister.java
index 86dc66d..d364a37 100644
--- a/services/core/java/com/android/server/wm/LaunchParamsPersister.java
+++ b/services/core/java/com/android/server/wm/LaunchParamsPersister.java
@@ -306,10 +306,10 @@
 
     private class PackageListObserver implements PackageManagerInternal.PackageListObserver {
         @Override
-        public void onPackageAdded(String packageName) { }
+        public void onPackageAdded(String packageName, int uid) { }
 
         @Override
-        public void onPackageRemoved(String packageName) {
+        public void onPackageRemoved(String packageName, int uid) {
             removeRecordForPackage(packageName);
         }
     }
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index 0480d43..d69ae3d 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -60,6 +60,7 @@
 import android.os.Environment;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.text.TextUtils;
@@ -67,8 +68,11 @@
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
+import android.view.MotionEvent;
+import android.view.WindowManagerPolicyConstants.PointerEventListener;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.am.ActivityManagerService;
 
 import com.google.android.collect.Sets;
@@ -109,8 +113,11 @@
 
     private static final int DEFAULT_INITIAL_CAPACITY = 5;
 
-    // Whether or not to move all affiliated tasks to the front when one of the tasks is launched
-    private static final boolean MOVE_AFFILIATED_TASKS_TO_FRONT = false;
+    // The duration of time after freezing the recent tasks list where getRecentTasks() will return
+    // a stable ordering of the tasks. Upon the next call to getRecentTasks() beyond this duration,
+    // the task list will be unfrozen and committed (the current top task will be moved to the
+    // front of the list)
+    private static final long FREEZE_TASK_LIST_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(5);
 
     // Comparator to sort by taskId
     private static final Comparator<TaskRecord> TASK_ID_COMPARATOR =
@@ -174,12 +181,45 @@
     private int mMaxNumVisibleTasks;
     private long mActiveTasksSessionDurationMs;
 
+    // When set, the task list will not be reordered as tasks within the list are moved to the
+    // front. Newly created tasks, or tasks that are removed from the list will continue to change
+    // the list.  This does not affect affiliated tasks.
+    private boolean mFreezeTaskListReordering;
+    private long mFreezeTaskListReorderingTime;
+    private long mFreezeTaskListTimeoutMs = FREEZE_TASK_LIST_TIMEOUT_MS;
+
     // Mainly to avoid object recreation on multiple calls.
     private final ArrayList<TaskRecord> mTmpRecents = new ArrayList<>();
     private final HashMap<ComponentName, ActivityInfo> mTmpAvailActCache = new HashMap<>();
     private final HashMap<String, ApplicationInfo> mTmpAvailAppCache = new HashMap<>();
     private final SparseBooleanArray mTmpQuietProfileUserIds = new SparseBooleanArray();
 
+    // TODO(b/127498985): This is currently a rough heuristic for interaction inside an app
+    private final PointerEventListener mListener = new PointerEventListener() {
+        @Override
+        public void onPointerEvent(MotionEvent ev) {
+            if (!mFreezeTaskListReordering || ev.getAction() != MotionEvent.ACTION_DOWN) {
+                // Skip if we aren't freezing or starting a gesture
+                return;
+            }
+            int displayId = ev.getDisplayId();
+            int x = (int) ev.getX();
+            int y = (int) ev.getY();
+            mService.mH.post(PooledLambda.obtainRunnable((nonArg) -> {
+                synchronized (mService.mGlobalLock) {
+                    // Unfreeze the task list once we touch down in a task
+                    final RootActivityContainer rac = mService.mRootActivityContainer;
+                    final DisplayContent dc = rac.getActivityDisplay(displayId).mDisplayContent;
+                    if (dc.pointWithinAppWindow(x, y)) {
+                        final ActivityStack stack = mService.getTopDisplayFocusedStack();
+                        final TaskRecord topTask = stack != null ? stack.topTask() : null;
+                        resetFreezeTaskListReordering(topTask);
+                    }
+                }
+            }, null).recycleOnUse());
+        }
+    };
+
     @VisibleForTesting
     RecentTasks(ActivityTaskManagerService service, TaskPersister taskPersister) {
         mService = service;
@@ -214,6 +254,73 @@
         mGlobalMaxNumTasks = globalMaxNumTasks;
     }
 
+    @VisibleForTesting
+    void setFreezeTaskListTimeoutParams(long reorderingTime, long timeoutMs) {
+        mFreezeTaskListReorderingTime = reorderingTime;
+        mFreezeTaskListTimeoutMs = timeoutMs;
+    }
+
+    PointerEventListener getInputListener() {
+        return mListener;
+    }
+
+    /**
+     * Freezes the current recent task list order until either a user interaction with the current
+     * app, or a timeout occurs.
+     */
+    void setFreezeTaskListReordering() {
+        // Always update the reordering time when this is called to ensure that the timeout
+        // is reset
+        mFreezeTaskListReordering = true;
+        mFreezeTaskListReorderingTime = SystemClock.elapsedRealtime();
+    }
+
+    /**
+     * Commits the frozen recent task list order, moving the provided {@param topTask} to the
+     * front of the list.
+     */
+    void resetFreezeTaskListReordering(TaskRecord topTask) {
+        if (!mFreezeTaskListReordering) {
+            return;
+        }
+
+        // Once we end freezing the task list, reset the existing task order to the stable state
+        mFreezeTaskListReordering = false;
+
+        // If the top task is provided, then restore the top task to the front of the list
+        if (topTask != null) {
+            mTasks.remove(topTask);
+            mTasks.add(0, topTask);
+        }
+
+        // Resume trimming tasks
+        trimInactiveRecentTasks();
+    }
+
+    /**
+     * Resets the frozen recent task list order if the timeout has passed. This should be called
+     * before we need to iterate the task list in order (either for purposes of returning the list
+     * to SystemUI or if we need to trim tasks in order)
+     */
+    void resetFreezeTaskListReorderingOnTimeout() {
+        // Unfreeze the recent task list if the time heuristic has passed
+        if (mFreezeTaskListReorderingTime
+                > (SystemClock.elapsedRealtime() - mFreezeTaskListTimeoutMs)) {
+            return;
+        }
+
+        final ActivityStack focusedStack = mService.getTopDisplayFocusedStack();
+        final TaskRecord topTask = focusedStack != null
+                ? focusedStack.topTask()
+                : null;
+        resetFreezeTaskListReordering(topTask);
+    }
+
+    @VisibleForTesting
+    boolean isFreezeTaskListReorderingSet() {
+        return mFreezeTaskListReordering;
+    }
+
     /**
      * Loads the parameters from the system resources.
      */
@@ -351,7 +458,8 @@
         }
 
         Slog.i(TAG, "Loading recents for user " + userId + " into memory.");
-        mTasks.addAll(mTaskPersister.restoreTasksForUserLocked(userId, preaddedTasks));
+        List<TaskRecord> tasks = mTaskPersister.restoreTasksForUserLocked(userId, preaddedTasks);
+        mTasks.addAll(tasks);
         cleanupLocked(userId);
         mUsersWithRecentsLoaded.put(userId, true);
 
@@ -746,11 +854,10 @@
                 getDetailedTasks, userId, callingUid));
     }
 
-
     /**
      * @return the list of recent tasks for presentation.
      */
-    ArrayList<ActivityManager.RecentTaskInfo> getRecentTasksImpl(int maxNum, int flags,
+    private ArrayList<ActivityManager.RecentTaskInfo> getRecentTasksImpl(int maxNum, int flags,
             boolean getTasksAllowed, boolean getDetailedTasks, int userId, int callingUid) {
         final boolean withExcluded = (flags & RECENT_WITH_EXCLUDED) != 0;
 
@@ -763,6 +870,9 @@
         final Set<Integer> includedUsers = getProfileIds(userId);
         includedUsers.add(Integer.valueOf(userId));
 
+        // Check if the frozen task list has timed out
+        resetFreezeTaskListReorderingOnTimeout();
+
         final ArrayList<ActivityManager.RecentTaskInfo> res = new ArrayList<>();
         final int size = mTasks.size();
         int numVisibleTasks = 0;
@@ -946,24 +1056,20 @@
         if (task.inRecents) {
             int taskIndex = mTasks.indexOf(task);
             if (taskIndex >= 0) {
-                if (!isAffiliated || !MOVE_AFFILIATED_TASKS_TO_FRONT) {
-                    // Simple case: this is not an affiliated task, so we just move it to the front.
-                    mTasks.remove(taskIndex);
-                    mTasks.add(0, task);
-                    notifyTaskPersisterLocked(task, false);
-                    if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: moving to top " + task
-                            + " from " + taskIndex);
-                    return;
-                } else {
-                    // More complicated: need to keep all affiliated tasks together.
-                    if (moveAffiliatedTasksToFront(task, taskIndex)) {
-                        // All went well.
-                        return;
-                    }
+                if (!isAffiliated) {
+                    if (!mFreezeTaskListReordering) {
+                        // Simple case: this is not an affiliated task, so we just move it to the
+                        // front unless overridden by the provided activity options
+                        mTasks.remove(taskIndex);
+                        mTasks.add(0, task);
 
-                    // Uh oh...  something bad in the affiliation chain, try to rebuild
-                    // everything and then go through our general path of adding a new task.
-                    needAffiliationFix = true;
+                        if (DEBUG_RECENTS) {
+                            Slog.d(TAG_RECENTS, "addRecent: moving to top " + task
+                                    + " from " + taskIndex);
+                        }
+                    }
+                    notifyTaskPersisterLocked(task, false);
+                    return;
                 }
             } else {
                 Slog.wtf(TAG, "Task with inRecent not in recents: " + task);
@@ -1063,6 +1169,11 @@
      * Trims the recents task list to the global max number of recents.
      */
     private void trimInactiveRecentTasks() {
+        if (mFreezeTaskListReordering) {
+            // Defer trimming inactive recent tasks until we are unfrozen
+            return;
+        }
+
         int recentsCount = mTasks.size();
 
         // Remove from the end of the list until we reach the max number of recents
@@ -1086,7 +1197,7 @@
                     + " quiet=" + mTmpQuietProfileUserIds.get(userId));
         }
 
-        // Remove any inactive tasks, calculate the latest set of visible tasks
+        // Remove any inactive tasks, calculate the latest set of visible tasks.
         int numVisibleTasks = 0;
         for (int i = 0; i < mTasks.size();) {
             final TaskRecord task = mTasks.get(i);
@@ -1300,6 +1411,11 @@
      * list (if any).
      */
     private int findRemoveIndexForAddTask(TaskRecord task) {
+        if (mFreezeTaskListReordering) {
+            // Defer removing tasks due to the addition of new tasks until the task list is unfrozen
+            return -1;
+        }
+
         final int recentsCount = mTasks.size();
         final Intent intent = task.intent;
         final boolean document = intent != null && intent.isDocument();
@@ -1536,6 +1652,9 @@
         pw.println("ACTIVITY MANAGER RECENT TASKS (dumpsys activity recents)");
         pw.println("mRecentsUid=" + mRecentsUid);
         pw.println("mRecentsComponent=" + mRecentsComponent);
+        pw.println("mFreezeTaskListReordering=" + mFreezeTaskListReordering);
+        pw.println("mFreezeTaskListReorderingTime (time since)="
+                + (SystemClock.elapsedRealtime() - mFreezeTaskListReorderingTime) + "ms");
         if (mTasks.isEmpty()) {
             return;
         }
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index f964b57..24cf7f1 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -114,6 +114,7 @@
 import com.android.server.am.ActivityManagerService;
 import com.android.server.am.AppTimeTracker;
 import com.android.server.am.UserState;
+import com.android.server.policy.WindowManagerPolicy;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -345,6 +346,10 @@
         }
     }
 
+    boolean startHomeOnDisplay(int userId, String reason, int displayId) {
+        return startHomeOnDisplay(userId, reason, displayId, false /*fromHomeKey*/);
+    }
+
     /**
      * This starts home activity on displays that can have system decorations based on displayId -
      * Default display always use primary home component.
@@ -356,7 +361,12 @@
      *    If there are multiple activities matched, use first one.
      *  - Use the secondary home defined in the config.
      */
-    boolean startHomeOnDisplay(int userId, String reason, int displayId) {
+    boolean startHomeOnDisplay(int userId, String reason, int displayId, boolean fromHomeKey) {
+        // Fallback to top focused display if the displayId is invalid.
+        if (displayId == INVALID_DISPLAY) {
+            displayId = getTopDisplayFocusedStack().mDisplayId;
+        }
+
         Intent homeIntent;
         ActivityInfo aInfo;
         if (displayId == DEFAULT_DISPLAY) {
@@ -380,6 +390,10 @@
         // Updates the home component of the intent.
         homeIntent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
         homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK);
+        // Updates the extra information of the intent.
+        if (fromHomeKey) {
+            homeIntent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, true);
+        }
         // Update the reason for ANR debugging to verify if the user activity is the one that
         // actually launched.
         final String myReason = reason + ":" + userId + ":" + UserHandle.getUserId(
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 300cd17..8f4e842 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -193,8 +193,8 @@
     }
 
     DisplayContent getTopFocusedDisplayContent() {
-        return getDisplayContent(mTopFocusedDisplayId == INVALID_DISPLAY
-                ? DEFAULT_DISPLAY : mTopFocusedDisplayId);
+        final DisplayContent dc = getDisplayContent(mTopFocusedDisplayId);
+        return dc != null ? dc : getDisplayContent(DEFAULT_DISPLAY);
     }
 
     @Override
@@ -245,6 +245,34 @@
         return dc;
     }
 
+    /**
+     * Called when DisplayWindowSettings values may change.
+     */
+    void onSettingsRetrieved() {
+        final int numDisplays = mChildren.size();
+        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+            final DisplayContent displayContent = mChildren.get(displayNdx);
+            final boolean changed = mWmService.mDisplayWindowSettings.updateSettingsForDisplay(
+                    displayContent);
+            if (!changed) {
+                continue;
+            }
+
+            displayContent.initializeDisplayOverrideConfiguration();
+            mWmService.reconfigureDisplayLocked(displayContent);
+
+            // We need to update global configuration as well if config of default display has
+            // changed. Do it inline because ATMS#retrieveSettings() will soon update the
+            // configuration inline, which will overwrite the new windowing mode.
+            if (displayContent.isDefaultDisplay) {
+                final Configuration newConfig = mWmService.computeNewConfiguration(
+                        displayContent.getDisplayId());
+                mWmService.mAtmService.updateConfigurationLocked(newConfig, null /* starting */,
+                        false /* initLocale */);
+            }
+        }
+    }
+
     boolean isLayoutNeeded() {
         final int numDisplays = mChildren.size();
         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
@@ -1045,6 +1073,15 @@
         mWmService.scheduleAnimationLocked();
     }
 
+    @Override
+    protected void removeChild(DisplayContent dc) {
+        super.removeChild(dc);
+        if (mTopFocusedDisplayId == dc.getDisplayId()) {
+            mWmService.updateFocusedWindowLocked(
+                    UPDATE_FOCUS_NORMAL, true /* updateInputWindows */);
+        }
+    }
+
     /**
      * For all display at or below this call the callback.
      *
diff --git a/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java b/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java
index bdb76c2..bd4e542 100644
--- a/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java
+++ b/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java
@@ -83,7 +83,12 @@
     }
 
     public void systemReady() {
-        mGestureDetector = new GestureDetector(mContext, new FlingGestureDetector(), mHandler);
+        // GestureDetector records statistics about gesture classification events to inform gesture
+        // usage trends. SystemGesturesPointerEventListener creates a lot of noise in these
+        // statistics because it passes every touch event though a GestureDetector. By creating an
+        // anonymous subclass of GestureDetector, these statistics will be recorded with a unique
+        // source name that can be filtered.
+        mGestureDetector = new GestureDetector(mContext, new FlingGestureDetector(), mHandler) {};
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 499cbaf..bb7867c 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -433,29 +433,6 @@
         }
     }
 
-    /** Return true if the current bound can get outputted to the rest of the system as-is. */
-    private boolean useCurrentBounds() {
-        final DisplayContent displayContent = getDisplayContent();
-        return matchParentBounds()
-                || !inSplitScreenSecondaryWindowingMode()
-                || displayContent == null
-                || displayContent.getSplitScreenPrimaryStackIgnoringVisibility() != null;
-    }
-
-    @Override
-    public void getBounds(Rect out) {
-        if (useCurrentBounds()) {
-            // No need to adjust the output bounds if fullscreen or the docked stack is visible
-            // since it is already what we want to represent to the rest of the system.
-            super.getBounds(out);
-            return;
-        }
-
-        // The bounds has been adjusted to accommodate for a docked stack, but the docked stack is
-        // not currently visible. Go ahead a represent it as fullscreen to the rest of the system.
-        mStack.getDisplayContent().getBounds(out);
-    }
-
     @Override
     public Rect getDisplayedBounds() {
         if (mOverrideDisplayedBounds.isEmpty()) {
@@ -506,36 +483,28 @@
         // a DimLayer anyway if we weren't visible.
         final boolean dockedResizing = displayContent != null
                 && displayContent.mDividerControllerLocked.isResizing();
-        if (useCurrentBounds()) {
-            if (inFreeformWindowingMode() && getMaxVisibleBounds(out)) {
-                return;
-            }
-
-            if (!matchParentBounds()) {
-                // When minimizing the docked stack when going home, we don't adjust the task bounds
-                // so we need to intersect the task bounds with the stack bounds here.
-                //
-                // If we are Docked Resizing with snap points, the task bounds could be smaller than the stack
-                // bounds and so we don't even want to use them. Even if the app should not be resized the Dim
-                // should keep up with the divider.
-                if (dockedResizing) {
-                    mStack.getBounds(out);
-                } else {
-                    mStack.getBounds(mTmpRect);
-                    mTmpRect.intersect(getBounds());
-                    out.set(mTmpRect);
-                }
-            } else {
-                out.set(getBounds());
-            }
+        if (inFreeformWindowingMode() && getMaxVisibleBounds(out)) {
             return;
         }
 
-        // The bounds has been adjusted to accommodate for a docked stack, but the docked stack is
-        // not currently visible. Go ahead a represent it as fullscreen to the rest of the system.
-        if (displayContent != null) {
-            displayContent.getBounds(out);
+        if (!matchParentBounds()) {
+            // When minimizing the docked stack when going home, we don't adjust the task bounds
+            // so we need to intersect the task bounds with the stack bounds here.
+            //
+            // If we are Docked Resizing with snap points, the task bounds could be smaller than the
+            // stack bounds and so we don't even want to use them. Even if the app should not be
+            // resized the Dim should keep up with the divider.
+            if (dockedResizing) {
+                mStack.getBounds(out);
+            } else {
+                mStack.getBounds(mTmpRect);
+                mTmpRect.intersect(getBounds());
+                out.set(mTmpRect);
+            }
+        } else {
+            out.set(getBounds());
         }
+        return;
     }
 
     void setDragResizing(boolean dragResizing, int dragResizeMode) {
@@ -702,16 +671,6 @@
         positionChildAt(position, aToken, false /* includeParents */);
     }
 
-    boolean isFullscreen() {
-        if (useCurrentBounds()) {
-            return matchParentBounds();
-        }
-        // The bounds has been adjusted to accommodate for a docked stack, but the docked stack
-        // is not currently visible. Go ahead a represent it as fullscreen to the rest of the
-        // system.
-        return true;
-    }
-
     void forceWindowsScaleable(boolean force) {
         mWmService.openSurfaceTransaction();
         try {
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 241f14e..e6b8112 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -303,17 +303,6 @@
         return super.getBounds();
     }
 
-    /** Return true if the current bound can get outputted to the rest of the system as-is. */
-    private boolean useCurrentBounds() {
-        if (matchParentBounds()
-                || !inSplitScreenSecondaryWindowingMode()
-                || mDisplayContent == null
-                || mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility() != null) {
-            return true;
-        }
-        return false;
-    }
-
     @Override
     public void getBounds(Rect bounds) {
         bounds.set(getBounds());
@@ -321,22 +310,15 @@
 
     @Override
     public Rect getBounds() {
-        if (useCurrentBounds()) {
-            // If we're currently adjusting for IME or minimized docked stack, we use the adjusted
-            // bounds; otherwise, no need to adjust the output bounds if fullscreen or the docked
-            // stack is visible since it is already what we want to represent to the rest of the
-            // system.
-            if (!mAdjustedBounds.isEmpty()) {
-                return mAdjustedBounds;
-            } else {
-                return super.getBounds();
-            }
-        }
-
-        // The bounds has been adjusted to accommodate for a docked stack, but the docked stack
-        // is not currently visible. Go ahead a represent it as fullscreen to the rest of the
+        // If we're currently adjusting for IME or minimized docked stack, we use the adjusted
+        // bounds; otherwise, no need to adjust the output bounds if fullscreen or the docked
+        // stack is visible since it is already what we want to represent to the rest of the
         // system.
-        return mDisplayContent.getBounds();
+        if (!mAdjustedBounds.isEmpty()) {
+            return mAdjustedBounds;
+        } else {
+            return super.getBounds();
+        }
     }
 
     /**
@@ -1425,13 +1407,7 @@
 
     @Override
     boolean fillsParent() {
-        if (useCurrentBounds()) {
-            return matchParentBounds();
-        }
-        // The bounds has been adjusted to accommodate for a docked stack, but the docked stack
-        // is not currently visible. Go ahead a represent it as fullscreen to the rest of the
-        // system.
-        return true;
+        return matchParentBounds();
     }
 
     @Override
@@ -1516,7 +1492,7 @@
 
         for (int i = mChildren.size() - 1; i >= 0; --i) {
             final Task task = mChildren.get(i);
-            if (task.isFullscreen()) {
+            if (task.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
                 results.searchDone = true;
                 return;
             }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index e3a8be5..a6c9257 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -689,6 +689,8 @@
                 Settings.Secure.getUriFor(Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS);
         private final Uri mPolicyControlUri =
                 Settings.Global.getUriFor(Settings.Global.POLICY_CONTROL);
+        private final Uri mPointerLocationUri =
+                Settings.System.getUriFor(Settings.System.POINTER_LOCATION);
 
         public SettingsObserver() {
             super(new Handler());
@@ -703,8 +705,8 @@
                     UserHandle.USER_ALL);
             resolver.registerContentObserver(mImmersiveModeConfirmationsUri, false, this,
                     UserHandle.USER_ALL);
-            resolver.registerContentObserver(mPolicyControlUri, false, this,
-                    UserHandle.USER_ALL);
+            resolver.registerContentObserver(mPolicyControlUri, false, this, UserHandle.USER_ALL);
+            resolver.registerContentObserver(mPointerLocationUri, false, this, UserHandle.USER_ALL);
         }
 
         @Override
@@ -723,6 +725,11 @@
                 return;
             }
 
+            if (mPointerLocationUri.equals(uri)) {
+                updatePointerLocation();
+                return;
+            }
+
             @UpdateAnimationScaleMode
             final int mode;
             if (mWindowAnimationScaleUri.equals(uri)) {
@@ -749,6 +756,22 @@
                 updateRotation(false /* alwaysSendConfiguration */, false /* forceRelayout */);
             }
         }
+
+        void updatePointerLocation() {
+            ContentResolver resolver = mContext.getContentResolver();
+            final boolean enablePointerLocation = Settings.System.getIntForUser(resolver,
+                    Settings.System.POINTER_LOCATION, 0, UserHandle.USER_CURRENT) != 0;
+
+            if (mPointerLocationEnabled == enablePointerLocation) {
+                return;
+            }
+            mPointerLocationEnabled = enablePointerLocation;
+            synchronized (mGlobalLock) {
+                mRoot.forAllDisplayPolicies(PooledLambda.obtainConsumer(
+                        DisplayPolicy::setPointerLocationEnabled, PooledLambda.__(),
+                        mPointerLocationEnabled));
+            }
+        }
     }
 
     PowerManager mPowerManager;
@@ -758,6 +781,7 @@
     private float mTransitionAnimationScaleSetting = 1.0f;
     private float mAnimatorDurationScaleSetting = 1.0f;
     private boolean mAnimationsDisabled = false;
+    boolean mPointerLocationEnabled = false;
 
     final InputManagerService mInputManager;
     final DisplayManagerInternal mDisplayManagerInternal;
@@ -4363,6 +4387,7 @@
         mHasWideColorGamutSupport = queryWideColorGamutSupport();
         mHasHdrSupport = queryHdrSupport();
         UiThread.getHandler().post(mSettingsObserver::updateSystemUiSettings);
+        UiThread.getHandler().post(mSettingsObserver::updatePointerLocation);
         IVrManager vrManager = IVrManager.Stub.asInterface(
                 ServiceManager.getService(Context.VR_SERVICE));
         if (vrManager != null) {
@@ -7447,13 +7472,26 @@
 
     @Override
     public boolean injectInputAfterTransactionsApplied(InputEvent ev, int mode) {
-        waitForAnimationsToComplete();
-
-        synchronized (mGlobalLock) {
-            mWindowPlacerLocked.performSurfacePlacementIfScheduled();
+        boolean shouldWaitForAnimComplete = false;
+        if (ev instanceof KeyEvent) {
+            KeyEvent keyEvent = (KeyEvent) ev;
+            shouldWaitForAnimComplete = keyEvent.getSource() == InputDevice.SOURCE_MOUSE
+                    || keyEvent.getAction() == KeyEvent.ACTION_DOWN;
+        } else if (ev instanceof MotionEvent) {
+            MotionEvent motionEvent = (MotionEvent) ev;
+            shouldWaitForAnimComplete = motionEvent.getSource() == InputDevice.SOURCE_MOUSE
+                    || motionEvent.getAction() == MotionEvent.ACTION_DOWN;
         }
 
-        new SurfaceControl.Transaction().syncInputWindows().apply(true);
+        if (shouldWaitForAnimComplete) {
+            waitForAnimationsToComplete();
+
+            synchronized (mGlobalLock) {
+                mWindowPlacerLocked.performSurfacePlacementIfScheduled();
+            }
+
+            new SurfaceControl.Transaction().syncInputWindows().apply(true);
+        }
 
         return LocalServices.getService(InputManagerInternal.class).injectInputEvent(ev, mode);
     }
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 20cca66..ee445d8 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -826,7 +826,7 @@
         mHaveFrame = true;
 
         final Task task = getTask();
-        final boolean inFullscreenContainer = inFullscreenContainer();
+        final boolean isFullscreenAndFillsDisplay = !inMultiWindowMode() && matchesDisplayBounds();
         final boolean windowsAreFloating = task != null && task.isFloating();
         final DisplayContent dc = getDisplayContent();
 
@@ -845,7 +845,7 @@
         final WindowState imeWin = mWmService.mRoot.getCurrentInputMethodWindow();
         final boolean isImeTarget =
                 imeWin != null && imeWin.isVisibleNow() && isInputMethodTarget();
-        if (inFullscreenContainer || layoutInParentFrame()) {
+        if (isFullscreenAndFillsDisplay || layoutInParentFrame()) {
             // We use the parent frame as the containing frame for fullscreen and child windows
             mWindowFrames.mContainingFrame.set(mWindowFrames.mParentFrame);
             layoutDisplayFrame = mWindowFrames.mDisplayFrame;
@@ -983,7 +983,7 @@
                     Math.min(mWindowFrames.mStableFrame.bottom, mWindowFrames.mFrame.bottom));
         }
 
-        if (inFullscreenContainer && !windowsAreFloating) {
+        if (isFullscreenAndFillsDisplay && !windowsAreFloating) {
             // Windows that are not fullscreen can be positioned outside of the display frame,
             // but that is not a reason to provide them with overscan insets.
             InsetUtils.insetsBetweenFrames(layoutContainingFrame, mWindowFrames.mOverscanFrame,
@@ -996,7 +996,8 @@
             mWindowFrames.calculateDockedDividerInsets(c.getDisplayCutout().getSafeInsets());
         } else {
             getDisplayContent().getBounds(mTmpRect);
-            mWindowFrames.calculateInsets(windowsAreFloating, inFullscreenContainer, mTmpRect);
+            mWindowFrames.calculateInsets(
+                    windowsAreFloating, isFullscreenAndFillsDisplay, mTmpRect);
         }
 
         mWindowFrames.setDisplayCutout(
@@ -1038,9 +1039,7 @@
     // TODO: Look into whether this override is still necessary.
     @Override
     public Rect getBounds() {
-        if (isInMultiWindowMode()) {
-            return getTask().getBounds();
-        } else if (mAppToken != null){
+        if (mAppToken != null) {
             return mAppToken.getBounds();
         } else {
             return super.getBounds();
@@ -1751,6 +1750,10 @@
                 && mWindowFrames.mFrame.bottom >= displayInfo.appHeight;
     }
 
+    private boolean matchesDisplayBounds() {
+        return getDisplayContent().getBounds().equals(getBounds());
+    }
+
     /** Returns true if last applied config was not yet requested by client. */
     boolean isConfigChanged() {
         return !getLastReportedConfiguration().equals(getConfiguration());
@@ -3114,20 +3117,16 @@
         return getDisplayContent().mCurrentFocus == this;
     }
 
-    @Override
-    public boolean isInMultiWindowMode() {
-        final Task task = getTask();
-        return task != null && !task.isFullscreen();
-    }
 
     /** Is this window in a container that takes up the entire screen space? */
-    private boolean inFullscreenContainer() {
-        return mAppToken == null || (mAppToken.matchParentBounds() && !isInMultiWindowMode());
+    private boolean inAppWindowThatMatchesParentBounds() {
+        return mAppToken == null || (mAppToken.matchParentBounds() && !inMultiWindowMode());
     }
 
-    /** @return true when the window is in fullscreen task, but has non-fullscreen bounds set. */
+    /** @return true when the window is in fullscreen mode, but has non-fullscreen bounds set, or
+     *          is transitioning into/out-of fullscreen. */
     boolean isLetterboxedAppWindow() {
-        return !isInMultiWindowMode() && mAppToken != null && !mAppToken.matchParentBounds()
+        return !inMultiWindowMode() && !matchesDisplayBounds()
                 || isLetterboxedForDisplayCutoutLw();
     }
 
@@ -3494,7 +3493,7 @@
         final int pw = containingFrame.width();
         final int ph = containingFrame.height();
         final Task task = getTask();
-        final boolean inNonFullscreenContainer = !inFullscreenContainer();
+        final boolean inNonFullscreenContainer = !inAppWindowThatMatchesParentBounds();
         final boolean noLimits = (mAttrs.flags & FLAG_LAYOUT_NO_LIMITS) != 0;
 
         // We need to fit it to the display if either
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 92bb082..780d471 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -26,7 +26,6 @@
 
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
@@ -792,16 +791,10 @@
         if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Applying decor to crop win=" + w + " mDecorFrame="
                 + w.getDecorFrame() + " mSystemDecorRect=" + mSystemDecorRect);
 
-        final Task task = w.getTask();
-        final boolean fullscreen = w.fillsDisplay() || (task != null && task.isFullscreen());
-        final boolean isFreeformResizing =
-                w.isDragResizing() && w.getResizeMode() == DRAG_RESIZE_MODE_FREEFORM;
-
         // We use the clip rect as provided by the tranformation for non-fullscreen windows to
         // avoid premature clipping with the system decor rect.
         clipRect.set(mSystemDecorRect);
-        if (DEBUG_WINDOW_CROP) Slog.d(TAG, "win=" + w + " Initial clip rect: " + clipRect
-                + " fullscreen=" + fullscreen);
+        if (DEBUG_WINDOW_CROP) Slog.d(TAG, "win=" + w + " Initial clip rect: " + clipRect);
 
         w.expandForSurfaceInsets(clipRect);
 
diff --git a/services/core/java/com/android/server/wm/WindowTraceBuffer.java b/services/core/java/com/android/server/wm/WindowTraceBuffer.java
index a4ee907..8c65884 100644
--- a/services/core/java/com/android/server/wm/WindowTraceBuffer.java
+++ b/services/core/java/com/android/server/wm/WindowTraceBuffer.java
@@ -93,8 +93,8 @@
     void writeTraceToFile(File traceFile) throws IOException {
         synchronized (mBufferLock) {
             traceFile.delete();
-            traceFile.setReadable(true, false);
             try (OutputStream os = new FileOutputStream(traceFile)) {
+                traceFile.setReadable(true /* readable */, false /* ownerOnly */);
                 ProtoOutputStream proto = new ProtoOutputStream();
                 proto.write(MAGIC_NUMBER, MAGIC_NUMBER_VALUE);
                 os.write(proto.getBytes());
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index bce3e98..caba3af 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -335,6 +335,8 @@
 const char *const JavaMethodHelper<double>::signature_ = "(D)V";
 template<>
 const char *const JavaMethodHelper<bool>::signature_ = "(Z)V";
+template<>
+const char *const JavaMethodHelper<jstring>::signature_ = "(Ljava/lang/String;)V";
 
 #define SET(setter, value) object.callSetter("set" # setter, (value))
 
@@ -1056,9 +1058,10 @@
         <IGnssMeasurementCallback_V2_0::GnssMeasurement>(
         const IGnssMeasurementCallback_V2_0::GnssMeasurement* measurement_V2_0,
         JavaObject& object) {
+    JNIEnv* env = getJniEnv();
     translateSingleGnssMeasurement(&(measurement_V2_0->v1_1), object);
 
-    SET(CodeType, static_cast<int32_t>(measurement_V2_0->codeType));
+    SET(CodeType, env->NewStringUTF(measurement_V2_0->codeType.c_str()));
 
     // Overwrite with v2_0.state since v2_0->v1_1->v1_0.state is deprecated.
     SET(State, static_cast<int32_t>(measurement_V2_0->state));
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 3999edd..f6de82d 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -5912,10 +5912,13 @@
         delegateReceiver = resolveDelegateReceiver(DELEGATION_CERT_SELECTION,
                 DeviceAdminReceiver.ACTION_CHOOSE_PRIVATE_KEY_ALIAS, caller.getIdentifier());
 
+        final boolean isDelegate;
         if (delegateReceiver != null) {
             intent.setComponent(delegateReceiver);
+            isDelegate = true;
         } else {
             intent.setComponent(aliasChooser);
+            isDelegate = false;
         }
 
         final long id = mInjector.binderClearCallingIdentity();
@@ -5927,11 +5930,10 @@
                     sendPrivateKeyAliasResponse(chosenAlias, response);
                 }
             }, null, Activity.RESULT_OK, null, null);
-            final String adminPackageName =
-                    (aliasChooser != null ? aliasChooser.getPackageName() : null);
             DevicePolicyEventLogger
                     .createEvent(DevicePolicyEnums.CHOOSE_PRIVATE_KEY_ALIAS)
-                    .setAdmin(adminPackageName)
+                    .setAdmin(intent.getComponent())
+                    .setBoolean(isDelegate)
                     .write();
         } finally {
             mInjector.binderRestoreCallingIdentity(id);
@@ -13091,6 +13093,14 @@
             saveSettingsLocked(mInjector.userHandleGetCallingUserId());
 
             setNetworkLoggingActiveInternal(enabled);
+
+            final boolean isDelegate = (admin == null);
+            DevicePolicyEventLogger
+                    .createEvent(DevicePolicyEnums.SET_NETWORK_LOGGING_ENABLED)
+                    .setAdmin(packageName)
+                    .setBoolean(isDelegate)
+                    .setInt(enabled ? 1 : 0)
+                    .write();
         }
     }
 
@@ -13222,6 +13232,12 @@
                     || !isNetworkLoggingEnabledInternalLocked()) {
                 return null;
             }
+            final boolean isDelegate = (admin == null);
+            DevicePolicyEventLogger
+                    .createEvent(DevicePolicyEnums.RETRIEVE_NETWORK_LOGS)
+                    .setAdmin(packageName)
+                    .setBoolean(isDelegate)
+                    .write();
 
             final long currentTime = System.currentTimeMillis();
             DevicePolicyData policyData = getUserData(UserHandle.USER_SYSTEM);
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 3de3152..3f323d9 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1247,6 +1247,14 @@
             mSystemServiceManager.startService(ClipboardService.class);
             traceEnd();
 
+            traceBeginAndSlog("InitNetworkStackClient");
+            try {
+                NetworkStackClient.getInstance().init();
+            } catch (Throwable e) {
+                reportWtf("initializing NetworkStackClient", e);
+            }
+            traceEnd();
+
             traceBeginAndSlog("StartNetworkManagementService");
             try {
                 networkManagement = NetworkManagementService.create(context);
diff --git a/services/net/java/android/net/NetworkStackClient.java b/services/net/java/android/net/NetworkStackClient.java
index a8f4a77..cc09fe3 100644
--- a/services/net/java/android/net/NetworkStackClient.java
+++ b/services/net/java/android/net/NetworkStackClient.java
@@ -120,8 +120,7 @@
      *
      * <p>The INetworkMonitor will be returned asynchronously through the provided callbacks.
      */
-    public void makeNetworkMonitor(
-            NetworkParcelable network, String name, INetworkMonitorCallbacks cb) {
+    public void makeNetworkMonitor(Network network, String name, INetworkMonitorCallbacks cb) {
         requestConnector(connector -> {
             try {
                 connector.makeNetworkMonitor(network, name, cb);
@@ -165,6 +164,15 @@
     }
 
     /**
+     * Initialize the network stack. Should be called only once on device startup, before any
+     * client attempts to use the network stack.
+     */
+    public void init() {
+        log("Network stack init");
+        mNetworkStackStartRequested = true;
+    }
+
+    /**
      * Start the network stack. Should be called only once on device startup.
      *
      * <p>This method will start the network stack either in the network stack process, or inside
@@ -174,8 +182,6 @@
      */
     public void start(Context context) {
         log("Starting network stack");
-        mNetworkStackStartRequested = true;
-
         final PackageManager pm = context.getPackageManager();
 
         // Try to bind in-process if the device was shipped with an in-process version
diff --git a/services/net/java/android/net/ip/IpClientUtil.java b/services/net/java/android/net/ip/IpClientUtil.java
index bf917bf..90624e0 100644
--- a/services/net/java/android/net/ip/IpClientUtil.java
+++ b/services/net/java/android/net/ip/IpClientUtil.java
@@ -17,12 +17,10 @@
 package android.net.ip;
 
 import static android.net.shared.IpConfigurationParcelableUtil.fromStableParcelable;
-import static android.net.shared.LinkPropertiesParcelableUtil.fromStableParcelable;
 
 import android.content.Context;
 import android.net.DhcpResultsParcelable;
 import android.net.LinkProperties;
-import android.net.LinkPropertiesParcelable;
 import android.net.NetworkStackClient;
 import android.os.ConditionVariable;
 
@@ -122,18 +120,18 @@
         }
 
         @Override
-        public void onProvisioningSuccess(LinkPropertiesParcelable newLp) {
-            mCb.onProvisioningSuccess(fromStableParcelable(newLp));
+        public void onProvisioningSuccess(LinkProperties newLp) {
+            mCb.onProvisioningSuccess(newLp);
         }
         @Override
-        public void onProvisioningFailure(LinkPropertiesParcelable newLp) {
-            mCb.onProvisioningFailure(fromStableParcelable(newLp));
+        public void onProvisioningFailure(LinkProperties newLp) {
+            mCb.onProvisioningFailure(newLp);
         }
 
         // Invoked on LinkProperties changes.
         @Override
-        public void onLinkPropertiesChange(LinkPropertiesParcelable newLp) {
-            mCb.onLinkPropertiesChange(fromStableParcelable(newLp));
+        public void onLinkPropertiesChange(LinkProperties newLp) {
+            mCb.onLinkPropertiesChange(newLp);
         }
 
         // Called when the internal IpReachabilityMonitor (if enabled) has
diff --git a/services/net/java/android/net/shared/InitialConfiguration.java b/services/net/java/android/net/shared/InitialConfiguration.java
index 4ad7138..e423d62 100644
--- a/services/net/java/android/net/shared/InitialConfiguration.java
+++ b/services/net/java/android/net/shared/InitialConfiguration.java
@@ -23,13 +23,12 @@
 import android.net.InetAddresses;
 import android.net.InitialConfigurationParcelable;
 import android.net.IpPrefix;
-import android.net.IpPrefixParcelable;
 import android.net.LinkAddress;
-import android.net.LinkAddressParcelable;
 import android.net.RouteInfo;
 
 import java.net.Inet4Address;
 import java.net.InetAddress;
+import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -148,10 +147,8 @@
      */
     public InitialConfigurationParcelable toStableParcelable() {
         final InitialConfigurationParcelable p = new InitialConfigurationParcelable();
-        p.ipAddresses = toParcelableArray(ipAddresses,
-                LinkPropertiesParcelableUtil::toStableParcelable, LinkAddressParcelable.class);
-        p.directlyConnectedRoutes = toParcelableArray(directlyConnectedRoutes,
-                LinkPropertiesParcelableUtil::toStableParcelable, IpPrefixParcelable.class);
+        p.ipAddresses = ipAddresses.toArray(new LinkAddress[0]);
+        p.directlyConnectedRoutes = directlyConnectedRoutes.toArray(new IpPrefix[0]);
         p.dnsServers = toParcelableArray(
                 dnsServers, IpConfigurationParcelableUtil::parcelAddress, String.class);
         return p;
@@ -164,10 +161,8 @@
     public static InitialConfiguration fromStableParcelable(InitialConfigurationParcelable p) {
         if (p == null) return null;
         final InitialConfiguration config = new InitialConfiguration();
-        config.ipAddresses.addAll(fromParcelableArray(
-                p.ipAddresses, LinkPropertiesParcelableUtil::fromStableParcelable));
-        config.directlyConnectedRoutes.addAll(fromParcelableArray(
-                p.directlyConnectedRoutes, LinkPropertiesParcelableUtil::fromStableParcelable));
+        config.ipAddresses.addAll(Arrays.asList(p.ipAddresses));
+        config.directlyConnectedRoutes.addAll(Arrays.asList(p.directlyConnectedRoutes));
         config.dnsServers.addAll(
                 fromParcelableArray(p.dnsServers, IpConfigurationParcelableUtil::unparcelAddress));
         return config;
diff --git a/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java b/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java
index 1f0525e..6b5826f 100644
--- a/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java
+++ b/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java
@@ -44,7 +44,7 @@
             @Nullable StaticIpConfiguration config) {
         if (config == null) return null;
         final StaticIpConfigurationParcelable p = new StaticIpConfigurationParcelable();
-        p.ipAddress = LinkPropertiesParcelableUtil.toStableParcelable(config.getIpAddress());
+        p.ipAddress = config.getIpAddress();
         p.gateway = parcelAddress(config.getGateway());
         p.dnsServers = toParcelableArray(
                 config.getDnsServers(), IpConfigurationParcelableUtil::parcelAddress, String.class);
@@ -59,7 +59,7 @@
             @Nullable StaticIpConfigurationParcelable p) {
         if (p == null) return null;
         final StaticIpConfiguration config = new StaticIpConfiguration();
-        config.setIpAddress(LinkPropertiesParcelableUtil.fromStableParcelable(p.ipAddress));
+        config.setIpAddress(p.ipAddress);
         config.setGateway(unparcelAddress(p.gateway));
         for (InetAddress addr : fromParcelableArray(
                 p.dnsServers, IpConfigurationParcelableUtil::unparcelAddress)) {
diff --git a/services/net/java/android/net/shared/LinkPropertiesParcelableUtil.java b/services/net/java/android/net/shared/LinkPropertiesParcelableUtil.java
index 51d955d..1729da6 100644
--- a/services/net/java/android/net/shared/LinkPropertiesParcelableUtil.java
+++ b/services/net/java/android/net/shared/LinkPropertiesParcelableUtil.java
@@ -16,25 +16,9 @@
 
 package android.net.shared;
 
-import static android.net.shared.IpConfigurationParcelableUtil.parcelAddress;
-import static android.net.shared.IpConfigurationParcelableUtil.unparcelAddress;
-import static android.net.shared.ParcelableUtil.fromParcelableArray;
-import static android.net.shared.ParcelableUtil.toParcelableArray;
-
 import android.annotation.Nullable;
-import android.net.IpPrefix;
-import android.net.IpPrefixParcelable;
-import android.net.LinkAddress;
-import android.net.LinkAddressParcelable;
 import android.net.LinkProperties;
-import android.net.LinkPropertiesParcelable;
 import android.net.ProxyInfo;
-import android.net.ProxyInfoParcelable;
-import android.net.RouteInfo;
-import android.net.RouteInfoParcelable;
-import android.net.Uri;
-
-import java.util.Arrays;
 
 /**
  * Collection of utility methods to convert to and from stable AIDL parcelables for LinkProperties
@@ -42,177 +26,22 @@
  * @hide
  */
 public final class LinkPropertiesParcelableUtil {
+    // Temporary methods to facilitate migrating clients away from LinkPropertiesParcelable
+    // TODO: remove the following methods after migrating clients.
 
     /**
-     * Convert a ProxyInfo to a ProxyInfoParcelable
+     * @deprecated conversion to stable parcelable is no longer necessary.
      */
-    public static ProxyInfoParcelable toStableParcelable(@Nullable ProxyInfo proxyInfo) {
-        if (proxyInfo == null) {
-            return null;
-        }
-        final ProxyInfoParcelable parcel = new ProxyInfoParcelable();
-        parcel.host = proxyInfo.getHost();
-        parcel.port = proxyInfo.getPort();
-        parcel.exclusionList = proxyInfo.getExclusionList();
-        parcel.pacFileUrl = proxyInfo.getPacFileUrl().toString();
-        return parcel;
-    }
-
-    /**
-     * Convert a ProxyInfoParcelable to a ProxyInfo
-     */
-    public static ProxyInfo fromStableParcelable(@Nullable ProxyInfoParcelable parcel) {
-        if (parcel == null) {
-            return null;
-        }
-        if (Uri.EMPTY.toString().equals(parcel.pacFileUrl)) {
-            return ProxyInfo.buildDirectProxy(
-                    parcel.host, parcel.port, Arrays.asList(parcel.exclusionList));
-        } else {
-            return ProxyInfo.buildPacProxy(Uri.parse(parcel.pacFileUrl));
-        }
-    }
-
-    /**
-     * Convert an IpPrefixParcelable to an IpPrefix
-     */
-    public static IpPrefixParcelable toStableParcelable(@Nullable IpPrefix ipPrefix) {
-        if (ipPrefix == null) {
-            return null;
-        }
-        final IpPrefixParcelable parcel = new IpPrefixParcelable();
-        parcel.address = parcelAddress(ipPrefix.getAddress());
-        parcel.prefixLength = ipPrefix.getPrefixLength();
-        return parcel;
-    }
-
-    /**
-     * Convert an IpPrefix to an IpPrefixParcelable
-     */
-    public static IpPrefix fromStableParcelable(@Nullable IpPrefixParcelable parcel) {
-        if (parcel == null) {
-            return null;
-        }
-        return new IpPrefix(unparcelAddress(parcel.address), parcel.prefixLength);
-    }
-
-    /**
-     * Convert a RouteInfoParcelable to a RouteInfo
-     */
-    public static RouteInfoParcelable toStableParcelable(@Nullable RouteInfo routeInfo) {
-        if (routeInfo == null) {
-            return null;
-        }
-        final RouteInfoParcelable parcel = new RouteInfoParcelable();
-        parcel.destination = toStableParcelable(routeInfo.getDestination());
-        parcel.gatewayAddr = parcelAddress(routeInfo.getGateway());
-        parcel.ifaceName = routeInfo.getInterface();
-        parcel.type = routeInfo.getType();
-        return parcel;
-    }
-
-    /**
-     * Convert a RouteInfo to a RouteInfoParcelable
-     */
-    public static RouteInfo fromStableParcelable(@Nullable RouteInfoParcelable parcel) {
-        if (parcel == null) {
-            return null;
-        }
-        final IpPrefix destination = fromStableParcelable(parcel.destination);
-        return new RouteInfo(
-                destination, unparcelAddress(parcel.gatewayAddr),
-                parcel.ifaceName, parcel.type);
-    }
-
-    /**
-     * Convert a LinkAddressParcelable to a LinkAddress
-     */
-    public static LinkAddressParcelable toStableParcelable(@Nullable LinkAddress la) {
-        if (la == null) {
-            return null;
-        }
-        final LinkAddressParcelable parcel = new LinkAddressParcelable();
-        parcel.address = parcelAddress(la.getAddress());
-        parcel.prefixLength = la.getPrefixLength();
-        parcel.flags = la.getFlags();
-        parcel.scope = la.getScope();
-        return parcel;
-    }
-
-    /**
-     * Convert a LinkAddress to a LinkAddressParcelable
-     */
-    public static LinkAddress fromStableParcelable(@Nullable LinkAddressParcelable parcel) {
-        if (parcel == null) {
-            return null;
-        }
-        return new LinkAddress(
-                unparcelAddress(parcel.address),
-                parcel.prefixLength,
-                parcel.flags,
-                parcel.scope);
-    }
-
-    /**
-     * Convert a LinkProperties to a LinkPropertiesParcelable
-     */
-    public static LinkPropertiesParcelable toStableParcelable(@Nullable LinkProperties lp) {
-        if (lp == null) {
-            return null;
-        }
-        final LinkPropertiesParcelable parcel = new LinkPropertiesParcelable();
-        parcel.ifaceName = lp.getInterfaceName();
-        parcel.linkAddresses = toParcelableArray(
-                lp.getLinkAddresses(),
-                LinkPropertiesParcelableUtil::toStableParcelable,
-                LinkAddressParcelable.class);
-        parcel.dnses = toParcelableArray(
-                lp.getDnsServers(), IpConfigurationParcelableUtil::parcelAddress, String.class);
-        parcel.pcscfs = toParcelableArray(
-                lp.getPcscfServers(), IpConfigurationParcelableUtil::parcelAddress, String.class);
-        parcel.validatedPrivateDnses = toParcelableArray(lp.getValidatedPrivateDnsServers(),
-                IpConfigurationParcelableUtil::parcelAddress, String.class);
-        parcel.usePrivateDns = lp.isPrivateDnsActive();
-        parcel.privateDnsServerName = lp.getPrivateDnsServerName();
-        parcel.domains = lp.getDomains();
-        parcel.routes = toParcelableArray(
-                lp.getRoutes(), LinkPropertiesParcelableUtil::toStableParcelable,
-                RouteInfoParcelable.class);
-        parcel.httpProxy = toStableParcelable(lp.getHttpProxy());
-        parcel.mtu = lp.getMtu();
-        parcel.tcpBufferSizes = lp.getTcpBufferSizes();
-        parcel.nat64Prefix = toStableParcelable(lp.getNat64Prefix());
-        return parcel;
-    }
-
-    /**
-     * Convert a LinkPropertiesParcelable to a LinkProperties
-     */
-    public static LinkProperties fromStableParcelable(@Nullable LinkPropertiesParcelable parcel) {
-        if (parcel == null) {
-            return null;
-        }
-        final LinkProperties lp = new LinkProperties();
-        lp.setInterfaceName(parcel.ifaceName);
-        lp.setLinkAddresses(fromParcelableArray(parcel.linkAddresses,
-                LinkPropertiesParcelableUtil::fromStableParcelable));
-        lp.setDnsServers(fromParcelableArray(
-                parcel.dnses, IpConfigurationParcelableUtil::unparcelAddress));
-        lp.setPcscfServers(fromParcelableArray(
-                parcel.pcscfs, IpConfigurationParcelableUtil::unparcelAddress));
-        lp.setValidatedPrivateDnsServers(
-                fromParcelableArray(parcel.validatedPrivateDnses,
-                IpConfigurationParcelableUtil::unparcelAddress));
-        lp.setUsePrivateDns(parcel.usePrivateDns);
-        lp.setPrivateDnsServerName(parcel.privateDnsServerName);
-        lp.setDomains(parcel.domains);
-        for (RouteInfoParcelable route : parcel.routes) {
-            lp.addRoute(fromStableParcelable(route));
-        }
-        lp.setHttpProxy(fromStableParcelable(parcel.httpProxy));
-        lp.setMtu(parcel.mtu);
-        lp.setTcpBufferSizes(parcel.tcpBufferSizes);
-        lp.setNat64Prefix(fromStableParcelable(parcel.nat64Prefix));
+    @Deprecated
+    public static LinkProperties toStableParcelable(@Nullable LinkProperties lp) {
         return lp;
     }
+
+    /**
+     * @deprecated conversion to stable parcelable is no longer necessary.
+     */
+    @Deprecated
+    public static ProxyInfo toStableParcelable(@Nullable ProxyInfo info) {
+        return info;
+    }
 }
diff --git a/services/net/java/android/net/shared/NetworkParcelableUtil.java b/services/net/java/android/net/shared/NetworkParcelableUtil.java
deleted file mode 100644
index d0b54b8..0000000
--- a/services/net/java/android/net/shared/NetworkParcelableUtil.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2019 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.net.shared;
-
-import android.annotation.Nullable;
-import android.net.Network;
-import android.net.NetworkParcelable;
-
-/**
- * Utility methods to convert to/from stable AIDL parcelables for network attribute classes.
- * @hide
- */
-public final class NetworkParcelableUtil {
-    /**
-     * Convert from a Network to a NetworkParcelable.
-     */
-    public static NetworkParcelable toStableParcelable(@Nullable Network network) {
-        if (network == null) {
-            return null;
-        }
-        final NetworkParcelable p = new NetworkParcelable();
-        p.networkHandle = network.getNetworkHandle();
-
-        return p;
-    }
-
-    /**
-     * Convert from a NetworkParcelable to a Network.
-     */
-    public static Network fromStableParcelable(@Nullable NetworkParcelable p) {
-        if (p == null) {
-            return null;
-        }
-        return Network.fromNetworkHandle(p.networkHandle);
-    }
-}
diff --git a/services/net/java/android/net/shared/ProvisioningConfiguration.java b/services/net/java/android/net/shared/ProvisioningConfiguration.java
index f937065..0aceb22 100644
--- a/services/net/java/android/net/shared/ProvisioningConfiguration.java
+++ b/services/net/java/android/net/shared/ProvisioningConfiguration.java
@@ -239,7 +239,7 @@
         p.apfCapabilities = IpConfigurationParcelableUtil.toStableParcelable(mApfCapabilities);
         p.provisioningTimeoutMs = mProvisioningTimeoutMs;
         p.ipv6AddrGenMode = mIPv6AddrGenMode;
-        p.network = NetworkParcelableUtil.toStableParcelable(mNetwork);
+        p.network = mNetwork;
         p.displayName = mDisplayName;
         return p;
     }
@@ -263,7 +263,7 @@
                 p.apfCapabilities);
         config.mProvisioningTimeoutMs = p.provisioningTimeoutMs;
         config.mIPv6AddrGenMode = p.ipv6AddrGenMode;
-        config.mNetwork = NetworkParcelableUtil.fromStableParcelable(p.network);
+        config.mNetwork = p.network;
         config.mDisplayName = p.displayName;
         return config;
     }
diff --git a/services/robotests/backup/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java b/services/robotests/backup/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java
index f17a9fe..f4cea7a 100644
--- a/services/robotests/backup/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java
@@ -326,15 +326,14 @@
     }
 
     @Test
-    public void testRestoreSome_for2Packages() throws Exception {
+    public void testRestorePackages_for2Packages() throws Exception {
         mShadowApplication.grantPermissions(android.Manifest.permission.BACKUP);
         TransportMock transportMock = setUpTransport(mTransport);
         IRestoreSession restoreSession =
                 createActiveRestoreSessionWithRestoreSets(null, mTransport, mRestoreSet1);
 
-        int result =
-                restoreSession.restoreSome(
-                        TOKEN_1, mObserver, mMonitor, new String[] {PACKAGE_1, PACKAGE_2});
+        int result = restoreSession.restorePackages(TOKEN_1, mObserver,
+                new String[] {PACKAGE_1, PACKAGE_2}, mMonitor);
 
         mShadowBackupLooper.runToEndOfTasks();
         assertThat(result).isEqualTo(0);
@@ -349,27 +348,27 @@
     }
 
     @Test
-    public void testRestoreSome_for2Packages_createsSystemRestoreTask() throws Exception {
+    public void testRestorePackages_for2Packages_createsSystemRestoreTask() throws Exception {
         mShadowApplication.grantPermissions(android.Manifest.permission.BACKUP);
         setUpTransport(mTransport);
         IRestoreSession restoreSession =
                 createActiveRestoreSessionWithRestoreSets(null, mTransport, mRestoreSet1);
 
-        restoreSession.restoreSome(
-                TOKEN_1, mObserver, mMonitor, new String[] {PACKAGE_1, PACKAGE_2});
+        restoreSession.restorePackages(TOKEN_1, mObserver, new String[] {PACKAGE_1, PACKAGE_2},
+                mMonitor);
 
         mShadowBackupLooper.runToEndOfTasks();
         assertThat(ShadowPerformUnifiedRestoreTask.getLastCreated().isFullSystemRestore()).isTrue();
     }
 
     @Test
-    public void testRestoreSome_for1Package() throws Exception {
+    public void testRestorePackages_for1Package() throws Exception {
         mShadowApplication.grantPermissions(android.Manifest.permission.BACKUP);
         setUpTransport(mTransport);
         IRestoreSession restoreSession =
                 createActiveRestoreSessionWithRestoreSets(null, mTransport, mRestoreSet1);
 
-        restoreSession.restoreSome(TOKEN_1, mObserver, mMonitor, new String[] {PACKAGE_1});
+        restoreSession.restorePackages(TOKEN_1, mObserver, new String[] {PACKAGE_1}, mMonitor);
 
         mShadowBackupLooper.runToEndOfTasks();
         ShadowPerformUnifiedRestoreTask shadowTask =
@@ -379,13 +378,13 @@
     }
 
     @Test
-    public void testRestoreSome_for1Package_createsNonSystemRestoreTask() throws Exception {
+    public void testRestorePackages_for1Package_createsNonSystemRestoreTask() throws Exception {
         mShadowApplication.grantPermissions(android.Manifest.permission.BACKUP);
         setUpTransport(mTransport);
         IRestoreSession restoreSession =
                 createActiveRestoreSessionWithRestoreSets(null, mTransport, mRestoreSet1);
 
-        restoreSession.restoreSome(TOKEN_1, mObserver, mMonitor, new String[] {PACKAGE_1});
+        restoreSession.restorePackages(TOKEN_1, mObserver, new String[] {PACKAGE_1}, mMonitor);
 
         mShadowBackupLooper.runToEndOfTasks();
         assertThat(ShadowPerformUnifiedRestoreTask.getLastCreated().isFullSystemRestore())
@@ -393,32 +392,32 @@
     }
 
     @Test
-    public void testRestoreSome_whenNoRestoreSets() throws Exception {
+    public void testRestorePackages_whenNoRestoreSets() throws Exception {
         mShadowApplication.grantPermissions(android.Manifest.permission.BACKUP);
         setUpTransport(mTransport);
         IRestoreSession restoreSession = createActiveRestoreSession(null, mTransport);
 
-        int result =
-                restoreSession.restoreSome(TOKEN_1, mObserver, mMonitor, new String[] {PACKAGE_1});
+        int result = restoreSession.restorePackages(TOKEN_1, mObserver, new String[] {PACKAGE_1},
+                mMonitor);
 
         assertThat(result).isEqualTo(-1);
     }
 
     @Test
-    public void testRestoreSome_whenSinglePackageSession() throws Exception {
+    public void testRestorePackages_whenSinglePackageSession() throws Exception {
         mShadowApplication.grantPermissions(android.Manifest.permission.BACKUP);
         setUpTransport(mTransport);
         IRestoreSession restoreSession =
                 createActiveRestoreSessionWithRestoreSets(PACKAGE_1, mTransport, mRestoreSet1);
 
-        int result =
-                restoreSession.restoreSome(TOKEN_1, mObserver, mMonitor, new String[] {PACKAGE_2});
+        int result = restoreSession.restorePackages(TOKEN_1, mObserver, new String[] {PACKAGE_2},
+                mMonitor);
 
         assertThat(result).isEqualTo(-1);
     }
 
     @Test
-    public void testRestoreSome_whenSessionEnded() throws Exception {
+    public void testRestorePackages_whenSessionEnded() throws Exception {
         mShadowApplication.grantPermissions(android.Manifest.permission.BACKUP);
         setUpTransport(mTransport);
         IRestoreSession restoreSession =
@@ -429,19 +428,19 @@
         expectThrows(
                 IllegalStateException.class,
                 () ->
-                        restoreSession.restoreSome(
-                                TOKEN_1, mObserver, mMonitor, new String[] {PACKAGE_1}));
+                        restoreSession.restorePackages(TOKEN_1, mObserver, new String[] {PACKAGE_1},
+                                mMonitor));
     }
 
     @Test
-    public void testRestoreSome_whenTransportNotRegistered() throws Exception {
+    public void testRestorePackages_whenTransportNotRegistered() throws Exception {
         mShadowApplication.grantPermissions(android.Manifest.permission.BACKUP);
         setUpTransport(mTransport.unregistered());
         IRestoreSession restoreSession =
                 createActiveRestoreSessionWithRestoreSets(null, mTransport, mRestoreSet1);
 
-        int result =
-                restoreSession.restoreSome(TOKEN_1, mObserver, mMonitor, new String[] {PACKAGE_1});
+        int result = restoreSession.restorePackages(TOKEN_1, mObserver, new String[] {PACKAGE_1},
+                mMonitor);
 
         assertThat(result).isEqualTo(-1);
     }
diff --git a/services/tests/mockingservicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java b/services/tests/mockingservicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java
index 86e8598..2e5efbd 100644
--- a/services/tests/mockingservicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java
@@ -28,6 +28,7 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.res.Resources;
+import android.os.PowerManager;
 import android.provider.Settings.Global;
 
 import androidx.test.filters.SmallTest;
@@ -452,6 +453,21 @@
         assertEquals(true, mDevice.batterySaverEnabled);
         assertEquals(30, mPersistedState.batteryLevel);
         assertEquals(true, mPersistedState.batteryLow);
+
+        // Disable auto battery saver.
+        mDevice.putGlobalSetting(Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
+        mDevice.setBatteryLevel(25);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(25, mPersistedState.batteryLevel);
+        assertEquals(false, mPersistedState.batteryLow);
+
+        // PowerManager sets batteryLow to true at 15% if battery saver trigger level is lower.
+        mDevice.setBatteryLevel(15);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(15, mPersistedState.batteryLevel);
+        assertEquals(true, mPersistedState.batteryLow);
     }
 
     @Test
@@ -542,6 +558,12 @@
         assertEquals(100, mPersistedState.batteryLevel);
         assertEquals(false, mPersistedState.batteryLow);
 
+        mDevice.setBatteryLevel(97);
+
+        assertEquals(true, mDevice.batterySaverEnabled); // Stays on.
+        assertEquals(97, mPersistedState.batteryLevel);
+        assertEquals(false, mPersistedState.batteryLow);
+
         mDevice.setBatteryLevel(95);
 
         assertEquals(true, mDevice.batterySaverEnabled); // Stays on.
@@ -719,6 +741,48 @@
     }
 
     @Test
+    public void testAutoBatterySaver_withSticky_withAutoOffToggled() {
+        mDevice.putGlobalSetting(Global.LOW_POWER_MODE_TRIGGER_LEVEL, 50);
+        mDevice.putGlobalSetting(Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_ENABLED, 1);
+        mDevice.putGlobalSetting(Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_LEVEL, 90);
+
+        // Scenario 1: User turns BS on manually above the threshold, it shouldn't turn off even
+        // with battery level change above threshold.
+        mDevice.setBatteryLevel(100);
+        mTarget.setBatterySaverEnabledManually(true);
+
+        assertEquals(true, mDevice.batterySaverEnabled);
+        assertEquals(100, mPersistedState.batteryLevel);
+        assertEquals(false, mPersistedState.batteryLow);
+
+        mDevice.setBatteryLevel(95);
+
+        assertEquals(true, mDevice.batterySaverEnabled); // Stays on.
+        assertEquals(95, mPersistedState.batteryLevel);
+        assertEquals(false, mPersistedState.batteryLow);
+
+        // Disable auto disable while in the pending sticky state. BS should reactivate after
+        // unplug.
+        mDevice.setPowered(true);
+        mDevice.putGlobalSetting(Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_ENABLED, 0);
+        mDevice.setPowered(false);
+
+        assertEquals(true, mDevice.batterySaverEnabled); // Sticky BS should activate.
+        assertEquals(95, mPersistedState.batteryLevel);
+        assertEquals(false, mPersistedState.batteryLow);
+
+        // Enable auto disable while in the pending sticky state. Sticky should turn off after
+        // unplug.
+        mDevice.setPowered(true);
+        mDevice.putGlobalSetting(Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_ENABLED, 1);
+        mDevice.setPowered(false);
+
+        assertEquals(false, mDevice.batterySaverEnabled); // Sticky BS no longer enabled.
+        assertEquals(95, mPersistedState.batteryLevel);
+        assertEquals(false, mPersistedState.batteryLow);
+    }
+
+    @Test
     public void testAutoBatterySaver_withStickyDisabled() {
         when(mMockResources.getBoolean(
                 com.android.internal.R.bool.config_batterySaverStickyBehaviourDisabled))
@@ -739,7 +803,9 @@
         assertEquals(30, mPersistedState.batteryLevel);
         assertEquals(true, mPersistedState.batteryLow);
 
+        mDevice.setPowered(true);
         mDevice.setBatteryLevel(80);
+        mDevice.setPowered(false);
 
         assertEquals(false, mDevice.batterySaverEnabled); // Not sticky.
         assertEquals(80, mPersistedState.batteryLevel);
@@ -830,10 +896,9 @@
         assertEquals(90, mPersistedState.batteryLevel);
         assertEquals(false, mPersistedState.batteryLow);
 
-        // Reboot -- setting BS from adb is also sticky.
+        // Reboot -- LOW_POWER_MODE shouldn't be persisted.
         initDevice();
-
-        assertEquals(true, mDevice.batterySaverEnabled);
+        assertEquals(false, mDevice.batterySaverEnabled);
         assertEquals(90, mPersistedState.batteryLevel);
         assertEquals(false, mPersistedState.batteryLow);
     }
@@ -841,7 +906,8 @@
     @Test
     public void testAutoBatterySaver_smartBatterySaverEnabled() {
         mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, 50);
-        mDevice.putGlobalSetting(Global.AUTOMATIC_POWER_SAVER_MODE, 1);
+        mDevice.putGlobalSetting(Global.AUTOMATIC_POWER_SAVER_MODE,
+                PowerManager.POWER_SAVER_MODE_DYNAMIC);
         mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_ENABLED, 0);
 
         assertEquals(false, mDevice.batterySaverEnabled);
@@ -922,8 +988,8 @@
         mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, 71);
         mDevice.setBatteryLevel(mPersistedState.batteryLevel);
 
-        // changes are only registered if some battery level changed
-        assertEquals(false, mDevice.batterySaverEnabled);
+        // Changes should register immediately.
+        assertEquals(true, mDevice.batterySaverEnabled);
         assertEquals(70, mPersistedState.batteryLevel);
 
         mDevice.setBatteryLevel(69);
@@ -935,8 +1001,8 @@
         mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, 60);
         mDevice.setBatteryLevel(mPersistedState.batteryLevel);
 
-        // changes are only registered if battery level changed
-        assertEquals(true, mDevice.batterySaverEnabled);
+        // Changes should register immediately.
+        assertEquals(false, mDevice.batterySaverEnabled);
         assertEquals(69, mPersistedState.batteryLevel);
 
         mDevice.setBatteryLevel(68);
@@ -956,4 +1022,220 @@
         assertEquals(true, mDevice.batterySaverEnabled);
         assertEquals(30, mPersistedState.batteryLevel);
     }
+
+    @Test
+    public void testAutoBatterySaver_snoozed_autoEnabled() {
+        mDevice.putGlobalSetting(Global.LOW_POWER_MODE_TRIGGER_LEVEL, 30);
+        // Test dynamic threshold higher than automatic to make sure it doesn't interfere when it's
+        // not enabled.
+        mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, 50);
+        mDevice.putGlobalSetting(Global.AUTOMATIC_POWER_SAVER_MODE,
+                PowerManager.POWER_SAVER_MODE_PERCENTAGE);
+        mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_ENABLED, 0);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(100, mPersistedState.batteryLevel);
+
+        mDevice.setBatteryLevel(90);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(90, mPersistedState.batteryLevel);
+
+        mDevice.setBatteryLevel(51);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(51, mPersistedState.batteryLevel);
+
+        // Hit dynamic threshold. BS should be disabled since dynamic is off
+        mDevice.setBatteryLevel(50);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(50, mPersistedState.batteryLevel);
+
+        mDevice.setBatteryLevel(30);
+
+        assertEquals(true, mDevice.batterySaverEnabled);
+        assertEquals(30, mPersistedState.batteryLevel);
+
+        mDevice.setPowered(true);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(30, mPersistedState.batteryLevel);
+
+        mDevice.setPowered(false);
+
+        assertEquals(true, mDevice.batterySaverEnabled);
+        assertEquals(30, mPersistedState.batteryLevel);
+
+        mTarget.setBatterySaverEnabledManually(false); // Manually disable -> snooze.
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(30, mPersistedState.batteryLevel);
+
+        mDevice.setBatteryLevel(20);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(20, mPersistedState.batteryLevel);
+
+        // Lower threshold. Level is still below, so should still be snoozed.
+        mDevice.putGlobalSetting(Global.LOW_POWER_MODE_TRIGGER_LEVEL, 25);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(20, mPersistedState.batteryLevel);
+
+        // Lower threshold even more. Battery no longer considered "low" so snoozing should be
+        // disabled.
+        mDevice.putGlobalSetting(Global.LOW_POWER_MODE_TRIGGER_LEVEL, 10);
+        // "batteryLow" is set in setBatteryLevel.
+        mDevice.setBatteryLevel(19);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(19, mPersistedState.batteryLevel);
+
+        mDevice.setBatteryLevel(10);
+
+        assertEquals(true, mDevice.batterySaverEnabled); // No longer snoozing.
+        assertEquals(10, mPersistedState.batteryLevel);
+
+        mTarget.setBatterySaverEnabledManually(false); // Manually disable -> snooze.
+
+        // Plug in and out, snooze will reset.
+        mDevice.setPowered(true);
+        mDevice.setPowered(false);
+
+        assertEquals(true, mDevice.batterySaverEnabled);
+        assertEquals(10, mPersistedState.batteryLevel);
+
+        mDevice.setPowered(true);
+        mDevice.setBatteryLevel(60);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(60, mPersistedState.batteryLevel);
+
+        // Test toggling resets snooze.
+        mDevice.putGlobalSetting(Global.LOW_POWER_MODE_TRIGGER_LEVEL, 50);
+        mDevice.setPowered(false);
+        mDevice.setBatteryLevel(45);
+
+        assertEquals(true, mDevice.batterySaverEnabled);
+        assertEquals(45, mPersistedState.batteryLevel);
+
+        mTarget.setBatterySaverEnabledManually(false); // Manually disable -> snooze.
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(45, mPersistedState.batteryLevel);
+
+        // Disable and re-enable.
+        mDevice.putGlobalSetting(Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
+        mDevice.putGlobalSetting(Global.LOW_POWER_MODE_TRIGGER_LEVEL, 50);
+
+        assertEquals(true, mDevice.batterySaverEnabled); // Snooze reset
+        assertEquals(45, mPersistedState.batteryLevel);
+    }
+
+    @Test
+    public void testAutoBatterySaver_snoozed_dynamicEnabled() {
+        // Test auto threshold higher than dynamic to make sure it doesn't interfere when it's
+        // not enabled.
+        mDevice.putGlobalSetting(Global.LOW_POWER_MODE_TRIGGER_LEVEL, 50);
+        mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, 30);
+        mDevice.putGlobalSetting(Global.AUTOMATIC_POWER_SAVER_MODE,
+                PowerManager.POWER_SAVER_MODE_DYNAMIC);
+        mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_ENABLED, 1);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(100, mPersistedState.batteryLevel);
+
+        mDevice.setBatteryLevel(90);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(90, mPersistedState.batteryLevel);
+
+        mDevice.setBatteryLevel(51);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(51, mPersistedState.batteryLevel);
+
+        // Hit automatic threshold. BS should be disabled since automatic is off
+        mDevice.setBatteryLevel(50);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(50, mPersistedState.batteryLevel);
+
+        mDevice.setBatteryLevel(30);
+
+        assertEquals(true, mDevice.batterySaverEnabled);
+        assertEquals(30, mPersistedState.batteryLevel);
+
+        mDevice.setPowered(true);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(30, mPersistedState.batteryLevel);
+
+        mDevice.setPowered(false);
+
+        assertEquals(true, mDevice.batterySaverEnabled);
+        assertEquals(30, mPersistedState.batteryLevel);
+
+        mTarget.setBatterySaverEnabledManually(false); // Manually disable -> snooze.
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(30, mPersistedState.batteryLevel);
+
+        mDevice.setBatteryLevel(20);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(20, mPersistedState.batteryLevel);
+
+        // Lower threshold. Level is still below, so should still be snoozed.
+        mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, 25);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(20, mPersistedState.batteryLevel);
+
+        // Lower threshold even more. Battery no longer considered "low" so snoozing should be
+        // disabled.
+        mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, 10);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(20, mPersistedState.batteryLevel);
+
+        mDevice.setBatteryLevel(10);
+
+        assertEquals(true, mDevice.batterySaverEnabled); // No longer snoozing.
+        assertEquals(10, mPersistedState.batteryLevel);
+
+        mTarget.setBatterySaverEnabledManually(false); // Manually disable -> snooze.
+
+        // Plug in and out, snooze will reset.
+        mDevice.setPowered(true);
+        mDevice.setPowered(false);
+
+        assertEquals(true, mDevice.batterySaverEnabled);
+        assertEquals(10, mPersistedState.batteryLevel);
+
+        mDevice.setPowered(true);
+        mDevice.setBatteryLevel(60);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(60, mPersistedState.batteryLevel);
+
+        // Test toggling resets snooze.
+        mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, 50);
+        mDevice.setPowered(false);
+        mDevice.setBatteryLevel(45);
+
+        assertEquals(true, mDevice.batterySaverEnabled);
+        assertEquals(45, mPersistedState.batteryLevel);
+
+        mTarget.setBatterySaverEnabledManually(false); // Manually disable -> snooze.
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(45, mPersistedState.batteryLevel);
+
+        // Disable and re-enable.
+        mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_ENABLED, 0);
+        mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_ENABLED, 1);
+
+        assertEquals(true, mDevice.batterySaverEnabled); // Snooze reset
+        assertEquals(45, mPersistedState.batteryLevel);
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
index 66d9345..2ed25ea 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
@@ -99,8 +99,8 @@
     public void bind_requestsContextToBindService() {
         mConnection.bindLocked();
         verify(mMockContext).bindServiceAsUser(any(Intent.class), eq(mConnection),
-                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE),
-                any(UserHandle.class));
+                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE
+                | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS), any(UserHandle.class));
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java b/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java
index 93cac08..71b4397 100644
--- a/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java
@@ -21,6 +21,7 @@
 import static com.android.server.am.MemoryStatUtil.MemoryStat;
 import static com.android.server.am.MemoryStatUtil.PAGE_SIZE;
 import static com.android.server.am.MemoryStatUtil.parseCmdlineFromProcfs;
+import static com.android.server.am.MemoryStatUtil.parseIonHeapSizeFromDebugfs;
 import static com.android.server.am.MemoryStatUtil.parseMemoryStatFromMemcg;
 import static com.android.server.am.MemoryStatUtil.parseMemoryStatFromProcfs;
 import static com.android.server.am.MemoryStatUtil.parseVmHWMFromProcfs;
@@ -178,6 +179,33 @@
             + "voluntary_ctxt_switches:\t903\n"
             + "nonvoluntary_ctxt_switches:\t104\n";
 
+    private static final String DEBUG_SYSTEM_ION_HEAP_CONTENTS = String.join(
+            "          client              pid             size\n",
+            "----------------------------------------------------\n",
+            " audio@2.0-servi              765             4096\n",
+            " audio@2.0-servi              765            61440\n",
+            " audio@2.0-servi              765             4096\n",
+            "     voip_client               96             8192\n",
+            "     voip_client               96             4096\n",
+            "   system_server             1232         16728064\n",
+            "  surfaceflinger              611         50642944\n",
+            "----------------------------------------------------\n",
+            "orphaned allocations (info is from last known client):\n",
+            "----------------------------------------------------\n",
+            "  total orphaned                0\n",
+            "          total          55193600\n",
+            "   deferred free                0\n",
+            "----------------------------------------------------\n",
+            "0 order 4 highmem pages in uncached pool = 0 total\n",
+            "0 order 4 lowmem pages in uncached pool = 0 total\n",
+            "1251 order 4 lowmem pages in cached pool = 81985536 total\n",
+            "VMID 8: 0 order 4 highmem pages in secure pool = 0 total\n",
+            "VMID  8: 0 order 4 lowmem pages in secure pool = 0 total\n",
+            "--------------------------------------------\n",
+            "uncached pool = 4096 cached pool = 83566592 secure pool = 0\n",
+            "pool total (uncached + cached + secure) = 83570688\n",
+            "--------------------------------------------\n");
+
     @Test
     public void testParseMemoryStatFromMemcg_parsesCorrectValues() {
         MemoryStat stat = parseMemoryStatFromMemcg(MEMORY_STAT_CONTENTS);
@@ -271,4 +299,21 @@
         output.write(bytes, 0, bytes.length);
         return output.toString();
     }
+
+    @Test
+    public void testParseIonHeapSizeFromDebugfs_emptyContents() {
+        assertEquals(0, parseIonHeapSizeFromDebugfs(""));
+
+        assertEquals(0, parseIonHeapSizeFromDebugfs(null));
+    }
+
+    @Test
+    public void testParseIonHeapSizeFromDebugfs_invalidValue() {
+        assertEquals(0, parseIonHeapSizeFromDebugfs("<<no-value>>"));
+    }
+
+    @Test
+    public void testParseIonHeapSizeFromDebugfs_correctValue() {
+        assertEquals(55193600, parseIonHeapSizeFromDebugfs(DEBUG_SYSTEM_ION_HEAP_CONTENTS));
+    }
 }
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 28a815e..bd7774a 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -5021,8 +5021,7 @@
         configureContextForAccess(mContext, false);
 
         assertExpectException(SecurityException.class, /* messageRegex= */ null,
-                () -> dpm.setProfileOwnerCanAccessDeviceIdsForUser(admin2,
-                        UserHandle.of(DpmMockContext.CALLER_UID)));
+                () -> dpm.setProfileOwnerCanAccessDeviceIds(admin2));
     }
 
     public void testGrantDeviceIdsAccess_notByAuthorizedCaller() throws Exception {
@@ -5030,8 +5029,7 @@
         configureContextForAccess(mContext, false);
 
         assertExpectException(SecurityException.class, /* messageRegex= */ null,
-                () -> dpm.setProfileOwnerCanAccessDeviceIdsForUser(admin1,
-                        UserHandle.of(DpmMockContext.CALLER_UID)));
+                () -> dpm.setProfileOwnerCanAccessDeviceIds(admin1));
     }
 
     public void testGrantDeviceIdsAccess_byAuthorizedSystemCaller() throws Exception {
@@ -5060,8 +5058,7 @@
                         DpmMockContext.CALLER_MANAGED_PROVISIONING_UID);
         try {
             runAsCaller(mServiceContext, dpms, dpm -> {
-                dpm.setProfileOwnerCanAccessDeviceIdsForUser(admin1,
-                        UserHandle.of(DpmMockContext.CALLER_USER_HANDLE));
+                dpm.setProfileOwnerCanAccessDeviceIds(admin1);
             });
         } finally {
             mServiceContext.binder.restoreCallingIdentity(ident);
@@ -5314,7 +5311,7 @@
         mServiceContext.binder.callingUid =
                 UserHandle.getUid(DpmMockContext.CALLER_USER_HANDLE, DpmMockContext.SYSTEM_UID);
         runAsCaller(mServiceContext, dpms, dpm -> {
-            dpm.setProfileOwnerCanAccessDeviceIdsForUser(who, UserHandle.of(userId));
+            dpm.setProfileOwnerCanAccessDeviceIds(who);
         });
         mServiceContext.binder.restoreCallingIdentity(ident);
     }
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
index 77515258..6a07a45 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -338,12 +338,15 @@
         initializeCredentialUnderSP(password, PRIMARY_USER_ID);
         final byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
 
+        assertFalse(mService.hasPendingEscrowToken(PRIMARY_USER_ID));
         long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
         assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
+        assertTrue(mService.hasPendingEscrowToken(PRIMARY_USER_ID));
 
         mService.verifyCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0,
                 PRIMARY_USER_ID).getResponseCode();
         assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
+        assertFalse(mService.hasPendingEscrowToken(PRIMARY_USER_ID));
 
         mLocalService.setLockCredentialWithToken(pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
                 handle, token, PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID);
diff --git a/services/tests/servicestests/src/com/android/server/pm/LauncherAppsServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/LauncherAppsServiceTest.java
deleted file mode 100644
index d7dc58d..0000000
--- a/services/tests/servicestests/src/com/android/server/pm/LauncherAppsServiceTest.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.pm;
-
-import static org.junit.Assert.assertEquals;
-
-import android.content.pm.PackageParser;
-import android.content.pm.Signature;
-import android.content.pm.SigningInfo;
-import android.platform.test.annotations.Presubmit;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.junit.MockitoJUnitRunner;
-
-@Presubmit
-@RunWith(MockitoJUnitRunner.class)
-public class LauncherAppsServiceTest {
-
-    private static final Signature SIGNATURE_1 = new Signature(new byte[]{0x00, 0x01, 0x02, 0x03});
-    private static final Signature SIGNATURE_2 = new Signature(new byte[]{0x04, 0x05, 0x06, 0x07});
-    private static final Signature SIGNATURE_3 = new Signature(new byte[]{0x08, 0x09, 0x10, 0x11});
-
-    @Test
-    public void testComputePackageCertDigest() {
-        String digest = LauncherAppsService.LauncherAppsImpl.computePackageCertDigest(SIGNATURE_1);
-        assertEquals("A02A05B025B928C039CF1AE7E8EE04E7C190C0DB", digest);
-    }
-
-    @Test
-    public void testGetLatestSignaturesWithSingleCert() {
-        SigningInfo signingInfo = new SigningInfo(
-                new PackageParser.SigningDetails(
-                        new Signature[]{SIGNATURE_1},
-                        PackageParser.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3,
-                        null,
-                        null));
-        Signature[] signatures = LauncherAppsService.LauncherAppsImpl.getLatestSignatures(
-                signingInfo);
-        assertEquals(1, signatures.length);
-        assertEquals(SIGNATURE_1, signatures[0]);
-    }
-
-    @Test
-    public void testGetLatestSignaturesWithMultiCert() {
-        SigningInfo signingInfo = new SigningInfo(
-                new PackageParser.SigningDetails(
-                        new Signature[]{SIGNATURE_1, SIGNATURE_2},
-                        PackageParser.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3,
-                        null,
-                        null));
-        Signature[] signatures = LauncherAppsService.LauncherAppsImpl.getLatestSignatures(
-                signingInfo);
-        assertEquals(2, signatures.length);
-        assertEquals(SIGNATURE_1, signatures[0]);
-        assertEquals(SIGNATURE_2, signatures[1]);
-    }
-
-    @Test
-    public void testGetLatestSignaturesWithCertHistory() {
-        SigningInfo signingInfo = new SigningInfo(
-                new PackageParser.SigningDetails(
-                        new Signature[]{SIGNATURE_1},
-                        PackageParser.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3,
-                        null,
-                        new Signature[]{SIGNATURE_2, SIGNATURE_3}));
-        Signature[] signatures = LauncherAppsService.LauncherAppsImpl.getLatestSignatures(
-                signingInfo);
-        assertEquals(1, signatures.length);
-        assertEquals(SIGNATURE_2, signatures[0]);
-    }
-
-}
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
index 26722fd..d3f33a1 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
@@ -167,6 +167,7 @@
                 /* stageDir */ mTmpDir,
                 /* stageCid */ null,
                 /* prepared */ true,
+                /* committed */ true,
                 /* sealed */ false,  // Setting to true would trigger some PM logic.
                 /* childSessionIds */ childSessionIds != null ? childSessionIds : new int[0],
                 /* parentSessionId */ parentSessionId,
@@ -300,6 +301,7 @@
         assertEquals(expected.getStagedSessionErrorMessage(),
                 actual.getStagedSessionErrorMessage());
         assertEquals(expected.isPrepared(), actual.isPrepared());
+        assertEquals(expected.isCommitted(), actual.isCommitted());
         assertEquals(expected.isSealed(), actual.isSealed());
         assertEquals(expected.isMultiPackage(), actual.isMultiPackage());
         assertEquals(expected.hasParentSessionId(), actual.hasParentSessionId());
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
index 111fb74..4cfd098 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
@@ -56,11 +56,11 @@
             }
 
             @Override
-            public void notifyPackageAdded(String packageName) {
+            public void notifyPackageAdded(String packageName, int uid) {
             }
 
             @Override
-            public void notifyPackageRemoved(String packageName) {
+            public void notifyPackageRemoved(String packageName, int uid) {
             }
         }
 
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppTimeLimitControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppTimeLimitControllerTests.java
index 1f86171..958b23f 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppTimeLimitControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppTimeLimitControllerTests.java
@@ -175,9 +175,9 @@
     /** Verify app usage limit observer is added */
     @Test
     public void testAppUsageLimitObserver_AddObserver() {
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, 0);
         assertTrue("Observer wasn't added", hasAppUsageLimitObserver(UID, OBS_ID1));
-        addAppUsageLimitObserver(OBS_ID2, GROUP_GAME, TIME_30_MIN, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID2, GROUP_GAME, TIME_30_MIN, 0);
         assertTrue("Observer wasn't added", hasAppUsageLimitObserver(UID, OBS_ID2));
         assertTrue("Observer wasn't added", hasAppUsageLimitObserver(UID, OBS_ID1));
     }
@@ -203,7 +203,7 @@
     /** Verify app usage limit observer is removed */
     @Test
     public void testAppUsageLimitObserver_RemoveObserver() {
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, 0);
         assertTrue("Observer wasn't added", hasAppUsageLimitObserver(UID, OBS_ID1));
         mController.removeAppUsageLimitObserver(UID, OBS_ID1, USER_ID);
         assertFalse("Observer wasn't removed", hasAppUsageLimitObserver(UID, OBS_ID1));
@@ -290,9 +290,9 @@
     /** Re-adding an observer should result in only one copy */
     @Test
     public void testAppUsageLimitObserver_ObserverReAdd() {
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, 0);
         assertTrue("Observer wasn't added", hasAppUsageLimitObserver(UID, OBS_ID1));
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_10_MIN, TIME_10_MIN);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_10_MIN, 0);
         assertTrue("Observer wasn't added",
                 getAppUsageLimitObserver(UID, OBS_ID1).getTimeLimitMs() == TIME_10_MIN);
         mController.removeAppUsageLimitObserver(UID, OBS_ID1, USER_ID);
@@ -304,7 +304,7 @@
     public void testAllObservers_ExclusiveObserverIds() {
         addAppUsageObserver(OBS_ID1, GROUP1, TIME_10_MIN);
         addUsageSessionObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_1_MIN);
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_10_MIN, TIME_10_MIN);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_10_MIN, 0);
         assertTrue("Observer wasn't added", hasAppUsageObserver(UID, OBS_ID1));
         assertTrue("Observer wasn't added", hasUsageSessionObserver(UID, OBS_ID1));
         assertTrue("Observer wasn't added", hasAppUsageLimitObserver(UID, OBS_ID1));
@@ -396,7 +396,7 @@
     @Test
     public void testAppUsageLimitObserver_Accumulation() throws Exception {
         setTime(0L);
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, 0);
         startUsage(PKG_SOC1);
         // Add 10 mins
         setTime(TIME_10_MIN);
@@ -456,7 +456,7 @@
     @Test
     public void testAppUsageLimitObserver_TimeoutOtherApp() throws Exception {
         setTime(0L);
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, 4_000L, 4_000L);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, 4_000L, 0);
         startUsage(PKG_SOC2);
         assertFalse(mLimitReachedLatch.await(6_000L, TimeUnit.MILLISECONDS));
         setTime(6_000L);
@@ -498,7 +498,7 @@
     @Test
     public void testAppUsageLimitObserver_Timeout() throws Exception {
         setTime(0L);
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, 4_000L, 4_000L);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, 4_000L, 0);
         startUsage(PKG_SOC1);
         setTime(6_000L);
         assertTrue(mLimitReachedLatch.await(6_000L, TimeUnit.MILLISECONDS));
@@ -551,7 +551,7 @@
         setTime(TIME_10_MIN);
         startUsage(PKG_GAME1);
         setTime(TIME_30_MIN);
-        addAppUsageLimitObserver(OBS_ID2, GROUP_GAME, TIME_30_MIN, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID2, GROUP_GAME, TIME_30_MIN, 0);
         setTime(TIME_30_MIN + TIME_10_MIN);
         stopUsage(PKG_GAME1);
         assertFalse(mLimitReachedLatch.await(1_000L, TimeUnit.MILLISECONDS));
@@ -612,7 +612,7 @@
         startUsage(PKG_SOC1);
         setTime(TIME_10_MIN);
         // 10 second time limit
-        addAppUsageLimitObserver(OBS_ID1, GROUP_SOC, 10_000L, 10_000L);
+        addAppUsageLimitObserver(OBS_ID1, GROUP_SOC, 10_000L, 0);
         setTime(TIME_10_MIN + 5_000L);
         // Shouldn't call back in 6 seconds
         assertFalse(mLimitReachedLatch.await(6_000L, TimeUnit.MILLISECONDS));
@@ -692,23 +692,23 @@
     public void testAppUsageLimitObserver_MaxObserverLimit() throws Exception {
         boolean receivedException = false;
         int ANOTHER_UID = UID + 1;
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN);
-        addAppUsageLimitObserver(OBS_ID2, GROUP1, TIME_30_MIN, TIME_30_MIN);
-        addAppUsageLimitObserver(OBS_ID3, GROUP1, TIME_30_MIN, TIME_30_MIN);
-        addAppUsageLimitObserver(OBS_ID4, GROUP1, TIME_30_MIN, TIME_30_MIN);
-        addAppUsageLimitObserver(OBS_ID5, GROUP1, TIME_30_MIN, TIME_30_MIN);
-        addAppUsageLimitObserver(OBS_ID6, GROUP1, TIME_30_MIN, TIME_30_MIN);
-        addAppUsageLimitObserver(OBS_ID7, GROUP1, TIME_30_MIN, TIME_30_MIN);
-        addAppUsageLimitObserver(OBS_ID8, GROUP1, TIME_30_MIN, TIME_30_MIN);
-        addAppUsageLimitObserver(OBS_ID9, GROUP1, TIME_30_MIN, TIME_30_MIN);
-        addAppUsageLimitObserver(OBS_ID10, GROUP1, TIME_30_MIN, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, 0);
+        addAppUsageLimitObserver(OBS_ID2, GROUP1, TIME_30_MIN, 0);
+        addAppUsageLimitObserver(OBS_ID3, GROUP1, TIME_30_MIN, 0);
+        addAppUsageLimitObserver(OBS_ID4, GROUP1, TIME_30_MIN, 0);
+        addAppUsageLimitObserver(OBS_ID5, GROUP1, TIME_30_MIN, 0);
+        addAppUsageLimitObserver(OBS_ID6, GROUP1, TIME_30_MIN, 0);
+        addAppUsageLimitObserver(OBS_ID7, GROUP1, TIME_30_MIN, 0);
+        addAppUsageLimitObserver(OBS_ID8, GROUP1, TIME_30_MIN, 0);
+        addAppUsageLimitObserver(OBS_ID9, GROUP1, TIME_30_MIN, 0);
+        addAppUsageLimitObserver(OBS_ID10, GROUP1, TIME_30_MIN, 0);
         // Readding an observer should not cause an IllegalStateException
-        addAppUsageLimitObserver(OBS_ID5, GROUP1, TIME_30_MIN, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID5, GROUP1, TIME_30_MIN, 0);
         // Adding an observer for a different uid shouldn't cause an IllegalStateException
         mController.addAppUsageLimitObserver(
-                ANOTHER_UID, OBS_ID11, GROUP1, TIME_30_MIN, TIME_30_MIN, null, USER_ID);
+                ANOTHER_UID, OBS_ID11, GROUP1, TIME_30_MIN, 0, null, USER_ID);
         try {
-            addAppUsageLimitObserver(OBS_ID11, GROUP1, TIME_30_MIN, TIME_30_MIN);
+            addAppUsageLimitObserver(OBS_ID11, GROUP1, TIME_30_MIN, 0);
         } catch (IllegalStateException ise) {
             receivedException = true;
         }
@@ -748,9 +748,9 @@
     public void testAppUsageLimitObserver_MinimumTimeLimit() throws Exception {
         boolean receivedException = false;
         // adding an observer with a one minute time limit should not cause an exception
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, MIN_TIME_LIMIT, MIN_TIME_LIMIT);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, MIN_TIME_LIMIT, 0);
         try {
-            addAppUsageLimitObserver(OBS_ID1, GROUP1, MIN_TIME_LIMIT - 1, MIN_TIME_LIMIT - 1);
+            addAppUsageLimitObserver(OBS_ID1, GROUP1, MIN_TIME_LIMIT - 1, 0);
         } catch (IllegalArgumentException iae) {
             receivedException = true;
         }
@@ -807,7 +807,7 @@
     @Test
     public void testAppUsageLimitObserver_ConcurrentUsage() throws Exception {
         setTime(0L);
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, 0);
         AppTimeLimitController.UsageGroup group = getAppUsageLimitObserver(UID, OBS_ID1);
         startUsage(PKG_SOC1);
         // Add 10 mins
@@ -967,7 +967,7 @@
     /** Verify app usage limit observer added correctly reports its total usage limit */
     @Test
     public void testAppUsageLimitObserver_GetTotalUsageLimit() {
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, 0);
         AppTimeLimitController.AppUsageLimitGroup group = getAppUsageLimitObserver(UID, OBS_ID1);
         assertNotNull("Observer wasn't added", group);
         assertEquals("Observer didn't correctly report total usage limit",
@@ -978,7 +978,7 @@
     @Test
     public void testAppUsageLimitObserver_GetUsageRemaining() {
         setTime(0L);
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, 0);
         startUsage(PKG_SOC1);
         setTime(TIME_10_MIN);
         stopUsage(PKG_SOC1);
@@ -993,8 +993,8 @@
      */
     @Test
     public void testAppUsageLimitObserver_GetAppUsageLimit() {
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN);
-        addAppUsageLimitObserver(OBS_ID2, GROUP_SOC, TIME_10_MIN, TIME_10_MIN);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, 0);
+        addAppUsageLimitObserver(OBS_ID2, GROUP_SOC, TIME_10_MIN, 0);
         UsageStatsManagerInternal.AppUsageLimitData group = getAppUsageLimit(PKG_SOC1);
         assertEquals("Observer with the smallest usage limit remaining wasn't returned",
                 TIME_10_MIN, group.getTotalUsageLimit());
@@ -1006,8 +1006,8 @@
     @Test
     public void testAppUsageLimitObserver_GetAppUsageLimitUsed() {
         setTime(0L);
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN);
-        addAppUsageLimitObserver(OBS_ID2, GROUP_SOC, TIME_10_MIN, TIME_10_MIN);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, 0);
+        addAppUsageLimitObserver(OBS_ID2, GROUP_SOC, TIME_10_MIN, 0);
         startUsage(PKG_GAME1);
         setTime(TIME_10_MIN * 2 + TIME_1_MIN);
         stopUsage(PKG_GAME1);
@@ -1024,8 +1024,8 @@
     @Test
     public void testAppUsageLimitObserver_GetAppUsageLimitAllUsed() {
         setTime(0L);
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN);
-        addAppUsageLimitObserver(OBS_ID2, GROUP_SOC, TIME_10_MIN, TIME_10_MIN);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, 0);
+        addAppUsageLimitObserver(OBS_ID2, GROUP_SOC, TIME_10_MIN, 0);
         startUsage(PKG_SOC1);
         setTime(TIME_10_MIN);
         stopUsage(PKG_SOC1);
@@ -1046,10 +1046,10 @@
         }
     }
 
-    /** Verify that a limit of 0 is allowed for the special case of re-registering an observer. */
+    /** Verify that timeUsed can be the same as timeLimit (for re-registering observers). */
     @Test
     public void testAppUsageLimitObserver_ZeroTimeRemainingIsAllowed() {
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_1_MIN, 0);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_1_MIN, TIME_1_MIN);
         AppTimeLimitController.AppUsageLimitGroup group = getAppUsageLimitObserver(UID, OBS_ID1);
         assertNotNull("Observer wasn't added", group);
         assertEquals("Usage remaining was not 0.", 0, group.getUsageRemaining());
@@ -1078,8 +1078,8 @@
     }
 
     private void addAppUsageLimitObserver(int observerId, String[] packages, long timeLimit,
-            long timeRemaining) {
-        mController.addAppUsageLimitObserver(UID, observerId, packages, timeLimit, timeRemaining,
+            long timeUsed) {
+        mController.addAppUsageLimitObserver(UID, observerId, packages, timeLimit, timeUsed,
                 null, USER_ID);
     }
 
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 7df52b2..6f96759 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -37,6 +37,7 @@
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
 import static android.content.pm.PackageManager.FEATURE_WATCH;
 import static android.content.pm.PackageManager.PERMISSION_DENIED;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.os.Build.VERSION_CODES.O_MR1;
 import static android.os.Build.VERSION_CODES.P;
 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
@@ -111,12 +112,14 @@
 import android.testing.TestableContext;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
+import android.testing.TestablePermissions;
 import android.text.Html;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.AtomicFile;
 
 import androidx.annotation.Nullable;
+import androidx.test.InstrumentationRegistry;
 
 import com.android.internal.R;
 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
@@ -311,6 +314,9 @@
 
     @Before
     public void setUp() throws Exception {
+        InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
+                "android.permission.WRITE_DEVICE_CONFIG", "android.permission.READ_DEVICE_CONFIG");
+
         MockitoAnnotations.initMocks(this);
 
         LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
@@ -392,6 +398,8 @@
     public void tearDown() throws Exception {
         mFile.delete();
         clearDeviceConfig();
+        InstrumentationRegistry.getInstrumentation()
+                .getUiAutomation().dropShellPermissionIdentity();
     }
 
     public void waitForIdle() {
@@ -4165,6 +4173,25 @@
     }
 
     @Test
+    public void testCanNotifyAsUser_crossUser() throws Exception {
+        // same user no problem
+        mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId());
+
+        // cross user, no permission, problem
+        try {
+            mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
+            fail("Should not be callable cross user without cross user permission");
+        } catch (SecurityException e) {
+            // good
+        }
+
+        // cross user, with permission, no problem
+        TestablePermissions perms = mContext.getTestablePermissions();
+        perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
+        mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
+    }
+
+    @Test
     public void setDefaultAssistantForUser_fromConfigXml() {
         clearDeviceConfig();
         ComponentName xmlConfig = new ComponentName("config", "xml");
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
index 9f11472..e375195 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
@@ -19,6 +19,7 @@
 import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
 import static android.app.NotificationManager.IMPORTANCE_HIGH;
 import static android.app.NotificationManager.IMPORTANCE_LOW;
+import static android.service.notification.Adjustment.KEY_IMPORTANCE;
 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_POSITIVE;
@@ -423,6 +424,138 @@
                 (int) logMaker.getTaggedData(MetricsEvent.NOTIFICATION_SINCE_VISIBLE_MILLIS));
         assertEquals(record.getInterruptionMs(timestamp),
                 (int) logMaker.getTaggedData(MetricsEvent.NOTIFICATION_SINCE_INTERRUPTION_MILLIS));
+        // If no importance calculation has been run, no explanation is available.
+        assertNull(logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_IMPORTANCE_EXPLANATION));
+        assertNull(logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_IMPORTANCE_INITIAL));
+        assertNull(logMaker.getTaggedData(
+                MetricsEvent.FIELD_NOTIFICATION_IMPORTANCE_INITIAL_EXPLANATION));
+        assertNull(logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_IMPORTANCE_ASST));
+    }
+
+    @Test
+    public void testLogMakerImportanceApp() {
+        long timestamp = 1000L;
+        StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, null /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+
+        record.calculateImportance();  // This importance calculation will yield 'app'
+        final LogMaker logMaker = record.getLogMaker(timestamp);
+        assertEquals(MetricsEvent.IMPORTANCE_EXPLANATION_APP,
+                logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_IMPORTANCE_EXPLANATION));
+        assertEquals(channel.getImportance(),
+                logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_IMPORTANCE));
+        // The additional information is only populated if the initial importance is overridden.
+        assertNull(logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_IMPORTANCE_INITIAL));
+        assertNull(logMaker.getTaggedData(
+                MetricsEvent.FIELD_NOTIFICATION_IMPORTANCE_INITIAL_EXPLANATION));
+        assertNull(logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_IMPORTANCE_ASST));
+    }
+
+    @Test
+    public void testLogMakerImportanceAsst() {
+        long timestamp = 1000L;
+        StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, null /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+        Bundle signals = new Bundle();
+        signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
+        record.addAdjustment(new Adjustment(PKG_O, KEY_IMPORTANCE, signals, "", uid));
+        record.applyAdjustments();
+        record.calculateImportance();  // This importance calculation will yield 'asst'
+        final LogMaker logMaker = record.getLogMaker(timestamp);
+        assertEquals(MetricsEvent.IMPORTANCE_EXPLANATION_ASST,
+                logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_IMPORTANCE_EXPLANATION));
+        // Therefore this is the assistant-set importance
+        assertEquals(IMPORTANCE_LOW,
+                logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_IMPORTANCE));
+        // Initial importance is populated so we know what it was, since it didn't get used.
+        assertEquals(channel.getImportance(),
+                logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_IMPORTANCE_INITIAL));
+        assertEquals(MetricsEvent.IMPORTANCE_EXPLANATION_APP,
+                logMaker.getTaggedData(
+                        MetricsEvent.FIELD_NOTIFICATION_IMPORTANCE_INITIAL_EXPLANATION));
+        // This field is only populated if the assistant was itself overridden by the system.
+        assertNull(logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_IMPORTANCE_ASST));
+    }
+
+    @Test
+    public void testLogMakerImportanceSystem() {
+        long timestamp = 1000L;
+        StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, null /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+        record.setSystemImportance(IMPORTANCE_HIGH);
+        record.calculateImportance();  // This importance calculation will yield 'system'
+        final LogMaker logMaker = record.getLogMaker(timestamp);
+        assertEquals(MetricsEvent.IMPORTANCE_EXPLANATION_SYSTEM,
+                logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_IMPORTANCE_EXPLANATION));
+        // Therefore this is the system-set importance
+        assertEquals(IMPORTANCE_HIGH,
+                logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_IMPORTANCE));
+        // Initial importance is populated so we know what it was, since it didn't get used.
+        assertEquals(channel.getImportance(),
+                logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_IMPORTANCE_INITIAL));
+        assertEquals(MetricsEvent.IMPORTANCE_EXPLANATION_APP,
+                logMaker.getTaggedData(
+                        MetricsEvent.FIELD_NOTIFICATION_IMPORTANCE_INITIAL_EXPLANATION));
+        assertNull(logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_IMPORTANCE_ASST));
+    }
+
+    @Test
+    public void testLogMakerImportanceUser() {
+        long timestamp = 1000L;
+        channel.lockFields(channel.USER_LOCKED_IMPORTANCE);
+        StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, null /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+        record.calculateImportance();  // This importance calculation will yield 'user'
+        final LogMaker logMaker = record.getLogMaker(timestamp);
+        assertEquals(MetricsEvent.IMPORTANCE_EXPLANATION_USER,
+                logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_IMPORTANCE_EXPLANATION));
+        // Therefore this is the user-set importance
+        assertEquals(channel.getImportance(),
+                logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_IMPORTANCE));
+        // The additional information is only populated if the initial importance is overridden.
+        assertNull(logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_IMPORTANCE_INITIAL));
+        assertNull(logMaker.getTaggedData(
+                MetricsEvent.FIELD_NOTIFICATION_IMPORTANCE_INITIAL_EXPLANATION));
+        assertNull(logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_IMPORTANCE_ASST));
+    }
+
+    @Test
+    public void testLogMakerImportanceMulti() {
+        long timestamp = 1000L;
+        channel.lockFields(channel.USER_LOCKED_IMPORTANCE);
+        StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, null /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+        // Add all 3 ways of overriding the app-set importance of the notification
+        Bundle signals = new Bundle();
+        signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
+        record.addAdjustment(new Adjustment(PKG_O, KEY_IMPORTANCE, signals, "", uid));
+        record.applyAdjustments();
+        record.setSystemImportance(IMPORTANCE_HIGH);
+        record.calculateImportance();  // This importance calculation will yield 'system'
+        final LogMaker logMaker = record.getLogMaker(timestamp);
+        assertEquals(MetricsEvent.IMPORTANCE_EXPLANATION_SYSTEM,
+                logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_IMPORTANCE_EXPLANATION));
+        // Therefore this is the system-set importance
+        assertEquals(IMPORTANCE_HIGH,
+                logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_IMPORTANCE));
+        // Initial importance is populated so we know what it was, since it didn't get used.
+        assertEquals(channel.getImportance(),
+                logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_IMPORTANCE_INITIAL));
+        assertEquals(MetricsEvent.IMPORTANCE_EXPLANATION_USER, logMaker.getTaggedData(
+                MetricsEvent.FIELD_NOTIFICATION_IMPORTANCE_INITIAL_EXPLANATION));
+        // Assistant importance is populated so we know what it was, since it didn't get used.
+        assertEquals(IMPORTANCE_LOW, logMaker.getTaggedData(
+                MetricsEvent.FIELD_NOTIFICATION_IMPORTANCE_ASST));
     }
 
     @Test
@@ -807,7 +940,7 @@
         assertEquals(IMPORTANCE_DEFAULT, record.getImportance());
 
         Bundle bundle = new Bundle();
-        bundle.putInt(Adjustment.KEY_IMPORTANCE, IMPORTANCE_LOW);
+        bundle.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
         Adjustment adjustment = new Adjustment(
                 PKG_O, record.getKey(), bundle, "", record.getUserId());
 
@@ -831,7 +964,7 @@
         assertEquals(IMPORTANCE_DEFAULT, record.getImportance());
 
         Bundle bundle = new Bundle();
-        bundle.putInt(Adjustment.KEY_IMPORTANCE, IMPORTANCE_LOW);
+        bundle.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
         Adjustment adjustment = new Adjustment(
                 PKG_O, record.getKey(), bundle, "", record.getUserId());
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
index 59e71c4..9583b8ac 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
@@ -18,32 +18,26 @@
 
 import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
 import static android.app.ActivityManager.START_TASK_TO_FRONT;
+import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.contains;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 
 import android.app.WaitResult;
+import android.content.pm.ActivityInfo;
 import android.platform.test.annotations.Presubmit;
 
 import androidx.test.filters.MediumTest;
@@ -112,4 +106,44 @@
             assertEquals(deliverToTopWait.who, firstActivity.mActivityComponent);
         }
     }
+
+    /**
+     * Ensures that {@link TaskChangeNotificationController} notifies only when an activity is
+     * forced to resize on secondary display.
+     */
+    @Test
+    public void testHandleNonResizableTaskOnSecondaryDisplay() {
+        // Create an unresizable task on secondary display.
+        final ActivityDisplay newDisplay = addNewActivityDisplayAt(ActivityDisplay.POSITION_TOP);
+        final ActivityStack stack = new StackBuilder(mRootActivityContainer)
+                .setDisplay(newDisplay).build();
+        final ActivityRecord unresizableActivity = stack.getTopActivity();
+        final TaskRecord task = unresizableActivity.getTaskRecord();
+        unresizableActivity.info.resizeMode = ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+        task.setResizeMode(unresizableActivity.info.resizeMode);
+
+        final TaskChangeNotificationController taskChangeNotifier =
+                mService.getTaskChangeNotificationController();
+        spyOn(taskChangeNotifier);
+
+        mSupervisor.handleNonResizableTaskIfNeeded(task, newDisplay.getWindowingMode(),
+                newDisplay.mDisplayId, stack);
+        // The top activity is unresizable, so it should notify the activity is forced resizing.
+        verify(taskChangeNotifier).notifyActivityForcedResizable(eq(task.taskId),
+                eq(FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY),
+                eq(unresizableActivity.packageName));
+        reset(taskChangeNotifier);
+
+        // Put a resizable activity on top of the unresizable task.
+        final ActivityRecord resizableActivity = new ActivityBuilder(mService)
+                .setTask(task).build();
+        resizableActivity.info.resizeMode = ActivityInfo.RESIZE_MODE_RESIZEABLE;
+
+        mSupervisor.handleNonResizableTaskIfNeeded(task, newDisplay.getWindowingMode(),
+                newDisplay.mDisplayId, stack);
+        // For the resizable activity, it is no need to force resizing or dismiss the docked stack.
+        verify(taskChangeNotifier, never()).notifyActivityForcedResizable(anyInt() /* taskId */,
+                anyInt() /* reason */, anyString() /* packageName */);
+        verify(taskChangeNotifier, never()).notifyActivityDismissingDockedStack();
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
index 5e12a95..81133d1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
@@ -18,6 +18,7 @@
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
 import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
 import static android.view.WindowManager.TRANSIT_TASK_OPEN;
 
@@ -77,4 +78,21 @@
                             TRANSIT_TASK_CLOSE));
         }
     }
+
+    @Test
+    public void testChangeIsNotOverwritten() {
+        synchronized (mWm.mGlobalLock) {
+            final AppWindowToken behind = createAppWindowToken(mDisplayContent,
+                    WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+            final AppWindowToken translucentOpening = createAppWindowToken(mDisplayContent,
+                    WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+            translucentOpening.setFillsParent(false);
+            translucentOpening.setHidden(true);
+            mDisplayContent.mOpeningApps.add(behind);
+            mDisplayContent.mOpeningApps.add(translucentOpening);
+            assertEquals(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
+                    mAppTransitionController.maybeUpdateTransitToTranslucentAnim(
+                            TRANSIT_TASK_CHANGE_WINDOWING_MODE));
+        }
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index 70c8c93..d17e5c3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -16,8 +16,6 @@
 
 package com.android.server.wm;
 
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
@@ -48,7 +46,6 @@
 import static org.mockito.Mockito.verify;
 
 import android.content.res.Configuration;
-import android.graphics.Point;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
 import android.view.Display;
@@ -475,32 +472,6 @@
         assertHasStartingWindow(tokenBottom);
     }
 
-    @Test
-    public void testTransitionAnimationPositionAndBounds() {
-        final Rect stackBounds = new Rect(
-                0/* left */, 0 /* top */, 1000 /* right */, 1000 /* bottom */);
-        final Rect taskBounds = new Rect(
-                100/* left */, 200 /* top */, 600 /* right */, 600 /* bottom */);
-        mStack.setBounds(stackBounds);
-        mTask.setBounds(taskBounds);
-
-        mTask.setWindowingMode(WINDOWING_MODE_FREEFORM);
-        assertTransitionAnimationPositionAndBounds(taskBounds.left, taskBounds.top, stackBounds);
-
-        mTask.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
-        assertTransitionAnimationPositionAndBounds(stackBounds.left, stackBounds.top, stackBounds);
-    }
-
-    private void assertTransitionAnimationPositionAndBounds(int expectedX, int expectedY,
-            Rect expectedBounds) {
-        final Point outPosition = new Point();
-        final Rect outBounds = new Rect();
-        mToken.getAnimationBounds(outPosition, outBounds);
-        assertEquals(expectedX, outPosition.x);
-        assertEquals(expectedY, outPosition.y);
-        assertEquals(expectedBounds, outBounds);
-    }
-
     private void assertHasStartingWindow(AppWindowToken atoken) {
         assertNotNull(atoken.startingSurface);
         assertNotNull(atoken.startingData);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index b26aa05..98333b2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -34,11 +34,12 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.same;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 import static com.android.server.wm.WindowContainer.POSITION_TOP;
@@ -663,6 +664,15 @@
     }
 
     @Test
+    public void testComputeImeParent_app_notMatchParentBounds() {
+        spyOn(mAppWindow.mAppToken);
+        doReturn(false).when(mAppWindow.mAppToken).matchParentBounds();
+        mDisplayContent.mInputMethodTarget = mAppWindow;
+        // The surface parent of IME should be the display instead of app window.
+        assertEquals(mDisplayContent.getWindowingLayer(), mDisplayContent.computeImeParent());
+    }
+
+    @Test
     public void testComputeImeParent_noApp() throws Exception {
         try (final InsetsModeSession session =
                      new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
index 2dad187..9a8a732 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
@@ -148,6 +148,19 @@
     }
 
     @Test
+    public void testPrimaryDisplayUpdateToFreeform_HasFreeformSupport_IsPc() {
+        mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
+
+        mWm.setSupportsFreeformWindowManagement(true);
+        mWm.setIsPc(true);
+
+        mTarget.updateSettingsForDisplay(mPrimaryDisplay);
+
+        assertEquals(WindowConfiguration.WINDOWING_MODE_FREEFORM,
+                mPrimaryDisplay.getWindowingMode());
+    }
+
+    @Test
     public void testSecondaryDisplayDefaultToFullscreen_NoFreeformSupport() {
         mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
index aeda473..e4d3770 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
@@ -316,7 +316,7 @@
     public void testClearsRecordInMemoryOnPackageUninstalled() {
         mTarget.saveTask(mTestTask);
 
-        mObserver.onPackageRemoved(TEST_COMPONENT.getPackageName());
+        mObserver.onPackageRemoved(TEST_COMPONENT.getPackageName(), TEST_USER_ID);
 
         mTarget.getLaunchParams(mTestTask, null, mResult);
 
@@ -327,7 +327,7 @@
     public void testClearsWriteQueueItemOnPackageUninstalled() {
         mTarget.saveTask(mTestTask);
 
-        mObserver.onPackageRemoved(TEST_COMPONENT.getPackageName());
+        mObserver.onPackageRemoved(TEST_COMPONENT.getPackageName(), TEST_USER_ID);
 
         final LaunchParamsPersister target = new LaunchParamsPersister(mPersisterQueue, mSupervisor,
                 mUserFolderGetter);
@@ -344,7 +344,7 @@
         mTarget.saveTask(mTestTask);
         mPersisterQueue.flush();
 
-        mObserver.onPackageRemoved(TEST_COMPONENT.getPackageName());
+        mObserver.onPackageRemoved(TEST_COMPONENT.getPackageName(), TEST_USER_ID);
 
         final LaunchParamsPersister target = new LaunchParamsPersister(mPersisterQueue, mSupervisor,
                 mUserFolderGetter);
diff --git a/services/tests/wmtests/src/com/android/server/wm/PersisterQueueTests.java b/services/tests/wmtests/src/com/android/server/wm/PersisterQueueTests.java
index 8327440..a166444 100644
--- a/services/tests/wmtests/src/com/android/server/wm/PersisterQueueTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/PersisterQueueTests.java
@@ -28,6 +28,7 @@
 import android.os.SystemClock;
 import android.platform.test.annotations.Presubmit;
 
+import androidx.test.filters.FlakyTest;
 import androidx.test.filters.MediumTest;
 
 import org.junit.After;
@@ -157,6 +158,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 128526085)
     public void testProcessTwoItems_OneAfterAnother() throws Exception {
         // First item
         mLatch = new CountDownLatch(1);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index fc1eb1c..68e7470 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -583,6 +583,114 @@
     }
 
     @Test
+    public void testFreezeTaskListOrder_reorderExistingTask() {
+        // Add some tasks
+        mRecentTasks.add(mTasks.get(0));
+        mRecentTasks.add(mTasks.get(1));
+        mRecentTasks.add(mTasks.get(2));
+        mRecentTasks.add(mTasks.get(3));
+        mRecentTasks.add(mTasks.get(4));
+        mCallbacksRecorder.clear();
+
+        // Freeze the list
+        mRecentTasks.setFreezeTaskListReordering();
+        assertTrue(mRecentTasks.isFreezeTaskListReorderingSet());
+
+        // Relaunch a few tasks
+        mRecentTasks.add(mTasks.get(3));
+        mRecentTasks.add(mTasks.get(2));
+
+        // Commit the task ordering with a specific task focused
+        mRecentTasks.resetFreezeTaskListReordering(mTasks.get(2));
+        assertFalse(mRecentTasks.isFreezeTaskListReorderingSet());
+
+        // Ensure that the order of the task list is the same as before, but with the focused task
+        // at the front
+        assertRecentTasksOrder(mTasks.get(2),
+                mTasks.get(4),
+                mTasks.get(3),
+                mTasks.get(1),
+                mTasks.get(0));
+
+        assertThat(mCallbacksRecorder.mAdded).isEmpty();
+        assertThat(mCallbacksRecorder.mTrimmed).isEmpty();
+        assertThat(mCallbacksRecorder.mRemoved).isEmpty();
+    }
+
+    @Test
+    public void testFreezeTaskListOrder_addRemoveTasks() {
+        // Add some tasks
+        mRecentTasks.add(mTasks.get(0));
+        mRecentTasks.add(mTasks.get(1));
+        mRecentTasks.add(mTasks.get(2));
+        mCallbacksRecorder.clear();
+
+        // Freeze the list
+        mRecentTasks.setFreezeTaskListReordering();
+        assertTrue(mRecentTasks.isFreezeTaskListReorderingSet());
+
+        // Add and remove some tasks
+        mRecentTasks.add(mTasks.get(3));
+        mRecentTasks.add(mTasks.get(4));
+        mRecentTasks.remove(mTasks.get(0));
+        mRecentTasks.remove(mTasks.get(1));
+
+        // Unfreeze the list
+        mRecentTasks.resetFreezeTaskListReordering(null);
+        assertFalse(mRecentTasks.isFreezeTaskListReorderingSet());
+
+        // Ensure that the order of the task list accounts for the added and removed tasks (added
+        // at the end)
+        assertRecentTasksOrder(mTasks.get(4),
+                mTasks.get(3),
+                mTasks.get(2));
+
+        assertThat(mCallbacksRecorder.mAdded).hasSize(2);
+        assertThat(mCallbacksRecorder.mAdded).contains(mTasks.get(3));
+        assertThat(mCallbacksRecorder.mAdded).contains(mTasks.get(4));
+        assertThat(mCallbacksRecorder.mRemoved).hasSize(2);
+        assertThat(mCallbacksRecorder.mRemoved).contains(mTasks.get(0));
+        assertThat(mCallbacksRecorder.mRemoved).contains(mTasks.get(1));
+    }
+
+    @Test
+    public void testFreezeTaskListOrder_timeout() {
+        // Add some tasks
+        mRecentTasks.add(mTasks.get(0));
+        mRecentTasks.add(mTasks.get(1));
+        mRecentTasks.add(mTasks.get(2));
+        mRecentTasks.add(mTasks.get(3));
+        mRecentTasks.add(mTasks.get(4));
+
+        // Freeze the list
+        long freezeTime = SystemClock.elapsedRealtime();
+        mRecentTasks.setFreezeTaskListReordering();
+        assertTrue(mRecentTasks.isFreezeTaskListReorderingSet());
+
+        // Relaunch a few tasks
+        mRecentTasks.add(mTasks.get(2));
+        mRecentTasks.add(mTasks.get(1));
+
+        // Override the freeze timeout params to simulate the timeout (simulate the freeze at 100ms
+        // ago with a timeout of 1ms)
+        mRecentTasks.setFreezeTaskListTimeoutParams(freezeTime - 100, 1);
+
+        ActivityStack stack = mTasks.get(2).getStack();
+        stack.moveToFront("", mTasks.get(2));
+        doReturn(stack).when(mTestService.mRootActivityContainer).getTopDisplayFocusedStack();
+        mRecentTasks.resetFreezeTaskListReorderingOnTimeout();
+        assertFalse(mRecentTasks.isFreezeTaskListReorderingSet());
+
+        // Ensure that the order of the task list is the same as before, but with the focused task
+        // at the front
+        assertRecentTasksOrder(mTasks.get(2),
+                mTasks.get(4),
+                mTasks.get(3),
+                mTasks.get(1),
+                mTasks.get(0));
+    }
+
+    @Test
     public void testBackStackTasks_expectNoTrim() {
         mRecentTasks.setParameters(-1 /* min */, 1 /* max */, -1 /* ms */);
 
@@ -721,6 +829,18 @@
                         true /* showRecents */));
     }
 
+    /**
+     * Ensures that the recent tasks list is in the provided order. Note that the expected tasks
+     * should be ordered from least to most recent.
+     */
+    private void assertRecentTasksOrder(TaskRecord... expectedTasks) {
+        ArrayList<TaskRecord> tasks = mRecentTasks.getRawTasks();
+        assertTrue(expectedTasks.length == tasks.size());
+        for (int i = 0; i < tasks.size(); i++)  {
+            assertTrue(expectedTasks[i] == tasks.get(i));
+        }
+    }
+
     private void assertNotRestoreTask(Runnable action) {
         // Verify stack count doesn't change because task with fullscreen mode and standard type
         // would have its own stack.
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index 45fe5d2..35a8ec3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -20,9 +20,11 @@
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
+import android.app.WindowConfiguration;
 import android.platform.test.annotations.Presubmit;
 
 import androidx.test.filters.SmallTest;
@@ -71,5 +73,21 @@
         assertFalse(app.isVisible());
         assertFalse(mWm.mRoot.isAnyNonToastWindowVisibleForUid(FAKE_CALLING_UID));
     }
+
+    @Test
+    public void testUpdateDefaultDisplayWindowingModeOnSettingsRetrieved() {
+        synchronized (mWm.mGlobalLock) {
+            assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN,
+                    mWm.getDefaultDisplayContentLocked().getWindowingMode());
+
+            mWm.mIsPc = true;
+            mWm.mSupportsFreeformWindowManagement = true;
+
+            mWm.mRoot.onSettingsRetrieved();
+
+            assertEquals(WindowConfiguration.WINDOWING_MODE_FREEFORM,
+                    mWm.getDefaultDisplayContentLocked().getWindowingMode());
+        }
+    }
 }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java
index 1b396f5..00e479f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java
@@ -32,7 +32,6 @@
 import android.platform.test.annotations.Presubmit;
 import android.view.InputChannel;
 
-import androidx.test.filters.FlakyTest;
 import androidx.test.filters.SmallTest;
 
 import org.junit.Before;
@@ -89,7 +88,6 @@
         assertNull(mTarget.getDragWindowHandleLocked());
     }
 
-    @FlakyTest(bugId = 69229402)
     @Test
     public void testHandleTapOutsideTask() {
         synchronized (mWm.mGlobalLock) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
index b140da5..b9e9909 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
@@ -100,6 +100,7 @@
     }
 
     @Test
+    @Presubmit
     public void testTaskDescriptionChanged() throws Exception {
         final Object[] params = new Object[2];
         final CountDownLatch latch = new CountDownLatch(1);
@@ -132,6 +133,7 @@
     }
 
     @Test
+    @Presubmit
     public void testActivityRequestedOrientationChanged() throws Exception {
         final int[] params = new int[2];
         final CountDownLatch latch = new CountDownLatch(1);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
index 2ccdb9e..78fca0f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
@@ -19,6 +19,7 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
 import static android.view.DisplayCutout.fromBoundingRect;
 import static android.view.WindowManager.LayoutParams.MATCH_PARENT;
@@ -27,7 +28,6 @@
 import static org.junit.Assert.assertEquals;
 import static org.mockito.Mockito.mock;
 
-import android.app.ActivityManager.TaskDescription;
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
@@ -54,23 +54,15 @@
 @Presubmit
 public class WindowFrameTests extends WindowTestsBase {
 
-    private WindowToken mWindowToken;
     private final IWindow mIWindow = new TestIWindow();
     private final Rect mEmptyRect = new Rect();
 
-    static class WindowStateWithTask extends WindowState {
-        final Task mTask;
+    static class FrameTestWindowState extends WindowState {
         boolean mDockedResizingForTest = false;
-        WindowStateWithTask(WindowManagerService wm, IWindow iWindow, WindowToken windowToken,
-                WindowManager.LayoutParams attrs, Task t) {
+        FrameTestWindowState(WindowManagerService wm, IWindow iWindow, WindowToken windowToken,
+                WindowManager.LayoutParams attrs) {
             super(wm, mock(Session.class), iWindow, windowToken, null, 0, 0, attrs, 0, 0,
                     false /* ownerCanAddInternalSystemWindow */);
-            mTask = t;
-        }
-
-        @Override
-        Task getTask() {
-            return mTask;
         }
 
         @Override
@@ -79,52 +71,10 @@
         }
     }
 
-    private static class TaskWithBounds extends Task {
-        Rect mBounds;
-        final Rect mOverrideDisplayedBounds = new Rect();
-        boolean mFullscreenForTest = true;
-
-        TaskWithBounds(TaskStack stack, WindowManagerService wm, Rect bounds) {
-            super(0, stack, 0, wm, 0, false, new TaskDescription(), null);
-            setBounds(bounds);
-        }
-
-        @Override
-        public int setBounds(Rect bounds) {
-            mBounds = bounds;
-            return super.setBounds(bounds);
-        }
-
-        @Override
-        public Rect getBounds() {
-            return mBounds;
-        }
-
-        @Override
-        public void getBounds(Rect out) {
-            out.set(mBounds);
-        }
-
-        @Override
-        public void getRequestedOverrideBounds(Rect outBounds) {
-            outBounds.set(mBounds);
-        }
-        @Override
-        Rect getOverrideDisplayedBounds() {
-            return mOverrideDisplayedBounds;
-        }
-        @Override
-        boolean isFullscreen() {
-            return mFullscreenForTest;
-        }
-    }
-
     TaskStack mStubStack;
 
     @Before
     public void setUp() throws Exception {
-        mWindowToken = createAppWindowToken(mWm.getDefaultDisplayContentLocked(),
-                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
         mStubStack = mock(TaskStack.class);
     }
 
@@ -168,7 +118,8 @@
                 expectedRect.bottom);
     }
 
-    private void assertPolicyCrop(WindowStateWithTask w, int left, int top, int right, int bottom) {
+    private void assertPolicyCrop(
+            FrameTestWindowState w, int left, int top, int right, int bottom) {
         Rect policyCrop = new Rect();
         w.calculatePolicyCrop(policyCrop);
         assertRect(policyCrop, left, top, right, bottom);
@@ -177,8 +128,7 @@
     @Test
     public void testLayoutInFullscreenTaskInsets() {
         // fullscreen task doesn't use bounds for computeFrame
-        final Task task = new TaskWithBounds(mStubStack, mWm, null);
-        WindowState w = createWindow(task, MATCH_PARENT, MATCH_PARENT);
+        WindowState w = createWindow(MATCH_PARENT, MATCH_PARENT);
         w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
 
         final int bottomContentInset = 100;
@@ -235,8 +185,7 @@
     @Test
     public void testLayoutInFullscreenTaskNoInsets() {
         // fullscreen task doesn't use bounds for computeFrame
-        final Task task = new TaskWithBounds(mStubStack, mWm, null);
-        WindowState w = createWindow(task, MATCH_PARENT, MATCH_PARENT);
+        WindowState w = createWindow(MATCH_PARENT, MATCH_PARENT);
         w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
 
         // With no insets or system decor all the frames incoming from PhoneWindowManager
@@ -323,9 +272,11 @@
         final int taskRight = logicalWidth / 4 * 3;
         final int taskBottom = logicalHeight / 4 * 3;
         final Rect taskBounds = new Rect(taskLeft, taskTop, taskRight, taskBottom);
-        final TaskWithBounds task = new TaskWithBounds(mStubStack, mWm, taskBounds);
-        task.mFullscreenForTest = false;
-        WindowState w = createWindow(task, MATCH_PARENT, MATCH_PARENT);
+        WindowState w = createWindow(MATCH_PARENT, MATCH_PARENT);
+        final Task task = w.getTask();
+        // Use split-screen because it is non-fullscreen, but also not floating
+        task.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+        task.setBounds(taskBounds);
         w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
 
         final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
@@ -359,8 +310,8 @@
         final int insetTop = logicalHeight / 5;
         final int insetRight = insetLeft + (taskRight - taskLeft);
         final int insetBottom = insetTop + (taskBottom - taskTop);
-        task.mOverrideDisplayedBounds.set(taskBounds);
-        task.mBounds.set(insetLeft, insetTop, insetRight, insetBottom);
+        task.setOverrideDisplayedBounds(taskBounds);
+        task.setBounds(insetLeft, insetTop, insetRight, insetBottom);
         windowFrames.setFrames(pf, pf, pf, cf, cf, pf, cf, mEmptyRect);
         w.computeFrameLw();
         assertFrame(w, taskLeft, taskTop, taskRight, taskBottom);
@@ -373,8 +324,7 @@
 
     @Test
     public void testCalculatePolicyCrop() {
-        final WindowStateWithTask w = createWindow(
-                new TaskWithBounds(mStubStack, mWm, null), MATCH_PARENT, MATCH_PARENT);
+        final FrameTestWindowState w = createWindow(MATCH_PARENT, MATCH_PARENT);
         w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
 
         final DisplayInfo displayInfo = w.getDisplayContent().getDisplayInfo();
@@ -439,9 +389,11 @@
         final int taskRight = logicalWidth / 4 * 3;
         final int taskBottom = logicalHeight / 4 * 3;
         final Rect taskBounds = new Rect(taskLeft, taskTop, taskRight, taskBottom);
-        final TaskWithBounds task = new TaskWithBounds(mStubStack, mWm, taskBounds);
-        task.mFullscreenForTest = false;
-        WindowState w = createWindow(task, MATCH_PARENT, MATCH_PARENT);
+        WindowState w = createWindow(MATCH_PARENT, MATCH_PARENT);
+        final Task task = w.getTask();
+        // Use split-screen because it is non-fullscreen, but also not floating
+        task.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+        task.setBounds(taskBounds);
         w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
 
         final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
@@ -461,7 +413,8 @@
         config.windowConfiguration.setBounds(cf);
         w.mAppToken.onRequestedOverrideConfigurationChanged(config);
         pf.set(0, 0, logicalWidth, logicalHeight);
-        task.mFullscreenForTest = true;
+        task.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+        task.setBounds(null);
         windowFrames.setFrames(pf, pf, pf, cf, cf, pf, cf, mEmptyRect);
         w.computeFrameLw();
         assertFrame(w, cf.left, cf.top, cf.right, cf.bottom);
@@ -472,8 +425,7 @@
     @Test
     public void testDisplayCutout() {
         // Regular fullscreen task and window
-        final Task task = new TaskWithBounds(mStubStack, mWm, null);
-        WindowState w = createWindow(task, MATCH_PARENT, MATCH_PARENT);
+        WindowState w = createWindow(MATCH_PARENT, MATCH_PARENT);
         w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
 
         final Rect pf = new Rect(0, 0, 1000, 2000);
@@ -496,11 +448,10 @@
     @Test
     public void testDisplayCutout_tempDisplayedBounds() {
         // Regular fullscreen task and window
-        final TaskWithBounds task = new TaskWithBounds(mStubStack, mWm,
-                new Rect(0, 0, 1000, 2000));
-        task.mFullscreenForTest = false;
+        WindowState w = createWindow(MATCH_PARENT, MATCH_PARENT);
+        final Task task = w.getTask();
+        task.setBounds(new Rect(0, 0, 1000, 2000));
         task.setOverrideDisplayedBounds(new Rect(0, -500, 1000, 1500));
-        WindowState w = createWindow(task, MATCH_PARENT, MATCH_PARENT);
         w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
 
         final Rect pf = new Rect(0, -500, 1000, 1500);
@@ -523,12 +474,10 @@
     @Test
     public void testFreeformContentInsets() {
         // fullscreen task doesn't use bounds for computeFrame
-        final Task task = new TaskWithBounds(mStubStack, mWm, null);
-        WindowState w = createWindow(task, MATCH_PARENT, MATCH_PARENT);
+        WindowState w = createWindow(MATCH_PARENT, MATCH_PARENT);
+        final Task task = w.getTask();
         w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
         task.setWindowingMode(WINDOWING_MODE_FREEFORM);
-        ((TaskWithBounds) task).mFullscreenForTest = false;
-        w.setWindowingMode(WINDOWING_MODE_FREEFORM);
 
         DisplayContent dc = mWm.getDefaultDisplayContentLocked();
         dc.mInputMethodTarget = w;
@@ -551,7 +500,6 @@
         final Rect winRect = new Rect(200, 200, 300, 500);
 
         task.setBounds(winRect);
-        w.setBounds(winRect);
         w.getWindowFrames().setFrames(pf, df, of, cf, vf, dcf, sf, mEmptyRect);
         w.computeFrameLw();
 
@@ -580,11 +528,16 @@
         assertEquals(winRect, w.getFrameLw());
     }
 
-    private WindowStateWithTask createWindow(Task task, int width, int height) {
+    private FrameTestWindowState createWindow(int width, int height) {
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION);
         attrs.width = width;
         attrs.height = height;
 
-        return new WindowStateWithTask(mWm, mIWindow, mWindowToken, attrs, task);
+        AppWindowToken token = createAppWindowToken(mWm.getDefaultDisplayContentLocked(),
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+
+        FrameTestWindowState ws = new FrameTestWindowState(mWm, mIWindow, token, attrs);
+        token.addWindow(ws);
+        return ws;
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index fb698d9..8c37ca5e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -229,10 +229,11 @@
         } catch (Exception e) {
             Log.e(TAG, "Failed to tear down test", e);
             throw e;
+        } finally {
+            mMockTracker.close();
+            mMockTracker = null;
         }
 
-        mMockTracker.close();
-        mMockTracker = null;
     }
 
     private WindowState createCommonWindow(WindowState parent, int type, String name) {
diff --git a/services/usage/java/com/android/server/usage/AppTimeLimitController.java b/services/usage/java/com/android/server/usage/AppTimeLimitController.java
index f3d6387..6861ad1 100644
--- a/services/usage/java/com/android/server/usage/AppTimeLimitController.java
+++ b/services/usage/java/com/android/server/usage/AppTimeLimitController.java
@@ -511,10 +511,10 @@
 
     class AppUsageLimitGroup extends UsageGroup {
         public AppUsageLimitGroup(UserData user, ObserverAppData observerApp, int observerId,
-                String[] observed, long timeLimitMs, long timeRemainingMs,
+                String[] observed, long timeLimitMs, long timeUsedMs,
                 PendingIntent limitReachedCallback) {
             super(user, observerApp, observerId, observed, timeLimitMs, limitReachedCallback);
-            mUsageTimeMs = timeLimitMs - timeRemainingMs;
+            mUsageTimeMs = timeUsedMs;
         }
 
         @Override
@@ -841,7 +841,7 @@
      * Existing app usage limit observer with the same observerId will be removed.
      */
     public void addAppUsageLimitObserver(int requestingUid, int observerId, String[] observed,
-            long timeLimit, long timeRemaining, PendingIntent callbackIntent,
+            long timeLimit, long timeUsed, PendingIntent callbackIntent,
             @UserIdInt int userId) {
         if (timeLimit < getMinTimeLimit()) {
             throw new IllegalArgumentException("Time limit must be >= " + getMinTimeLimit());
@@ -861,7 +861,7 @@
                         "Too many app usage observers added by uid " + requestingUid);
             }
             group = new AppUsageLimitGroup(user, observerApp, observerId, observed, timeLimit,
-                    timeRemaining, timeRemaining == 0L ? null : callbackIntent);
+                    timeUsed, timeUsed >= timeLimit ? null : callbackIntent);
             observerApp.appUsageLimitGroups.append(observerId, group);
 
             if (DEBUG) {
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 27fdbcb..1ec680f 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -1399,7 +1399,7 @@
 
         @Override
         public void registerAppUsageLimitObserver(int observerId, String[] packages,
-                long timeLimitMs, long timeRemainingMs, PendingIntent callbackIntent,
+                long timeLimitMs, long timeUsedMs, PendingIntent callbackIntent,
                 String callingPackage) {
             if (!hasPermissions(callingPackage,
                     Manifest.permission.SUSPEND_APPS, Manifest.permission.OBSERVE_APP_USAGE)) {
@@ -1410,11 +1410,7 @@
             if (packages == null || packages.length == 0) {
                 throw new IllegalArgumentException("Must specify at least one package");
             }
-            if (timeRemainingMs > timeLimitMs) {
-                throw new IllegalArgumentException(
-                        "Remaining time can't be greater than total time.");
-            }
-            if (callbackIntent == null && timeRemainingMs != 0L) {
+            if (callbackIntent == null && timeUsedMs < timeLimitMs) {
                 throw new NullPointerException("callbackIntent can't be null");
             }
             final int callingUid = Binder.getCallingUid();
@@ -1422,7 +1418,7 @@
             final long token = Binder.clearCallingIdentity();
             try {
                 UsageStatsService.this.registerAppUsageLimitObserver(callingUid, observerId,
-                        packages, timeLimitMs, timeRemainingMs, callbackIntent, userId);
+                        packages, timeLimitMs, timeUsedMs, callbackIntent, userId);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -1550,9 +1546,9 @@
     }
 
     void registerAppUsageLimitObserver(int callingUid, int observerId, String[] packages,
-            long timeLimitMs, long timeRemainingMs, PendingIntent callbackIntent, int userId) {
+            long timeLimitMs, long timeUsedMs, PendingIntent callbackIntent, int userId) {
         mAppTimeLimit.addAppUsageLimitObserver(callingUid, observerId, packages,
-                timeLimitMs, timeRemainingMs, callbackIntent, userId);
+                timeLimitMs, timeUsedMs, callbackIntent, userId);
     }
 
     void unregisterAppUsageLimitObserver(int callingUid, int observerId, int userId) {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 61d7d6c..8d2cbca 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -357,7 +357,8 @@
         Intent intent = new Intent(VoiceInteractionService.SERVICE_INTERFACE);
         intent.setComponent(mComponent);
         mBound = mContext.bindServiceAsUser(intent, mConnection,
-                Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, new UserHandle(mUser));
+                Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
+                | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS, new UserHandle(mUser));
         if (!mBound) {
             Slog.w(TAG, "Failed binding to voice interaction service " + mComponent);
         }
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index 1bf0723..24690f5 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -159,7 +159,8 @@
         mBindIntent.setComponent(mSessionComponentName);
         mBound = mContext.bindServiceAsUser(mBindIntent, this,
                 Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY
-                        | Context.BIND_ALLOW_OOM_MANAGEMENT, new UserHandle(mUser));
+                        | Context.BIND_ALLOW_OOM_MANAGEMENT
+                        | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS, new UserHandle(mUser));
         if (mBound) {
             try {
                 mIWindowManager.addWindowToken(mToken, TYPE_VOICE_INTERACTION, DEFAULT_DISPLAY);
@@ -191,7 +192,8 @@
             if (!mFullyBound) {
                 mFullyBound = mContext.bindServiceAsUser(mBindIntent, mFullConnection,
                         Context.BIND_AUTO_CREATE | Context.BIND_TREAT_LIKE_ACTIVITY
-                                | Context.BIND_FOREGROUND_SERVICE,
+                                | Context.BIND_FOREGROUND_SERVICE
+                                | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS,
                         new UserHandle(mUser));
             }
 
diff --git a/telecomm/java/android/telecom/AudioState.java b/telecomm/java/android/telecom/AudioState.java
index 4e74395..6b9b83d 100644
--- a/telecomm/java/android/telecom/AudioState.java
+++ b/telecomm/java/android/telecom/AudioState.java
@@ -18,6 +18,7 @@
 
 import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
+import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -54,11 +55,11 @@
     private static final int ROUTE_ALL = ROUTE_EARPIECE | ROUTE_BLUETOOTH | ROUTE_WIRED_HEADSET |
             ROUTE_SPEAKER;
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 127403196)
     private final boolean isMuted;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 127403196)
     private final int route;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 127403196)
     private final int supportedRouteMask;
 
     public AudioState(boolean muted, int route, int supportedRouteMask) {
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index dcaa499..c05a346 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -144,6 +144,16 @@
     public static final String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS =
             "android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS";
 
+
+    /**
+     * Extra key used to indicate whether a {@link CallScreeningService} has requested to silence
+     * the ringtone for a call.  If the {@link InCallService} declares
+     * {@link TelecomManager#METADATA_IN_CALL_SERVICE_RINGING} in its manifest, it should not
+     * play a ringtone for an incoming call with this extra key set.
+     */
+    public static final String EXTRA_SILENT_RINGING_REQUESTED =
+            "android.telecom.extra.SILENT_RINGING_REQUESTED";
+
     /**
      * Call event sent from a {@link Call} via {@link #sendCallEvent(String, Bundle)} to inform
      * Telecom that the user has requested that the current {@link Call} should be handed over
diff --git a/telecomm/java/android/telecom/CallRedirectionService.java b/telecomm/java/android/telecom/CallRedirectionService.java
index 3299117..d01c889 100644
--- a/telecomm/java/android/telecom/CallRedirectionService.java
+++ b/telecomm/java/android/telecom/CallRedirectionService.java
@@ -17,6 +17,7 @@
 package android.telecom;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SdkConstant;
 import android.app.Service;
 import android.content.Intent;
@@ -62,16 +63,20 @@
     private ICallRedirectionAdapter mCallRedirectionAdapter;
 
     /**
-     * Telecom calls this method to inform the implemented {@link CallRedirectionService} of
-     * a new outgoing call which is being placed. Telecom does not request to redirect emergency
-     * calls and does not request to redirect calls with gateway information.
+     * Telecom calls this method once upon binding to a {@link CallRedirectionService} to inform
+     * it of a new outgoing call which is being placed. Telecom does not request to redirect
+     * emergency calls and does not request to redirect calls with gateway information.
      *
      * <p>Telecom will cancel the call if Telecom does not receive a response in 5 seconds from
      * the implemented {@link CallRedirectionService} set by users.
      *
      * <p>The implemented {@link CallRedirectionService} can call {@link #placeCallUnmodified()},
      * {@link #redirectCall(Uri, PhoneAccountHandle, boolean)}, and {@link #cancelCall()} only
-     * from here.
+     * from here. Calls to these methods are assumed by the Telecom framework to be the response
+     * for the phone call for which {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)} was
+     * invoked by Telecom. The Telecom framework will only invoke
+     * {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)} once each time it binds to a
+     * {@link CallRedirectionService}.
      *
      * @param handle the phone number dialed by the user, represented in E.164 format if possible
      * @param initialPhoneAccount the {@link PhoneAccountHandle} on which the call will be placed.
@@ -91,13 +96,15 @@
      * no changes are required to the outgoing call, and that the call should be placed as-is.
      *
      * <p>This can only be called from implemented
-     * {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)}.
+     * {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)}. The response corresponds to the
+     * latest request via {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)}.
      *
      */
     public final void placeCallUnmodified() {
         try {
             mCallRedirectionAdapter.placeCallUnmodified();
         } catch (RemoteException e) {
+            e.rethrowAsRuntimeException();
         }
     }
 
@@ -109,7 +116,8 @@
      * replies Telecom a handle for an emergency number.
      *
      * <p>This can only be called from implemented
-     * {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)}.
+     * {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)}. The response corresponds to the
+     * latest request via {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)}.
      *
      * @param handle the new phone number to dial
      * @param targetPhoneAccount the {@link PhoneAccountHandle} to use when placing the call.
@@ -126,6 +134,7 @@
         try {
             mCallRedirectionAdapter.redirectCall(handle, targetPhoneAccount, confirmFirst);
         } catch (RemoteException e) {
+            e.rethrowAsRuntimeException();
         }
     }
 
@@ -135,13 +144,15 @@
      * an outgoing call should be canceled entirely.
      *
      * <p>This can only be called from implemented
-     * {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)}.
+     * {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)}. The response corresponds to the
+     * latest request via {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)}.
      *
      */
     public final void cancelCall() {
         try {
             mCallRedirectionAdapter.cancelCall();
         } catch (RemoteException e) {
+            e.rethrowAsRuntimeException();
         }
     }
 
@@ -196,12 +207,12 @@
     }
 
     @Override
-    public final IBinder onBind(Intent intent) {
+    public final @Nullable IBinder onBind(@NonNull Intent intent) {
         return new CallRedirectionBinder();
     }
 
     @Override
-    public final boolean onUnbind(Intent intent) {
+    public final boolean onUnbind(@NonNull Intent intent) {
         return false;
     }
 }
diff --git a/telecomm/java/android/telecom/CallScreeningService.java b/telecomm/java/android/telecom/CallScreeningService.java
index 2fa388f..b1aece7 100644
--- a/telecomm/java/android/telecom/CallScreeningService.java
+++ b/telecomm/java/android/telecom/CallScreeningService.java
@@ -259,12 +259,14 @@
     public static class CallResponse {
         private final boolean mShouldDisallowCall;
         private final boolean mShouldRejectCall;
+        private final boolean mShouldSilenceCall;
         private final boolean mShouldSkipCallLog;
         private final boolean mShouldSkipNotification;
 
         private CallResponse(
                 boolean shouldDisallowCall,
                 boolean shouldRejectCall,
+                boolean shouldSilenceCall,
                 boolean shouldSkipCallLog,
                 boolean shouldSkipNotification) {
             if (!shouldDisallowCall
@@ -276,6 +278,7 @@
             mShouldRejectCall = shouldRejectCall;
             mShouldSkipCallLog = shouldSkipCallLog;
             mShouldSkipNotification = shouldSkipNotification;
+            mShouldSilenceCall = shouldSilenceCall;
         }
 
         /*
@@ -294,6 +297,13 @@
         }
 
         /*
+         * @return Whether the ringtone should be silenced for the incoming call.
+         */
+        public boolean getSilenceCall() {
+            return mShouldSilenceCall;
+        }
+
+        /*
          * @return Whether the incoming call should not be displayed in the call log.
          */
         public boolean getSkipCallLog() {
@@ -310,6 +320,7 @@
         public static class Builder {
             private boolean mShouldDisallowCall;
             private boolean mShouldRejectCall;
+            private boolean mShouldSilenceCall;
             private boolean mShouldSkipCallLog;
             private boolean mShouldSkipNotification;
 
@@ -331,6 +342,21 @@
             }
 
             /**
+             * Sets whether ringing should be silenced for the incoming call.  When set
+             * to {@code true}, the Telecom framework will not play a ringtone for the call.
+             * The call will, however, still be sent to the default dialer app if it is not blocked.
+             * A {@link CallScreeningService} can use this to ensure a potential nuisance call is
+             * still surfaced to the user, but in a less intrusive manner.
+             *
+             * Setting this to true only makes sense when the call has not been disallowed
+             * using {@link #setDisallowCall(boolean)}.
+             */
+            public @NonNull Builder setSilenceCall(boolean shouldSilenceCall) {
+                mShouldSilenceCall = shouldSilenceCall;
+                return this;
+            }
+
+            /**
              * Sets whether the incoming call should not be displayed in the call log. This property
              * should only be set to true if the call is disallowed.
              * <p>
@@ -356,6 +382,7 @@
                 return new CallResponse(
                         mShouldDisallowCall,
                         mShouldRejectCall,
+                        mShouldSilenceCall,
                         mShouldSkipCallLog,
                         mShouldSkipNotification);
             }
@@ -411,10 +438,11 @@
     public abstract void onScreenCall(@NonNull Call.Details callDetails);
 
     /**
-     * Responds to the given incoming call, either allowing it or disallowing it.
+     * Responds to the given incoming call, either allowing it, silencing it or disallowing it.
      * <p>
      * The {@link CallScreeningService} calls this method to inform the system whether the call
-     * should be silently blocked or not.
+     * should be silently blocked or not. In the event that it should not be blocked, it may
+     * also be requested to ring silently.
      * <p>
      * Calls to this method are ignored unless the {@link Call.Details#getCallDirection()} is
      * {@link Call.Details#DIRECTION_INCOMING}.
@@ -436,6 +464,8 @@
                         !response.getSkipCallLog(),
                         !response.getSkipNotification(),
                         new ComponentName(getPackageName(), getClass().getName()));
+            } else if (response.getSilenceCall()) {
+                mCallScreeningAdapter.silenceCall(callDetails.getTelecomCallId());
             } else {
                 mCallScreeningAdapter.allowCall(callDetails.getTelecomCallId());
             }
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index ae12a17..28e6596 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -555,6 +555,15 @@
     public static final String EVENT_CALL_MERGE_FAILED = "android.telecom.event.CALL_MERGE_FAILED";
 
     /**
+     * Connection event used to inform Telecom when a hold operation on a call has failed.
+     * Not intended for use by the UI at this time.
+     * Sent via {@link #sendConnectionEvent(String, Bundle)}.  The {@link Bundle} parameter is
+     * expected to be null when this connection event is used.
+     * @hide
+     */
+    public static final String EVENT_CALL_HOLD_FAILED = "android.telecom.event.CALL_HOLD_FAILED";
+
+    /**
      * Connection event used to inform {@link InCallService}s when the process of merging a
      * Connection into a conference has begun.
      * <p>
diff --git a/telecomm/java/android/telecom/Phone.java b/telecomm/java/android/telecom/Phone.java
index d3ccd2c..0cc052e 100644
--- a/telecomm/java/android/telecom/Phone.java
+++ b/telecomm/java/android/telecom/Phone.java
@@ -19,6 +19,7 @@
 import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.bluetooth.BluetoothDevice;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.util.ArrayMap;
@@ -328,10 +329,12 @@
      * become active, and the touch screen and display will be turned off when the user's face
      * is detected to be in close proximity to the screen. This operation is a no-op on devices
      * that do not have a proximity sensor.
-     *
+     * <p>
+     * This API does not actually turn on the proximity sensor; apps should do this on their own if
+     * required.
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 127403196)
     public final void setProximitySensorOn() {
         mInCallAdapter.turnProximitySensorOn();
     }
@@ -344,10 +347,12 @@
      * @param screenOnImmediately If true, the screen will be turned on immediately if it was
      * previously off. Otherwise, the screen will only be turned on after the proximity sensor
      * is no longer triggered.
-     *
+     * <p>
+     * This API does not actually turn of the proximity sensor; apps should do this on their own if
+     * required.
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 127403196)
     public final void setProximitySensorOff(boolean screenOnImmediately) {
         mInCallAdapter.turnProximitySensorOff(screenOnImmediately);
     }
diff --git a/telecomm/java/android/telecom/PhoneAccountHandle.java b/telecomm/java/android/telecom/PhoneAccountHandle.java
index a84ce55..71a28b5 100644
--- a/telecomm/java/android/telecom/PhoneAccountHandle.java
+++ b/telecomm/java/android/telecom/PhoneAccountHandle.java
@@ -42,7 +42,7 @@
  * See {@link PhoneAccount}, {@link TelecomManager}.
  */
 public final class PhoneAccountHandle implements Parcelable {
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 127403196)
     private final ComponentName mComponentName;
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private final String mId;
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 52c5425..3d0a3c5 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1589,7 +1589,7 @@
                                 Build.VERSION_CODES.O_MR1) {
                     Log.e("TAG", "addNewIncomingCall failed. Use public api " +
                             "acceptHandover for API > O-MR1");
-                    // TODO add "return" after DUO team adds support for new handover API
+                    return;
                 }
                 getTelecomService().addNewIncomingCall(
                         phoneAccount, extras == null ? new Bundle() : extras);
diff --git a/telecomm/java/android/telecom/VideoCallImpl.java b/telecomm/java/android/telecom/VideoCallImpl.java
index 2c7fecb..cb74012 100644
--- a/telecomm/java/android/telecom/VideoCallImpl.java
+++ b/telecomm/java/android/telecom/VideoCallImpl.java
@@ -18,6 +18,7 @@
 
 import android.annotation.UnsupportedAppUsage;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -218,7 +219,7 @@
         mTargetSdkVersion = sdkVersion;
     }
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 127403196)
     public void destroy() {
         unregisterCallback(mCallback);
     }
diff --git a/telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl b/telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl
index a86c830..1160d27 100644
--- a/telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl
@@ -29,6 +29,8 @@
 oneway interface ICallScreeningAdapter {
     void allowCall(String callId);
 
+    void silenceCall(String callId);
+
     void disallowCall(
             String callId,
             boolean shouldReject,
diff --git a/telephony/java/android/telephony/AccessNetworkConstants.java b/telephony/java/android/telephony/AccessNetworkConstants.java
index 75165af..81553a3 100644
--- a/telephony/java/android/telephony/AccessNetworkConstants.java
+++ b/telephony/java/android/telephony/AccessNetworkConstants.java
@@ -16,13 +16,59 @@
 
 package android.telephony;
 
+import android.annotation.IntDef;
 import android.annotation.SystemApi;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * Contains access network related constants.
  */
 public final class AccessNetworkConstants {
 
+    /**
+     * Wireless transportation type
+     *
+     * @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"TRANSPORT_TYPE_"},
+            value = {
+                    TRANSPORT_TYPE_INVALID,
+                    TRANSPORT_TYPE_WWAN,
+                    TRANSPORT_TYPE_WLAN})
+    public @interface TransportType {}
+
+    /**
+     * Invalid transport type
+     * @hide
+     */
+    @SystemApi
+    public static final int TRANSPORT_TYPE_INVALID = -1;
+
+    /**
+     * Transport type for Wireless Wide Area Networks (i.e. Cellular)
+     * @hide
+     */
+    @SystemApi
+    public static final int TRANSPORT_TYPE_WWAN = 1;
+
+    /**
+     * Transport type for Wireless Local Area Networks (i.e. Wifi)
+     * @hide
+     */
+    @SystemApi
+    public static final int TRANSPORT_TYPE_WLAN = 2;
+
+    /** @hide */
+    public static String transportTypeToString(@TransportType int transportType) {
+        switch (transportType) {
+            case TRANSPORT_TYPE_WWAN: return "WWAN";
+            case TRANSPORT_TYPE_WLAN: return "WLAN";
+            default: return Integer.toString(transportType);
+        }
+    }
+
     public static final class AccessNetworkType {
         public static final int UNKNOWN = 0;
         public static final int GERAN = 1;
@@ -49,39 +95,7 @@
     }
 
     /**
-     * Wireless transportation type
-     * @hide
-     */
-    @SystemApi
-    public static final class TransportType {
-        /**
-         * Invalid transport type.
-         * @hide
-         */
-        public static final int INVALID = -1;
-
-        /** 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;
-
-        /** @hide */
-        private TransportType() {}
-
-        /** @hide */
-        public static String toString(int type) {
-            switch (type) {
-                case INVALID: return "INVALID";
-                case WWAN: return "WWAN";
-                case WLAN: return "WLAN";
-                default: return Integer.toString(type);
-            }
-        }
-    }
-
-    /**
-     * Frenquency bands for GERAN.
+     * Frequency bands for GERAN.
      * http://www.etsi.org/deliver/etsi_ts/145000_145099/145005/14.00.00_60/ts_145005v140000p.pdf
      */
     public static final class GeranBand {
diff --git a/telephony/java/android/telephony/DebugEventReporter.java b/telephony/java/android/telephony/AnomalyReporter.java
similarity index 82%
rename from telephony/java/android/telephony/DebugEventReporter.java
rename to telephony/java/android/telephony/AnomalyReporter.java
index 14b7dd6..9753d8b 100644
--- a/telephony/java/android/telephony/DebugEventReporter.java
+++ b/telephony/java/android/telephony/AnomalyReporter.java
@@ -29,7 +29,6 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.List;
-import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
@@ -37,7 +36,7 @@
 /**
  * A Simple Surface for Telephony to notify a loosely-coupled debugger of particular issues.
  *
- * DebugEventReporter allows an optional external logging component to receive events detected by
+ * AnomalyReporter allows an optional external logging component to receive events detected by
  * the framework and take action. This log surface is designed to provide maximium flexibility
  * to the receiver of these events. Envisioned use cases of this include notifying a vendor
  * component of: an event that necessitates (timely) log collection on non-AOSP components;
@@ -49,8 +48,8 @@
  *
  * @hide
  */
-public final class DebugEventReporter {
-    private static final String TAG = "DebugEventReporter";
+public final class AnomalyReporter {
+    private static final String TAG = "AnomalyReporter";
 
     private static Context sContext = null;
 
@@ -63,12 +62,12 @@
      */
     private static String sDebugPackageName = null;
 
-    private DebugEventReporter() {};
+    private AnomalyReporter() {};
 
     /**
      * If enabled, build and send an intent to a Debug Service for logging.
      *
-     * This method sends the {@link TelephonyManager#DEBUG_EVENT DEBUG_EVENT} broadcast, which is
+     * This method sends the {@link TelephonyManager#ACTION_ANOMALY_REPORTED} broadcast, which is
      * system protected. Invoking this method unless you are the system will result in an error.
      *
      * @param eventId a fixed event ID that will be sent for each instance of the same event. This
@@ -77,9 +76,9 @@
      *        identification and discussion of this event. This description should ideally be
      *        static and must not contain any sensitive information (especially PII).
      */
-    public static void sendEvent(@NonNull UUID eventId, String description) {
+    public static void reportAnomaly(@NonNull UUID eventId, String description) {
         if (sContext == null) {
-            Rlog.w(TAG, "DebugEventReporter not yet initialized, dropping event=" + eventId);
+            Rlog.w(TAG, "AnomalyReporter not yet initialized, dropping event=" + eventId);
             return;
         }
 
@@ -94,28 +93,28 @@
         // so drop these events silently.
         if (sDebugPackageName == null) return;
 
-        Intent dbgIntent = new Intent(TelephonyManager.ACTION_DEBUG_EVENT);
-        dbgIntent.putExtra(TelephonyManager.EXTRA_DEBUG_EVENT_ID, new ParcelUuid(eventId));
+        Intent dbgIntent = new Intent(TelephonyManager.ACTION_ANOMALY_REPORTED);
+        dbgIntent.putExtra(TelephonyManager.EXTRA_ANOMALY_ID, new ParcelUuid(eventId));
         if (description != null) {
-            dbgIntent.putExtra(TelephonyManager.EXTRA_DEBUG_EVENT_DESCRIPTION, description);
+            dbgIntent.putExtra(TelephonyManager.EXTRA_ANOMALY_DESCRIPTION, description);
         }
         dbgIntent.setPackage(sDebugPackageName);
         sContext.sendBroadcast(dbgIntent, android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
     }
 
     /**
-     * Initialize the DebugEventReporter with the current context.
+     * Initialize the AnomalyReporter with the current context.
      *
-     * This method must be invoked before any calls to sendEvent() will succeed. This method should
-     * only be invoked at most once.
+     * This method must be invoked before any calls to reportAnomaly() will succeed. This method
+     * should only be invoked at most once.
      *
-     * @param context a Context object used to initialize this singleton DebugEventReporter in
+     * @param context a Context object used to initialize this singleton AnomalyReporter in
      *        the current process.
      */
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public static void initialize(@NonNull Context context) {
         if (context == null) {
-            throw new IllegalArgumentException("DebugEventReporter needs a non-null context.");
+            throw new IllegalArgumentException("AnomalyReporter needs a non-null context.");
         }
 
         // Ensure that this context has sufficient permissions to send debug events.
@@ -129,13 +128,13 @@
         PackageManager pm = sContext.getPackageManager();
         if (pm == null) return;
         List<ResolveInfo> packages = pm.queryBroadcastReceivers(
-                new Intent(TelephonyManager.ACTION_DEBUG_EVENT),
+                new Intent(TelephonyManager.ACTION_ANOMALY_REPORTED),
                 PackageManager.MATCH_SYSTEM_ONLY
                         | PackageManager.MATCH_DIRECT_BOOT_AWARE
                         | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
         if (packages == null || packages.isEmpty()) return;
         if (packages.size() > 1) {
-            Rlog.e(TAG, "Multiple DebugEvent Receivers installed.");
+            Rlog.e(TAG, "Multiple Anomaly Receivers installed.");
         }
 
         for (ResolveInfo r : packages) {
@@ -156,14 +155,14 @@
         // Initialization may only be performed once.
     }
 
-    /** Dump the contents of the DebugEventReporter */
+    /** Dump the contents of the AnomalyReporter */
     public static void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
         if (sContext == null) return;
         IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, "  ");
         sContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, "Requires DUMP");
         pw.println("Initialized=" + (sContext != null ? "Yes" : "No"));
         pw.println("Debug Package=" + sDebugPackageName);
-        pw.println("Event Counts:");
+        pw.println("Anomaly Counts:");
         pw.increaseIndent();
         for (UUID event : sEvents.keySet()) {
             pw.println(event + ": " + sEvents.get(event));
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index d79a168..5f9ef3c 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1520,6 +1520,14 @@
             "carrier_app_no_wake_signal_config";
 
     /**
+     * Determines whether the carrier app needed to be involved when users try to finish setting up
+     * the SIM card to get network service.
+     * @hide
+     */
+    public static final String KEY_CARRIER_APP_REQUIRED_DURING_SIM_SETUP_BOOL =
+            "carrier_app_required_during_setup_bool";
+
+    /**
      * Default value for {@link Settings.Global#DATA_ROAMING}
      * @hide
      */
@@ -2307,9 +2315,9 @@
             "undelivered_sms_message_expiration_time";
 
     /**
-     * Specifies a carrier-defined {@link CallRedirectionService} which Telecom will bind
-     * to for outgoing calls.  An empty string indicates that no carrier-defined
-     * {@link CallRedirectionService} is specified.
+     * Specifies a carrier-defined {@link android.telecom.CallRedirectionService} which Telecom
+     * will bind to for outgoing calls.  An empty string indicates that no carrier-defined
+     * {@link android.telecom.CallRedirectionService} is specified.
      * @hide
      */
     public static final String KEY_CALL_REDIRECTION_SERVICE_COMPONENT_NAME_STRING =
@@ -2520,6 +2528,18 @@
             "emergency_number_prefix_string_array";
 
     /**
+     * Indicates when a carrier has a primary subscription and an opportunistic subscription active,
+     * and when Internet data is switched to opportunistic network, whether to still show
+     * signal bar of primary network. By default it will be false, meaning whenever data
+     * is going over opportunistic network, signal bar will reflect signal strength and rat
+     * icon of that network.
+     *
+     * @hide
+     */
+    public static final String KEY_ALWAYS_SHOW_PRIMARY_SIGNAL_BAR_IN_OPPORTUNISTIC_NETWORK_BOOLEAN =
+            "always_show_primary_signal_bar_in_opportunistic_network_boolean";
+
+    /**
      * GPS configs. See android.hardware.gnss@1.0 IGnssConfiguration.
      * @hide
      */
@@ -2855,6 +2875,7 @@
         sDefaults.putString(KEY_CARRIER_NAME_STRING, "");
         sDefaults.putString(KEY_SIM_COUNTRY_ISO_OVERRIDE_STRING, "");
         sDefaults.putString(KEY_CARRIER_CALL_SCREENING_APP_STRING, "");
+        sDefaults.putString(KEY_CALL_REDIRECTION_SERVICE_COMPONENT_NAME_STRING, null);
         sDefaults.putBoolean(KEY_CDMA_HOME_REGISTERED_PLMN_NAME_OVERRIDE_BOOL, false);
         sDefaults.putString(KEY_CDMA_HOME_REGISTERED_PLMN_NAME_STRING, "");
         sDefaults.putBoolean(KEY_SUPPORT_DIRECT_FDN_DIALING_BOOL, false);
@@ -2910,6 +2931,7 @@
                                 + "com.android.internal.telephony.CARRIER_SIGNAL_RESET"
                 });
         sDefaults.putStringArray(KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY, null);
+        sDefaults.putBoolean(KEY_CARRIER_APP_REQUIRED_DURING_SIM_SETUP_BOOL, false);
 
 
         // Default carrier app configurations
@@ -3052,6 +3074,8 @@
         sDefaults.putStringArray(KEY_EMERGENCY_NUMBER_PREFIX_STRING_ARRAY, new String[0]);
         sDefaults.putBoolean(KEY_USE_USIM_BOOL, false);
         sDefaults.putBoolean(KEY_AUTO_CANCEL_CS_REJECT_NOTIFICATION, false);
+        sDefaults.putBoolean(KEY_ALWAYS_SHOW_PRIMARY_SIGNAL_BAR_IN_OPPORTUNISTIC_NETWORK_BOOLEAN,
+                false);
     }
 
     /**
diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java
index 6c835dc..e5aadad 100644
--- a/telephony/java/android/telephony/CellIdentity.java
+++ b/telephony/java/android/telephony/CellIdentity.java
@@ -86,7 +86,7 @@
         }
 
         if ((mMccStr != null && mMncStr == null) || (mMccStr == null && mMncStr != null)) {
-            DebugEventReporter.sendEvent(
+            AnomalyReporter.reportAnomaly(
                     UUID.fromString("a3ab0b9d-f2aa-4baf-911d-7096c0d4645a"),
                     "CellIdentity Missing Half of PLMN ID");
         }
diff --git a/telephony/java/android/telephony/CellIdentityNr.java b/telephony/java/android/telephony/CellIdentityNr.java
index 5a89ae8..4be52a3 100644
--- a/telephony/java/android/telephony/CellIdentityNr.java
+++ b/telephony/java/android/telephony/CellIdentityNr.java
@@ -16,13 +16,15 @@
 
 package android.telephony;
 
+import android.annotation.IntRange;
+import android.annotation.Nullable;
 import android.os.Parcel;
 import android.telephony.gsm.GsmCellLocation;
 
 import java.util.Objects;
 
 /**
- * Information to represent a unique 5G NR cell.
+ * Information to represent a unique NR(New Radio 5G) cell.
  */
 public final class CellIdentityNr extends CellIdentity {
     private static final String TAG = "CellIdentityNr";
@@ -79,7 +81,7 @@
     }
 
     /**
-     * Get the NR Cell Identity.
+     * Get the NR(New Radio 5G) Cell Identity.
      *
      * @return The 36-bit NR Cell Identity in range [0, 68719476735] or
      *         {@link CellInfo#UNAVAILABLE_LONG} if unknown.
@@ -96,6 +98,7 @@
      *
      * @return Integer value in range [0, 3279165] or {@link CellInfo#UNAVAILABLE} if unknown.
      */
+    @IntRange(from = 0, to = 3279165)
     public int getNrarfcn() {
         return mNrArfcn;
     }
@@ -104,6 +107,7 @@
      * Get the physical cell id.
      * @return Integer value in range [0, 1007] or {@link CellInfo#UNAVAILABLE} if unknown.
      */
+    @IntRange(from = 0, to = 1007)
     public int getPci() {
         return mPci;
     }
@@ -112,6 +116,7 @@
      * Get the tracking area code.
      * @return a 16 bit integer or {@link CellInfo#UNAVAILABLE} if unknown.
      */
+    @IntRange(from = 0, to = 65535)
     public int getTac() {
         return mTac;
     }
@@ -119,6 +124,7 @@
     /**
      * @return Mobile Country Code in string format, or {@code null} if unknown.
      */
+    @Nullable
     public String getMccString() {
         return mMccStr;
     }
@@ -126,6 +132,7 @@
     /**
      * @return Mobile Network Code in string fomrat, or {@code null} if unknown.
      */
+    @Nullable
     public String getMncString() {
         return mMncStr;
     }
diff --git a/telephony/java/android/telephony/CellInfoNr.java b/telephony/java/android/telephony/CellInfoNr.java
index fb147ce..0227610 100644
--- a/telephony/java/android/telephony/CellInfoNr.java
+++ b/telephony/java/android/telephony/CellInfoNr.java
@@ -16,6 +16,7 @@
 
 package android.telephony;
 
+import android.annotation.NonNull;
 import android.os.Parcel;
 
 import java.util.Objects;
@@ -36,11 +37,13 @@
     }
 
     @Override
+    @NonNull
     public CellIdentity getCellIdentity() {
         return mCellIdentity;
     }
 
     @Override
+    @NonNull
     public CellSignalStrength getCellSignalStrength() {
         return mCellSignalStrength;
     }
diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java
index ca264f7..f0a26f5 100644
--- a/telephony/java/android/telephony/DataFailCause.java
+++ b/telephony/java/android/telephony/DataFailCause.java
@@ -318,8 +318,8 @@
     public static final int LOW_POWER_MODE_OR_POWERING_DOWN = 0x7FC;
     /** APN has been disabled. */
     public static final int APN_DISABLED = 0x7FD;
-    /** Maximum PPP inactivity timer expired. */
-    public static final int MAX_PPP_INACTIVITY_TIMER_EXPIRED = 0x7FE;
+    /** PPP inactivity timer expired. */
+    public static final int PPP_INACTIVITY_TIMER_EXPIRED = 0x7FE;
     /** IPv6 address transfer failed. */
     public static final int IPV6_ADDRESS_TRANSFER_FAILED = 0x7FF;
     /** Target RAT swap failed. */
@@ -339,12 +339,12 @@
      * IPv4 data call bring up is rejected because the UE already maintains the allotted maximum
      * number of IPv4 data connections.
      */
-    public static final int MAX_IPV4_CONNECTIONS = 0x804;
+    public static final int IPV4_CONNECTIONS_LIMIT_REACHED = 0x804;
     /**
      * IPv6 data call bring up is rejected because the UE already maintains the allotted maximum
      * number of IPv6 data connections.
      */
-    public static final int MAX_IPV6_CONNECTIONS = 0x805;
+    public static final int IPV6_CONNECTIONS_LIMIT_REACHED = 0x805;
     /**
      * New PDN bring up is rejected during interface selection because the UE has already allotted
      * the available interfaces for other PDNs.
@@ -416,7 +416,7 @@
      */
     public static final int CHANNEL_ACQUISITION_FAILURE = 0x81E;
     /** Maximum access probes transmitted. */
-    public static final int MAX_ACCESS_PROBE = 0x81F;
+    public static final int ACCESS_PROBE_LIMIT_REACHED = 0x81F;
     /** Concurrent service is not supported by base station. */
     public static final int CONCURRENT_SERVICE_NOT_SUPPORTED_BY_BASE_STATION = 0x820;
     /** There was no response received from the base station. */
@@ -1079,14 +1079,14 @@
             SIM_CARD_CHANGED,
             LOW_POWER_MODE_OR_POWERING_DOWN,
             APN_DISABLED,
-            MAX_PPP_INACTIVITY_TIMER_EXPIRED,
+            PPP_INACTIVITY_TIMER_EXPIRED,
             IPV6_ADDRESS_TRANSFER_FAILED,
             TRAT_SWAP_FAILED,
             EHRPD_TO_HRPD_FALLBACK,
             MIP_CONFIG_FAILURE,
             PDN_INACTIVITY_TIMER_EXPIRED,
-            MAX_IPV4_CONNECTIONS,
-            MAX_IPV6_CONNECTIONS,
+            IPV4_CONNECTIONS_LIMIT_REACHED,
+            IPV6_CONNECTIONS_LIMIT_REACHED,
             APN_MISMATCH,
             IP_VERSION_MISMATCH,
             DUN_CALL_DISALLOWED,
@@ -1112,7 +1112,7 @@
             CDMA_INCOMING_CALL,
             CDMA_ALERT_STOP,
             CHANNEL_ACQUISITION_FAILURE,
-            MAX_ACCESS_PROBE,
+            ACCESS_PROBE_LIMIT_REACHED,
             CONCURRENT_SERVICE_NOT_SUPPORTED_BY_BASE_STATION,
             NO_RESPONSE_FROM_BASE_STATION,
             REJECTED_BY_BASE_STATION,
@@ -1447,14 +1447,14 @@
         sFailCauseMap.put(SIM_CARD_CHANGED, "SIM_CARD_CHANGED");
         sFailCauseMap.put(LOW_POWER_MODE_OR_POWERING_DOWN, "LOW_POWER_MODE_OR_POWERING_DOWN");
         sFailCauseMap.put(APN_DISABLED, "APN_DISABLED");
-        sFailCauseMap.put(MAX_PPP_INACTIVITY_TIMER_EXPIRED, "MAX_PPP_INACTIVITY_TIMER_EXPIRED");
+        sFailCauseMap.put(PPP_INACTIVITY_TIMER_EXPIRED, "PPP_INACTIVITY_TIMER_EXPIRED");
         sFailCauseMap.put(IPV6_ADDRESS_TRANSFER_FAILED, "IPV6_ADDRESS_TRANSFER_FAILED");
         sFailCauseMap.put(TRAT_SWAP_FAILED, "TRAT_SWAP_FAILED");
         sFailCauseMap.put(EHRPD_TO_HRPD_FALLBACK, "EHRPD_TO_HRPD_FALLBACK");
         sFailCauseMap.put(MIP_CONFIG_FAILURE, "MIP_CONFIG_FAILURE");
         sFailCauseMap.put(PDN_INACTIVITY_TIMER_EXPIRED, "PDN_INACTIVITY_TIMER_EXPIRED");
-        sFailCauseMap.put(MAX_IPV4_CONNECTIONS, "MAX_IPV4_CONNECTIONS");
-        sFailCauseMap.put(MAX_IPV6_CONNECTIONS, "MAX_IPV6_CONNECTIONS");
+        sFailCauseMap.put(IPV4_CONNECTIONS_LIMIT_REACHED, "IPV4_CONNECTIONS_LIMIT_REACHED");
+        sFailCauseMap.put(IPV6_CONNECTIONS_LIMIT_REACHED, "IPV6_CONNECTIONS_LIMIT_REACHED");
         sFailCauseMap.put(APN_MISMATCH, "APN_MISMATCH");
         sFailCauseMap.put(IP_VERSION_MISMATCH, "IP_VERSION_MISMATCH");
         sFailCauseMap.put(DUN_CALL_DISALLOWED, "DUN_CALL_DISALLOWED");
@@ -1480,7 +1480,7 @@
         sFailCauseMap.put(CDMA_INCOMING_CALL, "CDMA_INCOMING_CALL");
         sFailCauseMap.put(CDMA_ALERT_STOP, "CDMA_ALERT_STOP");
         sFailCauseMap.put(CHANNEL_ACQUISITION_FAILURE, "CHANNEL_ACQUISITION_FAILURE");
-        sFailCauseMap.put(MAX_ACCESS_PROBE, "MAX_ACCESS_PROBE");
+        sFailCauseMap.put(ACCESS_PROBE_LIMIT_REACHED, "ACCESS_PROBE_LIMIT_REACHED");
         sFailCauseMap.put(CONCURRENT_SERVICE_NOT_SUPPORTED_BY_BASE_STATION,
                 "CONCURRENT_SERVICE_NOT_SUPPORTED_BY_BASE_STATION");
         sFailCauseMap.put(NO_RESPONSE_FROM_BASE_STATION, "NO_RESPONSE_FROM_BASE_STATION");
diff --git a/telephony/java/android/telephony/INetworkService.aidl b/telephony/java/android/telephony/INetworkService.aidl
index 9ef7186..67e5650 100644
--- a/telephony/java/android/telephony/INetworkService.aidl
+++ b/telephony/java/android/telephony/INetworkService.aidl
@@ -25,7 +25,7 @@
 {
     void createNetworkServiceProvider(int slotId);
     void removeNetworkServiceProvider(int slotId);
-    void getNetworkRegistrationState(int slotId, int domain, INetworkServiceCallback callback);
-    void registerForNetworkRegistrationStateChanged(int slotId, INetworkServiceCallback callback);
-    void unregisterForNetworkRegistrationStateChanged(int slotId, INetworkServiceCallback callback);
+    void getNetworkRegistrationInfo(int slotId, int domain, INetworkServiceCallback callback);
+    void registerForNetworkRegistrationInfoChanged(int slotId, INetworkServiceCallback callback);
+    void unregisterForNetworkRegistrationInfoChanged(int slotId, INetworkServiceCallback callback);
 }
diff --git a/telephony/java/android/telephony/INetworkServiceCallback.aidl b/telephony/java/android/telephony/INetworkServiceCallback.aidl
index 520598f..33b3ac0 100644
--- a/telephony/java/android/telephony/INetworkServiceCallback.aidl
+++ b/telephony/java/android/telephony/INetworkServiceCallback.aidl
@@ -16,7 +16,7 @@
 
 package android.telephony;
 
-import android.telephony.NetworkRegistrationState;
+import android.telephony.NetworkRegistrationInfo;
 
 /**
  * Network service call back interface
@@ -24,6 +24,6 @@
  */
 oneway interface INetworkServiceCallback
 {
-    void onGetNetworkRegistrationStateComplete(int result, in NetworkRegistrationState state);
+    void onGetNetworkRegistrationInfoComplete(int result, in NetworkRegistrationInfo state);
     void onNetworkStateChanged();
 }
diff --git a/telephony/java/android/telephony/NetworkRegistrationState.aidl b/telephony/java/android/telephony/NetworkRegistrationInfo.aidl
similarity index 94%
rename from telephony/java/android/telephony/NetworkRegistrationState.aidl
rename to telephony/java/android/telephony/NetworkRegistrationInfo.aidl
index 98cba77..5c803bf 100644
--- a/telephony/java/android/telephony/NetworkRegistrationState.aidl
+++ b/telephony/java/android/telephony/NetworkRegistrationInfo.aidl
@@ -16,4 +16,4 @@
 
 package android.telephony;
 
-parcelable NetworkRegistrationState;
+parcelable NetworkRegistrationInfo;
diff --git a/telephony/java/android/telephony/NetworkRegistrationState.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java
similarity index 85%
rename from telephony/java/android/telephony/NetworkRegistrationState.java
rename to telephony/java/android/telephony/NetworkRegistrationInfo.java
index a6c81db..c31a14e 100644
--- a/telephony/java/android/telephony/NetworkRegistrationState.java
+++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java
@@ -32,11 +32,11 @@
 import java.util.stream.Collectors;
 
 /**
- * Description of a mobile network registration state
+ * Description of a mobile network registration info
  * @hide
  */
 @SystemApi
-public class NetworkRegistrationState implements Parcelable {
+public class NetworkRegistrationInfo implements Parcelable {
     /**
      * Network domain
      * @hide
@@ -129,7 +129,6 @@
     @Domain
     private final int mDomain;
 
-    /** {@link TransportType} */
     private final int mTransportType;
 
     @RegState
@@ -165,14 +164,15 @@
     private DataSpecificRegistrationStates mDataSpecificStates;
 
     /**
-     * @param domain Network domain. Must be a {@link Domain}. For {@link TransportType#WLAN}
-     * transport, this must set to {@link #DOMAIN_PS}.
-     * @param transportType Transport type. Must be one of the{@link TransportType}.
+     * @param domain Network domain. Must be a {@link Domain}. For transport type
+     * {@link AccessNetworkConstants#TRANSPORT_TYPE_WLAN}, this must set to {@link #DOMAIN_PS}.
+     * @param transportType Transport type.
      * @param regState Network registration state. Must be one of the {@link RegState}. For
-     * {@link TransportType#WLAN} transport, only {@link #REG_STATE_HOME} and
-     * {@link #REG_STATE_NOT_REG_NOT_SEARCHING} are valid states.
-     * @param accessNetworkTechnology Access network technology.For {@link TransportType#WLAN}
-     * transport, set to {@link TelephonyManager#NETWORK_TYPE_IWLAN}.
+     * transport type {@link AccessNetworkConstants#TRANSPORT_TYPE_WLAN}, only
+     * {@link #REG_STATE_HOME} and {@link #REG_STATE_NOT_REG_NOT_SEARCHING} are valid states.
+     * @param accessNetworkTechnology Access network technology.For transport type
+     * {@link AccessNetworkConstants#TRANSPORT_TYPE_WLAN}, set to
+     * {@link TelephonyManager#NETWORK_TYPE_IWLAN}.
      * @param rejectCause Reason for denial if the registration state is {@link #REG_STATE_DENIED}.
      * Depending on {@code accessNetworkTechnology}, the values are defined in 3GPP TS 24.008
      * 10.5.3.6 for UMTS, 3GPP TS 24.301 9.9.3.9 for LTE, and 3GPP2 A.S0001 6.2.2.44 for CDMA. If
@@ -184,11 +184,12 @@
      * @param cellIdentity The identity representing a unique cell or wifi AP. Set to null if the
      * information is not available.
      */
-    public NetworkRegistrationState(@Domain int domain, int transportType, @RegState int regState,
-                                    @NetworkType int accessNetworkTechnology, int rejectCause,
-                                    boolean emergencyOnly,
-                                    @NonNull @ServiceType int[] availableServices,
-                                    @Nullable CellIdentity cellIdentity) {
+    public NetworkRegistrationInfo(@Domain int domain, @TransportType int transportType,
+                                   @RegState int regState,
+                                   @NetworkType int accessNetworkTechnology, int rejectCause,
+                                   boolean emergencyOnly,
+                                   @NonNull @ServiceType int[] availableServices,
+                                   @Nullable CellIdentity cellIdentity) {
         mDomain = domain;
         mTransportType = transportType;
         mRegState = regState;
@@ -203,13 +204,15 @@
     }
 
     /**
-     * Constructor for voice network registration states.
+     * Constructor for voice network registration info.
      * @hide
      */
-    public NetworkRegistrationState(int domain, int transportType, int regState,
-            int accessNetworkTechnology, int rejectCause, boolean emergencyOnly,
-            int[] availableServices, @Nullable CellIdentity cellIdentity, boolean cssSupported,
-            int roamingIndicator, int systemIsInPrl, int defaultRoamingIndicator) {
+    public NetworkRegistrationInfo(int domain, @TransportType int transportType, int regState,
+                                   int accessNetworkTechnology, int rejectCause,
+                                   boolean emergencyOnly, int[] availableServices,
+                                   @Nullable CellIdentity cellIdentity, boolean cssSupported,
+                                   int roamingIndicator, int systemIsInPrl,
+                                   int defaultRoamingIndicator) {
         this(domain, transportType, regState, accessNetworkTechnology, rejectCause, emergencyOnly,
                 availableServices, cellIdentity);
 
@@ -218,14 +221,16 @@
     }
 
     /**
-     * Constructor for data network registration states.
+     * Constructor for data network registration info.
      * @hide
      */
-    public NetworkRegistrationState(int domain, int transportType, int regState,
-            int accessNetworkTechnology, int rejectCause, boolean emergencyOnly,
-            int[] availableServices, @Nullable CellIdentity cellIdentity, int maxDataCalls,
-            boolean isDcNrRestricted, boolean isNrAvailable, boolean isEndcAvailable,
-            LteVopsSupportInfo lteVopsSupportInfo) {
+    public NetworkRegistrationInfo(int domain, @TransportType int transportType, int regState,
+                                   int accessNetworkTechnology, int rejectCause,
+                                   boolean emergencyOnly, int[] availableServices,
+                                   @Nullable CellIdentity cellIdentity, int maxDataCalls,
+                                   boolean isDcNrRestricted, boolean isNrAvailable,
+                                   boolean isEndcAvailable,
+                                   LteVopsSupportInfo lteVopsSupportInfo) {
         this(domain, transportType, regState, accessNetworkTechnology, rejectCause, emergencyOnly,
                 availableServices, cellIdentity);
 
@@ -234,7 +239,7 @@
         updateNrStatus(mDataSpecificStates);
     }
 
-    private NetworkRegistrationState(Parcel source) {
+    private NetworkRegistrationInfo(Parcel source) {
         mDomain = source.readInt();
         mTransportType = source.readInt();
         mRegState = source.readInt();
@@ -432,9 +437,10 @@
 
     @Override
     public String toString() {
-        return new StringBuilder("NetworkRegistrationState{")
+        return new StringBuilder("NetworkRegistrationInfo{")
                 .append(" domain=").append((mDomain == DOMAIN_CS) ? "CS" : "PS")
-                .append(" transportType=").append(TransportType.toString(mTransportType))
+                .append(" transportType=").append(
+                        AccessNetworkConstants.transportTypeToString(mTransportType))
                 .append(" regState=").append(regStateToString(mRegState))
                 .append(" roamingType=").append(ServiceState.roamingTypeToString(mRoamingType))
                 .append(" accessNetworkTechnology=")
@@ -463,11 +469,11 @@
     public boolean equals(Object o) {
         if (this == o) return true;
 
-        if (!(o instanceof NetworkRegistrationState)) {
+        if (!(o instanceof NetworkRegistrationInfo)) {
             return false;
         }
 
-        NetworkRegistrationState other = (NetworkRegistrationState) o;
+        NetworkRegistrationInfo other = (NetworkRegistrationInfo) o;
         return mDomain == other.mDomain
                 && mTransportType == other.mTransportType
                 && mRegState == other.mRegState
@@ -526,46 +532,46 @@
         }
     }
 
-    public static final @android.annotation.NonNull Parcelable.Creator<NetworkRegistrationState> CREATOR =
-            new Parcelable.Creator<NetworkRegistrationState>() {
-        @Override
-        public NetworkRegistrationState createFromParcel(Parcel source) {
-            return new NetworkRegistrationState(source);
-        }
+    public static final @NonNull Parcelable.Creator<NetworkRegistrationInfo> CREATOR =
+            new Parcelable.Creator<NetworkRegistrationInfo>() {
+                @Override
+                public NetworkRegistrationInfo createFromParcel(Parcel source) {
+                    return new NetworkRegistrationInfo(source);
+                }
 
-        @Override
-        public NetworkRegistrationState[] newArray(int size) {
-            return new NetworkRegistrationState[size];
-        }
-    };
+                @Override
+                public NetworkRegistrationInfo[] newArray(int size) {
+                    return new NetworkRegistrationInfo[size];
+                }
+            };
 
     /**
      * @hide
      */
-    public NetworkRegistrationState sanitizeLocationInfo() {
-        NetworkRegistrationState result = copy();
+    public NetworkRegistrationInfo sanitizeLocationInfo() {
+        NetworkRegistrationInfo result = copy();
         result.mCellIdentity = null;
         return result;
     }
 
-    private NetworkRegistrationState copy() {
+    private NetworkRegistrationInfo copy() {
         Parcel p = Parcel.obtain();
         this.writeToParcel(p, 0);
         p.setDataPosition(0);
-        NetworkRegistrationState result = new NetworkRegistrationState(p);
+        NetworkRegistrationInfo result = new NetworkRegistrationInfo(p);
         p.recycle();
         return result;
     }
 
     /**
-     * Provides a convenient way to set the fields of a {@link NetworkRegistrationState} when
+     * Provides a convenient way to set the fields of a {@link NetworkRegistrationInfo} when
      * creating a new instance.
      *
-     * <p>The example below shows how you might create a new {@code NetworkRegistrationState}:
+     * <p>The example below shows how you might create a new {@code NetworkRegistrationInfo}:
      *
      * <pre><code>
      *
-     * NetworkRegistrationState nrs = new NetworkRegistrationState.Builder()
+     * NetworkRegistrationInfo nrs = new NetworkRegistrationInfo.Builder()
      *     .setApnTypeBitmask(ApnSetting.TYPE_DEFAULT | ApnSetting.TYPE_MMS)
      *     .setApnName("apn.example.com")
      *     .setEntryName("Example Carrier APN")
@@ -627,7 +633,7 @@
          *
          * @return The same instance of the builder.
          */
-        public @NonNull Builder setTransportType(int transportType) {
+        public @NonNull Builder setTransportType(@TransportType int transportType) {
             mTransportType = transportType;
             return this;
         }
@@ -734,12 +740,12 @@
         }
 
         /**
-         * Build the NetworkRegistrationState.
+         * Build the NetworkRegistrationInfo.
          *
-         * @return the NetworkRegistrationState object.
+         * @return the NetworkRegistrationInfo object.
          */
-        public @NonNull NetworkRegistrationState build() {
-            return new NetworkRegistrationState(mDomain, mTransportType, mRegState,
+        public @NonNull NetworkRegistrationInfo build() {
+            return new NetworkRegistrationInfo(mDomain, mTransportType, mRegState,
                     mAccessNetworkTechnology, mRejectCause, mEmergencyOnly, mAvailableServices,
                     mCellIdentity);
         }
diff --git a/telephony/java/android/telephony/NetworkService.java b/telephony/java/android/telephony/NetworkService.java
index f1240e9..bc989dd 100644
--- a/telephony/java/android/telephony/NetworkService.java
+++ b/telephony/java/android/telephony/NetworkService.java
@@ -27,7 +27,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
-import android.telephony.NetworkRegistrationState.Domain;
+import android.telephony.NetworkRegistrationInfo.Domain;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -59,10 +59,10 @@
     private static final int NETWORK_SERVICE_CREATE_NETWORK_SERVICE_PROVIDER                 = 1;
     private static final int NETWORK_SERVICE_REMOVE_NETWORK_SERVICE_PROVIDER                 = 2;
     private static final int NETWORK_SERVICE_REMOVE_ALL_NETWORK_SERVICE_PROVIDERS            = 3;
-    private static final int NETWORK_SERVICE_GET_REGISTRATION_STATE                          = 4;
-    private static final int NETWORK_SERVICE_REGISTER_FOR_STATE_CHANGE                       = 5;
-    private static final int NETWORK_SERVICE_UNREGISTER_FOR_STATE_CHANGE                     = 6;
-    private static final int NETWORK_SERVICE_INDICATION_NETWORK_STATE_CHANGED                = 7;
+    private static final int NETWORK_SERVICE_GET_REGISTRATION_INFO                           = 4;
+    private static final int NETWORK_SERVICE_REGISTER_FOR_INFO_CHANGE                        = 5;
+    private static final int NETWORK_SERVICE_UNREGISTER_FOR_INFO_CHANGE                      = 6;
+    private static final int NETWORK_SERVICE_INDICATION_NETWORK_INFO_CHANGED                 = 7;
 
 
     private final HandlerThread mHandlerThread;
@@ -86,7 +86,7 @@
         private final int mSlotIndex;
 
         private final List<INetworkServiceCallback>
-                mNetworkRegistrationStateChangedCallbacks = new ArrayList<>();
+                mNetworkRegistrationInfoChangedCallbacks = new ArrayList<>();
 
         /**
          * Constructor
@@ -104,38 +104,38 @@
         }
 
         /**
-         * API to get network registration state. The result will be passed to the callback.
+         * API to get network registration info. The result will be passed to the callback.
          * @param domain Network domain
-         * @param callback The callback for reporting network registration state
+         * @param callback The callback for reporting network registration info
          */
-        public void getNetworkRegistrationState(@Domain int domain,
-                                                @NonNull NetworkServiceCallback callback) {
-            callback.onGetNetworkRegistrationStateComplete(
+        public void getNetworkRegistrationInfo(@Domain int domain,
+                                               @NonNull NetworkServiceCallback callback) {
+            callback.onGetNetworkRegistrationInfoComplete(
                     NetworkServiceCallback.RESULT_ERROR_UNSUPPORTED, null);
         }
 
         /**
-         * Notify the system that network registration state is changed.
+         * Notify the system that network registration info is changed.
          */
-        public final void notifyNetworkRegistrationStateChanged() {
-            mHandler.obtainMessage(NETWORK_SERVICE_INDICATION_NETWORK_STATE_CHANGED,
+        public final void notifyNetworkRegistrationInfoChanged() {
+            mHandler.obtainMessage(NETWORK_SERVICE_INDICATION_NETWORK_INFO_CHANGED,
                     mSlotIndex, 0, null).sendToTarget();
         }
 
-        private void registerForStateChanged(@NonNull INetworkServiceCallback callback) {
-            synchronized (mNetworkRegistrationStateChangedCallbacks) {
-                mNetworkRegistrationStateChangedCallbacks.add(callback);
+        private void registerForInfoChanged(@NonNull INetworkServiceCallback callback) {
+            synchronized (mNetworkRegistrationInfoChangedCallbacks) {
+                mNetworkRegistrationInfoChangedCallbacks.add(callback);
             }
         }
 
-        private void unregisterForStateChanged(@NonNull INetworkServiceCallback callback) {
-            synchronized (mNetworkRegistrationStateChangedCallbacks) {
-                mNetworkRegistrationStateChangedCallbacks.remove(callback);
+        private void unregisterForInfoChanged(@NonNull INetworkServiceCallback callback) {
+            synchronized (mNetworkRegistrationInfoChangedCallbacks) {
+                mNetworkRegistrationInfoChangedCallbacks.remove(callback);
             }
         }
 
-        private void notifyStateChangedToCallbacks() {
-            for (INetworkServiceCallback callback : mNetworkRegistrationStateChangedCallbacks) {
+        private void notifyInfoChangedToCallbacks() {
+            for (INetworkServiceCallback callback : mNetworkRegistrationInfoChangedCallbacks) {
                 try {
                     callback.onNetworkStateChanged();
                 } catch (RemoteException exception) {
@@ -189,24 +189,24 @@
                     }
                     mServiceMap.clear();
                     break;
-                case NETWORK_SERVICE_GET_REGISTRATION_STATE:
+                case NETWORK_SERVICE_GET_REGISTRATION_INFO:
                     if (serviceProvider == null) break;
                     int domainId = message.arg2;
-                    serviceProvider.getNetworkRegistrationState(domainId,
+                    serviceProvider.getNetworkRegistrationInfo(domainId,
                             new NetworkServiceCallback(callback));
 
                     break;
-                case NETWORK_SERVICE_REGISTER_FOR_STATE_CHANGE:
+                case NETWORK_SERVICE_REGISTER_FOR_INFO_CHANGE:
                     if (serviceProvider == null) break;
-                    serviceProvider.registerForStateChanged(callback);
+                    serviceProvider.registerForInfoChanged(callback);
                     break;
-                case NETWORK_SERVICE_UNREGISTER_FOR_STATE_CHANGE:
+                case NETWORK_SERVICE_UNREGISTER_FOR_INFO_CHANGE:
                     if (serviceProvider == null) break;
-                    serviceProvider.unregisterForStateChanged(callback);
+                    serviceProvider.unregisterForInfoChanged(callback);
                     break;
-                case NETWORK_SERVICE_INDICATION_NETWORK_STATE_CHANGED:
+                case NETWORK_SERVICE_INDICATION_NETWORK_INFO_CHANGED:
                     if (serviceProvider == null) break;
-                    serviceProvider.notifyStateChangedToCallbacks();
+                    serviceProvider.notifyInfoChangedToCallbacks();
                     break;
                 default:
                     break;
@@ -280,23 +280,23 @@
         }
 
         @Override
-        public void getNetworkRegistrationState(
+        public void getNetworkRegistrationInfo(
                 int slotIndex, int domain, INetworkServiceCallback callback) {
-            mHandler.obtainMessage(NETWORK_SERVICE_GET_REGISTRATION_STATE, slotIndex,
+            mHandler.obtainMessage(NETWORK_SERVICE_GET_REGISTRATION_INFO, slotIndex,
                     domain, callback).sendToTarget();
         }
 
         @Override
-        public void registerForNetworkRegistrationStateChanged(
+        public void registerForNetworkRegistrationInfoChanged(
                 int slotIndex, INetworkServiceCallback callback) {
-            mHandler.obtainMessage(NETWORK_SERVICE_REGISTER_FOR_STATE_CHANGE, slotIndex,
+            mHandler.obtainMessage(NETWORK_SERVICE_REGISTER_FOR_INFO_CHANGE, slotIndex,
                     0, callback).sendToTarget();
         }
 
         @Override
-        public void unregisterForNetworkRegistrationStateChanged(
+        public void unregisterForNetworkRegistrationInfoChanged(
                 int slotIndex, INetworkServiceCallback callback) {
-            mHandler.obtainMessage(NETWORK_SERVICE_UNREGISTER_FOR_STATE_CHANGE, slotIndex,
+            mHandler.obtainMessage(NETWORK_SERVICE_UNREGISTER_FOR_INFO_CHANGE, slotIndex,
                     0, callback).sendToTarget();
         }
     }
diff --git a/telephony/java/android/telephony/NetworkServiceCallback.java b/telephony/java/android/telephony/NetworkServiceCallback.java
index c2fcfb7..cc25240 100644
--- a/telephony/java/android/telephony/NetworkServiceCallback.java
+++ b/telephony/java/android/telephony/NetworkServiceCallback.java
@@ -28,8 +28,8 @@
 
 /**
  * Network service callback. Object of this class is passed to NetworkServiceProvider upon
- * calling getNetworkRegistrationState, to receive asynchronous feedback from NetworkServiceProvider
- * upon onGetNetworkRegistrationStateComplete. It's like a wrapper of INetworkServiceCallback
+ * calling getNetworkRegistrationInfo, to receive asynchronous feedback from NetworkServiceProvider
+ * upon onGetNetworkRegistrationInfoComplete. It's like a wrapper of INetworkServiceCallback
  * because INetworkServiceCallback can't be a parameter type in public APIs.
  *
  * @hide
@@ -70,20 +70,20 @@
 
     /**
      * Called to indicate result of
-     * {@link NetworkServiceProvider#getNetworkRegistrationState(int, NetworkServiceCallback)}
+     * {@link NetworkServiceProvider#getNetworkRegistrationInfo(int, NetworkServiceCallback)}
      *
      * @param result Result status like {@link NetworkServiceCallback#RESULT_SUCCESS} or
      *                {@link NetworkServiceCallback#RESULT_ERROR_UNSUPPORTED}
      * @param state The state information to be returned to callback.
      */
-    public void onGetNetworkRegistrationStateComplete(int result,
-                                                      @Nullable NetworkRegistrationState state) {
+    public void onGetNetworkRegistrationInfoComplete(int result,
+                                                      @Nullable NetworkRegistrationInfo state) {
         INetworkServiceCallback callback = mCallback.get();
         if (callback != null) {
             try {
-                callback.onGetNetworkRegistrationStateComplete(result, state);
+                callback.onGetNetworkRegistrationInfoComplete(result, state);
             } catch (RemoteException e) {
-                Rlog.e(mTag, "Failed to onGetNetworkRegistrationStateComplete on the remote");
+                Rlog.e(mTag, "Failed to onGetNetworkRegistrationInfoComplete on the remote");
             }
         } else {
             Rlog.e(mTag, "Weak reference of callback is null.");
diff --git a/telephony/java/android/telephony/RadioAccessFamily.java b/telephony/java/android/telephony/RadioAccessFamily.java
index 48c07e8..28f6515 100644
--- a/telephony/java/android/telephony/RadioAccessFamily.java
+++ b/telephony/java/android/telephony/RadioAccessFamily.java
@@ -397,81 +397,4 @@
         }
         return result;
     }
-
-    /**
-     * convert RAF from {@link android.hardware.radio.V1_0.RadioAccessFamily} to
-     * {@link TelephonyManager.NetworkTypeBitMask}, the bitmask represented by
-     * {@link TelephonyManager.NetworkType}.
-     *
-     * @param raf {@link android.hardware.radio.V1_0.RadioAccessFamily}
-     * @return {@link TelephonyManager.NetworkTypeBitMask}
-     */
-    public static int convertToNetworkTypeBitMask(int raf) {
-        int networkTypeRaf = 0;
-
-        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.GSM) != 0) {
-            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_GSM;
-        }
-        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.GPRS) != 0) {
-            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_GPRS;
-        }
-        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.EDGE) != 0) {
-            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_EDGE;
-        }
-        // convert both IS95A/IS95B to CDMA as network mode doesn't support CDMA
-        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.IS95A) != 0) {
-            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_CDMA;
-        }
-        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.IS95B) != 0) {
-            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_CDMA;
-        }
-        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.ONE_X_RTT) != 0) {
-            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_1xRTT;
-        }
-        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.EVDO_0) != 0) {
-            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_0;
-        }
-        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.EVDO_A) != 0) {
-            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_A;
-        }
-        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.EVDO_B) != 0) {
-            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_B;
-        }
-        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.EHRPD) != 0) {
-            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_EHRPD;
-        }
-        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.HSUPA) != 0) {
-            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_HSUPA;
-        }
-        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.HSDPA) != 0) {
-            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_HSDPA;
-        }
-        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.HSPA) != 0) {
-            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_HSPA;
-        }
-        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.HSPAP) != 0) {
-            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_HSPAP;
-        }
-        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.UMTS) != 0) {
-            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_UMTS;
-        }
-        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.TD_SCDMA) != 0) {
-            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_TD_SCDMA;
-        }
-        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.LTE) != 0) {
-            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_LTE;
-        }
-        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.LTE_CA) != 0) {
-            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_LTE_CA;
-        }
-        if ((raf & android.hardware.radio.V1_4.RadioAccessFamily.NR) != 0) {
-            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_NR;
-        }
-        // TODO: need hal definition
-        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN)) != 0) {
-            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_IWLAN;
-        }
-
-        return (networkTypeRaf == 0) ? TelephonyManager.NETWORK_TYPE_UNKNOWN : networkTypeRaf;
-    }
 }
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index bddf978..adbe295 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -28,8 +28,9 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.AccessNetworkConstants.AccessNetworkType;
-import android.telephony.NetworkRegistrationState.Domain;
-import android.telephony.NetworkRegistrationState.NRStatus;
+import android.telephony.AccessNetworkConstants.TransportType;
+import android.telephony.NetworkRegistrationInfo.Domain;
+import android.telephony.NetworkRegistrationInfo.NRStatus;
 import android.text.TextUtils;
 
 import java.lang.annotation.Retention;
@@ -348,7 +349,7 @@
      * Reference: 3GPP TS 36.104 5.4.3 */
     private int mLteEarfcnRsrpBoost = 0;
 
-    private List<NetworkRegistrationState> mNetworkRegistrationStates = new ArrayList<>();
+    private List<NetworkRegistrationInfo> mNetworkRegistrationInfos = new ArrayList<>();
 
     /**
      * get String description of roaming type
@@ -431,8 +432,8 @@
         mCellBandwidths = s.mCellBandwidths == null ? null :
                 Arrays.copyOf(s.mCellBandwidths, s.mCellBandwidths.length);
         mLteEarfcnRsrpBoost = s.mLteEarfcnRsrpBoost;
-        mNetworkRegistrationStates = s.mNetworkRegistrationStates == null ? null :
-                new ArrayList<>(s.mNetworkRegistrationStates);
+        mNetworkRegistrationInfos = s.mNetworkRegistrationInfos == null ? null :
+                new ArrayList<>(s.mNetworkRegistrationInfos);
         mNrFrequencyRange = s.mNrFrequencyRange;
     }
 
@@ -465,8 +466,8 @@
         mIsEmergencyOnly = in.readInt() != 0;
         mIsUsingCarrierAggregation = in.readInt() != 0;
         mLteEarfcnRsrpBoost = in.readInt();
-        mNetworkRegistrationStates = new ArrayList<>();
-        in.readList(mNetworkRegistrationStates, NetworkRegistrationState.class.getClassLoader());
+        mNetworkRegistrationInfos = new ArrayList<>();
+        in.readList(mNetworkRegistrationInfos, NetworkRegistrationInfo.class.getClassLoader());
         mChannelNumber = in.readInt();
         mCellBandwidths = in.createIntArray();
         mNrFrequencyRange = in.readInt();
@@ -494,7 +495,7 @@
         out.writeInt(mIsEmergencyOnly ? 1 : 0);
         out.writeInt(mIsUsingCarrierAggregation ? 1 : 0);
         out.writeInt(mLteEarfcnRsrpBoost);
-        out.writeList(mNetworkRegistrationStates);
+        out.writeList(mNetworkRegistrationInfos);
         out.writeInt(mChannelNumber);
         out.writeIntArray(mCellBandwidths);
         out.writeInt(mNrFrequencyRange);
@@ -619,8 +620,8 @@
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public @RoamingType int getVoiceRoamingType() {
-        final NetworkRegistrationState regState = getNetworkRegistrationState(
-                NetworkRegistrationState.DOMAIN_CS, AccessNetworkConstants.TransportType.WWAN);
+        final NetworkRegistrationInfo regState = getNetworkRegistrationInfo(
+                NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
         if (regState != null) {
             return regState.getRoamingType();
         }
@@ -643,10 +644,10 @@
      * @hide
      */
     public boolean getDataRoamingFromRegistration() {
-        final NetworkRegistrationState regState = getNetworkRegistrationState(
-                NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WWAN);
+        final NetworkRegistrationInfo regState = getNetworkRegistrationInfo(
+                NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
         if (regState != null) {
-            return (regState.getRegState() == NetworkRegistrationState.REG_STATE_ROAMING);
+            return (regState.getRegState() == NetworkRegistrationInfo.REG_STATE_ROAMING);
         }
         return false;
     }
@@ -658,8 +659,8 @@
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public @RoamingType int getDataRoamingType() {
-        final NetworkRegistrationState regState = getNetworkRegistrationState(
-                NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WWAN);
+        final NetworkRegistrationInfo regState = getNetworkRegistrationInfo(
+                NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
         if (regState != null) {
             return regState.getRoamingType();
         }
@@ -837,7 +838,7 @@
                 mVoiceRegState,
                 mDataRegState,
                 mChannelNumber,
-                mCellBandwidths,
+                Arrays.hashCode(mCellBandwidths),
                 mVoiceOperatorAlphaLong,
                 mVoiceOperatorAlphaShort,
                 mVoiceOperatorNumeric,
@@ -857,7 +858,7 @@
                 mIsEmergencyOnly,
                 mIsUsingCarrierAggregation,
                 mLteEarfcnRsrpBoost,
-                mNetworkRegistrationStates,
+                mNetworkRegistrationInfos,
                 mNrFrequencyRange);
     }
 
@@ -887,9 +888,9 @@
                         s.mCdmaDefaultRoamingIndicator)
                 && mIsEmergencyOnly == s.mIsEmergencyOnly
                 && mIsUsingCarrierAggregation == s.mIsUsingCarrierAggregation)
-                && (mNetworkRegistrationStates == null ? s.mNetworkRegistrationStates == null :
-                        s.mNetworkRegistrationStates != null &&
-                        mNetworkRegistrationStates.containsAll(s.mNetworkRegistrationStates))
+                && (mNetworkRegistrationInfos == null
+                ? s.mNetworkRegistrationInfos == null : s.mNetworkRegistrationInfos != null
+                && mNetworkRegistrationInfos.containsAll(s.mNetworkRegistrationInfos))
                 && mNrFrequencyRange == s.mNrFrequencyRange;
     }
 
@@ -1042,7 +1043,7 @@
             .append(", mIsEmergencyOnly=").append(mIsEmergencyOnly)
             .append(", mIsUsingCarrierAggregation=").append(mIsUsingCarrierAggregation)
             .append(", mLteEarfcnRsrpBoost=").append(mLteEarfcnRsrpBoost)
-            .append(", mNetworkRegistrationStates=").append(mNetworkRegistrationStates)
+            .append(", mNetworkRegistrationInfos=").append(mNetworkRegistrationInfos)
             .append(", mNrFrequencyRange=").append(mNrFrequencyRange)
             .append("}").toString();
     }
@@ -1072,7 +1073,7 @@
         mIsEmergencyOnly = false;
         mIsUsingCarrierAggregation = false;
         mLteEarfcnRsrpBoost = 0;
-        mNetworkRegistrationStates = new ArrayList<>();
+        mNetworkRegistrationInfos = new ArrayList<>();
         mNrFrequencyRange = FREQUENCY_RANGE_UNKNOWN;
     }
 
@@ -1129,14 +1130,14 @@
     /** @hide */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public void setVoiceRoamingType(@RoamingType int type) {
-        NetworkRegistrationState regState = getNetworkRegistrationState(
-                NetworkRegistrationState.DOMAIN_CS, AccessNetworkConstants.TransportType.WWAN);
+        NetworkRegistrationInfo regState = getNetworkRegistrationInfo(
+                NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
         if (regState == null) {
-            regState = new NetworkRegistrationState(
-                    NetworkRegistrationState.DOMAIN_CS, AccessNetworkConstants.TransportType.WWAN,
+            regState = new NetworkRegistrationInfo(
+                    NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
                     ServiceState.ROAMING_TYPE_NOT_ROAMING, TelephonyManager.NETWORK_TYPE_UNKNOWN, 0,
                     false, null, null);
-            addNetworkRegistrationState(regState);
+            addNetworkRegistrationInfo(regState);
         }
         regState.setRoamingType(type);
     }
@@ -1150,14 +1151,14 @@
     /** @hide */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public void setDataRoamingType(@RoamingType int type) {
-        NetworkRegistrationState regState = getNetworkRegistrationState(
-                NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WWAN);
+        NetworkRegistrationInfo regState = getNetworkRegistrationInfo(
+                NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
         if (regState == null) {
-            regState = new NetworkRegistrationState(
-                    NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WWAN,
+            regState = new NetworkRegistrationInfo(
+                    NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
                     ServiceState.ROAMING_TYPE_NOT_ROAMING, TelephonyManager.NETWORK_TYPE_UNKNOWN, 0,
                     false, null, null);
-            addNetworkRegistrationState(regState);
+            addNetworkRegistrationInfo(regState);
         }
         regState.setRoamingType(type);
     }
@@ -1325,14 +1326,14 @@
         this.mRilVoiceRadioTechnology = rt;
 
         // sync to network registration state
-        NetworkRegistrationState regState = getNetworkRegistrationState(
-                NetworkRegistrationState.DOMAIN_CS, AccessNetworkConstants.TransportType.WWAN);
+        NetworkRegistrationInfo regState = getNetworkRegistrationInfo(
+                NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
         if (regState == null) {
-            regState = new NetworkRegistrationState(
-                    NetworkRegistrationState.DOMAIN_CS, AccessNetworkConstants.TransportType.WWAN,
+            regState = new NetworkRegistrationInfo(
+                    NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
                     ServiceState.ROAMING_TYPE_NOT_ROAMING, TelephonyManager.NETWORK_TYPE_UNKNOWN,
                     0, false, null, null);
-            addNetworkRegistrationState(regState);
+            addNetworkRegistrationInfo(regState);
         }
         regState.setAccessNetworkTechnology(
                 rilRadioTechnologyToNetworkType(mRilVoiceRadioTechnology));
@@ -1352,15 +1353,15 @@
                 mRilDataRadioTechnology);
 
         // sync to network registration state
-        NetworkRegistrationState regState = getNetworkRegistrationState(
-                NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WWAN);
+        NetworkRegistrationInfo regState = getNetworkRegistrationInfo(
+                NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
 
         if (regState == null) {
-            regState = new NetworkRegistrationState(
-                    NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WWAN,
+            regState = new NetworkRegistrationInfo(
+                    NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
                     ServiceState.ROAMING_TYPE_NOT_ROAMING, TelephonyManager.NETWORK_TYPE_UNKNOWN,
                     0, false, null, null);
-            addNetworkRegistrationState(regState);
+            addNetworkRegistrationInfo(regState);
         }
         regState.setAccessNetworkTechnology(
                 rilRadioTechnologyToNetworkType(mRilDataRadioTechnology));
@@ -1390,9 +1391,9 @@
      * @hide
      */
     public @NRStatus int getNrStatus() {
-        final NetworkRegistrationState regState = getNetworkRegistrationState(
-                NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WWAN);
-        if (regState == null) return NetworkRegistrationState.NR_STATUS_NONE;
+        final NetworkRegistrationInfo regState = getNetworkRegistrationInfo(
+                NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+        if (regState == null) return NetworkRegistrationInfo.NR_STATUS_NONE;
         return regState.getNrStatus();
     }
 
@@ -1575,19 +1576,19 @@
     /** @hide */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public @TelephonyManager.NetworkType int getDataNetworkType() {
-        final NetworkRegistrationState iwlanRegState = getNetworkRegistrationState(
-                NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WLAN);
+        final NetworkRegistrationInfo iwlanRegState = getNetworkRegistrationInfo(
+                NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
         if (iwlanRegState != null
-                && iwlanRegState.getRegState() == NetworkRegistrationState.REG_STATE_HOME) {
+                && iwlanRegState.getRegState() == NetworkRegistrationInfo.REG_STATE_HOME) {
             // If the device is on IWLAN, return IWLAN as the network type. This is to simulate the
             // behavior of legacy mode device. In the future caller should use
-            // getNetworkRegistrationState() to retrieve the actual data network type on cellular
+            // getNetworkRegistrationInfo() to retrieve the actual data network type on cellular
             // or on IWLAN.
             return iwlanRegState.getAccessNetworkTechnology();
         }
 
-        final NetworkRegistrationState regState = getNetworkRegistrationState(
-                NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WWAN);
+        final NetworkRegistrationInfo regState = getNetworkRegistrationInfo(
+                NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
         if (regState != null) {
             return regState.getAccessNetworkTechnology();
         }
@@ -1597,8 +1598,8 @@
     /** @hide */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public @TelephonyManager.NetworkType int getVoiceNetworkType() {
-        final NetworkRegistrationState regState = getNetworkRegistrationState(
-                NetworkRegistrationState.DOMAIN_CS, AccessNetworkConstants.TransportType.WWAN);
+        final NetworkRegistrationInfo regState = getNetworkRegistrationInfo(
+                NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
         if (regState != null) {
             return regState.getAccessNetworkTechnology();
         }
@@ -1761,52 +1762,36 @@
     }
 
     /**
-     * Get all of the available network registration states.
+     * Get all of the available network registration info.
      *
-     * @return List of {@link NetworkRegistrationState}
+     * @return List of {@link NetworkRegistrationInfo}
      * @hide
      */
     @NonNull
     @SystemApi
-    public List<NetworkRegistrationState> getNetworkRegistrationStates() {
-        synchronized (mNetworkRegistrationStates) {
-            return new ArrayList<>(mNetworkRegistrationStates);
+    public List<NetworkRegistrationInfo> getNetworkRegistrationInfoList() {
+        synchronized (mNetworkRegistrationInfos) {
+            return new ArrayList<>(mNetworkRegistrationInfos);
         }
     }
 
     /**
-     * Get the network registration states for the transport type.
+     * Get the network registration info list for the transport type.
      *
-     * @param transportType The {@link AccessNetworkConstants.TransportType transport type}
-     * @return List of {@link NetworkRegistrationState}
-     * @hide
-     *
-     * @deprecated Use {@link #getNetworkRegistrationStatesFromTransportType(int)}
-     */
-    @NonNull
-    @Deprecated
-    @SystemApi
-    public List<NetworkRegistrationState> getNetworkRegistrationStates(int transportType) {
-        return getNetworkRegistrationStatesForTransportType(transportType);
-    }
-
-    /**
-     * Get the network registration states for the transport type.
-     *
-     * @param transportType The {@link AccessNetworkConstants.TransportType transport type}
-     * @return List of {@link NetworkRegistrationState}
+     * @param transportType The transport type
+     * @return List of {@link NetworkRegistrationInfo}
      * @hide
      */
     @NonNull
     @SystemApi
-    public List<NetworkRegistrationState> getNetworkRegistrationStatesForTransportType(
-            int transportType) {
-        List<NetworkRegistrationState> list = new ArrayList<>();
+    public List<NetworkRegistrationInfo> getNetworkRegistrationInfoListForTransportType(
+            @TransportType int transportType) {
+        List<NetworkRegistrationInfo> list = new ArrayList<>();
 
-        synchronized (mNetworkRegistrationStates) {
-            for (NetworkRegistrationState networkRegistrationState : mNetworkRegistrationStates) {
-                if (networkRegistrationState.getTransportType() == transportType) {
-                    list.add(networkRegistrationState);
+        synchronized (mNetworkRegistrationInfos) {
+            for (NetworkRegistrationInfo networkRegistrationInfo : mNetworkRegistrationInfos) {
+                if (networkRegistrationInfo.getTransportType() == transportType) {
+                    list.add(networkRegistrationInfo);
                 }
             }
         }
@@ -1815,22 +1800,22 @@
     }
 
     /**
-     * Get the network registration states for the network domain.
+     * Get the network registration info list for the network domain.
      *
-     * @param domain The network {@link NetworkRegistrationState.Domain domain}
-     * @return List of {@link NetworkRegistrationState}
+     * @param domain The network {@link NetworkRegistrationInfo.Domain domain}
+     * @return List of {@link NetworkRegistrationInfo}
      * @hide
      */
     @NonNull
     @SystemApi
-    public List<NetworkRegistrationState> getNetworkRegistrationStatesForDomain(
+    public List<NetworkRegistrationInfo> getNetworkRegistrationInfoListForDomain(
             @Domain int domain) {
-        List<NetworkRegistrationState> list = new ArrayList<>();
+        List<NetworkRegistrationInfo> list = new ArrayList<>();
 
-        synchronized (mNetworkRegistrationStates) {
-            for (NetworkRegistrationState networkRegistrationState : mNetworkRegistrationStates) {
-                if (networkRegistrationState.getDomain() == domain) {
-                    list.add(networkRegistrationState);
+        synchronized (mNetworkRegistrationInfos) {
+            for (NetworkRegistrationInfo networkRegistrationInfo : mNetworkRegistrationInfos) {
+                if (networkRegistrationInfo.getDomain() == domain) {
+                    list.add(networkRegistrationInfo);
                 }
             }
         }
@@ -1841,39 +1826,21 @@
     /**
      * Get the network registration state for the transport type and network domain.
      *
-     * @param domain The network {@link NetworkRegistrationState.Domain domain}
-     * @param transportType The {@link AccessNetworkConstants.TransportType transport type}
-     * @return The matching {@link NetworkRegistrationState}
-     * @hide
-     *
-     * @deprecated Use {@link #getNetworkRegistrationState(int, int)}
-     */
-    @Nullable
-    @Deprecated
-    @SystemApi
-    public NetworkRegistrationState getNetworkRegistrationStates(@Domain int domain,
-                                                                 int transportType) {
-        return getNetworkRegistrationState(domain, transportType);
-    }
-
-    /**
-     * Get the network registration state for the transport type and network domain.
-     *
-     * @param domain The network {@link NetworkRegistrationState.Domain domain}
-     * @param transportType The {@link AccessNetworkConstants.TransportType transport type}
-     * @return The matching {@link NetworkRegistrationState}
+     * @param domain The network {@link NetworkRegistrationInfo.Domain domain}
+     * @param transportType The transport type
+     * @return The matching {@link NetworkRegistrationInfo}
      * @hide
      *
      */
     @Nullable
     @SystemApi
-    public NetworkRegistrationState getNetworkRegistrationState(@Domain int domain,
-                                                                int transportType) {
-        synchronized (mNetworkRegistrationStates) {
-            for (NetworkRegistrationState networkRegistrationState : mNetworkRegistrationStates) {
-                if (networkRegistrationState.getTransportType() == transportType
-                        && networkRegistrationState.getDomain() == domain) {
-                    return networkRegistrationState;
+    public NetworkRegistrationInfo getNetworkRegistrationInfo(@Domain int domain,
+                                                              @TransportType int transportType) {
+        synchronized (mNetworkRegistrationInfos) {
+            for (NetworkRegistrationInfo networkRegistrationInfo : mNetworkRegistrationInfos) {
+                if (networkRegistrationInfo.getTransportType() == transportType
+                        && networkRegistrationInfo.getDomain() == domain) {
+                    return networkRegistrationInfo;
                 }
             }
         }
@@ -1884,20 +1851,20 @@
     /**
      * @hide
      */
-    public void addNetworkRegistrationState(NetworkRegistrationState regState) {
+    public void addNetworkRegistrationInfo(NetworkRegistrationInfo regState) {
         if (regState == null) return;
 
-        synchronized (mNetworkRegistrationStates) {
-            for (int i = 0; i < mNetworkRegistrationStates.size(); i++) {
-                NetworkRegistrationState curRegState = mNetworkRegistrationStates.get(i);
+        synchronized (mNetworkRegistrationInfos) {
+            for (int i = 0; i < mNetworkRegistrationInfos.size(); i++) {
+                NetworkRegistrationInfo curRegState = mNetworkRegistrationInfos.get(i);
                 if (curRegState.getTransportType() == regState.getTransportType()
                         && curRegState.getDomain() == regState.getDomain()) {
-                    mNetworkRegistrationStates.remove(i);
+                    mNetworkRegistrationInfos.remove(i);
                     break;
                 }
             }
 
-            mNetworkRegistrationStates.add(regState);
+            mNetworkRegistrationInfos.add(regState);
         }
     }
 
@@ -1912,15 +1879,15 @@
 
     /**
      * Returns a copy of self with location-identifying information removed.
-     * Always clears the NetworkRegistrationState's CellIdentity fields, but if removeCoarseLocation
+     * Always clears the NetworkRegistrationInfo's CellIdentity fields, but if removeCoarseLocation
      * is true, clears other info as well.
      * @hide
      */
     public ServiceState sanitizeLocationInfo(boolean removeCoarseLocation) {
         ServiceState state = new ServiceState(this);
-        if (state.mNetworkRegistrationStates != null) {
-            state.mNetworkRegistrationStates = state.mNetworkRegistrationStates.stream()
-                    .map(NetworkRegistrationState::sanitizeLocationInfo)
+        if (state.mNetworkRegistrationInfos != null) {
+            state.mNetworkRegistrationInfos = state.mNetworkRegistrationInfos.stream()
+                    .map(NetworkRegistrationInfo::sanitizeLocationInfo)
                     .collect(Collectors.toList());
         }
         if (!removeCoarseLocation) return state;
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index d9a37c6..3707aa4 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2009,21 +2009,27 @@
     }
 
     /**
-     * Checks if the supplied subscription ID is valid.
-     * Note: a valid subscription ID does not necessarily correspond to an active subscription.
+     * Check if the supplied subscription ID is valid.
+     *
+     * <p>A valid subscription ID is not necessarily an active subscription ID
+     * (see {@link #isActiveSubscriptionId(int)}) or an usable subscription ID
+     * (see {@link #isUsableSubscriptionId(int)}). Unless specifically noted, subscription
+     * APIs work with a valid subscription ID.
      *
      * @param subscriptionId The subscription ID.
-     * @return true if the supplied subscriptionId is valid; false otherwise.
+     * @return {@code true} if the supplied subscriptionId is valid; {@code false} otherwise.
      */
     public static boolean isValidSubscriptionId(int subscriptionId) {
         return subscriptionId > INVALID_SUBSCRIPTION_ID;
     }
 
     /**
-     * Check if the subscription ID is usable.
+     * Check if the supplied subscription ID is usable.
      *
-     * A usable subscription ID has a valid value except some special values such as
-     * {@link #DEFAULT_SUBSCRIPTION_ID}. It can be used for subscription functions.
+     * <p>A usable subscription ID is a valid subscription ID, but not necessarily an active
+     * subscription ID (see {@link #isActiveSubscriptionId(int)}). Some subscription APIs
+     * require a usable subscription ID, and this is noted in their documentation; otherwise, a
+     * subscription ID does not need to be usable for subscription functions, only valid.
      *
      * @param subscriptionId the subscription ID
      * @return {@code true} if the subscription ID is usable; {@code false} otherwise.
@@ -2281,7 +2287,8 @@
     }
 
     /**
-     * Checks if the supplied subscription ID corresponds to an active subscription.
+     * Checks if the supplied subscription ID corresponds to a subscription which is actively in
+     * use on the device. An active subscription ID is a valid and usable subscription ID.
      *
      * @param subscriptionId the subscription ID.
      * @return {@code true} if the supplied subscription ID corresponds to an active subscription;
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 16dafd6..99032bc 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -58,6 +58,8 @@
 import android.os.WorkSource;
 import android.provider.Settings.SettingNotFoundException;
 import android.service.carrier.CarrierIdentifier;
+import android.telecom.CallScreeningService;
+import android.telecom.InCallService;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
@@ -617,7 +619,13 @@
      * <p class="note">
      * Retrieve with
      * {@link android.content.Intent#getStringExtra(String)}.
+     * <p>
+     *
+     * @deprecated Companion apps for wearable devices should use the {@link InCallService} API
+     * to retrieve the phone number for calls instead.  Apps performing call screening should use
+     * the {@link CallScreeningService} API instead.
      */
+    @Deprecated
     public static final String EXTRA_INCOMING_NUMBER = "incoming_number";
 
     /**
@@ -1383,41 +1391,42 @@
      * in the application manifest. For performance reasons, if no application to receive these
      * events is detected at boot, then these events will not be sent.
      *
-     * <p>Each event will include an {@link EXTRA_DEBUG_EVENT_ID} that will uniquely identify the
+     * <p>Each event will include an {@link EXTRA_ANOMALY_ID} that will uniquely identify the
      * event that has occurred. Each event will be sent to the diagnostic monitor only once per
      * boot cycle (as another optimization).
      *
-     * @see #EXTRA_DEBUG_EVENT_ID
-     * @see #EXTRA_DEBUG_EVENT_DESCRIPTION
+     * @see #EXTRA_ANOMALY_ID
+     * @see #EXTRA_ANOMALY_DESCRIPTION
      * @hide
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
-    public static final String ACTION_DEBUG_EVENT = "android.telephony.action.DEBUG_EVENT";
+    public static final String ACTION_ANOMALY_REPORTED =
+            "android.telephony.action.ANOMALY_REPORTED";
 
     /**
      * An arbitrary ParcelUuid which should be consistent for each occurrence of a DebugEvent.
      *
-     * This field must be included in all {@link ACTION_DEBUG_EVENT} events.
+     * This field must be included in all {@link ACTION_ANOMALY_REPORTED} events.
      *
-     * @see #ACTION_DEBUG_EVENT
+     * @see #ACTION_ANOMALY_REPORTED
      * @hide
      */
     @SystemApi
-    public static final String EXTRA_DEBUG_EVENT_ID = "android.telephony.extra.DEBUG_EVENT_ID";
+    public static final String EXTRA_ANOMALY_ID = "android.telephony.extra.ANOMALY_ID";
 
     /**
-     * A freeform string description of the DebugEvent.
+     * A freeform string description of the Anomaly.
      *
-     * This field is optional for all {@link ACTION_DEBUG_EVENT}s, as a guideline should not
+     * This field is optional for all {@link ACTION_ANOMALY_REPORTED}s, as a guideline should not
      * exceed 80 characters, and should be as short as possible to convey the essence of the event.
      *
-     * @see #ACTION_DEBUG_EVENT
+     * @see #ACTION_ANOMALY_REPORTED
      * @hide
      */
     @SystemApi
-    public static final String EXTRA_DEBUG_EVENT_DESCRIPTION =
-            "android.telephony.extra.DEBUG_EVENT_DESCRIPTION";
+    public static final String EXTRA_ANOMALY_DESCRIPTION =
+            "android.telephony.extra.ANOMALY_DESCRIPTION";
 
     //
     //
@@ -3345,26 +3354,25 @@
     }
 
     /**
-     * Get the mapping from logical slots to physical slots. The mapping represent by a pair list.
-     * The key of the piar is the logical slot id and the value of the pair is the physical
-     * slots id mapped to this logical slot id.
+     * Get the mapping from logical slots to physical slots. The key of the map is the logical slot
+     * id and the value is the physical slots id mapped to this logical slot id.
      *
-     * @return an pair list indicates the mapping from logical slots to physical slots. The size of
-     * the list should be {@link #getPhoneCount()} if success, otherwise return an empty list.
+     * @return a map indicates the mapping from logical slots to physical slots. The size of the map
+     * should be {@link #getPhoneCount()} if success, otherwise return an empty map.
      *
      * @hide
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     @NonNull
-    public List<Pair<Integer, Integer>> getLogicalToPhysicalSlotMapping() {
-        List<Pair<Integer, Integer>> slotMapping = new ArrayList<>();
+    public Map<Integer, Integer> getLogicalToPhysicalSlotMapping() {
+        Map<Integer, Integer> slotMapping = new HashMap<>();
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
                 int[] slotMappingArray = telephony.getSlotsMapping();
                 for (int i = 0; i < slotMappingArray.length; i++) {
-                    slotMapping.add(new Pair(i, slotMappingArray[i]));
+                    slotMapping.put(i, slotMappingArray[i]);
                 }
             }
         } catch (RemoteException e) {
@@ -5188,6 +5196,40 @@
     }
 
     /**
+     * Opens a logical channel to the ICC card using the physical slot index.
+     *
+     * Use this method when no subscriptions are available on the SIM and the operation must be
+     * performed using the physical slot index.
+     *
+     * Input parameters equivalent to TS 27.007 AT+CCHO command.
+     *
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
+     *
+     * @param slotIndex the physical slot index of the ICC card
+     * @param aid Application id. See ETSI 102.221 and 101.220.
+     * @param p2 P2 parameter (described in ISO 7816-4).
+     * @return an IccOpenLogicalChannelResponse object.
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+    @SystemApi
+    @Nullable
+    public IccOpenLogicalChannelResponse iccOpenLogicalChannelBySlot(int slotIndex,
+            @Nullable String aid, int p2) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.iccOpenLogicalChannelBySlot(slotIndex, getOpPackageName(), aid,
+                        p2);
+            }
+        } catch (RemoteException ex) {
+        } catch (NullPointerException ex) {
+        }
+        return null;
+    }
+
+    /**
      * Opens a logical channel to the ICC card.
      *
      * Input parameters equivalent to TS 27.007 AT+CCHO command.
@@ -5231,6 +5273,38 @@
     }
 
     /**
+     * Closes a previously opened logical channel to the ICC card using the physical slot index.
+     *
+     * Use this method when no subscriptions are available on the SIM and the operation must be
+     * performed using the physical slot index.
+     *
+     * Input parameters equivalent to TS 27.007 AT+CCHC command.
+     *
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
+     *
+     * @param slotIndex the physical slot index of the ICC card
+     * @param channel is the channel id to be closed as returned by a successful
+     *            iccOpenLogicalChannel.
+     * @return true if the channel was closed successfully.
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+    @SystemApi
+    @Nullable
+    public boolean iccCloseLogicalChannelBySlot(int slotIndex, int channel) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.iccCloseLogicalChannelBySlot(slotIndex, channel);
+            }
+        } catch (RemoteException ex) {
+        } catch (NullPointerException ex) {
+        }
+        return false;
+    }
+
+    /**
      * Closes a previously opened logical channel to the ICC card.
      *
      * Input parameters equivalent to TS 27.007 AT+CCHC command.
@@ -5239,7 +5313,7 @@
      * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
      * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
-     * @param channel is the channel id to be closed as retruned by a successful
+     * @param channel is the channel id to be closed as returned by a successful
      *            iccOpenLogicalChannel.
      * @return true if the channel was closed successfully.
      */
@@ -5257,7 +5331,7 @@
      * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param subId The subscription to use.
-     * @param channel is the channel id to be closed as retruned by a successful
+     * @param channel is the channel id to be closed as returned by a successful
      *            iccOpenLogicalChannel.
      * @return true if the channel was closed successfully.
      * @hide
@@ -5274,6 +5348,48 @@
     }
 
     /**
+     * Transmit an APDU to the ICC card over a logical channel using the physical slot index.
+     *
+     * Use this method when no subscriptions are available on the SIM and the operation must be
+     * performed using the physical slot index.
+     *
+     * Input parameters equivalent to TS 27.007 AT+CGLA command.
+     *
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
+     *
+     * @param slotIndex the physical slot index of the ICC card
+     * @param channel is the channel id to be closed as returned by a successful
+     *            iccOpenLogicalChannel.
+     * @param cla Class of the APDU command.
+     * @param instruction Instruction of the APDU command.
+     * @param p1 P1 value of the APDU command.
+     * @param p2 P2 value of the APDU command.
+     * @param p3 P3 value of the APDU command. If p3 is negative a 4 byte APDU
+     *            is sent to the SIM.
+     * @param data Data to be sent with the APDU.
+     * @return The APDU response from the ICC card with the status appended at
+     *            the end.
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+    @SystemApi
+    @Nullable
+    public String iccTransmitApduLogicalChannelBySlot(int slotIndex, int channel, int cla,
+            int instruction, int p1, int p2, int p3, @Nullable String data) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.iccTransmitApduLogicalChannelBySlot(slotIndex, channel, cla,
+                        instruction, p1, p2, p3, data);
+            }
+        } catch (RemoteException ex) {
+        } catch (NullPointerException ex) {
+        }
+        return null;
+    }
+
+    /**
      * Transmit an APDU to the ICC card over a logical channel.
      *
      * Input parameters equivalent to TS 27.007 AT+CGLA command.
@@ -5337,6 +5453,46 @@
     }
 
     /**
+     * Transmit an APDU to the ICC card over the basic channel using the physical slot index.
+     *
+     * Use this method when no subscriptions are available on the SIM and the operation must be
+     * performed using the physical slot index.
+     *
+     * Input parameters equivalent to TS 27.007 AT+CSIM command.
+     *
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
+     *
+     * @param slotIndex the physical slot index of the ICC card to target
+     * @param cla Class of the APDU command.
+     * @param instruction Instruction of the APDU command.
+     * @param p1 P1 value of the APDU command.
+     * @param p2 P2 value of the APDU command.
+     * @param p3 P3 value of the APDU command. If p3 is negative a 4 byte APDU
+     *            is sent to the SIM.
+     * @param data Data to be sent with the APDU.
+     * @return The APDU response from the ICC card with the status appended at
+     *            the end.
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+    @SystemApi
+    @NonNull
+    public String iccTransmitApduBasicChannelBySlot(int slotIndex, int cla, int instruction, int p1,
+            int p2, int p3, @Nullable String data) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.iccTransmitApduBasicChannelBySlot(slotIndex, getOpPackageName(),
+                        cla, instruction, p1, p2, p3, data);
+            }
+        } catch (RemoteException ex) {
+        } catch (NullPointerException ex) {
+        }
+        return null;
+    }
+
+    /**
      * Transmit an APDU to the ICC card over the basic channel.
      *
      * Input parameters equivalent to TS 27.007 AT+CSIM command.
@@ -6003,7 +6159,7 @@
         // FIXME Need to get it from Telephony Dev Controller when that gets implemented!
         // and then this method shouldn't be used at all!
         if(isMultiSimEnabled()) {
-            return 2;
+            return getPhoneCount();
         } else {
             return 1;
         }
@@ -6625,14 +6781,12 @@
             }
         } catch (RemoteException ex) {
             Rlog.e(TAG, "getPreferredNetworkType RemoteException", ex);
-        } catch (NullPointerException ex) {
-            Rlog.e(TAG, "getPreferredNetworkType NPE", ex);
         }
         return -1;
     }
 
     /**
-     * Get the preferred network type bitmap.
+     * Get the preferred network type bitmask.
      *
      * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
      * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}
@@ -6641,13 +6795,13 @@
      * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
      * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
-     * @return The bitmap of preferred network types.
+     * @return The bitmask of preferred network types.
      *
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     @SystemApi
-    public @NetworkTypeBitMask long getPreferredNetworkTypeBitmap() {
+    public @NetworkTypeBitMask long getPreferredNetworkTypeBitmask() {
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
@@ -6655,9 +6809,7 @@
                         telephony.getPreferredNetworkType(getSubId()));
             }
         } catch (RemoteException ex) {
-            Rlog.e(TAG, "getPreferredNetworkTypeBitmap RemoteException", ex);
-        } catch (NullPointerException ex) {
-            Rlog.e(TAG, "getPreferredNetworkTypeBitmap NPE", ex);
+            Rlog.e(TAG, "getPreferredNetworkTypeBitmask RemoteException", ex);
         }
         return 0;
     }
@@ -6882,14 +7034,12 @@
             }
         } catch (RemoteException ex) {
             Rlog.e(TAG, "setPreferredNetworkType RemoteException", ex);
-        } catch (NullPointerException ex) {
-            Rlog.e(TAG, "setPreferredNetworkType NPE", ex);
         }
         return false;
     }
 
     /**
-     * Set the preferred network type bitmap.
+     * Set the preferred network type bitmask.
      *
      * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
      * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}
@@ -6898,24 +7048,22 @@
      * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
      * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
-     * @param networkTypeBitmap The bitmap of preferred network types.
+     * @param networkTypeBitmask The bitmask of preferred network types.
      * @return true on success; false on any failure.
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     @SystemApi
-    public boolean setPreferredNetworkTypeBitmap(@NetworkTypeBitMask long networkTypeBitmap) {
+    public boolean setPreferredNetworkTypeBitmask(@NetworkTypeBitMask long networkTypeBitmask) {
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
                 return telephony.setPreferredNetworkType(
                         getSubId(), RadioAccessFamily.getNetworkTypeFromRaf(
-                                (int) networkTypeBitmap));
+                                (int) networkTypeBitmask));
             }
         } catch (RemoteException ex) {
-            Rlog.e(TAG, "setPreferredNetworkType RemoteException", ex);
-        } catch (NullPointerException ex) {
-            Rlog.e(TAG, "setPreferredNetworkType NPE", ex);
+            Rlog.e(TAG, "setPreferredNetworkTypeBitmask RemoteException", ex);
         }
         return false;
     }
@@ -9717,8 +9865,11 @@
      * <p>Requires Permission:
      *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
      *
+     *
+     * @deprecated
      * @hide
      */
+    @Deprecated
     @TestApi
     public void setCarrierTestOverride(String mccmnc, String imsi, String iccid, String gid1,
             String gid2, String plmn, String spn) {
@@ -9726,7 +9877,35 @@
             ITelephony telephony = getITelephony();
             if (telephony != null) {
                 telephony.setCarrierTestOverride(
-                        getSubId(), mccmnc, imsi, iccid, gid1, gid2, plmn, spn);
+                        getSubId(), mccmnc, imsi, iccid, gid1, gid2, plmn, spn,
+                        null, null);
+            }
+        } catch (RemoteException ex) {
+            // This could happen if binder process crashes.
+        }
+    }
+
+    /**
+     * A test API to override carrier information including mccmnc, imsi, iccid, gid1, gid2,
+     * plmn, spn, apn and carrier priviledge. This would be handy for, eg, forcing a particular
+     * carrier id, carrier's config (also any country or carrier overlays) to be loaded when using
+     * a test SIM with a call box.
+     *
+     * <p>Requires Permission:
+     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+     *
+     * @hide
+     */
+    @TestApi
+    public void setCarrierTestOverride(String mccmnc, String imsi, String iccid, String gid1,
+                                       String gid2, String plmn, String spn,
+                                       String carrierPriviledgeRules, String apn) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                telephony.setCarrierTestOverride(
+                        getSubId(), mccmnc, imsi, iccid, gid1, gid2, plmn, spn,
+                        carrierPriviledgeRules, apn);
             }
         } catch (RemoteException ex) {
             // This could happen if binder process crashes.
@@ -10115,15 +10294,20 @@
     }
 
     /**
-     * Checks if the supplied number is an emergency number based on current locale, sim, default,
-     * modem and network.
+     * Identifies if the supplied phone number is an emergency number that matches a known
+     * emergency number based on current locale, SIM card(s), Android database, modem, network,
+     * or defaults.
+     *
+     * <p>This method assumes that only dialable phone numbers are passed in; non-dialable
+     * numbers are not considered emergency numbers. A dialable phone number consists only
+     * of characters/digits identified by {@link PhoneNumberUtils#isDialable(char)}.
      *
      * <p>The subscriptions which the identification would be based on, are all the active
      * subscriptions, no matter which subscription could be used to create TelephonyManager.
      *
      * @param number - the number to look up
      * @return {@code true} if the given number is an emergency number based on current locale,
-     * sim, modem and network; {@code false} otherwise.
+     * SIM card(s), Android database, modem, network or defaults; {@code false} otherwise.
      */
     public boolean isEmergencyNumber(@NonNull String number) {
         try {
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index 0b1d1fb..d0b52c9 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -1641,6 +1641,7 @@
          *
          * @param entryName the entry name to set for the APN
          */
+        @NonNull
         public Builder setEntryName(String entryName) {
             this.mEntryName = entryName;
             return this;
@@ -1651,6 +1652,7 @@
          *
          * @param apnName the name to set for the APN
          */
+        @NonNull
         public Builder setApnName(String apnName) {
             this.mApnName = apnName;
             return this;
@@ -1681,6 +1683,7 @@
          *
          * @param proxy the proxy address to set for the APN
          */
+        @NonNull
         public Builder setProxyAddress(String proxy) {
             this.mProxyAddress = proxy;
             return this;
@@ -1691,6 +1694,7 @@
          *
          * @param port the proxy port to set for the APN
          */
+        @NonNull
         public Builder setProxyPort(int port) {
             this.mProxyPort = port;
             return this;
@@ -1701,6 +1705,7 @@
          *
          * @param mmsc the MMSC Uri to set for the APN
          */
+        @NonNull
         public Builder setMmsc(Uri mmsc) {
             this.mMmsc = mmsc;
             return this;
@@ -1732,6 +1737,7 @@
          *
          * @param mmsProxy the MMS proxy address to set for the APN
          */
+        @NonNull
         public Builder setMmsProxyAddress(String mmsProxy) {
             this.mMmsProxyAddress = mmsProxy;
             return this;
@@ -1742,6 +1748,7 @@
          *
          * @param mmsPort the MMS proxy port to set for the APN
          */
+        @NonNull
         public Builder setMmsProxyPort(int mmsPort) {
             this.mMmsProxyPort = mmsPort;
             return this;
@@ -1752,6 +1759,7 @@
          *
          * @param user the APN username to set for the APN
          */
+        @NonNull
         public Builder setUser(String user) {
             this.mUser = user;
             return this;
@@ -1763,6 +1771,7 @@
          * @see android.provider.Telephony.Carriers#PASSWORD
          * @param password the APN password to set for the APN
          */
+        @NonNull
         public Builder setPassword(String password) {
             this.mPassword = password;
             return this;
@@ -1773,6 +1782,7 @@
          *
          * @param authType the authentication type to set for the APN
          */
+        @NonNull
         public Builder setAuthType(@AuthType int authType) {
             this.mAuthType = authType;
             return this;
@@ -1789,6 +1799,7 @@
          *
          * @param apnTypeBitmask a bitmask describing the types of the APN
          */
+        @NonNull
         public Builder setApnTypeBitmask(@ApnType int apnTypeBitmask) {
             this.mApnTypeBitmask = apnTypeBitmask;
             return this;
@@ -1801,6 +1812,7 @@
          *
          * @param operatorNumeric the numeric operator ID to set for this entry
          */
+        @NonNull
         public Builder setOperatorNumeric(String operatorNumeric) {
             this.mOperatorNumeric = operatorNumeric;
             return this;
@@ -1813,6 +1825,7 @@
          *
          * @param protocol the protocol to set to use to connect to this APN
          */
+        @NonNull
         public Builder setProtocol(@ProtocolType int protocol) {
             this.mProtocol = protocol;
             return this;
@@ -1825,6 +1838,7 @@
          *
          * @param roamingProtocol the protocol to set to use to connect to this APN when roaming
          */
+        @NonNull
         public Builder setRoamingProtocol(@ProtocolType  int roamingProtocol) {
             this.mRoamingProtocol = roamingProtocol;
             return this;
@@ -1835,6 +1849,7 @@
          *
          * @param carrierEnabled the current status to set for this APN
          */
+        @NonNull
         public Builder setCarrierEnabled(boolean carrierEnabled) {
             this.mCarrierEnabled = carrierEnabled;
             return this;
@@ -1845,6 +1860,7 @@
          *
          * @param networkTypeBitmask the Radio Technology (Network Type) info
          */
+        @NonNull
         public Builder setNetworkTypeBitmask(int networkTypeBitmask) {
             this.mNetworkTypeBitmask = networkTypeBitmask;
             return this;
@@ -1855,6 +1871,7 @@
          *
          * @param mvnoType the MVNO match type to set for this APN
          */
+        @NonNull
         public Builder setMvnoType(@MvnoType int mvnoType) {
             this.mMvnoType = mvnoType;
             return this;
diff --git a/telephony/java/android/telephony/emergency/EmergencyNumber.java b/telephony/java/android/telephony/emergency/EmergencyNumber.java
index 173f4ed..fa6cfcb 100644
--- a/telephony/java/android/telephony/emergency/EmergencyNumber.java
+++ b/telephony/java/android/telephony/emergency/EmergencyNumber.java
@@ -22,6 +22,7 @@
 import android.hardware.radio.V1_4.EmergencyServiceCategory;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.telephony.PhoneNumberUtils;
 import android.telephony.Rlog;
 
 import java.lang.annotation.Retention;
@@ -673,11 +674,20 @@
     }
 
     /**
-     * Validate Emergency Number address that only allows '0'-'9', '*', or '#'
+     * Validate Emergency Number address that only contains the dialable character
+     * {@link PhoneNumberUtils#isDialable(char)}
      *
      * @hide
      */
     public static boolean validateEmergencyNumberAddress(String address) {
-        return address.matches("[0-9*#]+");
+        if (address == null) {
+            return false;
+        }
+        for (char c : address.toCharArray()) {
+            if (!PhoneNumberUtils.isDialable(c)) {
+                return false;
+            }
+        }
+        return true;
     }
 }
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index afbf46d..875bd78 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -120,6 +120,10 @@
      * enable or disable a subscription. Must be accompanied with {@link #EXTRA_SUBSCRIPTION_ID} and
      * {@link #EXTRA_ENABLE_SUBSCRIPTION}.
      *
+     * Requires the caller to be a privileged process with the
+     * {@link android.permission#CALL_PRIVILEGED} permission for the intent to reach the Telephony
+     * stack.
+     *
      * <p>Unlike {@link #switchToSubscription(int, PendingIntent)}, using this action allows the
      * underlying eUICC service (i.e. the LPA app) to control the UI experience during this
      * operation. The action is received by the Telephony framework, which in turn selects and
@@ -139,6 +143,10 @@
      * Intent action sent by system apps (such as the Settings app) to the Telephony framework to
      * delete a subscription. Must be accompanied with {@link #EXTRA_SUBSCRIPTION_ID}.
      *
+     * Requires the caller to be a privileged process with the
+     * {@link android.permission#CALL_PRIVILEGED} permission for the intent to reach the Telephony
+     * stack.
+     *
      * <p>Unlike {@link #deleteSubscription(int, PendingIntent)}, using this action allows the
      * underlying eUICC service (i.e. the LPA app) to control the UI experience during this
      * operation. The action is received by the Telephony framework, which in turn selects and
@@ -159,6 +167,10 @@
      * rename a subscription. Must be accompanied with {@link #EXTRA_SUBSCRIPTION_ID} and
      * {@link #EXTRA_SUBSCRIPTION_NICKNAME}.
      *
+     * Requires the caller to be a privileged process with the
+     * {@link android.permission#CALL_PRIVILEGED} permission for the intent to reach the Telephony
+     * stack.
+     *
      * <p>Unlike {@link #updateSubscriptionNickname(int, String, PendingIntent)}, using this action
      * allows the the underlying eUICC service (i.e. the LPA app) to control the UI experience
      * during this operation. The action is received by the Telephony framework, which in turn
@@ -258,7 +270,10 @@
 
     /**
      * Key for an extra set on the {@link #ACTION_PROVISION_EMBEDDED_SUBSCRIPTION} intent for
-     * whether the user choses to use eUICC to set up network in SUW.
+     * whether eSIM provisioning flow is forced to be started or not. If this extra hasn't been
+     * set, eSIM provisioning flow may be skipped and the corresponding carrier's app will be
+     * notified. Otherwise, eSIM provisioning flow will be started when
+     * {@link #ACTION_PROVISION_EMBEDDED_SUBSCRIPTION} has been received.
      * @hide
      */
     @SystemApi
@@ -270,6 +285,8 @@
      * {@link #ACTION_DELETE_SUBSCRIPTION_PRIVILEGED}, and
      * {@link #ACTION_RENAME_SUBSCRIPTION_PRIVILEGED} providing the ID of the targeted subscription.
      *
+     * <p>Expected type of the extra data: int
+     *
      * @hide
      */
     @SystemApi
@@ -280,6 +297,8 @@
      * Key for an extra set on {@link #ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED} providing a boolean
      * value of whether to enable or disable the targeted subscription.
      *
+     * <p>Expected type of the extra data: boolean
+     *
      * @hide
      */
     @SystemApi
@@ -290,6 +309,8 @@
      * Key for an extra set on {@link #ACTION_RENAME_SUBSCRIPTION_PRIVILEGED} providing a new
      * nickname for the targeted subscription.
      *
+     * <p>Expected type of the extra data: String
+     *
      * @hide
      */
     @SystemApi
@@ -758,7 +779,7 @@
      */
     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
     public void updateSubscriptionNickname(
-            int subscriptionId, String nickname, PendingIntent callbackIntent) {
+            int subscriptionId, @Nullable String nickname, @NonNull PendingIntent callbackIntent) {
         if (!refreshCardIdIfUninitialized()) {
             sendUnavailableError(callbackIntent);
             return;
diff --git a/telephony/java/android/telephony/ims/ImsException.java b/telephony/java/android/telephony/ims/ImsException.java
index bdaad5b..02eddf6 100644
--- a/telephony/java/android/telephony/ims/ImsException.java
+++ b/telephony/java/android/telephony/ims/ImsException.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.content.pm.PackageManager;
 import android.text.TextUtils;
 
 import java.lang.annotation.Retention;
@@ -48,7 +49,9 @@
     /**
      * This device or carrier configuration does not support IMS for this subscription.
      * <p>
-     * This is a permanent configuration error and there should be no retry.
+     * This is a permanent configuration error and there should be no retry. Usually this is
+     * because {@link PackageManager#FEATURE_TELEPHONY_IMS} is not available
+     * or the device has no ImsService implementation to service this request.
      */
     public static final int CODE_ERROR_UNSUPPORTED_OPERATION = 2;
 
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index 58ddf21..e9aede7 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -25,6 +25,8 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.content.Context;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.RemoteException;
@@ -107,9 +109,9 @@
                         // case, since it is defined.
                         put(ImsRegistrationImplBase.REGISTRATION_TECH_NONE, -1);
                         put(ImsRegistrationImplBase.REGISTRATION_TECH_LTE,
-                                AccessNetworkConstants.TransportType.WWAN);
+                                AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
                         put(ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN,
-                                AccessNetworkConstants.TransportType.WLAN);
+                                AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
                     }};
 
             private final RegistrationCallback mLocalCallback;
@@ -314,7 +316,7 @@
     private int mSubId;
 
     /**
-     * Create an instance of ImsManager for the subscription id specified.
+     * Create an instance of {@link ImsMmTelManager} for the subscription id specified.
      *
      * @param subId The ID of the subscription that this ImsMmTelManager will use.
      * @see android.telephony.SubscriptionManager#getActiveSubscriptionInfoList()
@@ -366,12 +368,14 @@
         if (executor == null) {
             throw new IllegalArgumentException("Must include a non-null Executor.");
         }
+        if (!isImsAvailableOnDevice()) {
+            throw new ImsException("IMS not available on device.",
+                    ImsException.CODE_ERROR_UNSUPPORTED_OPERATION);
+        }
         c.setExecutor(executor);
         try {
             getITelephony().registerImsRegistrationCallback(mSubId, c.getBinder());
-        } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
-        } catch (IllegalStateException e) {
+        } catch (RemoteException | IllegalStateException e) {
             throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
         }
     }
@@ -434,6 +438,10 @@
         if (executor == null) {
             throw new IllegalArgumentException("Must include a non-null Executor.");
         }
+        if (!isImsAvailableOnDevice()) {
+            throw new ImsException("IMS not available on device.",
+                    ImsException.CODE_ERROR_UNSUPPORTED_OPERATION);
+        }
         c.setExecutor(executor);
         try {
             getITelephony().registerMmTelCapabilityCallback(mSubId, c.getBinder());
@@ -800,6 +808,22 @@
         }
     }
 
+    private static boolean isImsAvailableOnDevice() {
+        IPackageManager pm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
+        if (pm == null) {
+            // For some reason package manger is not available.. This will fail internally anyways,
+            // so do not throw error and allow.
+            return true;
+        }
+        try {
+            return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS, 0);
+        } catch (RemoteException e) {
+            // For some reason package manger is not available.. This will fail internally anyways,
+            // so do not throw error and allow.
+        }
+        return true;
+    }
+
     private static ITelephony getITelephony() {
         ITelephony binder = ITelephony.Stub.asInterface(
                 ServiceManager.getService(Context.TELEPHONY_SERVICE));
diff --git a/telephony/java/android/telephony/ims/ImsReasonInfo.java b/telephony/java/android/telephony/ims/ImsReasonInfo.java
index b018491..a478606 100644
--- a/telephony/java/android/telephony/ims/ImsReasonInfo.java
+++ b/telephony/java/android/telephony/ims/ImsReasonInfo.java
@@ -142,6 +142,11 @@
      * Call was disconnected because a handover is not feasible due to network conditions.
      */
     public static final int CODE_LOCAL_HO_NOT_FEASIBLE = 149;
+    /**
+     * This device does not support IMS.
+     * @hide
+     */
+    public static final int CODE_LOCAL_IMS_NOT_SUPPORTED_ON_DEVICE = 150;
 
     /*
      * TIMEOUT (IMS -> Telephony)
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
index d12cda8..8cdf6a2 100644
--- a/telephony/java/android/telephony/ims/ProvisioningManager.java
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -24,6 +24,8 @@
 import android.annotation.SystemApi;
 import android.annotation.WorkerThread;
 import android.content.Context;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
 import android.os.Binder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -209,12 +211,14 @@
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public void registerProvisioningChangedCallback(@NonNull @CallbackExecutor Executor executor,
             @NonNull Callback callback) throws ImsException {
+        if (!isImsAvailableOnDevice()) {
+            throw new ImsException("IMS not available on device.",
+                    ImsException.CODE_ERROR_UNSUPPORTED_OPERATION);
+        }
         callback.setExecutor(executor);
         try {
             getITelephony().registerImsProvisioningChangedCallback(mSubId, callback.getBinder());
-        } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
-        }  catch (IllegalStateException e) {
+        } catch (RemoteException | IllegalStateException e) {
             throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
         }
     }
@@ -232,8 +236,7 @@
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public void unregisterProvisioningChangedCallback(@NonNull Callback callback) {
         try {
-            getITelephony().unregisterImsProvisioningChangedCallback(mSubId,
-                    callback.getBinder());
+            getITelephony().unregisterImsProvisioningChangedCallback(mSubId, callback.getBinder());
         } catch (RemoteException e) {
             throw e.rethrowAsRuntimeException();
         }
@@ -373,6 +376,22 @@
         }
     }
 
+    private static boolean isImsAvailableOnDevice() {
+        IPackageManager pm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
+        if (pm == null) {
+            // For some reason package manger is not available.. This will fail internally anyways,
+            // so do not throw error and allow.
+            return true;
+        }
+        try {
+            return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS, 0);
+        } catch (RemoteException e) {
+            // For some reason package manger is not available.. This will fail internally anyways,
+            // so do not throw error and allow.
+        }
+        return true;
+    }
+
     private static ITelephony getITelephony() {
         ITelephony binder = ITelephony.Stub.asInterface(
                 ServiceManager.getService(Context.TELEPHONY_SERVICE));
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.java b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.java
index 1fb8798..bcadc80 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.java
@@ -17,6 +17,7 @@
 
 import static com.android.internal.annotations.VisibleForTesting.Visibility.PROTECTED;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.net.Uri;
 import android.os.Parcel;
@@ -42,7 +43,7 @@
                 new RcsParticipant(mOriginatingParticipantId), mNewIcon);
     }
 
-    public static final @android.annotation.NonNull Creator<RcsGroupThreadIconChangedEventDescriptor> CREATOR =
+    public static final @NonNull Creator<RcsGroupThreadIconChangedEventDescriptor> CREATOR =
             new Creator<RcsGroupThreadIconChangedEventDescriptor>() {
                 @Override
                 public RcsGroupThreadIconChangedEventDescriptor createFromParcel(Parcel in) {
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.java b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.java
index 980aba2..597fa0a 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.java
@@ -17,6 +17,7 @@
 
 import static com.android.internal.annotations.VisibleForTesting.Visibility.PROTECTED;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Parcel;
 
@@ -44,7 +45,7 @@
                 mNewName);
     }
 
-    public static final @android.annotation.NonNull Creator<RcsGroupThreadNameChangedEventDescriptor> CREATOR =
+    public static final @NonNull Creator<RcsGroupThreadNameChangedEventDescriptor> CREATOR =
             new Creator<RcsGroupThreadNameChangedEventDescriptor>() {
                 @Override
                 public RcsGroupThreadNameChangedEventDescriptor createFromParcel(Parcel in) {
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.java
index e899e1c..abea10a 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.java
@@ -17,6 +17,7 @@
 
 import static com.android.internal.annotations.VisibleForTesting.Visibility.PROTECTED;
 
+import android.annotation.NonNull;
 import android.os.Parcel;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -43,7 +44,7 @@
                 new RcsParticipant(mJoinedParticipantId));
     }
 
-    public static final @android.annotation.NonNull Creator<RcsGroupThreadParticipantJoinedEventDescriptor> CREATOR =
+    public static final @NonNull Creator<RcsGroupThreadParticipantJoinedEventDescriptor> CREATOR =
             new Creator<RcsGroupThreadParticipantJoinedEventDescriptor>() {
                 @Override
                 public RcsGroupThreadParticipantJoinedEventDescriptor createFromParcel(Parcel in) {
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.java
index 8eefb4b..f287db1 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.java
@@ -17,6 +17,7 @@
 
 import static com.android.internal.annotations.VisibleForTesting.Visibility.PROTECTED;
 
+import android.annotation.NonNull;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -44,7 +45,8 @@
                 new RcsParticipant(mLeavingParticipantId));
     }
 
-    public static final @android.annotation.NonNull Parcelable.Creator<RcsGroupThreadParticipantLeftEventDescriptor> CREATOR =
+    @NonNull
+    public static final Parcelable.Creator<RcsGroupThreadParticipantLeftEventDescriptor> CREATOR =
             new Creator<RcsGroupThreadParticipantLeftEventDescriptor>() {
                 @Override
                 public RcsGroupThreadParticipantLeftEventDescriptor createFromParcel(Parcel in) {
diff --git a/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParams.java b/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParams.java
index 955f263..d95dc4f 100644
--- a/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParams.java
+++ b/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParams.java
@@ -17,6 +17,7 @@
 package android.telephony.ims;
 
 import android.annotation.CheckResult;
+import android.annotation.NonNull;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -152,7 +153,7 @@
         return mSenderParticipantId;
     }
 
-    public static final @android.annotation.NonNull Creator<RcsIncomingMessageCreationParams> CREATOR =
+    public static final @NonNull Creator<RcsIncomingMessageCreationParams> CREATOR =
             new Creator<RcsIncomingMessageCreationParams>() {
                 @Override
                 public RcsIncomingMessageCreationParams createFromParcel(Parcel in) {
diff --git a/telephony/java/android/telephony/ims/RcsOutgoingMessageCreationParams.java b/telephony/java/android/telephony/ims/RcsOutgoingMessageCreationParams.java
index 22fd8a5..c001ffb 100644
--- a/telephony/java/android/telephony/ims/RcsOutgoingMessageCreationParams.java
+++ b/telephony/java/android/telephony/ims/RcsOutgoingMessageCreationParams.java
@@ -16,6 +16,7 @@
 
 package android.telephony.ims;
 
+import android.annotation.NonNull;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -64,7 +65,7 @@
         super(in);
     }
 
-    public static final @android.annotation.NonNull Creator<RcsOutgoingMessageCreationParams> CREATOR =
+    public static final @NonNull Creator<RcsOutgoingMessageCreationParams> CREATOR =
             new Creator<RcsOutgoingMessageCreationParams>() {
                 @Override
                 public RcsOutgoingMessageCreationParams createFromParcel(Parcel in) {
diff --git a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.java b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.java
index aad9fb3..b29896c 100644
--- a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.java
@@ -17,6 +17,7 @@
 
 import static com.android.internal.annotations.VisibleForTesting.Visibility.PROTECTED;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Parcel;
 
@@ -45,7 +46,7 @@
                 mTimestamp, new RcsParticipant(mParticipantId), mNewAlias);
     }
 
-    public static final @android.annotation.NonNull Creator<RcsParticipantAliasChangedEventDescriptor> CREATOR =
+    public static final @NonNull Creator<RcsParticipantAliasChangedEventDescriptor> CREATOR =
             new Creator<RcsParticipantAliasChangedEventDescriptor>() {
                 @Override
                 public RcsParticipantAliasChangedEventDescriptor createFromParcel(Parcel in) {
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 122747a65..c2c31cc 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -553,6 +553,20 @@
     void setCellInfoListRate(int rateInMillis);
 
     /**
+     * Opens a logical channel to the ICC card using the physical slot index.
+     *
+     * Input parameters equivalent to TS 27.007 AT+CCHO command.
+     *
+     * @param slotIndex The physical slot index of the target ICC card
+     * @param callingPackage the name of the package making the call.
+     * @param AID Application id. See ETSI 102.221 and 101.220.
+     * @param p2 P2 parameter (described in ISO 7816-4).
+     * @return an IccOpenLogicalChannelResponse object.
+     */
+    IccOpenLogicalChannelResponse iccOpenLogicalChannelBySlot(
+            int slotIndex, String callingPackage, String AID, int p2);
+
+    /**
      * Opens a logical channel to the ICC card.
      *
      * Input parameters equivalent to TS 27.007 AT+CCHO command.
@@ -567,12 +581,24 @@
             int subId, String callingPackage, String AID, int p2);
 
     /**
+     * Closes a previously opened logical channel to the ICC card using the physical slot index.
+     *
+     * Input parameters equivalent to TS 27.007 AT+CCHC command.
+     *
+     * @param slotIndex The physical slot index of the target ICC card
+     * @param channel is the channel id to be closed as returned by a
+     *            successful iccOpenLogicalChannel.
+     * @return true if the channel was closed successfully.
+     */
+    boolean iccCloseLogicalChannelBySlot(int slotIndex, int channel);
+
+    /**
      * Closes a previously opened logical channel to the ICC card.
      *
      * Input parameters equivalent to TS 27.007 AT+CCHC command.
      *
      * @param subId The subscription to use.
-     * @param channel is the channel id to be closed as retruned by a
+     * @param channel is the channel id to be closed as returned by a
      *            successful iccOpenLogicalChannel.
      * @return true if the channel was closed successfully.
      */
@@ -580,12 +606,33 @@
     boolean iccCloseLogicalChannel(int subId, int channel);
 
     /**
+     * Transmit an APDU to the ICC card over a logical channel using the physical slot index.
+     *
+     * Input parameters equivalent to TS 27.007 AT+CGLA command.
+     *
+     * @param slotIndex The physical slot index of the target ICC card
+     * @param channel is the channel id to be closed as returned by a
+     *            successful iccOpenLogicalChannel.
+     * @param cla Class of the APDU command.
+     * @param instruction Instruction of the APDU command.
+     * @param p1 P1 value of the APDU command.
+     * @param p2 P2 value of the APDU command.
+     * @param p3 P3 value of the APDU command. If p3 is negative a 4 byte APDU
+     *            is sent to the SIM.
+     * @param data Data to be sent with the APDU.
+     * @return The APDU response from the ICC card with the status appended at
+     *            the end.
+     */
+    String iccTransmitApduLogicalChannelBySlot(int slotIndex, int channel, int cla, int instruction,
+            int p1, int p2, int p3, String data);
+
+    /**
      * Transmit an APDU to the ICC card over a logical channel.
      *
      * Input parameters equivalent to TS 27.007 AT+CGLA command.
      *
      * @param subId The subscription to use.
-     * @param channel is the channel id to be closed as retruned by a
+     * @param channel is the channel id to be closed as returned by a
      *            successful iccOpenLogicalChannel.
      * @param cla Class of the APDU command.
      * @param instruction Instruction of the APDU command.
@@ -602,6 +649,26 @@
             int p1, int p2, int p3, String data);
 
     /**
+     * Transmit an APDU to the ICC card over the basic channel using the physical slot index.
+     *
+     * Input parameters equivalent to TS 27.007 AT+CSIM command.
+     *
+     * @param slotIndex The physical slot index of the target ICC card
+     * @param callingPackage the name of the package making the call.
+     * @param cla Class of the APDU command.
+     * @param instruction Instruction of the APDU command.
+     * @param p1 P1 value of the APDU command.
+     * @param p2 P2 value of the APDU command.
+     * @param p3 P3 value of the APDU command. If p3 is negative a 4 byte APDU
+     *            is sent to the SIM.
+     * @param data Data to be sent with the APDU.
+     * @return The APDU response from the ICC card with the status appended at
+     *            the end.
+     */
+    String iccTransmitApduBasicChannelBySlot(int slotIndex, String callingPackage, int cla,
+            int instruction, int p1, int p2, int p3, String data);
+
+    /**
      * Transmit an APDU to the ICC card over the basic channel.
      *
      * Input parameters equivalent to TS 27.007 AT+CSIM command.
@@ -1616,7 +1683,7 @@
      * (also any country or carrier overlays) to be loaded when using a test SIM with a call box.
      */
     void setCarrierTestOverride(int subId, String mccmnc, String imsi, String iccid, String gid1,
-            String gid2, String plmn, String spn);
+            String gid2, String plmn, String spn, String carrierPrivilegeRules, String apn);
 
     /**
      * A test API to return installed carrier id list version.
diff --git a/tests/ActivityManagerPerfTests/test-app/Android.bp b/tests/ActivityManagerPerfTests/test-app/Android.bp
new file mode 100644
index 0000000..ef9d587
--- /dev/null
+++ b/tests/ActivityManagerPerfTests/test-app/Android.bp
@@ -0,0 +1,21 @@
+// 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.
+
+android_test {
+    name: "ActivityManagerPerfTestsTestApp",
+    srcs: ["src/**/*.java"],
+    static_libs: ["ActivityManagerPerfTestsUtils"],
+    min_sdk_version: "25",
+    sdk_version: "current",
+}
diff --git a/tests/ActivityManagerPerfTests/test-app/Android.mk b/tests/ActivityManagerPerfTests/test-app/Android.mk
deleted file mode 100644
index 33d15d2..0000000
--- a/tests/ActivityManagerPerfTests/test-app/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := \
-    $(call all-java-files-under, src)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    ActivityManagerPerfTestsUtils
-
-LOCAL_MIN_SDK_VERSION := 25
-
-LOCAL_PACKAGE_NAME := ActivityManagerPerfTestsTestApp
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
diff --git a/tests/ActivityManagerPerfTests/tests/Android.bp b/tests/ActivityManagerPerfTests/tests/Android.bp
new file mode 100644
index 0000000..2ae2cc4
--- /dev/null
+++ b/tests/ActivityManagerPerfTests/tests/Android.bp
@@ -0,0 +1,27 @@
+// 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.
+
+android_test {
+    name: "ActivityManagerPerfTests",
+    srcs: ["src/**/*.java"],
+    static_libs: [
+        "androidx.test.rules",
+        "apct-perftests-utils",
+        "ActivityManagerPerfTestsUtils",
+    ],
+    platform_apis: true,
+    min_sdk_version: "25",
+    // For android.permission.FORCE_STOP_PACKAGES permission
+    certificate: "platform",
+}
diff --git a/tests/ActivityManagerPerfTests/tests/Android.mk b/tests/ActivityManagerPerfTests/tests/Android.mk
deleted file mode 100644
index e1f56b8..0000000
--- a/tests/ActivityManagerPerfTests/tests/Android.mk
+++ /dev/null
@@ -1,36 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := \
-    $(call all-java-files-under, src)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    androidx.test.rules \
-    apct-perftests-utils \
-    ActivityManagerPerfTestsUtils
-
-LOCAL_PACKAGE_NAME := ActivityManagerPerfTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_MIN_SDK_VERSION := 25
-
-# For android.permission.FORCE_STOP_PACKAGES permission
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/ActivityManagerPerfTests/utils/Android.bp b/tests/ActivityManagerPerfTests/utils/Android.bp
new file mode 100644
index 0000000..300b7ea
--- /dev/null
+++ b/tests/ActivityManagerPerfTests/utils/Android.bp
@@ -0,0 +1,27 @@
+// 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.
+
+java_test {
+    name: "ActivityManagerPerfTestsUtils",
+    sdk_version: "current",
+    srcs: [
+        "src/**/*.java",
+        "src/com/android/frameworks/perftests/am/util/ITimeReceiverCallback.aidl",
+    ],
+    static_libs: [
+        "androidx.test.rules",
+        "junit",
+        "ub-uiautomator",
+    ],
+}
diff --git a/tests/ActivityManagerPerfTests/utils/Android.mk b/tests/ActivityManagerPerfTests/utils/Android.mk
deleted file mode 100644
index 7a7471d..0000000
--- a/tests/ActivityManagerPerfTests/utils/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := current
-
-LOCAL_SRC_FILES := \
-    $(call all-java-files-under, src) \
-    src/com/android/frameworks/perftests/am/util/ITimeReceiverCallback.aidl
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    androidx.test.rules \
-    junit \
-    ub-uiautomator
-
-LOCAL_MODULE := ActivityManagerPerfTestsUtils
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tests/ActivityViewTest/Android.bp b/tests/ActivityViewTest/Android.bp
new file mode 100644
index 0000000..e7b8c8e
--- /dev/null
+++ b/tests/ActivityViewTest/Android.bp
@@ -0,0 +1,6 @@
+android_test {
+    name: "ActivityViewTest",
+    srcs: ["src/**/*.java"],
+    platform_apis: true,
+    certificate: "platform",
+}
diff --git a/tests/ActivityViewTest/Android.mk b/tests/ActivityViewTest/Android.mk
deleted file mode 100644
index 9c7ca7e..0000000
--- a/tests/ActivityViewTest/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := ActivityViewTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/AppLaunch/Android.bp b/tests/AppLaunch/Android.bp
new file mode 100644
index 0000000..f90f26f
--- /dev/null
+++ b/tests/AppLaunch/Android.bp
@@ -0,0 +1,13 @@
+android_test {
+    name: "AppLaunch",
+    // Only compile source java files in this apk.
+    srcs: ["src/**/*.java"],
+    platform_apis: true,
+    certificate: "platform",
+    libs: [
+        "android.test.base",
+        "android.test.runner",
+    ],
+    static_libs: ["androidx.test.rules"],
+    test_suites: ["device-tests"],
+}
diff --git a/tests/AppLaunch/Android.mk b/tests/AppLaunch/Android.mk
deleted file mode 100644
index f50bca5..0000000
--- a/tests/AppLaunch/Android.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := AppLaunch
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_CERTIFICATE := platform
-LOCAL_JAVA_LIBRARIES := android.test.base android.test.runner
-
-LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules
-
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_PACKAGE)
-
-# Use the following include to make our test apk.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/AppLaunchWear/Android.bp b/tests/AppLaunchWear/Android.bp
new file mode 100644
index 0000000..8d34b6e
--- /dev/null
+++ b/tests/AppLaunchWear/Android.bp
@@ -0,0 +1,13 @@
+android_test {
+    name: "AppLaunchWear",
+    // Only compile source java files in this apk.
+    srcs: ["src/**/*.java"],
+    platform_apis: true,
+    certificate: "platform",
+    libs: [
+        "android.test.base",
+        "android.test.runner",
+    ],
+    static_libs: ["androidx.test.rules"],
+    test_suites: ["device-tests"],
+}
diff --git a/tests/AppLaunchWear/Android.mk b/tests/AppLaunchWear/Android.mk
deleted file mode 100644
index 332b680..0000000
--- a/tests/AppLaunchWear/Android.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := AppLaunchWear
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_CERTIFICATE := platform
-LOCAL_JAVA_LIBRARIES := android.test.base android.test.runner
-
-LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules
-
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_PACKAGE)
-
-# Use the following include to make our test apk.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/BackgroundDexOptServiceIntegrationTests/Android.bp b/tests/BackgroundDexOptServiceIntegrationTests/Android.bp
new file mode 100644
index 0000000..a85d129
--- /dev/null
+++ b/tests/BackgroundDexOptServiceIntegrationTests/Android.bp
@@ -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.
+//
+
+android_test {
+    name: "BackgroundDexOptServiceIntegrationTests",
+    srcs: ["src/**/*.java"],
+    static_libs: ["androidx.test.rules"],
+    platform_apis: true,
+    test_suites: ["device-tests"],
+    certificate: "platform",
+}
diff --git a/tests/BackgroundDexOptServiceIntegrationTests/Android.mk b/tests/BackgroundDexOptServiceIntegrationTests/Android.mk
deleted file mode 100644
index f47cf96..0000000
--- a/tests/BackgroundDexOptServiceIntegrationTests/Android.mk
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    androidx.test.rules \
-
-LOCAL_PACKAGE_NAME := BackgroundDexOptServiceIntegrationTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/Compatibility/Android.bp b/tests/Compatibility/Android.bp
new file mode 100644
index 0000000..4ca406e
--- /dev/null
+++ b/tests/Compatibility/Android.bp
@@ -0,0 +1,22 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test {
+    name: "AppCompatibilityTest",
+    static_libs: ["androidx.test.rules"],
+    // Include all test java files.
+    srcs: ["src/**/*.java"],
+    platform_apis: true,
+    certificate: "platform",
+}
diff --git a/tests/Compatibility/Android.mk b/tests/Compatibility/Android.mk
deleted file mode 100644
index 643f9eb..0000000
--- a/tests/Compatibility/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (C) 2012 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules
-# Include all test java files.
-LOCAL_SRC_FILES := \
-	$(call all-java-files-under, src)
-
-
-LOCAL_PACKAGE_NAME := AppCompatibilityTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-include $(BUILD_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/FlickerTests/Android.bp b/tests/FlickerTests/Android.bp
new file mode 100644
index 0000000..05f0a8e7
--- /dev/null
+++ b/tests/FlickerTests/Android.bp
@@ -0,0 +1,30 @@
+//
+// 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.
+//
+
+android_test {
+    name: "FlickerTests",
+    srcs: ["src/**/*.java"],
+    platform_apis: true,
+    certificate: "platform",
+    test_suites: ["device-tests"],
+    libs: ["android.test.runner"],
+    static_libs: [
+        "flickertestapplib",
+        "flickerlib",
+        "truth-prebuilt",
+        "app-helpers-core",
+    ],
+}
diff --git a/tests/FlickerTests/Android.mk b/tests/FlickerTests/Android.mk
deleted file mode 100644
index 3c70f8b..0000000
--- a/tests/FlickerTests/Android.mk
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := FlickerTests
-LOCAL_MODULE_TAGS := tests optional
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    flickertestapplib \
-    flickerlib \
-    truth-prebuilt \
-    app-helpers-core
-
-include $(BUILD_PACKAGE)
-include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
diff --git a/tests/FlickerTests/lib/Android.bp b/tests/FlickerTests/lib/Android.bp
new file mode 100644
index 0000000..982fcba
--- /dev/null
+++ b/tests/FlickerTests/lib/Android.bp
@@ -0,0 +1,44 @@
+//
+// 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.
+//
+
+java_test {
+    name: "flickerlib",
+    platform_apis: true,
+    srcs: ["src/**/*.java"],
+    static_libs: [
+        "androidx.test.janktesthelper",
+        "cts-amwm-util",
+        "platformprotosnano",
+        "layersprotosnano",
+        "truth-prebuilt",
+        "sysui-helper",
+        "launcher-helper-lib",
+    ],
+}
+
+java_library {
+    name: "flickerautomationhelperlib",
+    sdk_version: "test_current",
+    srcs: [
+        "src/com/android/server/wm/flicker/AutomationUtils.java",
+        "src/com/android/server/wm/flicker/WindowUtils.java",
+    ],
+    static_libs: [
+        "sysui-helper",
+        "launcher-helper-lib",
+        "compatibility-device-util-axt",
+    ],
+}
diff --git a/tests/FlickerTests/lib/Android.mk b/tests/FlickerTests/lib/Android.mk
deleted file mode 100644
index e438822..0000000
--- a/tests/FlickerTests/lib/Android.mk
+++ /dev/null
@@ -1,48 +0,0 @@
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := flickerlib
-LOCAL_MODULE_TAGS := tests optional
-# sign this with platform cert, so this test is allowed to call private platform apis
-LOCAL_CERTIFICATE := platform
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_STATIC_JAVA_LIBRARIES := \
-   androidx.test.janktesthelper \
-   cts-amwm-util \
-   platformprotosnano \
-   layersprotosnano \
-   truth-prebuilt \
-   sysui-helper \
-   launcher-helper-lib \
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := flickerautomationhelperlib
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := src/com/android/server/wm/flicker/AutomationUtils.java \
-    src/com/android/server/wm/flicker/WindowUtils.java
-LOCAL_STATIC_JAVA_LIBRARIES := sysui-helper \
-    launcher-helper-lib \
-    compatibility-device-util-axt
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/FlickerTests/lib/test/Android.bp b/tests/FlickerTests/lib/test/Android.bp
new file mode 100644
index 0000000..bfeb75b2
--- /dev/null
+++ b/tests/FlickerTests/lib/test/Android.bp
@@ -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.
+//
+
+android_test {
+    name: "FlickerLibTest",
+    // sign this with platform cert, so this test is allowed to call private platform apis
+    certificate: "platform",
+    platform_apis: true,
+    test_suites: ["tests"],
+    srcs: ["src/**/*.java"],
+    libs: ["android.test.runner"],
+    static_libs: [
+        "androidx.test.rules",
+        "platform-test-annotations",
+        "truth-prebuilt",
+        "platformprotosnano",
+        "layersprotosnano",
+        "flickerlib",
+    ],
+}
diff --git a/tests/FlickerTests/lib/test/Android.mk b/tests/FlickerTests/lib/test/Android.mk
deleted file mode 100644
index 5be89ba..0000000
--- a/tests/FlickerTests/lib/test/Android.mk
+++ /dev/null
@@ -1,36 +0,0 @@
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := FlickerLibTest
-LOCAL_MODULE_TAGS := tests optional
-# sign this with platform cert, so this test is allowed to call private platform apis
-LOCAL_CERTIFICATE := platform
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_COMPATIBILITY_SUITE := tests
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    androidx.test.rules \
-    platform-test-annotations \
-    truth-prebuilt \
-    platformprotosnano \
-    layersprotosnano \
-    flickerlib
-
-include $(BUILD_PACKAGE)
-include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
diff --git a/tests/FlickerTests/test-apps/Android.bp b/tests/FlickerTests/test-apps/Android.bp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/FlickerTests/test-apps/Android.bp
diff --git a/tests/FlickerTests/test-apps/Android.mk b/tests/FlickerTests/test-apps/Android.mk
deleted file mode 100644
index 9af9f444..0000000
--- a/tests/FlickerTests/test-apps/Android.mk
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-include $(call all-subdir-makefiles)
diff --git a/tests/FlickerTests/test-apps/flickerapp/Android.bp b/tests/FlickerTests/test-apps/flickerapp/Android.bp
new file mode 100644
index 0000000..0bea209
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/Android.bp
@@ -0,0 +1,26 @@
+// 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.
+
+android_test {
+    name: "FlickerTestApp",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    test_suites: ["device-tests"],
+}
+
+java_test {
+    name: "flickertestapplib",
+    sdk_version: "current",
+    srcs: ["src/com/android/server/wm/flicker/testapp/ActivityOptions.java"],
+}
diff --git a/tests/FlickerTests/test-apps/flickerapp/Android.mk b/tests/FlickerTests/test-apps/flickerapp/Android.mk
deleted file mode 100644
index b916900..0000000
--- a/tests/FlickerTests/test-apps/flickerapp/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := FlickerTestApp
-LOCAL_MODULE_TAGS := tests optional
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-LOCAL_SDK_VERSION := current
-LOCAL_COMPATIBILITY_SUITE := device-tests
-include $(BUILD_PACKAGE)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := flickertestapplib
-LOCAL_MODULE_TAGS := tests optional
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := src/com/android/server/wm/flicker/testapp/ActivityOptions.java
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
diff --git a/tests/Internal/Android.bp b/tests/Internal/Android.bp
new file mode 100644
index 0000000..4cb9f8d
--- /dev/null
+++ b/tests/Internal/Android.bp
@@ -0,0 +1,18 @@
+android_test {
+    name: "InternalTests",
+    proto: {
+        type: "nano",
+    },
+    // Include some source files directly to be able to access package members
+    srcs: ["src/**/*.java"],
+    libs: ["android.test.runner"],
+    static_libs: [
+        "junit",
+        "androidx.test.rules",
+        "mockito-target-minus-junit4",
+    ],
+    java_resource_dirs: ["res"],
+    certificate: "platform",
+    platform_apis: true,
+    test_suites: ["device-tests"],
+}
diff --git a/tests/Internal/Android.mk b/tests/Internal/Android.mk
deleted file mode 100644
index 2e26ef1..0000000
--- a/tests/Internal/Android.mk
+++ /dev/null
@@ -1,24 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_PROTOC_OPTIMIZE_TYPE := nano
-
-# Include some source files directly to be able to access package members
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := junit \
-    androidx.test.rules \
-    mockito-target-minus-junit4
-
-LOCAL_JAVA_RESOURCE_DIRS := res
-LOCAL_CERTIFICATE := platform
-
-LOCAL_PACKAGE_NAME := InternalTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/PackageWatchdog/Android.bp b/tests/PackageWatchdog/Android.bp
new file mode 100644
index 0000000..b079965
--- /dev/null
+++ b/tests/PackageWatchdog/Android.bp
@@ -0,0 +1,28 @@
+// Copyright (C) 2019 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.
+
+// PackageWatchdogTest
+android_test {
+    name: "PackageWatchdogTest",
+    srcs: ["src/**/*.java"],
+    static_libs: [
+        "junit",
+        "frameworks-base-testutils",
+        "androidx.test.rules",
+        "services.core",
+    ],
+    libs: ["android.test.runner"],
+    platform_apis: true,
+    test_suites: ["device-tests"],
+}
diff --git a/tests/PackageWatchdog/Android.mk b/tests/PackageWatchdog/Android.mk
deleted file mode 100644
index 1e4aacc..0000000
--- a/tests/PackageWatchdog/Android.mk
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright (C) 2019 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-# PackageWatchdogTest
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_PACKAGE_NAME := PackageWatchdogTest
-LOCAL_MODULE_TAGS := tests
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    junit \
-    frameworks-base-testutils \
-    androidx.test.rules \
-    services.core
-
-LOCAL_JAVA_LIBRARIES := \
-    android.test.runner
-
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/RcsTests/Android.bp b/tests/RcsTests/Android.bp
new file mode 100644
index 0000000..8ee4960
--- /dev/null
+++ b/tests/RcsTests/Android.bp
@@ -0,0 +1,17 @@
+android_test {
+    name: "RcsTests",
+    // Only compile source java files in this apk.
+    srcs: ["src/**/*.java"],
+    platform_apis: true,
+    certificate: "platform",
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+    static_libs: [
+        "junit",
+        "androidx.test.rules",
+        "mockito-target-minus-junit4",
+        "truth-prebuilt",
+    ],
+}
diff --git a/tests/RcsTests/Android.mk b/tests/RcsTests/Android.mk
deleted file mode 100644
index a276584..0000000
--- a/tests/RcsTests/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := RcsTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_CERTIFICATE := platform
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
-LOCAL_STATIC_JAVA_LIBRARIES := junit androidx.test.rules mockito-target-minus-junit4 truth-prebuilt
-
-include $(BUILD_PACKAGE)
-
-# Use the following include to make our test apk.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
index a03fae0..9aed074 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
@@ -340,16 +340,26 @@
     }
 
     /**
-     * Asserts that the given RollbackInfo has a single package with expected
-     * package name and versions.
+     * Asserts that the given RollbackInfo has the given packages with expected
+     * package names and all are rolled to and from the same given versions.
      */
-    static void assertRollbackInfoEquals(String packageName,
+    static void assertRollbackInfoEquals(String[] packageNames,
             long versionRolledBackFrom, long versionRolledBackTo,
             RollbackInfo info, VersionedPackage... causePackages) {
         assertNotNull(info);
-        assertEquals(1, info.getPackages().size());
-        assertPackageRollbackInfoEquals(packageName, versionRolledBackFrom, versionRolledBackTo,
-                info.getPackages().get(0));
+        assertEquals(packageNames.length, info.getPackages().size());
+        int foundPackages = 0;
+        for (String packageName : packageNames) {
+            for (PackageRollbackInfo pkgRollbackInfo : info.getPackages()) {
+                if (packageName.equals(pkgRollbackInfo.getPackageName())) {
+                    foundPackages++;
+                    assertPackageRollbackInfoEquals(packageName, versionRolledBackFrom,
+                            versionRolledBackTo, pkgRollbackInfo);
+                    break;
+                }
+            }
+        }
+        assertEquals(packageNames.length, foundPackages);
         assertEquals(causePackages.length, info.getCausePackages().size());
         for (int i = 0; i < causePackages.length; ++i) {
             assertEquals(causePackages[i].getPackageName(),
@@ -360,6 +370,18 @@
     }
 
     /**
+     * Asserts that the given RollbackInfo has a single package with expected
+     * package name and versions.
+     */
+    static void assertRollbackInfoEquals(String packageName,
+            long versionRolledBackFrom, long versionRolledBackTo,
+            RollbackInfo info, VersionedPackage... causePackages) {
+        String[] packageNames = {packageName};
+        assertRollbackInfoEquals(packageNames, versionRolledBackFrom, versionRolledBackTo, info,
+                causePackages);
+    }
+
+    /**
      * Waits for the given session to be marked as ready.
      * Throws an assertion if the session fails.
      */
@@ -453,4 +475,17 @@
             fail(result);
         }
     }
+
+    /**
+     * Return the rollback info for a recently committed rollback, by matching the rollback id, or
+     * return null if no matching rollback is found.
+     */
+    static RollbackInfo getRecentlyCommittedRollbackInfoById(int getRollbackId) {
+        for (RollbackInfo info : getRollbackManager().getRecentlyCommittedRollbacks()) {
+            if (info.getRollbackId() == getRollbackId) {
+                return info;
+            }
+        }
+        return null;
+    }
 }
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
index 59ae8d9..047451b 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
@@ -17,6 +17,7 @@
 package com.android.tests.rollback;
 
 import static com.android.tests.rollback.RollbackTestUtils.assertRollbackInfoEquals;
+import static com.android.tests.rollback.RollbackTestUtils.getRecentlyCommittedRollbackInfoById;
 import static com.android.tests.rollback.RollbackTestUtils.getUniqueRollbackInfoForPackage;
 
 import android.Manifest;
@@ -25,7 +26,6 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 import org.junit.After;
@@ -47,6 +47,8 @@
 
     private static final String TAG = "RollbackTest";
     private static final String TEST_APP_A = "com.android.tests.rollback.testapp.A";
+    private static final String TEST_APP_A_V1 = "RollbackTestAppAv1.apk";
+    private static final String TEST_APP_A_V2 = "RollbackTestAppAv2.apk";
     private static final String TEST_APEX_PKG = "com.android.tests.rollback.testapex";
     private static final String TEST_APEX_V1 =
             "com.android.tests.rollback.testapex.RollbackTestApexV1.apex";
@@ -82,11 +84,11 @@
         RollbackTestUtils.uninstall(TEST_APP_A);
         assertEquals(-1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
 
-        RollbackTestUtils.install("RollbackTestAppAv1.apk", false);
+        RollbackTestUtils.install(TEST_APP_A_V1, false);
         assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
         RollbackTestUtils.processUserData(TEST_APP_A);
 
-        RollbackTestUtils.installStaged(true, "RollbackTestAppAv2.apk");
+        RollbackTestUtils.installStaged(true, TEST_APP_A_V2);
 
         // At this point, the host test driver will reboot the device and run
         // testApkOnlyCommitRollback().
@@ -142,6 +144,86 @@
     }
 
     /**
+     * Test rollbacks of staged installs an apk and an apex.
+     * Prepare apex (and apk) phase.
+     */
+    @Test
+    public void testApkAndApexPrepare() throws Exception {
+        RollbackTestUtils.uninstall(TEST_APP_A);
+        assertEquals(-1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
+
+        // Note: can't uninstall the apex. See note in #testApexOnlyPrepareApex().
+        RollbackTestUtils.installStaged(false, TEST_APP_A_V1, TEST_APEX_V1);
+
+        // At this point, the host test driver will reboot the device and run
+        // testApkAndApexEnableRollback().
+    }
+
+    /**
+     * Test rollbacks of staged installs an apk and an apex.
+     * Enable rollback phase.
+     */
+    @Test
+    public void testApkAndApexEnableRollback() throws Exception {
+        assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
+        assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
+
+        RollbackTestUtils.installStaged(true, TEST_APP_A_V2, TEST_APEX_V2);
+
+        // At this point, the host test driver will reboot the device and run
+        // testApkAndApexCommitRollback().
+    }
+
+    /**
+     * Test rollbacks of staged installs an apk and an apex.
+     * Commit rollback phase.
+     */
+    @Test
+    public void testApkAndApexCommitRollback() throws Exception {
+        assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
+        assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
+
+        RollbackTestUtils.processUserData(TEST_APP_A);
+
+        RollbackManager rm = RollbackTestUtils.getRollbackManager();
+
+        RollbackInfo rollback = getUniqueRollbackInfoForPackage(
+                rm.getAvailableRollbacks(), TEST_APP_A);
+        String[] packagesNames = {TEST_APEX_PKG, TEST_APP_A};
+        assertRollbackInfoEquals(packagesNames, 2, 1, rollback);
+        assertTrue(rollback.isStaged());
+
+        RollbackTestUtils.rollback(rollback.getRollbackId());
+
+        RollbackInfo committed = getRecentlyCommittedRollbackInfoById(rollback.getRollbackId());
+
+        assertRollbackInfoEquals(packagesNames, 2, 1, committed);
+        assertTrue(committed.isStaged());
+        assertNotEquals(-1, committed.getCommittedSessionId());
+
+        RollbackTestUtils.waitForSessionReady(committed.getCommittedSessionId());
+
+        // The apex and apk should not be rolled back until after reboot.
+        assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
+        assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
+
+        // At this point, the host test driver will reboot the device and run
+        // testApkAndApexConfirmRollback().
+    }
+
+    /**
+     * Test rollbacks of staged installs an apk and an apex.
+     * Confirm rollback phase.
+     */
+    @Test
+    public void testApkAndApexConfirmRollback() throws Exception {
+        assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
+        assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
+
+        RollbackTestUtils.processUserData(TEST_APP_A);
+    }
+
+    /**
      * Test rollbacks of staged installs involving only apex.
      * Prepare apex phase.
      */
@@ -171,7 +253,7 @@
     }
 
     /**
-     * Test rollbacks of staged installs involving only apks.
+     * Test rollbacks of staged installs involving only apex.
      * Commit rollback phase.
      */
     @Test
@@ -186,18 +268,8 @@
 
         RollbackTestUtils.rollback(rollback.getRollbackId());
 
-        // Note: We can't use getUniqueRollbackInfoForPackage for the apex,
-        // because we can't uninstall the apex (b/123667725), which means
-        // there's no way to clear info about rollbacks from previous tests
-        // run on the device. Look up the info by rollback id instead.
-        RollbackInfo committed = null;
-        for (RollbackInfo info : rm.getRecentlyCommittedRollbacks()) {
-            if (info.getRollbackId() == rollback.getRollbackId()) {
-                assertNull(committed);
-                committed = info;
-                break;
-            }
-        }
+        RollbackInfo committed = getRecentlyCommittedRollbackInfoById(rollback.getRollbackId());
+
         assertRollbackInfoEquals(TEST_APEX_PKG, 2, 1, committed);
         assertTrue(committed.isStaged());
         assertNotEquals(-1, committed.getCommittedSessionId());
@@ -212,7 +284,7 @@
     }
 
     /**
-     * Test rollbacks of staged installs involving only apks.
+     * Test rollbacks of staged installs involving only apex.
      * Confirm rollback phase.
      */
     @Test
diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
index 24a51dc..ac7f634 100644
--- a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
+++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
@@ -67,4 +67,18 @@
         getDevice().reboot();
         runPhase("testApexOnlyConfirmRollback");
     }
+
+    /**
+     * Tests staged rollbacks involving apk and apex.
+     */
+    @Test
+    public void testApkAndApex() throws Exception {
+        runPhase("testApkAndApexPrepare");
+        getDevice().reboot();
+        runPhase("testApkAndApexEnableRollback");
+        getDevice().reboot();
+        runPhase("testApkAndApexCommitRollback");
+        getDevice().reboot();
+        runPhase("testApkAndApexConfirmRollback");
+    }
 }
diff --git a/tests/ServiceCrashTest/Android.bp b/tests/ServiceCrashTest/Android.bp
new file mode 100644
index 0000000..40a377d
--- /dev/null
+++ b/tests/ServiceCrashTest/Android.bp
@@ -0,0 +1,12 @@
+android_test {
+    name: "ServiceCrashTest",
+    // Only compile source java files in this apk.
+    srcs: ["src/**/*.java"],
+    platform_apis: true,
+    certificate: "platform",
+    libs: ["android.test.base"],
+    static_libs: [
+        "compatibility-device-util-axt",
+        "androidx.test.rules",
+    ],
+}
diff --git a/tests/ServiceCrashTest/Android.mk b/tests/ServiceCrashTest/Android.mk
deleted file mode 100644
index 617ee7c..0000000
--- a/tests/ServiceCrashTest/Android.mk
+++ /dev/null
@@ -1,20 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := ServiceCrashTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_CERTIFICATE := platform
-LOCAL_JAVA_LIBRARIES := android.test.base
-
-LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util-axt androidx.test.rules
-
-include $(BUILD_PACKAGE)
-
-# Use the following include to make our test apk.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/SurfaceComposition/Android.bp b/tests/SurfaceComposition/Android.bp
new file mode 100644
index 0000000..53e4d52
--- /dev/null
+++ b/tests/SurfaceComposition/Android.bp
@@ -0,0 +1,32 @@
+// 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.
+
+android_test {
+    name: "SurfaceComposition",
+    // Don't include this package in any target
+    // When built, explicitly put it in the data partition.
+    dex_preopt: {
+        enabled: false,
+    },
+    optimize: {
+        enabled: false,
+    },
+    srcs: ["src/**/*.java"],
+    static_libs: ["junit"],
+    libs: [
+        "android.test.runner.stubs",
+        "android.test.base.stubs",
+    ],
+    sdk_version: "current",
+}
diff --git a/tests/SurfaceComposition/Android.mk b/tests/SurfaceComposition/Android.mk
deleted file mode 100644
index f59458d..0000000
--- a/tests/SurfaceComposition/Android.mk
+++ /dev/null
@@ -1,38 +0,0 @@
-# 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# Don't include this package in any target
-LOCAL_MODULE_TAGS := tests
-# When built, explicitly put it in the data partition.
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-
-LOCAL_JAVA_LIBRARIES := android.test.runner.stubs android.test.base.stubs
-
-LOCAL_PACKAGE_NAME := SurfaceComposition
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
diff --git a/tests/SystemMemoryTest/Android.mk b/tests/SystemMemoryTest/Android.mk
deleted file mode 100644
index 09a1618..0000000
--- a/tests/SystemMemoryTest/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(call all-subdir-makefiles)
diff --git a/tests/SystemMemoryTest/device/Android.bp b/tests/SystemMemoryTest/device/Android.bp
new file mode 100644
index 0000000..2bf0fec
--- /dev/null
+++ b/tests/SystemMemoryTest/device/Android.bp
@@ -0,0 +1,20 @@
+// 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.
+
+android_test_helper_app {
+    name: "SystemMemoryTestDevice",
+    sdk_version: "current",
+    srcs: ["src/**/*.java"],
+    test_suites: ["general-tests"],
+}
diff --git a/tests/SystemMemoryTest/device/Android.mk b/tests/SystemMemoryTest/device/Android.mk
deleted file mode 100644
index 75408df..0000000
--- a/tests/SystemMemoryTest/device/Android.mk
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_PACKAGE_NAME := SystemMemoryTestDevice
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_COMPATIBILITY_SUITE := general-tests
-include $(BUILD_PACKAGE)
diff --git a/tests/SystemMemoryTest/host/Android.bp b/tests/SystemMemoryTest/host/Android.bp
new file mode 100644
index 0000000..3bb5489
--- /dev/null
+++ b/tests/SystemMemoryTest/host/Android.bp
@@ -0,0 +1,20 @@
+// 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.
+
+java_test_host {
+    name: "system-memory-test",
+    srcs: ["src/**/*.java"],
+    libs: ["tradefed"],
+    test_suites: ["general-tests"],
+}
diff --git a/tests/SystemMemoryTest/host/Android.mk b/tests/SystemMemoryTest/host/Android.mk
deleted file mode 100644
index a516e38..0000000
--- a/tests/SystemMemoryTest/host/Android.mk
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_MODULE := system-memory-test
-LOCAL_MODULE_TAGS := optional
-LOCAL_JAVA_LIBRARIES := tradefed
-LOCAL_COMPATIBILITY_SUITE := general-tests
-include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/tests/UsageReportingTest/Android.bp b/tests/UsageReportingTest/Android.bp
new file mode 100644
index 0000000..0bac5a2
--- /dev/null
+++ b/tests/UsageReportingTest/Android.bp
@@ -0,0 +1,8 @@
+android_test {
+    name: "UsageReportingTest",
+    // Only compile source java files in this apk.
+    srcs: ["src/**/*.java"],
+    static_libs: ["androidx.legacy_legacy-support-v4"],
+    certificate: "platform",
+    platform_apis: true,
+}
diff --git a/tests/UsageReportingTest/Android.mk b/tests/UsageReportingTest/Android.mk
deleted file mode 100644
index afb6e16b1..0000000
--- a/tests/UsageReportingTest/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_USE_AAPT2 := true
-LOCAL_STATIC_ANDROID_LIBRARIES := androidx.legacy_legacy-support-v4
-
-LOCAL_CERTIFICATE := platform
-
-LOCAL_PACKAGE_NAME := UsageReportingTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
diff --git a/tests/UsageStatsPerfTests/Android.bp b/tests/UsageStatsPerfTests/Android.bp
new file mode 100644
index 0000000..3991fb8
--- /dev/null
+++ b/tests/UsageStatsPerfTests/Android.bp
@@ -0,0 +1,26 @@
+// 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.
+
+android_test {
+    name: "UsageStatsPerfTests",
+    srcs: ["src/**/*.java"],
+    static_libs: [
+        "androidx.test.rules",
+        "apct-perftests-utils",
+        "services.usage",
+    ],
+    platform_apis: true,
+    // For android.permission.FORCE_STOP_PACKAGES permission
+    certificate: "platform",
+}
diff --git a/tests/UsageStatsPerfTests/Android.mk b/tests/UsageStatsPerfTests/Android.mk
deleted file mode 100644
index 4304fb0..0000000
--- a/tests/UsageStatsPerfTests/Android.mk
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := \
-    $(call all-java-files-under, src)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    androidx.test.rules \
-    apct-perftests-utils \
-    services.usage
-
-LOCAL_PACKAGE_NAME := UsageStatsPerfTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-# For android.permission.FORCE_STOP_PACKAGES permission
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java b/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java
index adcd11a..bb985d7 100644
--- a/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java
+++ b/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java
@@ -197,7 +197,7 @@
                     intent.setPackage(getPackageName());
                     intent.putExtra(EXTRA_KEY_TIMEOUT, true);
                     mUsageStatsManager.registerAppUsageLimitObserver(1, packages,
-                            Duration.ofSeconds(60), Duration.ofSeconds(60),
+                            Duration.ofSeconds(60), Duration.ofSeconds(0),
                             PendingIntent.getActivity(UsageStatsActivity.this, 1, intent, 0));
                 }
             }
diff --git a/tests/UsbHostExternalManagmentTest/AoapTestDevice/Android.bp b/tests/UsbHostExternalManagmentTest/AoapTestDevice/Android.bp
new file mode 100644
index 0000000..c7e9df0
--- /dev/null
+++ b/tests/UsbHostExternalManagmentTest/AoapTestDevice/Android.bp
@@ -0,0 +1,27 @@
+// Copyright (C) 2016 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.
+//
+//
+
+//#################################################
+
+android_test {
+    name: "AoapTestDeviceApp",
+    srcs: ["src/**/*.java"],
+    resource_dirs: ["res"],
+    platform_apis: true,
+    optimize: {
+        enabled: false,
+    },
+}
diff --git a/tests/UsbHostExternalManagmentTest/AoapTestDevice/Android.mk b/tests/UsbHostExternalManagmentTest/AoapTestDevice/Android.mk
deleted file mode 100644
index cd7aaed..0000000
--- a/tests/UsbHostExternalManagmentTest/AoapTestDevice/Android.mk
+++ /dev/null
@@ -1,36 +0,0 @@
-# Copyright (C) 2016 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.
-#
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-##################################################
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_PACKAGE_NAME := AoapTestDeviceApp
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
-
diff --git a/tests/UsbHostExternalManagmentTest/AoapTestHost/Android.bp b/tests/UsbHostExternalManagmentTest/AoapTestHost/Android.bp
new file mode 100644
index 0000000..6fa58cb
--- /dev/null
+++ b/tests/UsbHostExternalManagmentTest/AoapTestHost/Android.bp
@@ -0,0 +1,27 @@
+// Copyright (C) 2016 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.
+//
+//
+
+//#################################################
+
+android_test {
+    name: "AoapTestHostApp",
+    srcs: ["src/**/*.java"],
+    resource_dirs: ["res"],
+    platform_apis: true,
+    optimize: {
+        enabled: false,
+    },
+}
diff --git a/tests/UsbHostExternalManagmentTest/AoapTestHost/Android.mk b/tests/UsbHostExternalManagmentTest/AoapTestHost/Android.mk
deleted file mode 100644
index bd8a51b..0000000
--- a/tests/UsbHostExternalManagmentTest/AoapTestHost/Android.mk
+++ /dev/null
@@ -1,36 +0,0 @@
-# Copyright (C) 2016 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.
-#
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-##################################################
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_PACKAGE_NAME := AoapTestHostApp
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
-
diff --git a/tests/UsbHostExternalManagmentTest/UsbHostExternalManagmentTestApp/Android.bp b/tests/UsbHostExternalManagmentTest/UsbHostExternalManagmentTestApp/Android.bp
new file mode 100644
index 0000000..edd4205
--- /dev/null
+++ b/tests/UsbHostExternalManagmentTest/UsbHostExternalManagmentTestApp/Android.bp
@@ -0,0 +1,32 @@
+// Copyright (C) 2016 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.
+//
+//
+
+//#################################################
+
+// TODO: should this be android_helper_test_app?
+android_app {
+    name: "UsbHostExternalManagementTestApp",
+    srcs: ["src/**/*.java"],
+    resource_dirs: ["res"],
+    platform_apis: true,
+    privileged: true,
+    // TODO remove tests tag
+    //LOCAL_MODULE_TAGS := tests
+    //LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+    optimize: {
+        enabled: false,
+    },
+}
diff --git a/tests/UsbHostExternalManagmentTest/UsbHostExternalManagmentTestApp/Android.mk b/tests/UsbHostExternalManagmentTest/UsbHostExternalManagmentTestApp/Android.mk
deleted file mode 100644
index fed454e..0000000
--- a/tests/UsbHostExternalManagmentTest/UsbHostExternalManagmentTestApp/Android.mk
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright (C) 2016 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.
-#
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-##################################################
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_PACKAGE_NAME := UsbHostExternalManagementTestApp
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_PRIVILEGED_MODULE := true
-# TODO remove tests tag
-#LOCAL_MODULE_TAGS := tests
-#LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
-
diff --git a/tests/UsbTests/Android.bp b/tests/UsbTests/Android.bp
new file mode 100644
index 0000000..1b2cf63
--- /dev/null
+++ b/tests/UsbTests/Android.bp
@@ -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.
+//
+
+android_test {
+    name: "UsbTests",
+    srcs: ["**/*.java"],
+    static_libs: [
+        "frameworks-base-testutils",
+        "androidx.test.rules",
+        "mockito-target-inline-minus-junit4",
+        "platform-test-annotations",
+        "services.core",
+        "services.net",
+        "services.usb",
+        "truth-prebuilt",
+    ],
+    jni_libs: ["libdexmakerjvmtiagent"],
+    certificate: "platform",
+    platform_apis: true,
+    test_suites: ["device-tests"],
+}
diff --git a/tests/UsbTests/Android.mk b/tests/UsbTests/Android.mk
deleted file mode 100644
index aef993b..0000000
--- a/tests/UsbTests/Android.mk
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    frameworks-base-testutils \
-    androidx.test.rules \
-    mockito-target-inline-minus-junit4 \
-    platform-test-annotations \
-    services.core \
-    services.net \
-    services.usb \
-    truth-prebuilt \
-
-LOCAL_JNI_SHARED_LIBRARIES := \
-    libdexmakerjvmtiagent \
-
-LOCAL_CERTIFICATE := platform
-
-LOCAL_PACKAGE_NAME := UsbTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/WindowAnimationJank/Android.bp b/tests/WindowAnimationJank/Android.bp
new file mode 100644
index 0000000..50b2297
--- /dev/null
+++ b/tests/WindowAnimationJank/Android.bp
@@ -0,0 +1,25 @@
+// 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.
+
+android_test {
+    name: "WindowAnimationJank",
+    srcs: ["src/**/*.java"],
+    static_libs: [
+        "ub-uiautomator",
+        "androidx.test.janktesthelper",
+        "junit",
+    ],
+    libs: ["android.test.base.stubs"],
+    sdk_version: "current",
+}
diff --git a/tests/WindowAnimationJank/Android.mk b/tests/WindowAnimationJank/Android.mk
deleted file mode 100644
index 1c2d167..0000000
--- a/tests/WindowAnimationJank/Android.mk
+++ /dev/null
@@ -1,36 +0,0 @@
-# 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := WindowAnimationJank
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    ub-uiautomator \
-    androidx.test.janktesthelper \
-    junit
-
-LOCAL_JAVA_LIBRARIES := android.test.base.stubs
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
diff --git a/tests/net/java/android/net/shared/LinkPropertiesParcelableUtilTest.java b/tests/net/java/android/net/shared/LinkPropertiesParcelableUtilTest.java
deleted file mode 100644
index 2d0e03d..0000000
--- a/tests/net/java/android/net/shared/LinkPropertiesParcelableUtilTest.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2019 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.net.shared;
-
-import static android.net.shared.LinkPropertiesParcelableUtil.fromStableParcelable;
-import static android.net.shared.LinkPropertiesParcelableUtil.toStableParcelable;
-import static android.net.shared.ParcelableTestUtil.assertFieldCountEquals;
-
-import static org.junit.Assert.assertEquals;
-
-import android.net.InetAddresses;
-import android.net.IpPrefix;
-import android.net.LinkAddress;
-import android.net.LinkProperties;
-import android.net.ProxyInfo;
-import android.net.RouteInfo;
-import android.net.Uri;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.Arrays;
-import java.util.Collections;
-
-/**
- * Tests for {@link LinkPropertiesParcelableUtil}
- */
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class LinkPropertiesParcelableUtilTest {
-    private LinkProperties mLinkProperties;
-
-    private static final String TEST_LINKPROPS_IFACE = "TEST_IFACE";
-
-    @Before
-    public void setUp() {
-        mLinkProperties = new LinkProperties();
-        mLinkProperties.setInterfaceName(TEST_LINKPROPS_IFACE);
-        mLinkProperties.setLinkAddresses(Arrays.asList(
-                new LinkAddress(InetAddresses.parseNumericAddress("192.168.0.42"), 16),
-                new LinkAddress(InetAddresses.parseNumericAddress("2001:db8::7"), 42)));
-        mLinkProperties.setDnsServers(Arrays.asList(
-                InetAddresses.parseNumericAddress("2001:db8::42"),
-                InetAddresses.parseNumericAddress("192.168.1.1")
-        ));
-        mLinkProperties.setValidatedPrivateDnsServers(Arrays.asList(
-                InetAddresses.parseNumericAddress("2001:db8::43"),
-                InetAddresses.parseNumericAddress("192.168.42.43")
-        ));
-        mLinkProperties.setPcscfServers(Arrays.asList(
-                InetAddresses.parseNumericAddress("2001:db8::47"),
-                InetAddresses.parseNumericAddress("192.168.42.47")
-        ));
-        mLinkProperties.setUsePrivateDns(true);
-        mLinkProperties.setPrivateDnsServerName("test.example.com");
-        mLinkProperties.setDomains("test1.example.com,test2.example.com");
-        mLinkProperties.addRoute(new RouteInfo(
-                new IpPrefix(InetAddresses.parseNumericAddress("2001:db8::44"), 45),
-                InetAddresses.parseNumericAddress("2001:db8::45"),
-                TEST_LINKPROPS_IFACE,
-                RouteInfo.RTN_UNICAST
-        ));
-        mLinkProperties.addRoute(new RouteInfo(
-                new IpPrefix(InetAddresses.parseNumericAddress("192.168.44.45"), 16),
-                InetAddresses.parseNumericAddress("192.168.45.1"),
-                TEST_LINKPROPS_IFACE,
-                RouteInfo.RTN_THROW
-        ));
-        mLinkProperties.setHttpProxy(new ProxyInfo("test3.example.com", 8000,
-                "excl1.example.com,excl2.example.com"));
-        mLinkProperties.setMtu(5000);
-        mLinkProperties.setTcpBufferSizes("1,2,3,4,5,6");
-        mLinkProperties.setNat64Prefix(
-                new IpPrefix(InetAddresses.parseNumericAddress("2001:db8::48"), 96));
-
-        // Verify that this test does not miss any new field added later.
-        // If any added field is not included in LinkProperties#equals, assertLinkPropertiesEquals
-        // must also be updated.
-        assertFieldCountEquals(14, LinkProperties.class);
-    }
-
-    @Test
-    public void testParcelUnparcel() {
-        doParcelUnparcelTest();
-    }
-
-    @Test
-    public void testParcelUnparcel_NullInterface() {
-        mLinkProperties.setInterfaceName(null);
-        doParcelUnparcelTest();
-    }
-
-    @Test
-    public void testParcelUnparcel_NullPrivateDnsServer() {
-        mLinkProperties.setPrivateDnsServerName(null);
-        doParcelUnparcelTest();
-    }
-
-    @Test
-    public void testParcelUnparcel_NullDomains() {
-        mLinkProperties.setDomains(null);
-        doParcelUnparcelTest();
-    }
-
-    @Test
-    public void testParcelUnparcel_NullProxy() {
-        mLinkProperties.setHttpProxy(null);
-        doParcelUnparcelTest();
-    }
-
-    @Test
-    public void testParcelUnparcel_NullTcpBufferSizes() {
-        mLinkProperties.setTcpBufferSizes(null);
-        doParcelUnparcelTest();
-    }
-
-    @Test
-    public void testParcelUnparcel_EmptyLinkAddresses() {
-        mLinkProperties.setLinkAddresses(Collections.emptyList());
-        doParcelUnparcelTest();
-    }
-
-    @Test
-    public void testParcelUnparcel_EmptyDnses() {
-        mLinkProperties.setDnsServers(Collections.emptyList());
-        doParcelUnparcelTest();
-    }
-
-    @Test
-    public void testParcelUnparcel_EmptyValidatedPrivateDnses() {
-        mLinkProperties.setValidatedPrivateDnsServers(Collections.emptyList());
-        doParcelUnparcelTest();
-    }
-
-    @Test
-    public void testParcelUnparcel_EmptyRoutes() {
-        for (RouteInfo r : mLinkProperties.getAllRoutes()) {
-            mLinkProperties.removeRoute(r);
-        }
-        doParcelUnparcelTest();
-    }
-
-    @Test
-    public void testParcelUnparcel_PacFileProxyInfo() {
-        mLinkProperties.setHttpProxy(new ProxyInfo(Uri.parse("http://pacfile.example.com")));
-        doParcelUnparcelTest();
-    }
-
-    @Test
-    public void testParcelUnparcel_NullNat64Prefix() {
-        mLinkProperties.setNat64Prefix(null);
-        doParcelUnparcelTest();
-    }
-
-    private void doParcelUnparcelTest() {
-        final LinkProperties unparceled = fromStableParcelable(toStableParcelable(mLinkProperties));
-        assertLinkPropertiesEquals(mLinkProperties, unparceled);
-    }
-
-    private static void assertLinkPropertiesEquals(LinkProperties expected, LinkProperties actual) {
-        assertEquals(expected, actual);
-
-        // Equality on stacked links is not tested as they should not be passed to processes using
-        // LinkPropertiesParcelable.
-    }
-}
diff --git a/tests/net/java/com/android/internal/util/TestUtils.java b/tests/net/java/com/android/internal/util/TestUtils.java
index 7e5a1d3..57cc172 100644
--- a/tests/net/java/com/android/internal/util/TestUtils.java
+++ b/tests/net/java/com/android/internal/util/TestUtils.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 
+import android.annotation.NonNull;
 import android.os.ConditionVariable;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -26,6 +27,8 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.util.concurrent.Executor;
+
 public final class TestUtils {
     private TestUtils() { }
 
@@ -54,6 +57,17 @@
         }
     }
 
+    /**
+     * Block until the given Serial Executor becomes idle, or until timeoutMs has passed.
+     */
+    public static void waitForIdleSerialExecutor(@NonNull Executor executor, long timeoutMs) {
+        final ConditionVariable cv = new ConditionVariable();
+        executor.execute(() -> cv.open());
+        if (!cv.block(timeoutMs)) {
+            fail(executor.toString() + " did not become idle after " + timeoutMs + " ms");
+        }
+    }
+
     // TODO : fetch the creator through reflection or something instead of passing it
     public static <T extends Parcelable, C extends Parcelable.Creator<T>>
             void assertParcelingIsLossless(T source, C creator) {
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 985d667..3263ef9 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -60,10 +60,10 @@
 import static android.net.NetworkPolicyManager.RULE_NONE;
 import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
 import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
-import static android.net.shared.NetworkParcelableUtil.fromStableParcelable;
 
 import static com.android.internal.util.TestUtils.waitForIdleHandler;
 import static com.android.internal.util.TestUtils.waitForIdleLooper;
+import static com.android.internal.util.TestUtils.waitForIdleSerialExecutor;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -88,6 +88,7 @@
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
+import android.annotation.NonNull;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
@@ -123,7 +124,6 @@
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkMisc;
-import android.net.NetworkParcelable;
 import android.net.NetworkRequest;
 import android.net.NetworkSpecifier;
 import android.net.NetworkStackClient;
@@ -190,6 +190,8 @@
 
 import java.net.Inet4Address;
 import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -206,6 +208,7 @@
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Consumer;
 import java.util.function.Predicate;
 
 /**
@@ -497,8 +500,7 @@
                 fail(e.getMessage());
             }
 
-            final ArgumentCaptor<NetworkParcelable> nmNetworkCaptor =
-                    ArgumentCaptor.forClass(NetworkParcelable.class);
+            final ArgumentCaptor<Network> nmNetworkCaptor = ArgumentCaptor.forClass(Network.class);
             final ArgumentCaptor<INetworkMonitorCallbacks> nmCbCaptor =
                     ArgumentCaptor.forClass(INetworkMonitorCallbacks.class);
             doNothing().when(mNetworkStack).makeNetworkMonitor(
@@ -538,8 +540,7 @@
                 }
             };
 
-            assertEquals(
-                    mNetworkAgent.netId, fromStableParcelable(nmNetworkCaptor.getValue()).netId);
+            assertEquals(mNetworkAgent.netId, nmNetworkCaptor.getValue().netId);
             mNmCallbacks = nmCbCaptor.getValue();
 
             try {
@@ -2549,7 +2550,8 @@
         verifyActiveNetwork(TRANSPORT_CELLULAR);
     }
 
-    @Test
+    // TODO: deflake and re-enable
+    // @Test
     public void testPartialConnectivity() {
         // Register network callback.
         NetworkRequest request = new NetworkRequest.Builder()
@@ -3758,7 +3760,7 @@
             }
         }
 
-        private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
+        private final LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
 
         @Override
         public void onStarted() {
@@ -3833,6 +3835,11 @@
         }
 
         private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
+        private final Executor mExecutor;
+
+        TestSocketKeepaliveCallback(@NonNull Executor executor) {
+            mExecutor = executor;
+        }
 
         @Override
         public void onStarted() {
@@ -3870,6 +3877,12 @@
         public void expectError(int error) {
             expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
         }
+
+        public void assertNoCallback() {
+            waitForIdleSerialExecutor(mExecutor, TIMEOUT_MS);
+            CallbackValue cv = mCallbacks.peek();
+            assertNull("Unexpected callback: " + cv, cv);
+        }
     }
 
     private Network connectKeepaliveNetwork(LinkProperties lp) {
@@ -3976,19 +3989,6 @@
         myNet = connectKeepaliveNetwork(lp);
         mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
 
-        // Check things work as expected when the keepalive is stopped and the network disconnects.
-        ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
-        callback.expectStarted();
-        ka.stop();
-        mWiFiNetworkAgent.disconnect();
-        waitFor(mWiFiNetworkAgent.getDisconnectedCV());
-        waitForIdle();
-        callback.expectStopped();
-
-        // Reconnect.
-        myNet = connectKeepaliveNetwork(lp);
-        mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
-
         // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
         mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
@@ -4018,17 +4018,24 @@
         callback3.expectStopped();
     }
 
-    @Test
-    public void testNattSocketKeepalives_SingleThreadExecutor() throws Exception {
+    // Helper method to prepare the executor and run test
+    private void runTestWithSerialExecutors(Consumer<Executor> functor) {
         final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
-        doTestNattSocketKeepalivesWithExecutor(executorSingleThread);
+        final Executor executorInline = (Runnable r) -> r.run();
+        functor.accept(executorSingleThread);
         executorSingleThread.shutdown();
+        functor.accept(executorInline);
     }
 
     @Test
-    public void testNattSocketKeepalives_InlineExecutor() throws Exception {
-        final Executor executorInline = (Runnable r) -> r.run();
-        doTestNattSocketKeepalivesWithExecutor(executorInline);
+    public void testNattSocketKeepalives() {
+        runTestWithSerialExecutors(executor -> {
+            try {
+                doTestNattSocketKeepalivesWithExecutor(executor);
+            } catch (Exception e) {
+                fail(e.getMessage());
+            }
+        });
     }
 
     private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception {
@@ -4057,7 +4064,7 @@
         Network notMyNet = new Network(61234);
         Network myNet = connectKeepaliveNetwork(lp);
 
-        TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback();
+        TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
         SocketKeepalive ka;
 
         // Attempt to start keepalives with invalid parameters and check for errors.
@@ -4100,6 +4107,22 @@
         ka.stop();
         callback.expectStopped();
 
+        // Check that keepalive could be restarted.
+        ka.start(validKaInterval);
+        callback.expectStarted();
+        ka.stop();
+        callback.expectStopped();
+
+        // Check that keepalive can be restarted without waiting for callback.
+        ka.start(validKaInterval);
+        callback.expectStarted();
+        ka.stop();
+        ka.start(validKaInterval);
+        callback.expectStopped();
+        callback.expectStarted();
+        ka.stop();
+        callback.expectStopped();
+
         // Check that deleting the IP address stops the keepalive.
         LinkProperties bogusLp = new LinkProperties(lp);
         ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
@@ -4124,20 +4147,7 @@
         final Network myNetAlias = myNet;
         assertNull(mCm.getNetworkCapabilities(myNetAlias));
         ka.stop();
-
-        // Reconnect.
-        myNet = connectKeepaliveNetwork(lp);
-        mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
-
-        // Check things work as expected when the keepalive is stopped and the network disconnects.
-        ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
-        ka.start(validKaInterval);
-        callback.expectStarted();
-        ka.stop();
-        mWiFiNetworkAgent.disconnect();
-        waitFor(mWiFiNetworkAgent.getDisconnectedCV());
-        waitForIdle();
-        callback.expectStopped();
+        callback.assertNoCallback();
 
         // Reconnect.
         myNet = connectKeepaliveNetwork(lp);
@@ -4152,7 +4162,7 @@
         // The second one gets slot 2.
         mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
         final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket(6789);
-        TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback();
+        TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor);
         SocketKeepalive ka2 =
                 mCm.createSocketKeepalive(myNet, testSocket2, myIPv4, dstIPv4, executor, callback2);
         ka2.start(validKaInterval);
@@ -4169,6 +4179,81 @@
 
         mWiFiNetworkAgent.disconnect();
         waitFor(mWiFiNetworkAgent.getDisconnectedCV());
+        mWiFiNetworkAgent = null;
+    }
+
+    @Test
+    public void testTcpSocketKeepalives() {
+        runTestWithSerialExecutors(executor -> {
+            try {
+                doTestTcpSocketKeepalivesWithExecutor(executor);
+            } catch (Exception e) {
+                fail(e.getMessage());
+            }
+        });
+    }
+
+    private void doTestTcpSocketKeepalivesWithExecutor(Executor executor) throws Exception {
+        final int srcPortV4 = 12345;
+        final int srcPortV6 = 23456;
+        final InetAddress myIPv4 = InetAddress.getByName("127.0.0.1");
+        final InetAddress myIPv6 = InetAddress.getByName("::1");
+
+        final int validKaInterval = 15;
+        final int invalidKaInterval = 9;
+
+        final LinkProperties lp = new LinkProperties();
+        lp.setInterfaceName("wlan12");
+        lp.addLinkAddress(new LinkAddress(myIPv6, 64));
+        lp.addLinkAddress(new LinkAddress(myIPv4, 25));
+        lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
+        lp.addRoute(new RouteInfo(InetAddress.getByName("127.0.0.254")));
+
+        final Network notMyNet = new Network(61234);
+        final Network myNet = connectKeepaliveNetwork(lp);
+
+        final Socket testSocketV4 = new Socket();
+        final Socket testSocketV6 = new Socket();
+
+        TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
+        SocketKeepalive ka;
+
+        // Attempt to start Tcp keepalives with invalid parameters and check for errors.
+        // Invalid network.
+        ka = mCm.createSocketKeepalive(notMyNet, testSocketV4, executor, callback);
+        ka.start(validKaInterval);
+        callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
+
+        // Invalid Socket (socket is not bound with IPv4 address).
+        ka = mCm.createSocketKeepalive(myNet, testSocketV4, executor, callback);
+        ka.start(validKaInterval);
+        callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
+
+        // Invalid Socket (socket is not bound with IPv6 address).
+        ka = mCm.createSocketKeepalive(myNet, testSocketV6, executor, callback);
+        ka.start(validKaInterval);
+        callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
+
+        // Bind the socket address
+        testSocketV4.bind(new InetSocketAddress(myIPv4, srcPortV4));
+        testSocketV6.bind(new InetSocketAddress(myIPv6, srcPortV6));
+
+        // Invalid Socket (socket is bound with IPv4 address).
+        ka = mCm.createSocketKeepalive(myNet, testSocketV4, executor, callback);
+        ka.start(validKaInterval);
+        callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
+
+        // Invalid Socket (socket is bound with IPv6 address).
+        ka = mCm.createSocketKeepalive(myNet, testSocketV6, executor, callback);
+        ka.start(validKaInterval);
+        callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
+
+        testSocketV4.close();
+        testSocketV6.close();
+
+        mWiFiNetworkAgent.disconnect();
+        waitFor(mWiFiNetworkAgent.getDisconnectedCV());
+        mWiFiNetworkAgent = null;
     }
 
     @Test
diff --git a/tools/processors/view_inspector/Android.bp b/tools/processors/view_inspector/Android.bp
index 06ff05e..069e61f 100644
--- a/tools/processors/view_inspector/Android.bp
+++ b/tools/processors/view_inspector/Android.bp
@@ -8,6 +8,7 @@
 
     static_libs: [
         "javapoet",
+        "stub-annotations",
     ],
 
     use_tools_jar: true,
diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/AnnotationUtils.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/AnnotationUtils.java
index 2690ee8..c833e47 100644
--- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/AnnotationUtils.java
+++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/AnnotationUtils.java
@@ -16,6 +16,8 @@
 
 package android.processor.view.inspector;
 
+import androidx.annotation.NonNull;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -40,7 +42,7 @@
     private final Elements mElementUtils;
     private final Types mTypeUtils;
 
-    AnnotationUtils(ProcessingEnvironment processingEnv) {
+    AnnotationUtils(@NonNull ProcessingEnvironment processingEnv) {
         mElementUtils = processingEnv.getElementUtils();
         mTypeUtils = processingEnv.getTypeUtils();
     }
@@ -53,7 +55,8 @@
      * @return The mirror of the requested annotation
      * @throws ProcessingException If there is not exactly one of the requested annotation.
      */
-    AnnotationMirror exactlyOneMirror(String qualifiedName, Element element) {
+    @NonNull
+    AnnotationMirror exactlyOneMirror(@NonNull String qualifiedName, @NonNull Element element) {
         final Element targetTypeElment = mElementUtils.getTypeElement(qualifiedName);
         final TypeMirror targetType = targetTypeElment.asType();
         AnnotationMirror result = null;
@@ -89,7 +92,7 @@
      * @param annotationQualifiedName The name of the annotation to check for
      * @return True if the annotation is present, false otherwise
      */
-    boolean hasAnnotation(Element element, String annotationQualifiedName) {
+    boolean hasAnnotation(@NonNull Element element, @NonNull String annotationQualifiedName) {
         final TypeElement namedElement = mElementUtils.getTypeElement(annotationQualifiedName);
 
         if (namedElement != null) {
@@ -118,10 +121,10 @@
      * @return A list containing the requested types
      */
     <T> List<T> typedArrayValuesByName(
-            String propertyName,
-            Class<T> valueClass,
-            Element element,
-            AnnotationMirror annotationMirror) {
+            @NonNull String propertyName,
+            @NonNull Class<T> valueClass,
+            @NonNull Element element,
+            @NonNull AnnotationMirror annotationMirror) {
         return untypedArrayValuesByName(propertyName, element, annotationMirror)
                 .stream()
                 .map(annotationValue -> {
@@ -159,10 +162,11 @@
      * @param annotationMirror An annotation mirror to search for the property
      * @return A list of annotation values, empty list if none found
      */
+    @NonNull
     List<AnnotationValue> untypedArrayValuesByName(
-            String propertyName,
-            Element element,
-            AnnotationMirror annotationMirror) {
+            @NonNull String propertyName,
+            @NonNull Element element,
+            @NonNull AnnotationMirror annotationMirror) {
         return typedValueByName(propertyName, List.class, element, annotationMirror)
                 .map(untypedValues -> {
                     List<AnnotationValue> typedValues = new ArrayList<>(untypedValues.size());
@@ -195,6 +199,7 @@
      * @param <T> The type of the value
      * @return An optional containing the typed value of the named property
      */
+    @NonNull
     <T> Optional<T> typedValueByName(
             String propertyName,
             Class<T> valueClass,
@@ -241,10 +246,11 @@
      * @return An optional containing the untyped value of the named property
      * @see AnnotationValue#getValue()
      */
+    @NonNull
     Optional<Object> untypedValueByName(
-            String propertyName,
-            Element element,
-            AnnotationMirror annotationMirror) {
+            @NonNull String propertyName,
+            @NonNull Element element,
+            @NonNull AnnotationMirror annotationMirror) {
         return valueByName(propertyName, annotationMirror).map(annotationValue -> {
             final Object value = annotationValue.getValue();
 
@@ -269,7 +275,10 @@
      * @param annotationMirror The mirror to search for the property
      * @return The value of the property
      */
-    Optional<AnnotationValue> valueByName(String propertyName, AnnotationMirror annotationMirror) {
+    @NonNull
+    Optional<AnnotationValue> valueByName(
+            @NonNull String propertyName,
+            @NonNull AnnotationMirror annotationMirror) {
         final Map<? extends ExecutableElement, ? extends AnnotationValue> valueMap =
                 annotationMirror.getElementValues();
 
diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableClassModel.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableClassModel.java
index 1ad7ada..147f054 100644
--- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableClassModel.java
+++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableClassModel.java
@@ -16,6 +16,9 @@
 
 package android.processor.view.inspector;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
 import com.squareup.javapoet.ClassName;
 
 import java.util.Collection;
@@ -34,27 +37,29 @@
  * testing {@link InspectionCompanionGenerator}.
  */
 public final class InspectableClassModel {
-    private final ClassName mClassName;
-    private final Map<String, Property> mPropertyMap;
-    private Optional<String> mNodeName = Optional.empty();
+    private final @NonNull ClassName mClassName;
+    private final @NonNull Map<String, Property> mPropertyMap;
+    private @NonNull Optional<String> mNodeName = Optional.empty();
 
     /**
      * @param className The name of the modeled class
      */
-    public InspectableClassModel(ClassName className) {
+    public InspectableClassModel(@NonNull ClassName className) {
         mClassName = className;
         mPropertyMap = new HashMap<>();
     }
 
+    @NonNull
     public ClassName getClassName() {
         return mClassName;
     }
 
+    @NonNull
     public Optional<String> getNodeName() {
         return mNodeName;
     }
 
-    public void setNodeName(Optional<String> nodeName) {
+    public void setNodeName(@NonNull Optional<String> nodeName) {
         mNodeName = nodeName;
     }
 
@@ -63,7 +68,7 @@
      *
      * @param property The property to add or replace
      */
-    public void putProperty(Property property) {
+    public void putProperty(@NonNull Property property) {
         mPropertyMap.put(property.getName(), property);
     }
 
@@ -73,7 +78,8 @@
      * @param name The name of the property
      * @return The property or an empty optional
      */
-    public Optional<Property> getProperty(String name) {
+    @NonNull
+    public Optional<Property> getProperty(@NonNull String name) {
         return Optional.ofNullable(mPropertyMap.get(name));
     }
 
@@ -82,6 +88,7 @@
      *
      * @return An un-ordered collection of properties
      */
+    @NonNull
     public Collection<Property> getAllProperties() {
         return mPropertyMap.values();
     }
@@ -90,8 +97,8 @@
      * Represents a way to access a property, either a getter or a field.
      */
     public static final class Accessor {
-        private final String mName;
-        private final Type mType;
+        private final @NonNull String mName;
+        private final @NonNull Type mType;
 
         /**
          * Construct an accessor for a field.
@@ -100,7 +107,8 @@
          * @return The new accessor
          * @see Type#FIELD
          */
-        static Accessor ofField(String name) {
+        @NonNull
+        static Accessor ofField(@NonNull String name) {
             return new Accessor(name, Type.FIELD);
         }
 
@@ -111,19 +119,22 @@
          * @return The new accessor
          * @see Type#GETTER
          */
-        static Accessor ofGetter(String name) {
+        @NonNull
+        static Accessor ofGetter(@NonNull String name) {
             return new Accessor(name, Type.GETTER);
         }
 
-        public Accessor(String name, Type type) {
+        public Accessor(@NonNull String name, @NonNull Type type) {
             mName = Objects.requireNonNull(name, "Accessor name must not be null");
             mType = Objects.requireNonNull(type, "Accessor type must not be null");
         }
 
+        @NonNull
         public String getName() {
             return mName;
         }
 
+        @NonNull
         public Type getType() {
             return mType;
         }
@@ -135,6 +146,7 @@
          *
          * @return A string representing the invocation of this accessor
          */
+        @NonNull
         public String invocation() {
             switch (mType) {
                 case FIELD:
@@ -168,15 +180,15 @@
      * Model an inspectable property
      */
     public static final class Property {
-        private final String mName;
-        private final Accessor mAccessor;
-        private final Type mType;
+        private final @NonNull String mName;
+        private final @NonNull Accessor mAccessor;
+        private final @NonNull Type mType;
         private boolean mAttributeIdInferrableFromR = true;
         private int mAttributeId = 0;
-        private List<IntEnumEntry> mIntEnumEntries;
-        private List<IntFlagEntry> mIntFlagEntries;
+        private @Nullable List<IntEnumEntry> mIntEnumEntries;
+        private @Nullable List<IntFlagEntry> mIntFlagEntries;
 
-        public Property(String name, Accessor accessor, Type type) {
+        public Property(@NonNull String name, @NonNull Accessor accessor, @NonNull Type type) {
             mName = Objects.requireNonNull(name, "Name must not be null");
             mAccessor = Objects.requireNonNull(accessor, "Accessor must not be null");
             mType = Objects.requireNonNull(type, "Type must not be null");
@@ -204,14 +216,17 @@
             mAttributeIdInferrableFromR = attributeIdInferrableFromR;
         }
 
+        @NonNull
         public String getName() {
             return mName;
         }
 
+        @NonNull
         public Accessor getAccessor() {
             return mAccessor;
         }
 
+        @NonNull
         public Type getType() {
             return mType;
         }
@@ -221,6 +236,7 @@
          *
          * @return A list of mapping entries, empty if absent
          */
+        @NonNull
         public List<IntEnumEntry> getIntEnumEntries() {
             if (mIntEnumEntries != null) {
                 return mIntEnumEntries;
@@ -229,7 +245,7 @@
             }
         }
 
-        public void setIntEnumEntries(List<IntEnumEntry> intEnumEntries) {
+        public void setIntEnumEntries(@NonNull List<IntEnumEntry> intEnumEntries) {
             mIntEnumEntries = intEnumEntries;
         }
 
@@ -238,6 +254,7 @@
          *
          * @return A list of mapping entries, empty if absent
          */
+        @NonNull
         public List<IntFlagEntry> getIntFlagEntries() {
             if (mIntFlagEntries != null) {
                 return mIntFlagEntries;
@@ -246,7 +263,7 @@
             }
         }
 
-        public void setIntFlagEntries(List<IntFlagEntry> intFlagEntries) {
+        public void setIntFlagEntries(@NonNull List<IntFlagEntry> intFlagEntries) {
             mIntFlagEntries = intFlagEntries;
         }
 
@@ -321,14 +338,15 @@
      * @see android.view.inspector.IntEnumMapping
      */
     public static final class IntEnumEntry {
-        private final String mName;
+        private final @NonNull String mName;
         private final int mValue;
 
-        public IntEnumEntry(String name, int value) {
+        public IntEnumEntry(int value, @NonNull String name) {
             mName = Objects.requireNonNull(name, "Name must not be null");
             mValue = value;
         }
 
+        @NonNull
         public String getName() {
             return mName;
         }
@@ -344,29 +362,21 @@
      * @see android.view.inspector.IntFlagMapping
      */
     public static final class IntFlagEntry {
-        private final String mName;
+        private final @NonNull String mName;
         private final int mTarget;
         private final int mMask;
 
-        public IntFlagEntry(String name, int target, int mask) {
+        public IntFlagEntry(int mask, int target, @NonNull String name) {
             mName = Objects.requireNonNull(name, "Name must not be null");
             mTarget = target;
             mMask = mask;
         }
 
-        public IntFlagEntry(String name, int target) {
-            this(name, target, target);
+        public IntFlagEntry(int target, String name) {
+            this(target, target, name);
         }
 
-        /**
-         * Determine if this entry has a bitmask.
-         *
-         * @return True if the bitmask and target are different, false otherwise
-         */
-        public boolean hasMask() {
-            return mTarget != mMask;
-        }
-
+        @NonNull
         public String getName() {
             return mName;
         }
diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableNodeNameProcessor.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableNodeNameProcessor.java
index 46819b2..64a60fb 100644
--- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableNodeNameProcessor.java
+++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableNodeNameProcessor.java
@@ -16,6 +16,8 @@
 
 package android.processor.view.inspector;
 
+import androidx.annotation.NonNull;
+
 import java.util.Optional;
 
 import javax.annotation.processing.ProcessingEnvironment;
@@ -28,17 +30,17 @@
  * @see android.view.inspector.InspectableNodeName
  */
 public final class InspectableNodeNameProcessor implements ModelProcessor {
-    private final String mQualifiedName;
-    private final ProcessingEnvironment mProcessingEnv;
-    private final AnnotationUtils mAnnotationUtils;
+    private final @NonNull String mQualifiedName;
+    private final @NonNull ProcessingEnvironment mProcessingEnv;
+    private final @NonNull AnnotationUtils mAnnotationUtils;
 
     /**
      * @param annotationQualifiedName The qualified name of the annotation to process
      * @param processingEnv The processing environment from the parent processor
      */
     public InspectableNodeNameProcessor(
-            String annotationQualifiedName,
-            ProcessingEnvironment processingEnv) {
+            @NonNull String annotationQualifiedName,
+            @NonNull ProcessingEnvironment processingEnv) {
         mQualifiedName = annotationQualifiedName;
         mProcessingEnv = processingEnv;
         mAnnotationUtils = new AnnotationUtils(processingEnv);
@@ -54,7 +56,7 @@
      * @param model The model this element should be merged into
      */
     @Override
-    public void process(Element element, InspectableClassModel model) {
+    public void process(@NonNull Element element, @NonNull InspectableClassModel model) {
         try {
             final AnnotationMirror mirror =
                     mAnnotationUtils.exactlyOneMirror(mQualifiedName, element);
diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectablePropertyProcessor.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectablePropertyProcessor.java
index 20de90d..2042a68 100644
--- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectablePropertyProcessor.java
+++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectablePropertyProcessor.java
@@ -21,6 +21,8 @@
 import android.processor.view.inspector.InspectableClassModel.IntFlagEntry;
 import android.processor.view.inspector.InspectableClassModel.Property;
 
+import androidx.annotation.NonNull;
+
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
@@ -45,9 +47,9 @@
  * @see android.view.inspector.InspectableProperty
  */
 public final class InspectablePropertyProcessor implements ModelProcessor {
-    private final String mQualifiedName;
-    private final ProcessingEnvironment mProcessingEnv;
-    private final AnnotationUtils mAnnotationUtils;
+    private final @NonNull String mQualifiedName;
+    private final @NonNull ProcessingEnvironment mProcessingEnv;
+    private final @NonNull AnnotationUtils mAnnotationUtils;
 
     /**
      * Regex that matches methods names of the form {@code #getValue()}.
@@ -130,15 +132,15 @@
      * @param processingEnv           The processing environment from the parent processor
      */
     public InspectablePropertyProcessor(
-            String annotationQualifiedName,
-            ProcessingEnvironment processingEnv) {
+            @NonNull String annotationQualifiedName,
+            @NonNull ProcessingEnvironment processingEnv) {
         mQualifiedName = annotationQualifiedName;
         mProcessingEnv = processingEnv;
         mAnnotationUtils = new AnnotationUtils(processingEnv);
     }
 
     @Override
-    public void process(Element element, InspectableClassModel model) {
+    public void process(@NonNull Element element, @NonNull InspectableClassModel model) {
         try {
             final AnnotationMirror annotation =
                     mAnnotationUtils.exactlyOneMirror(mQualifiedName, element);
@@ -169,7 +171,10 @@
      * @return A property for the getter and annotation
      * @throws ProcessingException If the supplied data is invalid and a property cannot be modeled
      */
-    private Property buildProperty(Element accessor, AnnotationMirror annotation) {
+    @NonNull
+    private Property buildProperty(
+            @NonNull Element accessor,
+            @NonNull AnnotationMirror annotation) {
         final Property property;
         final Optional<String> nameFromAnnotation = mAnnotationUtils
                 .typedValueByName("name", String.class, accessor, annotation);
@@ -227,7 +232,7 @@
      * @param element The element to check
      * @throws ProcessingException If the element's modifiers are invalid
      */
-    private void validateModifiers(Element element) {
+    private void validateModifiers(@NonNull Element element) {
         final Set<Modifier> modifiers = element.getModifiers();
 
         if (!modifiers.contains(Modifier.PUBLIC)) {
@@ -256,7 +261,8 @@
      * @return An {@link ExecutableElement} that represents a getter method.
      * @throws ProcessingException if the element isn't a getter
      */
-    private ExecutableElement ensureGetter(Element element) {
+    @NonNull
+    private ExecutableElement ensureGetter(@NonNull Element element) {
         if (element.getKind() != ElementKind.METHOD) {
             throw new ProcessingException(
                     String.format("Expected a method, got a %s", element.getKind()),
@@ -300,10 +306,10 @@
      * @throws ProcessingException If the property type cannot be resolved or is invalid
      * @see android.view.inspector.InspectableProperty#valueType()
      */
+    @NonNull
     private Property.Type determinePropertyType(
-            Element accessor,
-            AnnotationMirror annotation) {
-
+            @NonNull Element accessor,
+            @NonNull AnnotationMirror annotation) {
         final String valueType = mAnnotationUtils
                 .untypedValueByName("valueType", accessor, annotation)
                 .map(Object::toString)
@@ -437,7 +443,8 @@
      * @return The return or field type of the element
      * @throws ProcessingException If the element is not a field or a method
      */
-    private TypeMirror extractReturnOrFieldType(Element element) {
+    @NonNull
+    private TypeMirror extractReturnOrFieldType(@NonNull Element element) {
         switch (element.getKind()) {
             case FIELD:
                 return element.asType();
@@ -460,7 +467,10 @@
      * @return The property type returned by the getter
      * @throws ProcessingException If the return type is not a primitive or an object
      */
-    private Property.Type convertTypeMirrorToPropertyType(TypeMirror typeMirror, Element element) {
+    @NonNull
+    private Property.Type convertTypeMirrorToPropertyType(
+            @NonNull TypeMirror typeMirror,
+            @NonNull Element element) {
         switch (unboxType(typeMirror)) {
             case BOOLEAN:
                 return Property.Type.BOOLEAN;
@@ -503,10 +513,10 @@
      * @throws ProcessingException If the return type is not an int
      */
     private static void requirePackedIntToBeInt(
-            String typeName,
-            Property.Type returnType,
-            Element accessor,
-            AnnotationMirror annotation) {
+            @NonNull String typeName,
+            @NonNull Property.Type returnType,
+            @NonNull Element accessor,
+            @NonNull AnnotationMirror annotation) {
         if (returnType != Property.Type.INT) {
             throw new ProcessingException(
                     String.format(
@@ -528,7 +538,7 @@
      * @param accessor The getter or field to query
      * @return True if the getter has a color annotation, false otherwise
      */
-    private boolean hasColorAnnotation(Element accessor) {
+    private boolean hasColorAnnotation(@NonNull Element accessor) {
         switch (unboxType(extractReturnOrFieldType(accessor))) {
             case INT:
                 for (String name : COLOR_INT_ANNOTATION_NAMES) {
@@ -555,7 +565,7 @@
      * @param accessor The getter or field to query
      * @return True if the accessor is an integer and has a resource ID annotation, false otherwise
      */
-    private boolean hasResourceIdAnnotation(Element accessor) {
+    private boolean hasResourceIdAnnotation(@NonNull Element accessor) {
         if (unboxType(extractReturnOrFieldType(accessor)) == TypeKind.INT) {
             for (String name : RESOURCE_ID_ANNOTATION_NAMES) {
                 if (mAnnotationUtils.hasAnnotation(accessor, name)) {
@@ -581,7 +591,8 @@
      * @param getter An element representing a getter
      * @return A string property name
      */
-    private String inferPropertyNameFromGetter(ExecutableElement getter) {
+    @NonNull
+    private String inferPropertyNameFromGetter(@NonNull ExecutableElement getter) {
         final String name = getter.getSimpleName().toString();
 
         if (GETTER_GET_PREFIX.matcher(name).find()) {
@@ -600,7 +611,6 @@
      * {@link android.view.inspector.InspectableProperty.EnumMap} annotations into
      * {@link IntEnumEntry} objects. Further validation should be handled elsewhere
      *
-     * @see android.view.inspector.IntEnumMapping
      * @see android.view.inspector.InspectableProperty#enumMapping()
      * @param accessor The accessor of the property, used for exceptions
      * @param annotation The {@link android.view.inspector.InspectableProperty} annotation to
@@ -608,9 +618,10 @@
      * @return A list of int enum entries, in the order specified in source
      * @throws ProcessingException if mapping doesn't exist or is invalid
      */
+    @NonNull
     private List<IntEnumEntry> processEnumMapping(
-            Element accessor,
-            AnnotationMirror annotation) {
+            @NonNull Element accessor,
+            @NonNull AnnotationMirror annotation) {
         List<AnnotationMirror> enumAnnotations = mAnnotationUtils.typedArrayValuesByName(
                 "enumMapping", AnnotationMirror.class, accessor, annotation);
         List<IntEnumEntry> enumEntries = new ArrayList<>(enumAnnotations.size());
@@ -623,23 +634,19 @@
         for (AnnotationMirror enumAnnotation : enumAnnotations) {
             final String name = mAnnotationUtils.typedValueByName(
                     "name", String.class, accessor, enumAnnotation)
-                    .orElseThrow(() -> {
-                        throw new ProcessingException(
-                                "Name is required for @EnumMap",
-                                accessor,
-                                enumAnnotation);
-                    });
+                    .orElseThrow(() -> new ProcessingException(
+                            "Name is required for @EnumMap",
+                            accessor,
+                            enumAnnotation));
 
             final int value = mAnnotationUtils.typedValueByName(
                     "value", Integer.class, accessor, enumAnnotation)
-                    .orElseThrow(() -> {
-                        throw new ProcessingException(
-                                "Value is required for @EnumMap",
-                                accessor,
-                                enumAnnotation);
-                    });
+                    .orElseThrow(() -> new ProcessingException(
+                            "Value is required for @EnumMap",
+                            accessor,
+                            enumAnnotation));
 
-            enumEntries.add(new IntEnumEntry(name, value));
+            enumEntries.add(new IntEnumEntry(value, name));
         }
 
         return enumEntries;
@@ -660,9 +667,10 @@
      * @return A list of int flags entries, in the order specified in source
      * @throws ProcessingException if mapping doesn't exist or is invalid
      */
+    @NonNull
     private List<IntFlagEntry> processFlagMapping(
-            Element accessor,
-            AnnotationMirror annotation) {
+            @NonNull Element accessor,
+            @NonNull AnnotationMirror annotation) {
         List<AnnotationMirror> flagAnnotations = mAnnotationUtils.typedArrayValuesByName(
                 "flagMapping", AnnotationMirror.class, accessor, annotation);
         List<IntFlagEntry> flagEntries = new ArrayList<>(flagAnnotations.size());
@@ -675,29 +683,25 @@
         for (AnnotationMirror flagAnnotation : flagAnnotations) {
             final String name = mAnnotationUtils.typedValueByName(
                     "name", String.class, accessor, flagAnnotation)
-                    .orElseThrow(() -> {
-                        throw new ProcessingException(
-                                "Name is required for @FlagMap",
-                                accessor,
-                                flagAnnotation);
-                    });
+                    .orElseThrow(() -> new ProcessingException(
+                            "Name is required for @FlagMap",
+                            accessor,
+                            flagAnnotation));
 
             final int target = mAnnotationUtils.typedValueByName(
                     "target", Integer.class, accessor, flagAnnotation)
-                    .orElseThrow(() -> {
-                        throw new ProcessingException(
-                                "Target is required for @FlagMap",
-                                accessor,
-                                flagAnnotation);
-                    });
+                    .orElseThrow(() -> new ProcessingException(
+                            "Target is required for @FlagMap",
+                            accessor,
+                            flagAnnotation));
 
             final Optional<Integer> mask = mAnnotationUtils.typedValueByName(
                     "mask", Integer.class, accessor, flagAnnotation);
 
             if (mask.isPresent()) {
-                flagEntries.add(new IntFlagEntry(name, target, mask.get()));
+                flagEntries.add(new IntFlagEntry(mask.get(), target, name));
             } else {
-                flagEntries.add(new IntFlagEntry(name, target));
+                flagEntries.add(new IntFlagEntry(target, name));
             }
         }
 
@@ -710,7 +714,7 @@
      * @param type The type mirror to check
      * @return True if the type is a boolean
      */
-    private boolean isBoolean(TypeMirror type) {
+    private boolean isBoolean(@NonNull TypeMirror type) {
         if (type.getKind() == TypeKind.DECLARED) {
             return mProcessingEnv.getTypeUtils().unboxedType(type).getKind() == TypeKind.BOOLEAN;
         } else {
@@ -724,7 +728,8 @@
      * @param typeMirror The type mirror to unbox
      * @return The same type mirror, or an unboxed primitive version
      */
-    private TypeKind unboxType(TypeMirror typeMirror) {
+    @NonNull
+    private TypeKind unboxType(@NonNull TypeMirror typeMirror) {
         final TypeKind typeKind = typeMirror.getKind();
 
         if (typeKind.isPrimitive()) {
@@ -746,7 +751,7 @@
      * @param typeMirror The type mirror to test
      * @return True if it represents a subclass of color, false otherwise
      */
-    private boolean isColorType(TypeMirror typeMirror) {
+    private boolean isColorType(@NonNull TypeMirror typeMirror) {
         final TypeElement colorType = mProcessingEnv
                 .getElementUtils()
                 .getTypeElement("android.graphics.Color");
diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectionCompanionGenerator.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectionCompanionGenerator.java
index 6f6c1aa..c428a46 100644
--- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectionCompanionGenerator.java
+++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectionCompanionGenerator.java
@@ -16,11 +16,12 @@
 
 package android.processor.view.inspector;
 
-
 import android.processor.view.inspector.InspectableClassModel.IntEnumEntry;
 import android.processor.view.inspector.InspectableClassModel.IntFlagEntry;
 import android.processor.view.inspector.InspectableClassModel.Property;
 
+import androidx.annotation.NonNull;
+
 import com.squareup.javapoet.ClassName;
 import com.squareup.javapoet.CodeBlock;
 import com.squareup.javapoet.FieldSpec;
@@ -34,9 +35,11 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Comparator;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.NoSuchElementException;
-import java.util.Optional;
+import java.util.stream.Collectors;
 
 import javax.annotation.processing.Filer;
 import javax.lang.model.element.Modifier;
@@ -45,8 +48,8 @@
  * Generates a source file defining a {@link android.view.inspector.InspectionCompanion}.
  */
 public final class InspectionCompanionGenerator {
-    private final Filer mFiler;
-    private final Class mRequestingClass;
+    private final @NonNull Filer mFiler;
+    private final @NonNull Class mRequestingClass;
 
     /**
      * The class name for {@code R.java}.
@@ -72,10 +75,9 @@
             "android.view.inspector", "PropertyReader");
 
     /**
-     * The class name of {@link android.view.inspector.IntEnumMapping}.
+     * The class name of {@link android.util.SparseArray}.
      */
-    private static final ClassName INT_ENUM_MAPPING = ClassName.get(
-            "android.view.inspector", "IntEnumMapping");
+    private static final ClassName SPARSE_ARRAY = ClassName.get("android.util", "SparseArray");
 
     /**
      * The class name of {@link android.view.inspector.IntFlagMapping}.
@@ -84,17 +86,6 @@
             "android.view.inspector", "IntFlagMapping");
 
     /**
-     * The {@code mPropertiesMapped} field.
-     */
-    private static final FieldSpec M_PROPERTIES_MAPPED = FieldSpec
-            .builder(TypeName.BOOLEAN, "mPropertiesMapped", Modifier.PRIVATE)
-            .initializer("false")
-            .addJavadoc(
-                    "Set by {@link #mapProperties($T)} once properties have been mapped.\n",
-                    PROPERTY_MAPPER)
-            .build();
-
-    /**
      * The suffix of the generated class name after the class's binary name.
      */
     private static final String GENERATED_CLASS_SUFFIX = "$InspectionCompanion";
@@ -110,7 +101,7 @@
      * @param filer A filer to write the generated source to
      * @param requestingClass A class object representing the class that invoked the generator
      */
-    public InspectionCompanionGenerator(Filer filer, Class requestingClass) {
+    public InspectionCompanionGenerator(@NonNull Filer filer, @NonNull Class requestingClass) {
         mFiler = filer;
         mRequestingClass = requestingClass;
     }
@@ -121,7 +112,7 @@
      * @param model The model to generated
      * @throws IOException From the Filer
      */
-    public void generate(InspectableClassModel model) throws IOException {
+    public void generate(@NonNull InspectableClassModel model) throws IOException {
         generateFile(model).writeTo(mFiler);
     }
 
@@ -133,7 +124,8 @@
      * @param model The model to generate from
      * @return A generated file of an {@link android.view.inspector.InspectionCompanion}
      */
-    JavaFile generateFile(InspectableClassModel model) {
+    @NonNull
+    JavaFile generateFile(@NonNull InspectableClassModel model) {
         return JavaFile
                 .builder(model.getClassName().packageName(), generateTypeSpec(model))
                 .indent("    ")
@@ -147,8 +139,12 @@
      * @param model The model to generate from
      * @return A TypeSpec of the inspection companion
      */
-    private TypeSpec generateTypeSpec(InspectableClassModel model) {
-        final List<PropertyIdField> propertyIdFields = generatePropertyIdFields(model);
+    @NonNull
+    private TypeSpec generateTypeSpec(@NonNull InspectableClassModel model) {
+        final List<Property> properties = new ArrayList<>(model.getAllProperties());
+        properties.sort(Comparator.comparing(Property::getName));
+
+        final Map<Property, FieldSpec> fields = generateIdFieldSpecs(properties);
 
         TypeSpec.Builder builder = TypeSpec
                 .classBuilder(generateClassName(model))
@@ -158,238 +154,325 @@
                 .addJavadoc("Inspection companion for {@link $T}.\n\n", model.getClassName())
                 .addJavadoc("Generated by {@link $T}\n", getClass())
                 .addJavadoc("on behalf of {@link $T}.\n", mRequestingClass)
-                .addField(M_PROPERTIES_MAPPED);
+                .addField(FieldSpec
+                        .builder(TypeName.BOOLEAN, "mPropertiesMapped", Modifier.PRIVATE)
+                        .initializer("false")
+                        .addJavadoc("Guards against reading properties before mapping them.\n")
+                        .build())
+                .addFields(properties.stream().map(fields::get).collect(Collectors.toList()))
+                .addMethod(generateMapProperties(properties, fields))
+                .addMethod(generateReadProperties(properties, fields, model.getClassName()));
 
-        for (PropertyIdField propertyIdField : propertyIdFields) {
-            builder.addField(propertyIdField.mFieldSpec);
-        }
-
-        builder.addMethod(generateMapProperties(propertyIdFields))
-                .addMethod(generateReadProperties(model, propertyIdFields));
-
-        generateGetNodeName(model).ifPresent(builder::addMethod);
+        model.getNodeName().ifPresent(name -> builder.addMethod(generateGetNodeName(name)));
 
         return builder.build();
     }
 
     /**
-     * Build a list of {@link PropertyIdField}'s for a model.
+     * Map properties to fields to store the mapping IDs in the generated inspection companion.
      *
-     * To insure idempotency of the generated code, this method sorts the list of properties
-     * alphabetically by name.
-     *
-     * A {@link NameAllocator} is used to ensure that the field names are valid Java identifiers,
-     * and it prevents overlaps in names by suffixing them as needed.
-     *
-     * @param model The model to get properties from
-     * @return A list of properties and fields
+     * @param properties A list of property models
+     * @return A map of properties to their {@link FieldSpec}
      */
-    private List<PropertyIdField> generatePropertyIdFields(InspectableClassModel model) {
-        final NameAllocator nameAllocator = new NameAllocator();
-        final List<Property> sortedProperties = new ArrayList<>(model.getAllProperties());
-        final List<PropertyIdField> propertyIdFields = new ArrayList<>(sortedProperties.size());
+    @NonNull
+    private Map<Property, FieldSpec> generateIdFieldSpecs(@NonNull List<Property> properties) {
+        final Map<Property, FieldSpec> fields = new HashMap<>();
+        final NameAllocator fieldNames = new NameAllocator();
+        fieldNames.newName("mPropertiesMapped");
 
-        sortedProperties.sort(Comparator.comparing(Property::getName));
-
-        for (Property property : sortedProperties) {
-            // Format a property to a member field name like "someProperty" -> "mSomePropertyId"
-            final String memberName = String.format(
+        for (Property property : properties) {
+            final String memberName = fieldNames.newName(String.format(
                     "m%s%sId",
                     property.getName().substring(0, 1).toUpperCase(),
-                    property.getName().substring(1));
-            final FieldSpec fieldSpec = FieldSpec
-                    .builder(TypeName.INT, nameAllocator.newName(memberName), Modifier.PRIVATE)
-                    .addJavadoc("Property ID of {@code $L}.\n", property.getName())
-                    .build();
+                    property.getName().substring(1)));
 
-            propertyIdFields.add(new PropertyIdField(fieldSpec, property));
+            fields.put(property, FieldSpec
+                    .builder(TypeName.INT, memberName, Modifier.PRIVATE)
+                    .addJavadoc("Property ID of {@code $L}.\n", property.getName())
+                    .build());
         }
 
-        return propertyIdFields;
+        return fields;
     }
 
     /**
-     * Generate a method definition for
-     * {@link android.view.inspector.InspectionCompanion#getNodeName()}, if needed.
-     *
-     * If {@link InspectableClassModel#getNodeName()} is empty, This method returns an empty
-     * optional, otherwise, it generates a simple method that returns the string value of the
-     * node name.
-     *
-     * @param model The model to generate from
-     * @return The method definition or an empty Optional
-     */
-    private Optional<MethodSpec> generateGetNodeName(InspectableClassModel model) {
-        return model.getNodeName().map(nodeName -> MethodSpec.methodBuilder("getNodeName")
-                .addAnnotation(Override.class)
-                .addModifiers(Modifier.PUBLIC)
-                .returns(String.class)
-                .addStatement("return $S", nodeName)
-                .build());
-    }
-
-    /**
-     * Generate a method definition for
+     * Generates an implementation of
      * {@link android.view.inspector.InspectionCompanion#mapProperties(
      * android.view.inspector.PropertyMapper)}.
      *
-     * @param propertyIdFields A list of properties to map to ID fields
-     * @return The method definition
+     * Example:
+     * <pre>
+     *     @Override
+     *     public void mapProperties(PropertyMapper propertyMapper) {
+     *         mValueId = propertyMapper.mapInt("value", R.attr.value);
+     *         mPropertiesMapped = true;
+     *     }
+     * </pre>
+     *
+     * @param properties A sorted list of property models
+     * @param fields A map of properties to their ID field specs
+     * @return A method definition
      */
-    private MethodSpec generateMapProperties(List<PropertyIdField> propertyIdFields) {
+    @NonNull
+    private MethodSpec generateMapProperties(
+            @NonNull List<Property> properties,
+            @NonNull Map<Property, FieldSpec> fields) {
+        final NameAllocator mappingVariables = new NameAllocator();
+
         final MethodSpec.Builder builder = MethodSpec.methodBuilder("mapProperties")
                 .addAnnotation(Override.class)
                 .addModifiers(Modifier.PUBLIC)
                 .addParameter(PROPERTY_MAPPER, "propertyMapper");
 
-        propertyIdFields.forEach(p -> builder.addStatement(generatePropertyMapperInvocation(p)));
-        builder.addStatement("$N = true", M_PROPERTIES_MAPPED);
+        // Reserve existing names
+        mappingVariables.newName("mPropertiesMapped");
+        mappingVariables.newName("propertyMapper");
+        properties.forEach(p -> mappingVariables.newName(fields.get(p).name));
 
-        return builder.build();
-    }
-
-    /**
-     * Generate a method definition for
-     * {@link android.view.inspector.InspectionCompanion#readProperties(
-     * Object, android.view.inspector.PropertyReader)}.
-     *
-     * @param model The model to generate from
-     * @param propertyIdFields A list of properties and ID fields to read from
-     * @return The method definition
-     */
-    private MethodSpec generateReadProperties(
-            InspectableClassModel model,
-            List<PropertyIdField> propertyIdFields) {
-        final MethodSpec.Builder builder =  MethodSpec.methodBuilder("readProperties")
-                .addAnnotation(Override.class)
-                .addModifiers(Modifier.PUBLIC)
-                .addParameter(model.getClassName(), "node")
-                .addParameter(PROPERTY_READER, "propertyReader")
-                .addCode(generatePropertyMapInitializationCheck());
-
-        for (PropertyIdField propertyIdField : propertyIdFields) {
-            builder.addStatement(
-                    "propertyReader.read$L($N, node.$L)",
-                    methodSuffixForPropertyType(propertyIdField.mProperty.getType()),
-                    propertyIdField.mFieldSpec,
-                    propertyIdField.mProperty.getAccessor().invocation());
-        }
-
-        return builder.build();
-    }
-
-    /**
-     * Generate a statement maps a property with a {@link android.view.inspector.PropertyMapper}.
-     *
-     * @param propertyIdField The property model and ID field to generate from
-     * @return A statement that invokes property mapper method
-     */
-    private CodeBlock generatePropertyMapperInvocation(PropertyIdField propertyIdField) {
-        final CodeBlock.Builder builder = CodeBlock.builder();
-        final Property property = propertyIdField.mProperty;
-        final FieldSpec fieldSpec = propertyIdField.mFieldSpec;
-
-        builder.add(
-                "$N = propertyMapper.map$L($S,$W",
-                fieldSpec,
-                methodSuffixForPropertyType(property.getType()),
-                property.getName());
-
-        if (property.isAttributeIdInferrableFromR()) {
-            builder.add("$T.attr.$L", R_CLASS_NAME, property.getName());
-        } else {
-            if (property.getAttributeId() == ID_NULL) {
-                builder.add("$L", ID_NULL);
-            } else {
-                builder.add("$L", hexLiteral(property.getAttributeId()));
+        for (Property property : properties) {
+            final FieldSpec field = fields.get(property);
+            switch (property.getType()) {
+                case INT_ENUM:
+                    builder.addCode(generateIntEnumPropertyMapperInvocation(
+                            property,
+                            field,
+                            mappingVariables.newName(property.getName() + "EnumMapping")));
+                    break;
+                case INT_FLAG:
+                    builder.addCode(generateIntFlagPropertyMapperInvocation(
+                            property,
+                            field,
+                            mappingVariables.newName(property.getName() + "FlagMapping")));
+                    break;
+                default:
+                    builder.addCode(generateSimplePropertyMapperInvocation(property, field));
             }
         }
 
-        switch (property.getType()) {
-            case INT_ENUM:
-                builder.add(",$W");
-                builder.add(generateIntEnumMappingBuilder(property.getIntEnumEntries()));
-                break;
-            case INT_FLAG:
-                builder.add(",$W");
-                builder.add(generateIntFlagMappingBuilder(property.getIntFlagEntries()));
-                break;
-        }
+        builder.addStatement("mPropertiesMapped = true");
 
-        return builder.add(")").build();
+        return builder.build();
     }
 
     /**
-     * Generate a check that throws
-     * {@link android.view.inspector.InspectionCompanion.UninitializedPropertyMapException}
-     * if the properties haven't been initialized.
+     * Generate a {@link android.view.inspector.PropertyMapper} invocation.
      *
+     * Example:
      * <pre>
-     *     if (!mPropertiesMapped) {
-     *         throw new InspectionCompanion.UninitializedPropertyMapException();
-     *     }
+     *     mValueId = propertyMapper.mapInt("value", R.attr.value);
      * </pre>
      *
-     * @return A codeblock containing the property map initialization check
+     * @param property A property model to map
+     * @param field The property ID field for the property
+     * @return A code block containing a statement
      */
-    private CodeBlock generatePropertyMapInitializationCheck() {
-        return CodeBlock.builder()
-                .beginControlFlow("if (!$N)", M_PROPERTIES_MAPPED)
+    @NonNull
+    private CodeBlock generateSimplePropertyMapperInvocation(
+            @NonNull Property property,
+            @NonNull FieldSpec field) {
+        return CodeBlock
+                .builder()
                 .addStatement(
-                        "throw new $T()",
-                        INSPECTION_COMPANION.nestedClass("UninitializedPropertyMapException"))
-                .endControlFlow()
+                        "$N = propertyMapper.map$L($S, $L)",
+                        field,
+                        methodSuffixForPropertyType(property.getType()),
+                        property.getName(),
+                        generateAttributeId(property))
                 .build();
     }
 
     /**
-     * Generate an invocation of {@link android.view.inspector.IntEnumMapping.Builder}.
+     * Generate a {@link android.view.inspector.PropertyMapper} invocation for an int enum.
      *
+     * Example:
      * <pre>
-     *      new IntEnumMapping.Builder()
-     *          .addValue("ONE", 1)
-     *          .build()
+     *     final SparseArray<String> valueEnumMapping = new SparseArray<>();
+     *     valueEnumMapping.put(1, "ONE");
+     *     valueEnumMapping.put(2, "TWO");
+     *     mValueId = propertyMapper.mapIntEnum("value", R.attr.value, valueEnumMapping::get);
      * </pre>
      *
-     * @return A codeblock containing the an int enum mapping builder
+     * @param property A property model to map
+     * @param field The property ID field for the property
+     * @param variable The name of a local variable to use to store the mapping in
+     * @return A code block containing a series of statements
      */
-    private CodeBlock generateIntEnumMappingBuilder(List<IntEnumEntry> intEnumEntries) {
-        final ArrayList<IntEnumEntry> sortedEntries = new ArrayList<>(intEnumEntries);
-        sortedEntries.sort(Comparator.comparing(IntEnumEntry::getValue));
+    @NonNull
+    private CodeBlock generateIntEnumPropertyMapperInvocation(
+            @NonNull Property property,
+            @NonNull FieldSpec field,
+            @NonNull String variable) {
+        final CodeBlock.Builder builder = CodeBlock.builder();
 
-        final CodeBlock.Builder builder = CodeBlock.builder()
-                .add("new $T()$>", INT_ENUM_MAPPING.nestedClass("Builder"));
+        final List<IntEnumEntry> enumEntries = property.getIntEnumEntries();
+        enumEntries.sort(Comparator.comparing(IntEnumEntry::getValue));
 
-        for (IntEnumEntry entry : sortedEntries) {
-            builder.add("\n.addValue($S, $L)", entry.getName(), entry.getValue());
+        builder.addStatement(
+                "final $1T<$2T> $3N = new $1T<>()",
+                SPARSE_ARRAY,
+                String.class,
+                variable);
+
+        for (IntEnumEntry enumEntry : enumEntries) {
+            builder.addStatement(
+                    "$N.put($L, $S)",
+                    variable,
+                    enumEntry.getValue(),
+                    enumEntry.getName());
         }
 
-        return builder.add("\n.build()$<").build();
+        builder.addStatement(
+                "$N = propertyMapper.mapIntEnum($S, $L, $N::get)",
+                field,
+                property.getName(),
+                generateAttributeId(property),
+                variable);
+
+        return builder.build();
     }
 
-    private CodeBlock generateIntFlagMappingBuilder(List<IntFlagEntry> intFlagEntries) {
-        final ArrayList<IntFlagEntry> sortedEntries = new ArrayList<>(intFlagEntries);
-        sortedEntries.sort(Comparator.comparing(IntFlagEntry::getName));
+    /**
+     * Generate a {@link android.view.inspector.PropertyMapper} invocation for an int flag.
+     *
+     * Example:
+     * <pre>
+     *     final IntFlagMapping valueFlagMapping = new IntFlagMapping();
+     *     valueFlagMapping.add(0x00000003, 0x00000001, "ONE");
+     *     valueFlagMapping.add(0x00000003, 0x00000002, "TWO");
+     *     mValueId = propertyMapper.mapIntFlag("value", R.attr.value, valueFlagMapping::get);
+     * </pre>
+     *
+     * @param property A property model to map
+     * @param field The property ID field for the property
+     * @param variable The name of a local variable to use to store the mapping in
+     * @return A code block containing a series of statements
+     */
+    @NonNull
+    private CodeBlock generateIntFlagPropertyMapperInvocation(
+            @NonNull Property property,
+            @NonNull FieldSpec field,
+            @NonNull String variable) {
+        final CodeBlock.Builder builder = CodeBlock.builder();
 
-        final CodeBlock.Builder builder = CodeBlock.builder()
-                .add("new $T()$>", INT_FLAG_MAPPING.nestedClass("Builder"));
+        final List<IntFlagEntry> flagEntries = property.getIntFlagEntries();
+        flagEntries.sort(Comparator.comparing(IntFlagEntry::getName));
 
-        for (IntFlagEntry entry : sortedEntries) {
-            if (entry.hasMask()) {
-                builder.add(
-                        "\n.addFlag($S, $L, $L)",
-                        entry.getName(),
-                        hexLiteral(entry.getTarget()),
-                        hexLiteral(entry.getMask()));
-            } else {
-                builder.add(
-                        "\n.addFlag($S, $L)",
-                        entry.getName(),
-                        hexLiteral(entry.getTarget()));
-            }
+        builder.addStatement(
+                "final $1T $2N = new $1T()",
+                INT_FLAG_MAPPING,
+                variable);
+
+        for (IntFlagEntry flagEntry : flagEntries) {
+            builder.addStatement(
+                    "$N.add($L, $L, $S)",
+                    variable,
+                    hexLiteral(flagEntry.getMask()),
+                    hexLiteral(flagEntry.getTarget()),
+                    flagEntry.getName());
         }
 
-        return builder.add("\n.build()$<").build();
+        builder.addStatement(
+                "$N = propertyMapper.mapIntFlag($S, $L, $N::get)",
+                field,
+                property.getName(),
+                generateAttributeId(property),
+                variable);
+
+        return builder.build();
+    }
+
+    /**
+     * Generate a literal attribute ID or reference to {@link android.R.attr}.
+     *
+     * Example: {@code R.attr.value} or {@code 0xdecafbad}.
+     *
+     * @param property A property model
+     * @return A code block containing the attribute ID
+     */
+    @NonNull
+    private CodeBlock generateAttributeId(@NonNull Property property) {
+        if (property.isAttributeIdInferrableFromR()) {
+            return CodeBlock.of("$T.attr.$L", R_CLASS_NAME, property.getName());
+        } else {
+            if (property.getAttributeId() == ID_NULL) {
+                return CodeBlock.of("$L", ID_NULL);
+            } else {
+                return CodeBlock.of("$L", hexLiteral(property.getAttributeId()));
+            }
+        }
+    }
+
+    /**
+     * Generate an implementation of
+     * {@link android.view.inspector.InspectionCompanion#readProperties(Object,
+     * android.view.inspector.PropertyReader)}.
+     *
+     * Example:
+     * <pre>
+     *     @Override
+     *     public void readProperties(MyNode node, PropertyReader propertyReader) {
+     *         if (!mPropertiesMapped) {
+     *             throw new InspectionCompanion.UninitializedPropertyMapException();
+     *         }
+     *         propertyReader.readInt(mValueId, node.getValue());
+     *     }
+     * </pre>
+     *
+     * @param properties An ordered list of property models
+     * @param fields A map from properties to their field specs
+     * @param nodeClass The class of the node, used for the parameter type
+     * @return A method definition
+     */
+    @NonNull
+    private MethodSpec generateReadProperties(
+            @NonNull List<Property> properties,
+            @NonNull Map<Property, FieldSpec> fields,
+            @NonNull ClassName nodeClass) {
+        final MethodSpec.Builder builder =  MethodSpec.methodBuilder("readProperties")
+                .addAnnotation(Override.class)
+                .addModifiers(Modifier.PUBLIC)
+                .addParameter(nodeClass, "node")
+                .addParameter(PROPERTY_READER, "propertyReader")
+                .beginControlFlow("if (!mPropertiesMapped)")
+                .addStatement(
+                        "throw new $T()",
+                        INSPECTION_COMPANION.nestedClass("UninitializedPropertyMapException"))
+                .endControlFlow();
+
+        for (Property property : properties) {
+            builder.addStatement(
+                    "propertyReader.read$L($N, node.$L)",
+                    methodSuffixForPropertyType(property.getType()),
+                    fields.get(property),
+                    property.getAccessor().invocation());
+        }
+
+        return builder.build();
+    }
+
+    /**
+     * Generate an implementation of
+     * {@link android.view.inspector.InspectionCompanion#getNodeName()}.
+     *
+     * Example:
+     * <pre>
+     *     @Override
+     *     public String getNodeName() {
+     *         return "nodeName";
+     *     }
+     * </pre>
+     *
+     * @param nodeName The name of this node
+     * @return A method definition that returns the node name
+     */
+    @NonNull
+    private MethodSpec generateGetNodeName(@NonNull String nodeName) {
+        return MethodSpec.methodBuilder("getNodeName")
+                .addAnnotation(Override.class)
+                .addModifiers(Modifier.PUBLIC)
+                .returns(String.class)
+                .addStatement("return $S", nodeName)
+                .build();
     }
 
     /**
@@ -397,14 +480,15 @@
      *
      * The generated class is added to the same package as the source class. If the class in the
      * model is a nested class, the nested class names are joined with {@code "$"}. The suffix
-     * {@code "$$InspectionCompanion"} is always added the the generated name. E.g.: For modeled
+     * {@code "$InspectionCompanion"} is always added to the generated name. E.g.: For modeled
      * class {@code com.example.Outer.Inner}, the generated class name will be
-     * {@code com.example.Outer$Inner$$InspectionCompanion}.
+     * {@code com.example.Outer$Inner$InspectionCompanion}.
      *
      * @param model The model to generate from
      * @return A class name for the generated inspection companion class
      */
-    private static ClassName generateClassName(InspectableClassModel model) {
+    @NonNull
+    private static ClassName generateClassName(@NonNull InspectableClassModel model) {
         final ClassName className = model.getClassName();
 
         return ClassName.get(
@@ -418,7 +502,8 @@
      * @param type The requested property type
      * @return A method suffix
      */
-    private static String methodSuffixForPropertyType(Property.Type type) {
+    @NonNull
+    private static String methodSuffixForPropertyType(@NonNull Property.Type type) {
         switch (type) {
             case BOOLEAN:
                 return "Boolean";
@@ -453,20 +538,14 @@
         }
     }
 
+    /**
+     * Format an int as an 8 digit hex literal
+     *
+     * @param value The value to format
+     * @return A string representation of the hex literal
+     */
+    @NonNull
     private static String hexLiteral(int value) {
         return String.format("0x%08x", value);
     }
-
-    /**
-     * Value class that holds a {@link Property} and a {@link FieldSpec} for that property.
-     */
-    private static final class PropertyIdField {
-        private final FieldSpec mFieldSpec;
-        private final Property mProperty;
-
-        private PropertyIdField(FieldSpec fieldSpec, Property property) {
-            mFieldSpec = fieldSpec;
-            mProperty = property;
-        }
-    }
 }
diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/ModelProcessor.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/ModelProcessor.java
index 6f52260..ab38f4c 100644
--- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/ModelProcessor.java
+++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/ModelProcessor.java
@@ -16,6 +16,8 @@
 
 package android.processor.view.inspector;
 
+import androidx.annotation.NonNull;
+
 import javax.lang.model.element.Element;
 
 /**
@@ -28,5 +30,5 @@
      * @param element The annotated element to operate on
      * @param model The model this element should be merged into
      */
-    void process(Element element, InspectableClassModel model);
+    void process(@NonNull Element element, @NonNull InspectableClassModel model);
 }
diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/PlatformInspectableProcessor.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/PlatformInspectableProcessor.java
index fd142c6..d9ed1fb 100644
--- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/PlatformInspectableProcessor.java
+++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/PlatformInspectableProcessor.java
@@ -18,6 +18,8 @@
 
 import static javax.tools.Diagnostic.Kind.ERROR;
 
+import androidx.annotation.NonNull;
+
 import com.squareup.javapoet.ClassName;
 
 import java.io.IOException;
@@ -63,7 +65,9 @@
     }
 
     @Override
-    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+    public boolean process(
+            @NonNull Set<? extends TypeElement> annotations,
+            @NonNull RoundEnvironment roundEnv) {
         final Map<String, InspectableClassModel> modelMap = new HashMap<>();
 
         for (TypeElement annotation : annotations) {
@@ -109,9 +113,9 @@
      * @param modelMap A map of qualified class names to models
      */
     private void runModelProcessor(
-            Set<? extends Element> elements,
-            ModelProcessor processor,
-            Map<String, InspectableClassModel> modelMap) {
+            @NonNull Set<? extends Element> elements,
+            @NonNull ModelProcessor processor,
+            @NonNull Map<String, InspectableClassModel> modelMap) {
         for (Element element : elements) {
             final Optional<TypeElement> classElement = enclosingClassElement(element);
 
@@ -149,7 +153,7 @@
      * @param typeElement A type element representing the class to check
      * @return f the class contains a class named {@code InspectionCompanion}
      */
-    private static boolean hasNestedInspectionCompanion(TypeElement typeElement) {
+    private static boolean hasNestedInspectionCompanion(@NonNull TypeElement typeElement) {
         for (TypeElement nestedClass : ElementFilter.typesIn(typeElement.getEnclosedElements())) {
             if (nestedClass.getSimpleName().toString().equals("InspectionCompanion")) {
                 return true;
@@ -167,7 +171,8 @@
      * @param element An element to search from
      * @return A TypeElement of the nearest enclosing class or an empty optional
      */
-    private static Optional<TypeElement> enclosingClassElement(Element element) {
+    @NonNull
+    private static Optional<TypeElement> enclosingClassElement(@NonNull Element element) {
         Element cursor = element;
 
         while (cursor != null) {
@@ -186,7 +191,7 @@
      *
      * @param message Message to print
      */
-    private void fail(String message) {
+    private void fail(@NonNull String message) {
         processingEnv.getMessager().printMessage(ERROR, message);
     }
 
@@ -196,7 +201,7 @@
      * @param message Message to print
      * @param element The element that failed
      */
-    private void fail(String message, Element element) {
+    private void fail(@NonNull String message, @NonNull Element element) {
         processingEnv.getMessager().printMessage(ERROR, message, element);
     }
 }
diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/ProcessingException.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/ProcessingException.java
index b4c6466..7389c24 100644
--- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/ProcessingException.java
+++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/ProcessingException.java
@@ -18,6 +18,9 @@
 
 import static javax.tools.Diagnostic.Kind.ERROR;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
 import javax.annotation.processing.Messager;
 import javax.lang.model.element.AnnotationMirror;
 import javax.lang.model.element.AnnotationValue;
@@ -27,27 +30,30 @@
  * Internal exception used to signal an error processing an annotation.
  */
 final class ProcessingException extends RuntimeException {
-    private final Element mElement;
-    private final AnnotationMirror mAnnotationMirror;
-    private final AnnotationValue mAnnotationValue;
+    private final @Nullable Element mElement;
+    private final @Nullable AnnotationMirror mAnnotationMirror;
+    private final @Nullable AnnotationValue mAnnotationValue;
 
-    ProcessingException(String message) {
+    ProcessingException(@NonNull String message) {
         this(message, null, null, null);
     }
 
-    ProcessingException(String message, Element element) {
+    ProcessingException(@NonNull String message, @NonNull Element element) {
         this(message, element, null, null);
     }
 
-    ProcessingException(String message, Element element, AnnotationMirror annotationMirror) {
+    ProcessingException(
+            @NonNull String message,
+            @NonNull Element element,
+            @NonNull AnnotationMirror annotationMirror) {
         this(message, element, annotationMirror, null);
     }
 
     ProcessingException(
-            String message,
-            Element element,
-            AnnotationMirror annotationMirror,
-            AnnotationValue annotationValue) {
+            @NonNull String message,
+            @Nullable Element element,
+            @Nullable AnnotationMirror annotationMirror,
+            @Nullable AnnotationValue annotationValue) {
         super(message);
         mElement = element;
         mAnnotationMirror = annotationMirror;
@@ -59,7 +65,7 @@
      *
      * @param messager A Messager to print to
      */
-    void print(Messager messager) {
+    void print(@NonNull Messager messager) {
         if (mElement != null) {
             if (mAnnotationMirror != null) {
                 if (mAnnotationValue != null) {
diff --git a/tools/processors/view_inspector/test/java/android/processor/view/inspector/InspectionCompanionGeneratorTest.java b/tools/processors/view_inspector/test/java/android/processor/view/inspector/InspectionCompanionGeneratorTest.java
index 4eed504..3ec620a 100644
--- a/tools/processors/view_inspector/test/java/android/processor/view/inspector/InspectionCompanionGeneratorTest.java
+++ b/tools/processors/view_inspector/test/java/android/processor/view/inspector/InspectionCompanionGeneratorTest.java
@@ -118,9 +118,9 @@
                 Property.Type.INT_ENUM);
 
         property.setIntEnumEntries(Arrays.asList(
-                new IntEnumEntry("THREE", 3),
-                new IntEnumEntry("TWO", 2),
-                new IntEnumEntry("ONE", 1)));
+                new IntEnumEntry(3, "THREE"),
+                new IntEnumEntry(2, "TWO"),
+                new IntEnumEntry(1, "ONE")));
 
         mModel.putProperty(property);
 
@@ -136,9 +136,9 @@
 
         property.setAttributeIdInferrableFromR(false);
         property.setIntFlagEntries(Arrays.asList(
-                new IntFlagEntry("TURBO", 0x1, 0x3),
-                new IntFlagEntry("OVERDRIVE", 0x2, 0x3),
-                new IntFlagEntry("WARP", 0x4)
+                new IntFlagEntry(0x3, 0x1, "TURBO"),
+                new IntFlagEntry(0x3, 0x2, "OVERDRIVE"),
+                new IntFlagEntry(0x4, "WARP")
         ));
 
         assertGeneratedFileEquals("IntFlag");
diff --git a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/FieldProperty.java.txt b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/FieldProperty.java.txt
index 9a0fe5b..e4a8ba4 100644
--- a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/FieldProperty.java.txt
+++ b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/FieldProperty.java.txt
@@ -14,7 +14,7 @@
  */
 public final class TestNode$InspectionCompanion implements InspectionCompanion<TestNode> {
     /**
-     * Set by {@link #mapProperties(PropertyMapper)} once properties have been mapped.
+     * Guards against reading properties before mapping them.
      */
     private boolean mPropertiesMapped = false;
 
diff --git a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/IntEnum.java.txt b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/IntEnum.java.txt
index b491de1..fa9dbfd 100644
--- a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/IntEnum.java.txt
+++ b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/IntEnum.java.txt
@@ -1,11 +1,12 @@
 package com.android.node;
 
 import android.R;
+import android.util.SparseArray;
 import android.view.inspector.InspectionCompanion;
-import android.view.inspector.IntEnumMapping;
 import android.view.inspector.PropertyMapper;
 import android.view.inspector.PropertyReader;
 import java.lang.Override;
+import java.lang.String;
 
 /**
  * Inspection companion for {@link TestNode}.
@@ -15,7 +16,7 @@
  */
 public final class TestNode$InspectionCompanion implements InspectionCompanion<TestNode> {
     /**
-     * Set by {@link #mapProperties(PropertyMapper)} once properties have been mapped.
+     * Guards against reading properties before mapping them.
      */
     private boolean mPropertiesMapped = false;
 
@@ -26,12 +27,11 @@
 
     @Override
     public void mapProperties(PropertyMapper propertyMapper) {
-        mIntEnumPropertyId = propertyMapper.mapIntEnum("intEnumProperty", R.attr.intEnumProperty,
-                new IntEnumMapping.Builder()
-                    .addValue("ONE", 1)
-                    .addValue("TWO", 2)
-                    .addValue("THREE", 3)
-                    .build());
+        final SparseArray<String> intEnumPropertyEnumMapping = new SparseArray<>();
+        intEnumPropertyEnumMapping.put(1, "ONE");
+        intEnumPropertyEnumMapping.put(2, "TWO");
+        intEnumPropertyEnumMapping.put(3, "THREE");
+        mIntEnumPropertyId = propertyMapper.mapIntEnum("intEnumProperty", R.attr.intEnumProperty, intEnumPropertyEnumMapping::get);
         mPropertiesMapped = true;
     }
 
diff --git a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/IntFlag.java.txt b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/IntFlag.java.txt
index 7d18058..ed3d8ee 100644
--- a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/IntFlag.java.txt
+++ b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/IntFlag.java.txt
@@ -14,7 +14,7 @@
  */
 public final class TestNode$InspectionCompanion implements InspectionCompanion<TestNode> {
     /**
-     * Set by {@link #mapProperties(PropertyMapper)} once properties have been mapped.
+     * Guards against reading properties before mapping them.
      */
     private boolean mPropertiesMapped = false;
 
@@ -25,11 +25,11 @@
 
     @Override
     public void mapProperties(PropertyMapper propertyMapper) {
-        mIntFlagId = propertyMapper.mapIntFlag("intFlag", 0, new IntFlagMapping.Builder()
-                    .addFlag("OVERDRIVE", 0x00000002, 0x00000003)
-                    .addFlag("TURBO", 0x00000001, 0x00000003)
-                    .addFlag("WARP", 0x00000004)
-                    .build());
+        final IntFlagMapping intFlagFlagMapping = new IntFlagMapping();
+        intFlagFlagMapping.add(0x00000003, 0x00000002, "OVERDRIVE");
+        intFlagFlagMapping.add(0x00000003, 0x00000001, "TURBO");
+        intFlagFlagMapping.add(0x00000004, 0x00000004, "WARP");
+        mIntFlagId = propertyMapper.mapIntFlag("intFlag", 0, intFlagFlagMapping::get);
         mPropertiesMapped = true;
     }
 
diff --git a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NestedClass.java.txt b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NestedClass.java.txt
index dc27abb..4514ed9 100644
--- a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NestedClass.java.txt
+++ b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NestedClass.java.txt
@@ -13,7 +13,7 @@
  */
 public final class Outer$Inner$InspectionCompanion implements InspectionCompanion<Outer.Inner> {
     /**
-     * Set by {@link #mapProperties(PropertyMapper)} once properties have been mapped.
+     * Guards against reading properties before mapping them.
      */
     private boolean mPropertiesMapped = false;
 
diff --git a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NoAttributeId.java.txt b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NoAttributeId.java.txt
index 738bcd3..563f93df 100644
--- a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NoAttributeId.java.txt
+++ b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NoAttributeId.java.txt
@@ -13,7 +13,7 @@
  */
 public final class TestNode$InspectionCompanion implements InspectionCompanion<TestNode> {
     /**
-     * Set by {@link #mapProperties(PropertyMapper)} once properties have been mapped.
+     * Guards against reading properties before mapping them.
      */
     private boolean mPropertiesMapped = false;
 
diff --git a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NodeName.java.txt b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NodeName.java.txt
index 82dd66e..ffa1f0b 100644
--- a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NodeName.java.txt
+++ b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NodeName.java.txt
@@ -14,7 +14,7 @@
  */
 public final class TestNode$InspectionCompanion implements InspectionCompanion<TestNode> {
     /**
-     * Set by {@link #mapProperties(PropertyMapper)} once properties have been mapped.
+     * Guards against reading properties before mapping them.
      */
     private boolean mPropertiesMapped = false;
 
diff --git a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/SimpleProperties.java.txt b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/SimpleProperties.java.txt
index 08ea696..cb85767 100644
--- a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/SimpleProperties.java.txt
+++ b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/SimpleProperties.java.txt
@@ -14,7 +14,7 @@
  */
 public final class TestNode$InspectionCompanion implements InspectionCompanion<TestNode> {
     /**
-     * Set by {@link #mapProperties(PropertyMapper)} once properties have been mapped.
+     * Guards against reading properties before mapping them.
      */
     private boolean mPropertiesMapped = false;
 
diff --git a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/SuppliedAttributeId.java.txt b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/SuppliedAttributeId.java.txt
index 3bfa78a..731d410 100644
--- a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/SuppliedAttributeId.java.txt
+++ b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/SuppliedAttributeId.java.txt
@@ -13,7 +13,7 @@
  */
 public final class TestNode$InspectionCompanion implements InspectionCompanion<TestNode> {
     /**
-     * Set by {@link #mapProperties(PropertyMapper)} once properties have been mapped.
+     * Guards against reading properties before mapping them.
      */
     private boolean mPropertiesMapped = false;
 
@@ -24,8 +24,7 @@
 
     @Override
     public void mapProperties(PropertyMapper propertyMapper) {
-        mSuppliedAttributePropertyId = propertyMapper.mapInt("suppliedAttributeProperty",
-                0xdecafbad);
+        mSuppliedAttributePropertyId = propertyMapper.mapInt("suppliedAttributeProperty", 0xdecafbad);
         mPropertiesMapped = true;
     }
 
diff --git a/wifi/java/android/net/wifi/IWifiUsabilityStatsListener.aidl b/wifi/java/android/net/wifi/IOnWifiUsabilityStatsListener.aidl
similarity index 92%
rename from wifi/java/android/net/wifi/IWifiUsabilityStatsListener.aidl
rename to wifi/java/android/net/wifi/IOnWifiUsabilityStatsListener.aidl
index 284ffaa..4687f30 100644
--- a/wifi/java/android/net/wifi/IWifiUsabilityStatsListener.aidl
+++ b/wifi/java/android/net/wifi/IOnWifiUsabilityStatsListener.aidl
@@ -23,7 +23,7 @@
  *
  * @hide
  */
-oneway interface IWifiUsabilityStatsListener
+oneway interface IOnWifiUsabilityStatsListener
 {
     /**
      * Service to manager callback providing current Wi-Fi usability stats.
@@ -36,6 +36,6 @@
      *                           Wi-Fi usability stats.
      * @param stats The updated Wi-Fi usability statistics.
      */
-    void onStatsUpdated(int seqNum, boolean isSameBssidAndFreq,
+    void onWifiUsabilityStats(int seqNum, boolean isSameBssidAndFreq,
             in WifiUsabilityStatsEntry stats);
 }
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 17948e7..62ea9af 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -28,7 +28,7 @@
 import android.net.wifi.INetworkRequestMatchCallback;
 import android.net.wifi.ISoftApCallback;
 import android.net.wifi.ITrafficStateCallback;
-import android.net.wifi.IWifiUsabilityStatsListener;
+import android.net.wifi.IOnWifiUsabilityStatsListener;
 import android.net.wifi.PasspointManagementObjectDefinition;
 import android.net.wifi.ScanResult;
 import android.net.wifi.WifiActivityEnergyInfo;
@@ -190,9 +190,9 @@
 
     void unregisterSoftApCallback(int callbackIdentifier);
 
-    void addWifiUsabilityStatsListener(in IBinder binder, in IWifiUsabilityStatsListener listener, int listenerIdentifier);
+    void addOnWifiUsabilityStatsListener(in IBinder binder, in IOnWifiUsabilityStatsListener listener, int listenerIdentifier);
 
-    void removeWifiUsabilityStatsListener(int listenerIdentifier);
+    void removeOnWifiUsabilityStatsListener(int listenerIdentifier);
 
     void registerTrafficStateCallback(in IBinder binder, in ITrafficStateCallback callback, int callbackIdentifier);
 
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 379819d..47633005 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -1171,39 +1171,49 @@
          * This network is disabled because EAP-TLS failure
          */
         public static final int DISABLED_TLS_VERSION_MISMATCH = 8;
+        /**
+         * This network is disabled due to WifiManager.disconnect() call.
+         */
+        public static final int DISABLED_BY_WIFI_MANAGER_DISCONNECT = 9;
+
         // Values above are for temporary disablement; values below are for permanent disablement.
         /**
+         * The starting index for permanent network selection disabled reasons
+         */
+        public static final int NETWORK_SELECTION_DISABLED_PERMANENT_STARTING_INDEX = 10;
+        /**
          * This network is disabled due to absence of user credentials
          */
-        public static final int DISABLED_AUTHENTICATION_NO_CREDENTIALS = 9;
+        public static final int DISABLED_AUTHENTICATION_NO_CREDENTIALS = 10;
         /**
          * This network is permanently disabled because it has no Internet access and user does not
          * want to stay connected.
          */
-        public static final int DISABLED_NO_INTERNET_PERMANENT = 10;
+        public static final int DISABLED_NO_INTERNET_PERMANENT = 11;
         /**
-         * This network is disabled due to WifiManager disable it explicitly
+         * This network is disabled due to WifiManager.disable() call.
          */
-        public static final int DISABLED_BY_WIFI_MANAGER = 11;
+        public static final int DISABLED_BY_WIFI_MANAGER = 12;
         /**
          * This network is disabled due to user switching
          */
-        public static final int DISABLED_DUE_TO_USER_SWITCH = 12;
+        public static final int DISABLED_DUE_TO_USER_SWITCH = 13;
         /**
          * This network is disabled due to wrong password
          */
-        public static final int DISABLED_BY_WRONG_PASSWORD = 13;
+        public static final int DISABLED_BY_WRONG_PASSWORD = 14;
         /**
          * This network is disabled because service is not subscribed
          */
-        public static final int DISABLED_AUTHENTICATION_NO_SUBSCRIPTION = 14;
+        public static final int DISABLED_AUTHENTICATION_NO_SUBSCRIPTION = 15;
         /**
          * This Maximum disable reason value
          */
-        public static final int NETWORK_SELECTION_DISABLED_MAX = 15;
+        public static final int NETWORK_SELECTION_DISABLED_MAX = 16;
 
         /**
-         * Quality network selection disable reason String (for debug purpose)
+         * Quality network selection disable reason String (for debug purposes & configuration
+         * storage)
          */
         public static final String[] QUALITY_NETWORK_SELECTION_DISABLE_REASON = {
                 "NETWORK_SELECTION_ENABLE",
@@ -1215,6 +1225,7 @@
                 "NETWORK_SELECTION_DISABLED_NO_INTERNET_TEMPORARY",
                 "NETWORK_SELECTION_DISABLED_WPS_START",
                 "NETWORK_SELECTION_DISABLED_TLS_VERSION",
+                "NETWORK_SELECTION_DISABLED_BY_WIFI_MANAGER_DISCONNECT",
                 "NETWORK_SELECTION_DISABLED_AUTHENTICATION_NO_CREDENTIALS",
                 "NETWORK_SELECTION_DISABLED_NO_INTERNET_PERMANENT",
                 "NETWORK_SELECTION_DISABLED_BY_WIFI_MANAGER",
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 7a505a2..950c6f8 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -139,6 +139,8 @@
     private X509Certificate[] mClientCertificateChain;
     private int mEapMethod = Eap.NONE;
     private int mPhase2Method = Phase2.NONE;
+    private boolean mIsAppInstalledDeviceKeyAndCert = false;
+    private boolean mIsAppInstalledCaCert = false;
 
     private static final String TAG = "WifiEnterpriseConfig";
 
@@ -181,6 +183,8 @@
         }
         mEapMethod = source.mEapMethod;
         mPhase2Method = source.mPhase2Method;
+        mIsAppInstalledDeviceKeyAndCert = source.mIsAppInstalledDeviceKeyAndCert;
+        mIsAppInstalledCaCert = source.mIsAppInstalledCaCert;
     }
 
     /**
@@ -224,6 +228,8 @@
         ParcelUtil.writeCertificates(dest, mCaCerts);
         ParcelUtil.writePrivateKey(dest, mClientPrivateKey);
         ParcelUtil.writeCertificates(dest, mClientCertificateChain);
+        dest.writeBoolean(mIsAppInstalledDeviceKeyAndCert);
+        dest.writeBoolean(mIsAppInstalledCaCert);
     }
 
     public static final @android.annotation.NonNull Creator<WifiEnterpriseConfig> CREATOR =
@@ -243,6 +249,8 @@
                     enterpriseConfig.mCaCerts = ParcelUtil.readCertificates(in);
                     enterpriseConfig.mClientPrivateKey = ParcelUtil.readPrivateKey(in);
                     enterpriseConfig.mClientCertificateChain = ParcelUtil.readCertificates(in);
+                    enterpriseConfig.mIsAppInstalledDeviceKeyAndCert = in.readBoolean();
+                    enterpriseConfig.mIsAppInstalledCaCert = in.readBoolean();
                     return enterpriseConfig;
                 }
 
@@ -652,8 +660,10 @@
     public void setCaCertificate(@Nullable X509Certificate cert) {
         if (cert != null) {
             if (cert.getBasicConstraints() >= 0) {
+                mIsAppInstalledCaCert = true;
                 mCaCerts = new X509Certificate[] {cert};
             } else {
+                mCaCerts = null;
                 throw new IllegalArgumentException("Not a CA certificate");
             }
         } else {
@@ -694,10 +704,12 @@
                 if (certs[i].getBasicConstraints() >= 0) {
                     newCerts[i] = certs[i];
                 } else {
+                    mCaCerts = null;
                     throw new IllegalArgumentException("Not a CA certificate");
                 }
             }
             mCaCerts = newCerts;
+            mIsAppInstalledCaCert = true;
         } else {
             mCaCerts = null;
         }
@@ -853,6 +865,7 @@
 
         mClientPrivateKey = privateKey;
         mClientCertificateChain = newCerts;
+        mIsAppInstalledDeviceKeyAndCert = true;
     }
 
     /**
@@ -1147,4 +1160,30 @@
         }
         return true;
     }
+
+    /**
+     * Check if certificate was installed by an app, or manually (not by an app). If true,
+     * certificate and keys will be removed from key storage when this network is removed. If not,
+     * then certificates and keys remain persistent until the user manually removes them.
+     *
+     * @return true if certificate was installed by an app, false if certificate was installed
+     * manually by the user.
+     * @hide
+     */
+    public boolean isAppInstalledDeviceKeyAndCert() {
+        return mIsAppInstalledDeviceKeyAndCert;
+    }
+
+    /**
+     * Check if CA certificate was installed by an app, or manually (not by an app). If true,
+     * CA certificate will be removed from key storage when this network is removed. If not,
+     * then certificates and keys remain persistent until the user manually removes them.
+     *
+     * @return true if CA certificate was installed by an app, false if CA certificate was installed
+     * manually by the user.
+     * @hide
+     */
+    public boolean isAppInstalledCaCert() {
+        return mIsAppInstalledCaCert;
+    }
 }
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 4fd00f7..06a99e2 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -65,6 +65,7 @@
 import java.net.InetAddress;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -511,7 +512,7 @@
     /**
      * The look up key for an int that indicates why softAP started failed
      * currently support general and no_channel
-     * @see #SAP_START_FAILURE_GENERIC
+     * @see #SAP_START_FAILURE_GENERAL
      * @see #SAP_START_FAILURE_NO_CHANNEL
      *
      * @hide
@@ -615,15 +616,15 @@
     public @interface SapStartFailure {}
 
     /**
-     *  If WIFI AP start failed, this reason code means there is no legal channel exists on
-     *  user selected band by regulatory
+     *  All other reasons for AP start failure besides {@link #SAP_START_FAILURE_NO_CHANNEL}.
      *
      *  @hide
      */
     public static final int SAP_START_FAILURE_GENERAL= 0;
 
     /**
-     *  All other reason for AP start failed besides SAP_START_FAILURE_GENERAL
+     *  If Wi-Fi AP start failed, this reason code means that no legal channel exists on user
+     *  selected band due to regulatory constraints.
      *
      *  @hide
      */
@@ -947,7 +948,8 @@
     /**
      * Directed broadcast intent action indicating that the device has connected to one of the
      * network suggestions provided by the app. This will be sent post connection to a network
-     * which was created with {@link WifiNetworkSuggestion.Builder#setIsAppInteractionRequired()}
+     * which was created with {@link WifiNetworkSuggestion.Builder#setIsAppInteractionRequired(
+     * boolean)}
      * flag set.
      * <p>
      * Note: The broadcast is sent to the app only if it holds
@@ -1000,8 +1002,9 @@
     /**
      * In this Wi-Fi lock mode, Wi-Fi will not go to power save.
      * This results in operating with low packet latency.
-     * The lock is active  even when the device screen is off or
-     * the acquiring application is running in the background.
+     * The lock is only active when the device is connected to an access point.
+     * The lock is active even when the device screen is off or the acquiring application is
+     * running in the background.
      * This mode will consume more power and hence should be used only
      * when there is a need for this tradeoff.
      * <p>
@@ -1019,6 +1022,7 @@
      * In this Wi-Fi lock mode, Wi-Fi will operate with a priority to achieve low latency.
      * {@link #WIFI_MODE_FULL_LOW_LATENCY} lock has the following limitations:
      * <ol>
+     * <li>The lock is only active when the device is connected to an access point.</li>
      * <li>The lock is only active when the screen is on.</li>
      * <li>The lock is only active when the acquiring app is running in the foreground.</li>
      * </ol>
@@ -1272,7 +1276,10 @@
     })
     @NonNull
     public Map<OsuProvider, List<ScanResult>> getMatchingOsuProviders(
-            List<ScanResult> scanResults) {
+            @Nullable List<ScanResult> scanResults) {
+        if (scanResults == null) {
+            return new HashMap<>();
+        }
         try {
             return mService.getMatchingOsuProviders(scanResults);
         } catch (RemoteException e) {
@@ -4785,13 +4792,13 @@
 
     /**
      * Interface for Wi-Fi usability statistics listener. Should be implemented by applications and
-     * set when calling {@link WifiManager#addWifiUsabilityStatsListener(Executor,
-     * WifiUsabilityStatsListener)}.
+     * set when calling {@link WifiManager#addOnWifiUsabilityStatsListener(Executor,
+     * OnWifiUsabilityStatsListener)}.
      *
      * @hide
      */
     @SystemApi
-    public interface WifiUsabilityStatsListener {
+    public interface OnWifiUsabilityStatsListener {
         /**
          * Called when Wi-Fi usability statistics is updated.
          *
@@ -4803,15 +4810,15 @@
          *                           Wi-Fi usability stats.
          * @param stats The updated Wi-Fi usability statistics.
          */
-        void onStatsUpdated(int seqNum, boolean isSameBssidAndFreq,
-                WifiUsabilityStatsEntry stats);
+        void onWifiUsabilityStats(int seqNum, boolean isSameBssidAndFreq,
+                @NonNull WifiUsabilityStatsEntry stats);
     }
 
     /**
-     * Adds a listener for Wi-Fi usability statistics. See {@link WifiUsabilityStatsListener}.
+     * Adds a listener for Wi-Fi usability statistics. See {@link OnWifiUsabilityStatsListener}.
      * Multiple listeners can be added. Callers will be invoked periodically by framework to
      * inform clients about the current Wi-Fi usability statistics. Callers can remove a previously
-     * added listener using {@link removeWifiUsabilityStatsListener}.
+     * added listener using {@link removeOnWifiUsabilityStatsListener}.
      *
      * @param executor The executor on which callback will be invoked.
      * @param listener Listener for Wifi usability statistics.
@@ -4820,25 +4827,25 @@
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE)
-    public void addWifiUsabilityStatsListener(@NonNull @CallbackExecutor Executor executor,
-            @NonNull WifiUsabilityStatsListener listener) {
+    public void addOnWifiUsabilityStatsListener(@NonNull @CallbackExecutor Executor executor,
+            @NonNull OnWifiUsabilityStatsListener listener) {
         if (executor == null) throw new IllegalArgumentException("executor cannot be null");
         if (listener == null) throw new IllegalArgumentException("listener cannot be null");
         if (mVerboseLoggingEnabled) {
-            Log.v(TAG, "addWifiUsabilityStatsListener: listener=" + listener);
+            Log.v(TAG, "addOnWifiUsabilityStatsListener: listener=" + listener);
         }
         try {
-            mService.addWifiUsabilityStatsListener(new Binder(),
-                    new IWifiUsabilityStatsListener.Stub() {
+            mService.addOnWifiUsabilityStatsListener(new Binder(),
+                    new IOnWifiUsabilityStatsListener.Stub() {
                         @Override
-                        public void onStatsUpdated(int seqNum, boolean isSameBssidAndFreq,
+                        public void onWifiUsabilityStats(int seqNum, boolean isSameBssidAndFreq,
                                 WifiUsabilityStatsEntry stats) {
                             if (mVerboseLoggingEnabled) {
-                                Log.v(TAG, "WifiUsabilityStatsListener: onStatsUpdated: seqNum="
-                                        + seqNum);
+                                Log.v(TAG, "OnWifiUsabilityStatsListener: "
+                                        + "onWifiUsabilityStats: seqNum=" + seqNum);
                             }
                             Binder.withCleanCallingIdentity(() ->
-                                    executor.execute(() -> listener.onStatsUpdated(seqNum,
+                                    executor.execute(() -> listener.onWifiUsabilityStats(seqNum,
                                             isSameBssidAndFreq, stats)));
                         }
                     },
@@ -4859,13 +4866,13 @@
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE)
-    public void removeWifiUsabilityStatsListener(@NonNull WifiUsabilityStatsListener listener) {
+    public void removeOnWifiUsabilityStatsListener(@NonNull OnWifiUsabilityStatsListener listener) {
         if (listener == null) throw new IllegalArgumentException("listener cannot be null");
         if (mVerboseLoggingEnabled) {
-            Log.v(TAG, "removeWifiUsabilityStatsListener: listener=" + listener);
+            Log.v(TAG, "removeOnWifiUsabilityStatsListener: listener=" + listener);
         }
         try {
-            mService.removeWifiUsabilityStatsListener(listener.hashCode());
+            mService.removeOnWifiUsabilityStatsListener(listener.hashCode());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -4873,13 +4880,14 @@
 
     /**
      * Provide a Wi-Fi usability score information to be recorded (but not acted upon) by the
-     * framework. The Wi-Fi usability score is derived from {@link WifiUsabilityStatsListener}
+     * framework. The Wi-Fi usability score is derived from {@link OnWifiUsabilityStatsListener}
      * where a score is matched to Wi-Fi usability statistics using the sequence number. The score
      * is used to quantify whether Wi-Fi is usable in a future time.
      *
      * @param seqNum Sequence number of the Wi-Fi usability score.
-     * @param score The Wi-Fi usability score.
-     * @param predictionHorizonSec Prediction horizon of the Wi-Fi usability score.
+     * @param score The Wi-Fi usability score, expected range: [0, 100].
+     * @param predictionHorizonSec Prediction horizon of the Wi-Fi usability score in second,
+     *                             expected range: [0, 30].
      *
      * @hide
      */
diff --git a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
index 8b56b3f..6c2d7ff 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
@@ -183,10 +183,12 @@
         /**
          * Specifies whether this represents an Enhanced Open (OWE) network.
          *
+         * @param isEnhancedOpen {@code true} to indicate that the network uses enhanced open,
+         *                       {@code false} otherwise.
          * @return Instance of {@link Builder} to enable chaining of the builder method.
          */
-        public @NonNull Builder setIsEnhancedOpen() {
-            mIsEnhancedOpen = true;
+        public @NonNull Builder setIsEnhancedOpen(boolean isEnhancedOpen) {
+            mIsEnhancedOpen = isEnhancedOpen;
             return this;
         }
 
@@ -261,10 +263,12 @@
          * hidden networks need to be explicitly probed for.</li>
          * <li>If not set, defaults to false (i.e not a hidden network).</li>
          *
+         * @param isHiddenSsid {@code true} to indicate that the network is hidden, {@code false}
+         *                     otherwise.
          * @return Instance of {@link Builder} to enable chaining of the builder method.
          */
-        public @NonNull Builder setIsHiddenSsid() {
-            mIsHiddenSSID = true;
+        public @NonNull Builder setIsHiddenSsid(boolean isHiddenSsid) {
+            mIsHiddenSSID = isHiddenSsid;
             return this;
         }
 
diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
index 3742b83..a9c9939 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
@@ -18,6 +18,7 @@
 
 import static com.android.internal.util.Preconditions.checkNotNull;
 
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityThread;
@@ -159,10 +160,12 @@
         /**
          * Specifies whether this represents an Enhanced Open (OWE) network.
          *
+         * @param isEnhancedOpen {@code true} to indicate that the network used enhanced open,
+         *                       {@code false} otherwise.
          * @return Instance of {@link Builder} to enable chaining of the builder method.
          */
-        public @NonNull Builder setIsEnhancedOpen() {
-            mIsEnhancedOpen = true;
+        public @NonNull Builder setIsEnhancedOpen(boolean isEnhancedOpen) {
+            mIsEnhancedOpen = isEnhancedOpen;
             return this;
         }
 
@@ -235,10 +238,12 @@
          * <p>
          * <li>If not set, defaults to false (i.e not a hidden network).</li>
          *
+         * @param isHiddenSsid {@code true} to indicate that the network is hidden, {@code false}
+         *                     otherwise.
          * @return Instance of {@link Builder} to enable chaining of the builder method.
          */
-        public @NonNull Builder setIsHiddenSsid() {
-            mIsHiddenSSID = true;
+        public @NonNull Builder setIsHiddenSsid(boolean isHiddenSsid) {
+            mIsHiddenSSID = isHiddenSsid;
             return this;
         }
 
@@ -253,10 +258,12 @@
          * <p>
          * <li>If not set, defaults to false (i.e no app interaction required).</li>
          *
+         * @param isAppInteractionRequired {@code true} to indicate that app interaction is
+         *                                 required, {@code false} otherwise.
          * @return Instance of {@link Builder} to enable chaining of the builder method.
          */
-        public @NonNull Builder setIsAppInteractionRequired() {
-            mIsAppInteractionRequired = true;
+        public @NonNull Builder setIsAppInteractionRequired(boolean isAppInteractionRequired) {
+            mIsAppInteractionRequired = isAppInteractionRequired;
             return this;
         }
 
@@ -265,10 +272,12 @@
          * <p>
          * <li>If not set, defaults to false (i.e no user interaction required).</li>
          *
+         * @param isUserInteractionRequired {@code true} to indicate that user interaction is
+         *                                  required, {@code false} otherwise.
          * @return Instance of {@link Builder} to enable chaining of the builder method.
          */
-        public @NonNull Builder setIsUserInteractionRequired() {
-            mIsUserInteractionRequired = true;
+        public @NonNull Builder setIsUserInteractionRequired(boolean isUserInteractionRequired) {
+            mIsUserInteractionRequired = isUserInteractionRequired;
             return this;
         }
 
@@ -283,7 +292,7 @@
          * @return Instance of {@link Builder} to enable chaining of the builder method.
          * @throws IllegalArgumentException if the priority value is negative.
          */
-        public @NonNull Builder setPriority(int priority) {
+        public @NonNull Builder setPriority(@IntRange(from = 0) int priority) {
             if (priority < 0) {
                 throw new IllegalArgumentException("Invalid priority value " + priority);
             }
@@ -296,10 +305,12 @@
          * <p>
          * <li>If not set, defaults to false (i.e not metered).</li>
          *
+         * @param isMetered {@code true} to indicate that the network is metered, {@code false}
+         *                  otherwise.
          * @return Instance of {@link Builder} to enable chaining of the builder method.
          */
-        public @NonNull Builder setIsMetered() {
-            mIsMetered = true;
+        public @NonNull Builder setIsMetered(boolean isMetered) {
+            mIsMetered = isMetered;
             return this;
         }
 
@@ -392,7 +403,7 @@
          *      .setWpa3Passphrase("test6789")
          *      .build()
          * final List<WifiNetworkSuggestion> suggestionsList =
-         *      new ArrayList<WifiNetworkSuggestion> {{
+         *      new ArrayList<WifiNetworkSuggestion> &#123;{
          *          add(suggestion1);
          *          add(suggestion2);
          *          add(suggestion3);
diff --git a/wifi/java/android/net/wifi/WifiUsabilityStatsEntry.java b/wifi/java/android/net/wifi/WifiUsabilityStatsEntry.java
index 2dee971..51aa93a 100644
--- a/wifi/java/android/net/wifi/WifiUsabilityStatsEntry.java
+++ b/wifi/java/android/net/wifi/WifiUsabilityStatsEntry.java
@@ -51,87 +51,88 @@
     public static final int PROBE_STATUS_FAILURE = 3;
 
     /** Absolute milliseconds from device boot when these stats were sampled */
-    public final long timeStampMs;
+    private final long mTimeStampMillis;
     /** The RSSI (in dBm) at the sample time */
-    public final int rssi;
+    private final int mRssi;
     /** Link speed at the sample time in Mbps */
-    public final int linkSpeedMbps;
+    private final int mLinkSpeedMbps;
     /** The total number of tx success counted from the last radio chip reset */
-    public final long totalTxSuccess;
+    private final long mTotalTxSuccess;
     /** The total number of MPDU data packet retries counted from the last radio chip reset */
-    public final long totalTxRetries;
+    private final long mTotalTxRetries;
     /** The total number of tx bad counted from the last radio chip reset */
-    public final long totalTxBad;
+    private final long mTotalTxBad;
     /** The total number of rx success counted from the last radio chip reset */
-    public final long totalRxSuccess;
+    private final long mTotalRxSuccess;
     /** The total time the wifi radio is on in ms counted from the last radio chip reset */
-    public final long totalRadioOnTimeMs;
+    private final long mTotalRadioOnTimeMillis;
     /** The total time the wifi radio is doing tx in ms counted from the last radio chip reset */
-    public final long totalRadioTxTimeMs;
+    private final long mTotalRadioTxTimeMillis;
     /** The total time the wifi radio is doing rx in ms counted from the last radio chip reset */
-    public final long totalRadioRxTimeMs;
+    private final long mTotalRadioRxTimeMillis;
     /** The total time spent on all types of scans in ms counted from the last radio chip reset */
-    public final long totalScanTimeMs;
+    private final long mTotalScanTimeMillis;
     /** The total time spent on nan scans in ms counted from the last radio chip reset */
-    public final long totalNanScanTimeMs;
+    private final long mTotalNanScanTimeMillis;
     /** The total time spent on background scans in ms counted from the last radio chip reset */
-    public final long totalBackgroundScanTimeMs;
+    private final long mTotalBackgroundScanTimeMillis;
     /** The total time spent on roam scans in ms counted from the last radio chip reset */
-    public final long totalRoamScanTimeMs;
+    private final long mTotalRoamScanTimeMillis;
     /** The total time spent on pno scans in ms counted from the last radio chip reset */
-    public final long totalPnoScanTimeMs;
+    private final long mTotalPnoScanTimeMillis;
     /** The total time spent on hotspot2.0 scans and GAS exchange in ms counted from the last radio
      * chip reset */
-    public final long totalHotspot2ScanTimeMs;
+    private final long mTotalHotspot2ScanTimeMillis;
     /** The total time CCA is on busy status on the current frequency in ms counted from the last
      * radio chip reset */
-    public final long totalCcaBusyFreqTimeMs;
-    /** The total radio on time of the current frequency from the last radio chip reset */
-    public final long totalRadioOnFreqTimeMs;
+    private final long mTotalCcaBusyFreqTimeMillis;
+    /** The total radio on time on the current frequency from the last radio chip reset */
+    private final long mTotalRadioOnFreqTimeMillis;
     /** The total number of beacons received from the last radio chip reset */
-    public final long totalBeaconRx;
+    private final long mTotalBeaconRx;
     /** The status of link probe since last stats update */
-    public final int probeStatusSinceLastUpdate;
+    @ProbeStatus private final int mProbeStatusSinceLastUpdate;
     /** The elapsed time of the most recent link probe since last stats update */
-    public final int probeElapsedTimeMsSinceLastUpdate;
+    private final int mProbeElapsedTimeSinceLastUpdateMillis;
     /** The MCS rate of the most recent link probe since last stats update */
-    public final int probeMcsRateSinceLastUpdate;
+    private final int mProbeMcsRateSinceLastUpdate;
     /** Rx link speed at the sample time in Mbps */
-    public final int rxLinkSpeedMbps;
+    private final int mRxLinkSpeedMbps;
 
     /** Constructor function {@hide} */
-    public WifiUsabilityStatsEntry(long timeStampMs, int rssi,
-            int linkSpeedMbps, long totalTxSuccess, long totalTxRetries,
-            long totalTxBad, long totalRxSuccess, long totalRadioOnTimeMs,
-            long totalRadioTxTimeMs, long totalRadioRxTimeMs, long totalScanTimeMs,
-            long totalNanScanTimeMs, long totalBackgroundScanTimeMs, long totalRoamScanTimeMs,
-            long totalPnoScanTimeMs, long totalHotspot2ScanTimeMs, long totalCcaBusyFreqTimeMs,
-            long totalRadioOnFreqTimeMs, long totalBeaconRx,
-            @ProbeStatus int probeStatusSinceLastUpdate, int probeElapsedTimeMsSinceLastUpdate,
+    public WifiUsabilityStatsEntry(long timeStampMillis, int rssi, int linkSpeedMbps,
+            long totalTxSuccess, long totalTxRetries, long totalTxBad, long totalRxSuccess,
+            long totalRadioOnTimeMillis, long totalRadioTxTimeMillis, long totalRadioRxTimeMillis,
+            long totalScanTimeMillis, long totalNanScanTimeMillis,
+            long totalBackgroundScanTimeMillis,
+            long totalRoamScanTimeMillis, long totalPnoScanTimeMillis,
+            long totalHotspot2ScanTimeMillis,
+            long totalCcaBusyFreqTimeMillis, long totalRadioOnFreqTimeMillis, long totalBeaconRx,
+            @ProbeStatus int probeStatusSinceLastUpdate, int probeElapsedTimeSinceLastUpdateMillis,
             int probeMcsRateSinceLastUpdate, int rxLinkSpeedMbps) {
-        this.timeStampMs = timeStampMs;
-        this.rssi = rssi;
-        this.linkSpeedMbps = linkSpeedMbps;
-        this.totalTxSuccess = totalTxSuccess;
-        this.totalTxRetries = totalTxRetries;
-        this.totalTxBad = totalTxBad;
-        this.totalRxSuccess = totalRxSuccess;
-        this.totalRadioOnTimeMs = totalRadioOnTimeMs;
-        this.totalRadioTxTimeMs = totalRadioTxTimeMs;
-        this.totalRadioRxTimeMs = totalRadioRxTimeMs;
-        this.totalScanTimeMs = totalScanTimeMs;
-        this.totalNanScanTimeMs = totalNanScanTimeMs;
-        this.totalBackgroundScanTimeMs = totalBackgroundScanTimeMs;
-        this.totalRoamScanTimeMs = totalRoamScanTimeMs;
-        this.totalPnoScanTimeMs = totalPnoScanTimeMs;
-        this.totalHotspot2ScanTimeMs = totalHotspot2ScanTimeMs;
-        this.totalCcaBusyFreqTimeMs = totalCcaBusyFreqTimeMs;
-        this.totalRadioOnFreqTimeMs = totalRadioOnFreqTimeMs;
-        this.totalBeaconRx = totalBeaconRx;
-        this.probeStatusSinceLastUpdate = probeStatusSinceLastUpdate;
-        this.probeElapsedTimeMsSinceLastUpdate = probeElapsedTimeMsSinceLastUpdate;
-        this.probeMcsRateSinceLastUpdate = probeMcsRateSinceLastUpdate;
-        this.rxLinkSpeedMbps = rxLinkSpeedMbps;
+        mTimeStampMillis = timeStampMillis;
+        mRssi = rssi;
+        mLinkSpeedMbps = linkSpeedMbps;
+        mTotalTxSuccess = totalTxSuccess;
+        mTotalTxRetries = totalTxRetries;
+        mTotalTxBad = totalTxBad;
+        mTotalRxSuccess = totalRxSuccess;
+        mTotalRadioOnTimeMillis = totalRadioOnTimeMillis;
+        mTotalRadioTxTimeMillis = totalRadioTxTimeMillis;
+        mTotalRadioRxTimeMillis = totalRadioRxTimeMillis;
+        mTotalScanTimeMillis = totalScanTimeMillis;
+        mTotalNanScanTimeMillis = totalNanScanTimeMillis;
+        mTotalBackgroundScanTimeMillis = totalBackgroundScanTimeMillis;
+        mTotalRoamScanTimeMillis = totalRoamScanTimeMillis;
+        mTotalPnoScanTimeMillis = totalPnoScanTimeMillis;
+        mTotalHotspot2ScanTimeMillis = totalHotspot2ScanTimeMillis;
+        mTotalCcaBusyFreqTimeMillis = totalCcaBusyFreqTimeMillis;
+        mTotalRadioOnFreqTimeMillis = totalRadioOnFreqTimeMillis;
+        mTotalBeaconRx = totalBeaconRx;
+        mProbeStatusSinceLastUpdate = probeStatusSinceLastUpdate;
+        mProbeElapsedTimeSinceLastUpdateMillis = probeElapsedTimeSinceLastUpdateMillis;
+        mProbeMcsRateSinceLastUpdate = probeMcsRateSinceLastUpdate;
+        mRxLinkSpeedMbps = rxLinkSpeedMbps;
     }
 
     /** Implement the Parcelable interface */
@@ -141,29 +142,29 @@
 
     /** Implement the Parcelable interface */
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeLong(timeStampMs);
-        dest.writeInt(rssi);
-        dest.writeInt(linkSpeedMbps);
-        dest.writeLong(totalTxSuccess);
-        dest.writeLong(totalTxRetries);
-        dest.writeLong(totalTxBad);
-        dest.writeLong(totalRxSuccess);
-        dest.writeLong(totalRadioOnTimeMs);
-        dest.writeLong(totalRadioTxTimeMs);
-        dest.writeLong(totalRadioRxTimeMs);
-        dest.writeLong(totalScanTimeMs);
-        dest.writeLong(totalNanScanTimeMs);
-        dest.writeLong(totalBackgroundScanTimeMs);
-        dest.writeLong(totalRoamScanTimeMs);
-        dest.writeLong(totalPnoScanTimeMs);
-        dest.writeLong(totalHotspot2ScanTimeMs);
-        dest.writeLong(totalCcaBusyFreqTimeMs);
-        dest.writeLong(totalRadioOnFreqTimeMs);
-        dest.writeLong(totalBeaconRx);
-        dest.writeInt(probeStatusSinceLastUpdate);
-        dest.writeInt(probeElapsedTimeMsSinceLastUpdate);
-        dest.writeInt(probeMcsRateSinceLastUpdate);
-        dest.writeInt(rxLinkSpeedMbps);
+        dest.writeLong(mTimeStampMillis);
+        dest.writeInt(mRssi);
+        dest.writeInt(mLinkSpeedMbps);
+        dest.writeLong(mTotalTxSuccess);
+        dest.writeLong(mTotalTxRetries);
+        dest.writeLong(mTotalTxBad);
+        dest.writeLong(mTotalRxSuccess);
+        dest.writeLong(mTotalRadioOnTimeMillis);
+        dest.writeLong(mTotalRadioTxTimeMillis);
+        dest.writeLong(mTotalRadioRxTimeMillis);
+        dest.writeLong(mTotalScanTimeMillis);
+        dest.writeLong(mTotalNanScanTimeMillis);
+        dest.writeLong(mTotalBackgroundScanTimeMillis);
+        dest.writeLong(mTotalRoamScanTimeMillis);
+        dest.writeLong(mTotalPnoScanTimeMillis);
+        dest.writeLong(mTotalHotspot2ScanTimeMillis);
+        dest.writeLong(mTotalCcaBusyFreqTimeMillis);
+        dest.writeLong(mTotalRadioOnFreqTimeMillis);
+        dest.writeLong(mTotalBeaconRx);
+        dest.writeInt(mProbeStatusSinceLastUpdate);
+        dest.writeInt(mProbeElapsedTimeSinceLastUpdateMillis);
+        dest.writeInt(mProbeMcsRateSinceLastUpdate);
+        dest.writeInt(mRxLinkSpeedMbps);
     }
 
     /** Implement the Parcelable interface */
@@ -186,4 +187,121 @@
             return new WifiUsabilityStatsEntry[size];
         }
     };
+
+    /** Absolute milliseconds from device boot when these stats were sampled */
+    public long getTimeStampMillis() {
+        return mTimeStampMillis;
+    }
+
+    /** The RSSI (in dBm) at the sample time */
+    public int getRssi() {
+        return mRssi;
+    }
+
+    /** Link speed at the sample time in Mbps */
+    public int getLinkSpeedMbps() {
+        return mLinkSpeedMbps;
+    }
+
+    /** The total number of tx success counted from the last radio chip reset */
+    public long getTotalTxSuccess() {
+        return mTotalTxSuccess;
+    }
+
+    /** The total number of MPDU data packet retries counted from the last radio chip reset */
+    public long getTotalTxRetries() {
+        return mTotalTxRetries;
+    }
+
+    /** The total number of tx bad counted from the last radio chip reset */
+    public long getTotalTxBad() {
+        return mTotalTxBad;
+    }
+
+    /** The total number of rx success counted from the last radio chip reset */
+    public long getTotalRxSuccess() {
+        return mTotalRxSuccess;
+    }
+
+    /** The total time the wifi radio is on in ms counted from the last radio chip reset */
+    public long getTotalRadioOnTimeMillis() {
+        return mTotalRadioOnTimeMillis;
+    }
+
+    /** The total time the wifi radio is doing tx in ms counted from the last radio chip reset */
+    public long getTotalRadioTxTimeMillis() {
+        return mTotalRadioTxTimeMillis;
+    }
+
+    /** The total time the wifi radio is doing rx in ms counted from the last radio chip reset */
+    public long getTotalRadioRxTimeMillis() {
+        return mTotalRadioRxTimeMillis;
+    }
+
+    /** The total time spent on all types of scans in ms counted from the last radio chip reset */
+    public long getTotalScanTimeMillis() {
+        return mTotalScanTimeMillis;
+    }
+
+    /** The total time spent on nan scans in ms counted from the last radio chip reset */
+    public long getTotalNanScanTimeMillis() {
+        return mTotalNanScanTimeMillis;
+    }
+
+    /** The total time spent on background scans in ms counted from the last radio chip reset */
+    public long getTotalBackgroundScanTimeMillis() {
+        return mTotalBackgroundScanTimeMillis;
+    }
+
+    /** The total time spent on roam scans in ms counted from the last radio chip reset */
+    public long getTotalRoamScanTimeMillis() {
+        return mTotalRoamScanTimeMillis;
+    }
+
+    /** The total time spent on pno scans in ms counted from the last radio chip reset */
+    public long getTotalPnoScanTimeMillis() {
+        return mTotalPnoScanTimeMillis;
+    }
+
+    /** The total time spent on hotspot2.0 scans and GAS exchange in ms counted from the last radio
+     * chip reset */
+    public long getTotalHotspot2ScanTimeMillis() {
+        return mTotalHotspot2ScanTimeMillis;
+    }
+
+    /** The total time CCA is on busy status on the current frequency in ms counted from the last
+     * radio chip reset */
+    public long getTotalCcaBusyFreqTimeMillis() {
+        return mTotalCcaBusyFreqTimeMillis;
+    }
+
+    /** The total radio on time on the current frequency from the last radio chip reset */
+    public long getTotalRadioOnFreqTimeMillis() {
+        return mTotalRadioOnFreqTimeMillis;
+    }
+
+    /** The total number of beacons received from the last radio chip reset */
+    public long getTotalBeaconRx() {
+        return mTotalBeaconRx;
+    }
+
+    /** The status of link probe since last stats update */
+    @ProbeStatus public int getProbeStatusSinceLastUpdate() {
+        return mProbeStatusSinceLastUpdate;
+    }
+
+    /** The elapsed time of the most recent link probe since last stats update */
+    public int getProbeElapsedTimeSinceLastUpdateMillis() {
+        return mProbeElapsedTimeSinceLastUpdateMillis;
+    }
+
+    /** The MCS rate of the most recent link probe since last stats update */
+    public int getProbeMcsRateSinceLastUpdate() {
+        return mProbeMcsRateSinceLastUpdate;
+    }
+
+    /** Rx link speed at the sample time in Mbps */
+    public int getRxLinkSpeedMbps() {
+        return mRxLinkSpeedMbps;
+    }
 }
diff --git a/wifi/java/com/android/server/wifi/BaseWifiService.java b/wifi/java/com/android/server/wifi/BaseWifiService.java
index c236c7a..842d78d 100644
--- a/wifi/java/com/android/server/wifi/BaseWifiService.java
+++ b/wifi/java/com/android/server/wifi/BaseWifiService.java
@@ -23,10 +23,10 @@
 import android.net.Network;
 import android.net.wifi.IDppCallback;
 import android.net.wifi.INetworkRequestMatchCallback;
+import android.net.wifi.IOnWifiUsabilityStatsListener;
 import android.net.wifi.ISoftApCallback;
 import android.net.wifi.ITrafficStateCallback;
 import android.net.wifi.IWifiManager;
-import android.net.wifi.IWifiUsabilityStatsListener;
 import android.net.wifi.ScanResult;
 import android.net.wifi.WifiActivityEnergyInfo;
 import android.net.wifi.WifiConfiguration;
@@ -467,13 +467,13 @@
     }
 
     @Override
-    public void addWifiUsabilityStatsListener(
-            IBinder binder, IWifiUsabilityStatsListener listener, int listenerIdentifier) {
+    public void addOnWifiUsabilityStatsListener(
+            IBinder binder, IOnWifiUsabilityStatsListener listener, int listenerIdentifier) {
         throw new UnsupportedOperationException();
     }
 
     @Override
-    public void removeWifiUsabilityStatsListener(int listenerIdentifier) {
+    public void removeOnWifiUsabilityStatsListener(int listenerIdentifier) {
         throw new UnsupportedOperationException();
     }
 
diff --git a/wifi/tests/runtests.sh b/wifi/tests/runtests.sh
index 2caf8a5..1e0ec37 100755
--- a/wifi/tests/runtests.sh
+++ b/wifi/tests/runtests.sh
@@ -19,7 +19,7 @@
 adb root
 adb wait-for-device
 
-adb install -r -g "$OUT/data/app/FrameworksWifiApiTests/FrameworksWifiApiTests.apk"
+adb install -r -g "$OUT/testcases/FrameworksWifiApiTests/arm64/FrameworksWifiApiTests.apk"
 
 adb shell am instrument --no-hidden-api-checks -w "$@" \
   'android.net.wifi.test/androidx.test.runner.AndroidJUnitRunner'
diff --git a/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java b/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
index 6ec64ff..beed666 100644
--- a/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
@@ -423,4 +423,68 @@
         mEnterpriseConfig.setPassword(password);
         assertFalse(mEnterpriseConfig.toString().contains(password));
     }
+
+    /** Verifies that certificate ownership flag is set correctly */
+    @Test
+    public void testIsAppInstalledDeviceKeyAndCert() {
+        // First make sure that app didn't install anything
+        assertFalse(mEnterpriseConfig.isAppInstalledDeviceKeyAndCert());
+        assertFalse(mEnterpriseConfig.isAppInstalledCaCert());
+
+        // Then app loads keys via the enterprise config API
+        PrivateKey clientKey = FakeKeys.RSA_KEY1;
+        X509Certificate cert0 = FakeKeys.CLIENT_CERT;
+        X509Certificate cert1 = FakeKeys.CA_CERT1;
+        X509Certificate[] clientChain = new X509Certificate[] {cert0, cert1};
+        mEnterpriseConfig.setClientKeyEntryWithCertificateChain(clientKey, clientChain);
+        X509Certificate[] result = mEnterpriseConfig.getClientCertificateChain();
+        assertEquals(result.length, 2);
+        assertTrue(result[0] == cert0 && result[1] == cert1);
+        assertTrue(mEnterpriseConfig.getClientCertificate() == cert0);
+
+        // Make sure it is the owner now
+        assertTrue(mEnterpriseConfig.isAppInstalledDeviceKeyAndCert());
+        assertFalse(mEnterpriseConfig.isAppInstalledCaCert());
+    }
+
+    /** Verifies that certificate ownership flag is set correctly */
+    @Test
+    public void testIsAppInstalledCaCert() {
+        // First make sure that app didn't install anything
+        assertFalse(mEnterpriseConfig.isAppInstalledDeviceKeyAndCert());
+        assertFalse(mEnterpriseConfig.isAppInstalledCaCert());
+
+        // Then app loads CA cert via the enterprise config API
+        X509Certificate cert = FakeKeys.CA_CERT1;
+        mEnterpriseConfig.setCaCertificate(cert);
+        X509Certificate result = mEnterpriseConfig.getCaCertificate();
+        assertTrue(result == cert);
+
+        // Make sure it is the owner now
+        assertFalse(mEnterpriseConfig.isAppInstalledDeviceKeyAndCert());
+        assertTrue(mEnterpriseConfig.isAppInstalledCaCert());
+    }
+
+    /** Verifies that certificate ownership flag is set correctly */
+    @Test
+    public void testIsAppInstalledCaCerts() {
+        // First make sure that app didn't install anything
+        assertFalse(mEnterpriseConfig.isAppInstalledDeviceKeyAndCert());
+        assertFalse(mEnterpriseConfig.isAppInstalledCaCert());
+
+        // Then app loads CA cert via the enterprise config API
+        X509Certificate cert0 = FakeKeys.CA_CERT0;
+        X509Certificate cert1 = FakeKeys.CA_CERT1;
+        X509Certificate[] cert = new X509Certificate[] {cert0, cert1};
+
+        mEnterpriseConfig.setCaCertificates(cert);
+        X509Certificate[] result = mEnterpriseConfig.getCaCertificates();
+        assertEquals(result.length, 2);
+        assertTrue(result[0] == cert0 && result[1] == cert1);
+//        assertTrue(mEnterpriseConfig.getClientCertificate() == cert0);
+
+        // Make sure it is the owner now
+        assertFalse(mEnterpriseConfig.isAppInstalledDeviceKeyAndCert());
+        assertTrue(mEnterpriseConfig.isAppInstalledCaCert());
+    }
 }
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index 5c2f626..600abc9 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -59,9 +59,9 @@
 import android.net.wifi.WifiManager.LocalOnlyHotspotSubscription;
 import android.net.wifi.WifiManager.NetworkRequestMatchCallback;
 import android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback;
+import android.net.wifi.WifiManager.OnWifiUsabilityStatsListener;
 import android.net.wifi.WifiManager.SoftApCallback;
 import android.net.wifi.WifiManager.TrafficStateCallback;
-import android.net.wifi.WifiManager.WifiUsabilityStatsListener;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
@@ -105,7 +105,7 @@
     @Mock SoftApCallback mSoftApCallback;
     @Mock TrafficStateCallback mTrafficStateCallback;
     @Mock NetworkRequestMatchCallback mNetworkRequestMatchCallback;
-    @Mock WifiUsabilityStatsListener mWifiUsabilityStatsListener;
+    @Mock OnWifiUsabilityStatsListener mOnWifiUsabilityStatsListener;
 
     private Executor mExecutor;
     private Handler mHandler;
@@ -1348,29 +1348,29 @@
     }
 
     /**
-     * Verify the call to addWifiUsabilityStatsListener goes to WifiServiceImpl.
+     * Verify the call to addOnWifiUsabilityStatsListener goes to WifiServiceImpl.
      */
     @Test
-    public void addWifiUsabilityStatsListeneroesToWifiServiceImpl() throws Exception {
+    public void addOnWifiUsabilityStatsListeneroesToWifiServiceImpl() throws Exception {
         mExecutor = new SynchronousExecutor();
-        mWifiManager.addWifiUsabilityStatsListener(mExecutor, mWifiUsabilityStatsListener);
-        verify(mWifiService).addWifiUsabilityStatsListener(any(IBinder.class),
-                any(IWifiUsabilityStatsListener.Stub.class), anyInt());
+        mWifiManager.addOnWifiUsabilityStatsListener(mExecutor, mOnWifiUsabilityStatsListener);
+        verify(mWifiService).addOnWifiUsabilityStatsListener(any(IBinder.class),
+                any(IOnWifiUsabilityStatsListener.Stub.class), anyInt());
     }
 
     /**
-     * Verify the call to removeWifiUsabilityStatsListener goes to WifiServiceImpl.
+     * Verify the call to removeOnWifiUsabilityStatsListener goes to WifiServiceImpl.
      */
     @Test
-    public void removeWifiUsabilityListenerGoesToWifiServiceImpl() throws Exception {
+    public void removeOnWifiUsabilityListenerGoesToWifiServiceImpl() throws Exception {
         ArgumentCaptor<Integer> listenerIdentifier = ArgumentCaptor.forClass(Integer.class);
         mExecutor = new SynchronousExecutor();
-        mWifiManager.addWifiUsabilityStatsListener(mExecutor, mWifiUsabilityStatsListener);
-        verify(mWifiService).addWifiUsabilityStatsListener(any(IBinder.class),
-                any(IWifiUsabilityStatsListener.Stub.class), listenerIdentifier.capture());
+        mWifiManager.addOnWifiUsabilityStatsListener(mExecutor, mOnWifiUsabilityStatsListener);
+        verify(mWifiService).addOnWifiUsabilityStatsListener(any(IBinder.class),
+                any(IOnWifiUsabilityStatsListener.Stub.class), listenerIdentifier.capture());
 
-        mWifiManager.removeWifiUsabilityStatsListener(mWifiUsabilityStatsListener);
-        verify(mWifiService).removeWifiUsabilityStatsListener(
+        mWifiManager.removeOnWifiUsabilityStatsListener(mOnWifiUsabilityStatsListener);
+        verify(mWifiService).removeOnWifiUsabilityStatsListener(
                 eq((int) listenerIdentifier.getValue()));
     }
 
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java
index feac0e5..edb43d8 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java
@@ -114,7 +114,7 @@
                 .setSsid(TEST_SSID)
                 .setBssid(MacAddress.fromString(TEST_BSSID))
                 .setWpa2EnterpriseConfig(enterpriseConfig)
-                .setIsHiddenSsid()
+                .setIsHiddenSsid(true)
                 .build();
 
         assertTrue(specifier instanceof WifiNetworkSpecifier);
@@ -278,7 +278,7 @@
         new WifiNetworkSpecifier.Builder()
                 .setBssidPattern(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
                         MacAddress.fromString(TEST_BSSID_OUI_MASK))
-                .setIsHiddenSsid()
+                .setIsHiddenSsid(true)
                 .build();
     }
 
@@ -305,7 +305,7 @@
     public void testWifiNetworkSpecifierBuilderWithSsidMatchPatternForHiddenNetwork() {
         new WifiNetworkSpecifier.Builder()
                 .setSsidPattern(new PatternMatcher(TEST_SSID, PATTERN_PREFIX))
-                .setIsHiddenSsid()
+                .setIsHiddenSsid(true)
                 .build();
     }
 
@@ -341,14 +341,14 @@
     /**
      * Ensure {@link WifiNetworkSpecifier.Builder#build()} throws an exception
      * when both {@link WifiNetworkSpecifier.Builder#setWpa3Passphrase(String)} and
-     * {@link WifiNetworkSpecifier.Builder#setIsEnhancedOpen()} are invoked.
+     * {@link WifiNetworkSpecifier.Builder#setIsEnhancedOpen(boolean)} are invoked.
      */
     @Test(expected = IllegalStateException.class)
     public void testWifiNetworkSpecifierBuilderWithBothWpa3PasphraseAndEnhancedOpen() {
         new WifiNetworkSpecifier.Builder()
                 .setSsidPattern(new PatternMatcher(TEST_SSID, PATTERN_LITERAL))
                 .setWpa3Passphrase(TEST_PRESHARED_KEY)
-                .setIsEnhancedOpen()
+                .setIsEnhancedOpen(true)
                 .build();
     }
 
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
index 05ee22c..2b0c773 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
@@ -49,7 +49,7 @@
     public void testWifiNetworkSuggestionBuilderForOpenNetworkWithReqAppInteraction() {
         WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
                 .setSsid(TEST_SSID)
-                .setIsAppInteractionRequired()
+                .setIsAppInteractionRequired(true)
                 .build();
 
         assertEquals(Process.myUid(), suggestion.suggestorUid);
@@ -74,7 +74,7 @@
         WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
                 .setSsid(TEST_SSID)
                 .setWpa2Passphrase(TEST_PRESHARED_KEY)
-                .setIsAppInteractionRequired()
+                .setIsAppInteractionRequired(true)
                 .setPriority(0)
                 .build();
 
@@ -101,8 +101,8 @@
         WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
                 .setSsid(TEST_SSID)
                 .setWpa2Passphrase(TEST_PRESHARED_KEY)
-                .setIsUserInteractionRequired()
-                .setIsMetered()
+                .setIsUserInteractionRequired(true)
+                .setIsMetered(true)
                 .build();
 
         assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
@@ -126,7 +126,7 @@
         WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
                 .setSsid(TEST_SSID)
                 .setBssid(MacAddress.fromString(TEST_BSSID))
-                .setIsEnhancedOpen()
+                .setIsEnhancedOpen(true)
                 .build();
 
         assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
@@ -265,7 +265,7 @@
     public void testWifiNetworkSuggestionBuilderWithInvalidPriority() {
         new WifiNetworkSuggestion.Builder()
                 .setSsid(TEST_SSID)
-                .setPriority(-1)
+                .setPriority(-2)
                 .build();
     }
 
@@ -301,14 +301,14 @@
     /**
      * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
      * when both {@link WifiNetworkSuggestion.Builder#setWpa3Passphrase(String)} and
-     * {@link WifiNetworkSuggestion.Builder#setIsEnhancedOpen()} are invoked.
+     * {@link WifiNetworkSuggestion.Builder#setIsEnhancedOpen(boolean)} are invoked.
      */
     @Test(expected = IllegalStateException.class)
     public void testWifiNetworkSuggestionBuilderWithBothWpa3PasphraseAndEnhancedOpen() {
         new WifiNetworkSuggestion.Builder()
                 .setSsid(TEST_SSID)
                 .setWpa3Passphrase(TEST_PRESHARED_KEY)
-                .setIsEnhancedOpen()
+                .setIsEnhancedOpen(true)
                 .build();
     }
 
diff --git a/wifi/tests/src/android/net/wifi/WifiUsabilityStatsEntryTest.java b/wifi/tests/src/android/net/wifi/WifiUsabilityStatsEntryTest.java
index a22f8ce..8e37113 100644
--- a/wifi/tests/src/android/net/wifi/WifiUsabilityStatsEntryTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiUsabilityStatsEntryTest.java
@@ -81,29 +81,35 @@
     private static void assertWifiUsabilityStatsEntryEquals(
             WifiUsabilityStatsEntry expected,
             WifiUsabilityStatsEntry actual) {
-        assertEquals(expected.timeStampMs, actual.timeStampMs);
-        assertEquals(expected.rssi, actual.rssi);
-        assertEquals(expected.linkSpeedMbps, actual.linkSpeedMbps);
-        assertEquals(expected.totalTxSuccess, actual.totalTxSuccess);
-        assertEquals(expected.totalTxRetries, actual.totalTxRetries);
-        assertEquals(expected.totalTxBad, actual.totalTxBad);
-        assertEquals(expected.totalRxSuccess, actual.totalRxSuccess);
-        assertEquals(expected.totalRadioOnTimeMs, actual.totalRadioOnTimeMs);
-        assertEquals(expected.totalRadioTxTimeMs, actual.totalRadioTxTimeMs);
-        assertEquals(expected.totalRadioRxTimeMs, actual.totalRadioRxTimeMs);
-        assertEquals(expected.totalScanTimeMs, actual.totalScanTimeMs);
-        assertEquals(expected.totalNanScanTimeMs, actual.totalNanScanTimeMs);
-        assertEquals(expected.totalBackgroundScanTimeMs, actual.totalBackgroundScanTimeMs);
-        assertEquals(expected.totalRoamScanTimeMs, actual.totalRoamScanTimeMs);
-        assertEquals(expected.totalPnoScanTimeMs, actual.totalPnoScanTimeMs);
-        assertEquals(expected.totalHotspot2ScanTimeMs, actual.totalHotspot2ScanTimeMs);
-        assertEquals(expected.totalCcaBusyFreqTimeMs, actual.totalCcaBusyFreqTimeMs);
-        assertEquals(expected.totalRadioOnFreqTimeMs, actual.totalRadioOnFreqTimeMs);
-        assertEquals(expected.totalBeaconRx, actual.totalBeaconRx);
-        assertEquals(expected.probeStatusSinceLastUpdate, actual.probeStatusSinceLastUpdate);
-        assertEquals(expected.probeElapsedTimeMsSinceLastUpdate,
-                actual.probeElapsedTimeMsSinceLastUpdate);
-        assertEquals(expected.probeMcsRateSinceLastUpdate, actual.probeMcsRateSinceLastUpdate);
-        assertEquals(expected.rxLinkSpeedMbps, actual.rxLinkSpeedMbps);
+        assertEquals(expected.getTimeStampMillis(), actual.getTimeStampMillis());
+        assertEquals(expected.getRssi(), actual.getRssi());
+        assertEquals(expected.getLinkSpeedMbps(), actual.getLinkSpeedMbps());
+        assertEquals(expected.getTotalTxSuccess(), actual.getTotalTxSuccess());
+        assertEquals(expected.getTotalTxRetries(), actual.getTotalTxRetries());
+        assertEquals(expected.getTotalTxBad(), actual.getTotalTxBad());
+        assertEquals(expected.getTotalRxSuccess(), actual.getTotalRxSuccess());
+        assertEquals(expected.getTotalRadioOnTimeMillis(), actual.getTotalRadioOnTimeMillis());
+        assertEquals(expected.getTotalRadioTxTimeMillis(), actual.getTotalRadioTxTimeMillis());
+        assertEquals(expected.getTotalRadioRxTimeMillis(), actual.getTotalRadioRxTimeMillis());
+        assertEquals(expected.getTotalScanTimeMillis(), actual.getTotalScanTimeMillis());
+        assertEquals(expected.getTotalNanScanTimeMillis(), actual.getTotalNanScanTimeMillis());
+        assertEquals(expected.getTotalBackgroundScanTimeMillis(),
+                actual.getTotalBackgroundScanTimeMillis());
+        assertEquals(expected.getTotalRoamScanTimeMillis(), actual.getTotalRoamScanTimeMillis());
+        assertEquals(expected.getTotalPnoScanTimeMillis(), actual.getTotalPnoScanTimeMillis());
+        assertEquals(expected.getTotalHotspot2ScanTimeMillis(),
+                actual.getTotalHotspot2ScanTimeMillis());
+        assertEquals(expected.getTotalCcaBusyFreqTimeMillis(),
+                actual.getTotalCcaBusyFreqTimeMillis());
+        assertEquals(expected.getTotalRadioOnFreqTimeMillis(),
+                actual.getTotalRadioOnFreqTimeMillis());
+        assertEquals(expected.getTotalBeaconRx(), actual.getTotalBeaconRx());
+        assertEquals(expected.getProbeStatusSinceLastUpdate(),
+                actual.getProbeStatusSinceLastUpdate());
+        assertEquals(expected.getProbeElapsedTimeSinceLastUpdateMillis(),
+                actual.getProbeElapsedTimeSinceLastUpdateMillis());
+        assertEquals(expected.getProbeMcsRateSinceLastUpdate(),
+                actual.getProbeMcsRateSinceLastUpdate());
+        assertEquals(expected.getRxLinkSpeedMbps(), actual.getRxLinkSpeedMbps());
     }
 }